From 8577e2fbdf281336dcb83d90a7e934bc33ffc346 Mon Sep 17 00:00:00 2001 From: Codex Date: Mon, 1 Jun 2026 23:47:49 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=94=B6=E6=95=9B=20one-shot=20runner?= =?UTF-8?q?=20=E6=88=90=E5=8A=9F=E7=BB=88=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/runner/k8s-job.ts | 1 + src/runner/run-once.ts | 3 ++- src/selftest/cases/20-runner-k8s-job.ts | 1 + src/selftest/cases/30-codex-stdio.ts | 4 ++-- src/selftest/cases/60-hwlab-baseline-contract.ts | 4 ++++ 5 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/runner/k8s-job.ts b/src/runner/k8s-job.ts index f3cad5e..67996e0 100644 --- a/src/runner/k8s-job.ts +++ b/src/runner/k8s-job.ts @@ -158,6 +158,7 @@ function runnerEnv(options: RunnerJobRenderOptions, context: { namespace: string { name: "AGENTRUN_K8S_JOB_NAME", value: context.jobName }, { name: "AGENTRUN_LOG_PATH", value: "/tmp/agentrun-runner.jsonl" }, { name: "AGENTRUN_RUNNER_IDLE_TIMEOUT_MS", value: "600000" }, + { name: "AGENTRUN_RUNNER_ONE_SHOT", value: "true" }, { name: "HOME", value: "/home/agentrun" }, { name: "CODEX_HOME", value: codexHome }, ...(selectedSecret ? [{ name: "AGENTRUN_CODEX_SECRET_HOME", value: selectedSecret.projectionMountPath }] : []), diff --git a/src/runner/run-once.ts b/src/runner/run-once.ts index cf1d4df..d278c02 100644 --- a/src/runner/run-once.ts +++ b/src/runner/run-once.ts @@ -105,7 +105,7 @@ export async function runOnce(options: RunnerOnceOptions): Promise { : await executeCommand(api, options, command, runner, attemptId, workspacePath); commandResults.push(result); if (options.oneShot === true) { - const run = await api.getRun(options.runId); + const run = await api.reportStatus(options.runId, { terminalStatus: result.terminalStatus, failureKind: result.failureKind, failureMessage: null }); return { runner, commandId: command.id, terminalStatus: result.terminalStatus, failureKind: result.failureKind, run, commandsProcessed: commandResults.length, commandResults, stopped: "one-shot" } as JsonRecord; } } @@ -204,6 +204,7 @@ async function reportCommandFailure(api: RunnerManagerApi, runId: string, comman async function reportCancelled(api: RunnerManagerApi, runId: string, commandId: string, runner: RunnerRecord, attemptId: string, message: string): Promise { await api.reportCommandStatus(commandId, { terminalStatus: "cancelled", failureKind: "cancelled", failureMessage: message }); + await api.reportStatus(runId, { terminalStatus: "cancelled", failureKind: "cancelled", failureMessage: message }); await api.appendEvent(runId, { type: "backend_status", payload: { phase: "turn-cancelled", commandId, attemptId, runnerId: runner.id, failureKind: "cancelled", message } }); await api.appendEvent(runId, { type: "terminal_status", payload: { terminalStatus: "cancelled", failureKind: "cancelled", message, commandId, attemptId, runnerId: runner.id } }); return { commandId, terminalStatus: "cancelled", failureKind: "cancelled" }; diff --git a/src/selftest/cases/20-runner-k8s-job.ts b/src/selftest/cases/20-runner-k8s-job.ts index bee8072..e63eab0 100644 --- a/src/selftest/cases/20-runner-k8s-job.ts +++ b/src/selftest/cases/20-runner-k8s-job.ts @@ -126,6 +126,7 @@ function assertRunnerJobUsesWritableCodexHome(manifest: JsonRecord, expectedCode assert.equal(value("HOME"), "/home/agentrun"); assert.equal(value("CODEX_HOME"), expectedCodexHome); assert.equal(value("AGENTRUN_CODEX_SECRET_HOME"), projectionPath); + assert.equal(value("AGENTRUN_RUNNER_ONE_SHOT"), "true"); assert.notEqual(value("CODEX_HOME"), value("AGENTRUN_CODEX_SECRET_HOME")); } diff --git a/src/selftest/cases/30-codex-stdio.ts b/src/selftest/cases/30-codex-stdio.ts index 6a6c629..e5056cf 100644 --- a/src/selftest/cases/30-codex-stdio.ts +++ b/src/selftest/cases/30-codex-stdio.ts @@ -22,8 +22,8 @@ const selfTest: SelfTestCase = async (context) => { assert.ok(events.items?.some((event) => event.type === "backend_status" && JSON.stringify(event.payload).includes("run-claimed"))); assertNoSecretLeak(events); const finalRun = await client.get(`/api/v1/runs/${happy.runId}`) as { terminalStatus?: string | null; status?: string }; - assert.equal(finalRun.terminalStatus, null); - assert.equal(finalRun.status, "claimed"); + assert.equal(finalRun.terminalStatus, "completed"); + assert.equal(finalRun.status, "completed"); const finalCommand = await client.get(`/api/v1/runs/${happy.runId}/commands/${happy.commandId}`) as { state?: string }; assert.equal(finalCommand.state, "completed"); diff --git a/src/selftest/cases/60-hwlab-baseline-contract.ts b/src/selftest/cases/60-hwlab-baseline-contract.ts index cf09ae8..8b2523f 100644 --- a/src/selftest/cases/60-hwlab-baseline-contract.ts +++ b/src/selftest/cases/60-hwlab-baseline-contract.ts @@ -140,6 +140,10 @@ async function assertResourceBundleFailure(client: ManagerClient, context: SelfT assert.equal(envelope.failureKind, "infra-failed"); const commandRecord = await client.get(`/api/v1/runs/${run.id}/commands/${command.id}`) as { state?: string }; assert.equal(commandRecord.state, "failed"); + const runRecord = await client.get(`/api/v1/runs/${run.id}`) as { status?: string; terminalStatus?: string; failureKind?: string }; + assert.equal(runRecord.status, "failed"); + assert.equal(runRecord.terminalStatus, "failed"); + assert.equal(runRecord.failureKind, "infra-failed"); } function runPayload(context: SelfTestContext, backendProfile: BackendProfile, sessionId: string): JsonRecord {