fix(agent): align investigation waits and interruption messages
Generic Container CI/CD / test-build-publish (push) Successful in 54s
Agent CI/CD / build-test-publish-and-deploy (push) Successful in 54s

Separate waiting-stage reports from final recovery closure and route resumed runs through the actual handling phase. Keep superseded runs distinct from expired leases and transport failures, with focused heartbeat response coverage.
This commit is contained in:
2026-11-12 13:45:27 +08:00
parent f7e411c288
commit 9a77cb0557
7 changed files with 52 additions and 9 deletions
@@ -5,6 +5,8 @@ import {
humanTaskEvidenceCommandSchema,
hasOperationalTaskRun,
OperationalTaskClient,
OperationalTaskClientError,
taskRunInterruptionMessage,
proposedTaskActionSchema,
releaseOperationalTaskCredential,
} from "../../src/product/operational-task-client.js";
@@ -53,6 +55,32 @@ afterEach(() => {
releaseOperationalTaskCredential("runtime-1");
});
it.each([
["RUN_SUPERSEDED", "任务已收到更新,本轮执行已停止,由新一轮执行接续。"],
["LEASE_EXPIRED", "工况任务租约已失效,本次执行已停止,等待任务重新领取。"],
["VERSION_CONFLICT", "工况任务心跳校验失败,本次执行已停止,请检查任务状态或服务连接。"],
] as const)("distinguishes heartbeat interruption %s from lease expiry", async (code, message) => {
let calls = 0;
globalThis.fetch = (async () => ++calls === 1 ? Response.json(run)
: Response.json({ code, detail: "Server rejected heartbeat" }, { status: 409 })) as unknown as typeof fetch;
bindOperationalTaskCredential("runtime-1", { authorization: "Bearer test-only", projectId: "project-1" });
const client = new OperationalTaskClient("http://server.test");
await client.claimTask("runtime-1", taskId, runId, {
requestId: crypto.randomUUID(), expectedRevision: 1, sourceSessionId: "session-1",
});
let caught: Error | undefined;
try { await client.heartbeatTask("runtime-1", taskId, runId, "session-1"); }
catch (error) { caught = error as Error; }
expect(caught).toBeInstanceOf(OperationalTaskClientError);
expect(caught).toMatchObject({ code, status: 409 });
expect(taskRunInterruptionMessage(caught!)).toBe(message);
});
it("does not describe a network heartbeat failure as lease expiry", () => {
expect(taskRunInterruptionMessage(new Error("fetch failed")))
.toBe("工况任务心跳校验失败,本次执行已停止,请检查任务状态或服务连接。");
});
describe("OperationalTaskClient", () => {
it("requests a selected report while retaining the current task snapshot", async () => {
let requestedUrl = "";