From 1a9b6debbb2b3a851a339f06a8bb14db6ce18110 Mon Sep 17 00:00:00 2001 From: AgentRun Codex Date: Thu, 11 Jun 2026 22:47:26 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=BB=9F=E4=B8=80=E6=81=A2=E5=A4=8D?= =?UTF-8?q?=E5=BB=BA=E8=AE=AE=E4=BD=BF=E7=94=A8=20session=20send?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/reference/spec-v01-aipod-spec.md | 8 ++++---- docs/reference/spec-v01-queue.md | 3 +-- src/mgr/diagnosis.ts | 2 +- src/selftest/cases/55-timeout-liveness.ts | 4 ++-- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/docs/reference/spec-v01-aipod-spec.md b/docs/reference/spec-v01-aipod-spec.md index 41a80e9..04f056a 100644 --- a/docs/reference/spec-v01-aipod-spec.md +++ b/docs/reference/spec-v01-aipod-spec.md @@ -1,13 +1,13 @@ # v0.1 AipodSpec 规格 -`AipodSpec` 是 AgentRun `v0.1` 的声明式 agent 装配规格。它把已有的 `imageRef`、`backendProfile`、`executionPolicy.secretScope`、`ResourceBundleRef.kind="gitbundle"`、Queue task 和 Session turn 装配入口集中到 YAML 文件中,避免把某个 agent 的 work-ready env image、模型、SecretRef、gitbundle、skill 或 tool 写死在 manager、runner 或 CLI 源码里。 +`AipodSpec` 是 AgentRun `v0.1` 的声明式 agent 装配规格。它把已有的 `imageRef`、`backendProfile`、`executionPolicy.secretScope`、`ResourceBundleRef.kind="gitbundle"`、Queue task 和 Session send 装配入口集中到 YAML 文件中,避免把某个 agent 的 work-ready env image、模型、SecretRef、gitbundle、skill 或 tool 写死在 manager、runner 或 CLI 源码里。 ## 设计边界 - `AipodSpec` 只声明装配意图,不保存 API key、SSH private key、token、`auth.json`、`config.toml` 或其他 Secret 明文。 - manager 通过 `/api/v1/aipod-specs` 对 YAML 做增删改查;默认目录为仓库 `config/aipods/`,可用 `AGENTRUN_AIPOD_SPEC_DIR` 覆盖。 -- CLI 通过 `aipod-specs list|show|render|apply|delete` 管理规格,通过 `queue submit --aipod ` 或 `sessions turn --aipod ` 使用规格。 -- `render` 只把规格展开为标准 Queue task / Session turn 输入,输出必须脱敏,只显示 imageRef source 摘要、SecretRef 名称、key、projection、gitbundle 摘要和 `valuesPrinted=false`。 +- CLI 通过 `aipod-specs list|show|render|apply|delete` 管理规格,通过 `queue submit --aipod ` 或 `sessions send --aipod ` 使用规格。 +- `render` 只把规格展开为标准 Queue task / Session send 输入,输出必须脱敏,只显示 imageRef source 摘要、SecretRef 名称、key、projection、gitbundle 摘要和 `valuesPrinted=false`。 - `AipodSpec` 不引入第二套 scheduler、runner、backend adapter 或 Code Queue;最终执行仍走 AgentRun Queue、Sessions、runner Job 和 Codex app-server stdio backend。 ## YAML 结构 @@ -144,7 +144,7 @@ CLI: ./scripts/agentrun aipod-specs apply --yaml-stdin ./scripts/agentrun aipod-specs delete Artificer ./scripts/agentrun queue submit --aipod Artificer --prompt-stdin --idempotency-key -./scripts/agentrun sessions turn --aipod Artificer --prompt-stdin +./scripts/agentrun sessions send --aipod Artificer --prompt-stdin ./scripts/agentrun tool-credentials set-github-ssh --private-key-file --known-hosts-file [--config-file ] ``` diff --git a/docs/reference/spec-v01-queue.md b/docs/reference/spec-v01-queue.md index 921f50e..40e4600 100644 --- a/docs/reference/spec-v01-queue.md +++ b/docs/reference/spec-v01-queue.md @@ -93,8 +93,7 @@ Session 命令负责输出、trace 和会话控制: ```bash ./scripts/agentrun sessions ps [--state default|running|unread|terminal|idle|all] [--profile codex|deepseek|minimax-m3|M3] [--reader-id ] ./scripts/agentrun sessions show [--reader-id ] -./scripts/agentrun sessions turn [sessionId] [--json-stdin|--json-file ] [--prompt-stdin|--prompt-file |--prompt ] [--profile codex|deepseek|minimax-m3|M3] -./scripts/agentrun sessions steer [--prompt-stdin|--prompt-file |--prompt ] +./scripts/agentrun sessions send [sessionId] [--json-stdin|--json-file ] [--prompt-stdin|--prompt-file |--prompt ] [--profile codex|deepseek|minimax-m3|M3] ./scripts/agentrun sessions cancel [--reason ] ./scripts/agentrun sessions output [--after-seq ] [--limit ] ./scripts/agentrun sessions trace [--after-seq ] [--limit ] diff --git a/src/mgr/diagnosis.ts b/src/mgr/diagnosis.ts index 7d89a8c..6706ad2 100644 --- a/src/mgr/diagnosis.ts +++ b/src/mgr/diagnosis.ts @@ -171,7 +171,7 @@ function recoveryActionsForDiagnosis(input: { run: RunRecord; command: CommandRe if (input.command) actions.push({ action: "inspect-command", commandId: input.command.id, command: `./scripts/agentrun commands result ${input.command.id} --run-id ${input.run.id}`, valuesPrinted: false }); actions.push({ action: "poll-events", runId: input.run.id, afterSeq: input.lastSeq, command: `./scripts/agentrun runs events ${input.run.id} --after-seq ${input.lastSeq} --limit 100 --tail-summary`, valuesPrinted: false }); const sessionId = stringValue(input.session.sessionId); - if (sessionId) actions.push({ action: "resume-session", sessionId, command: `./scripts/agentrun sessions turn ${sessionId} --prompt-stdin`, valuesPrinted: false }); + if (sessionId) actions.push({ action: "continue-session", sessionId, command: `./scripts/agentrun sessions send ${sessionId} --prompt-stdin`, valuesPrinted: false }); else actions.push({ action: "session-unavailable", reason: "sessionRef=null", hint: "当前 run 没有 sessionRef,管理者只能从 run/events/command/runner-job 读取 trace 后重新提交;这表示该任务不可同 session 续跑。", valuesPrinted: false }); if (input.runnerLost || input.staleClaimed || input.terminalCommandOpenRun) actions.push({ action: "refresh-queue-or-resubmit", reason: input.failureKind ?? "stale-runner-state", hint: "先用 queue refresh/show 对齐 attempt;有 sessionId 时继续同一 session,没有 sessionId 才重新派发。", valuesPrinted: false }); return actions.slice(0, 6); diff --git a/src/selftest/cases/55-timeout-liveness.ts b/src/selftest/cases/55-timeout-liveness.ts index aaa993e..4825808 100644 --- a/src/selftest/cases/55-timeout-liveness.ts +++ b/src/selftest/cases/55-timeout-liveness.ts @@ -50,7 +50,7 @@ const selfTest: SelfTestCase = async (context: SelfTestContext) => { assert.equal(((terminalResult.terminalClassification as JsonRecord).idleTimeout), true); assert.equal(((terminalResult.terminalClassification as JsonRecord).providerEvidence), "insufficient"); assert.equal(((terminalLive.terminalClassification as JsonRecord).providerInterruptionKnown), false); - assert.ok((terminalLive.recoveryActions as JsonRecord[]).some((action) => action.action === "resume-session")); + assert.ok((terminalLive.recoveryActions as JsonRecord[]).some((action) => action.action === "continue-session")); assert.ok((terminalLive.recoveryActions as JsonRecord[]).some((action) => action.action === "split-task")); const noSession = await createActiveRun(client, context, "timeout-liveness-no-session", 50, { session: false }); @@ -70,7 +70,7 @@ const selfTest: SelfTestCase = async (context: SelfTestContext) => { assert.ok((noSessionDiagnosis.recoveryActions as JsonRecord[]).some((action) => action.action === "session-unavailable")); assert.match(String(noSessionClassification.providerInterruptionReason), /cannot distinguish provider outage/u); assert.equal((noSessionLive.transportDisconnect as JsonRecord).sourceSeq, 4); - assert.equal((noSessionLive.recoveryActions as JsonRecord[]).some((action) => action.action === "resume-session"), false, "sessionId=null must not suggest session-only resume"); + assert.equal((noSessionLive.recoveryActions as JsonRecord[]).some((action) => action.action === "continue-session"), false, "sessionId=null must not suggest session-only continuation"); assert.equal((noSessionLive.recoveryActions as JsonRecord[]).some((action) => action.action === "poll-output"), false, "sessionId=null must not suggest session output path"); assert.ok((noSessionLive.recoveryActions as JsonRecord[]).some((action) => action.action === "poll-trace" && String(action.command).includes("runs events")));