98 lines
3.9 KiB
TypeScript
98 lines
3.9 KiB
TypeScript
// SPEC: PJ2026-0104010803 Workbench唯一投影 draft-2026-06-24-p1-opencode-message-part-authority.
|
|
// Responsibility: AgentRun cancel control-path regressions without adding more cases to the legacy large server-agent-chat test file.
|
|
|
|
import assert from "node:assert/strict";
|
|
import { test } from "bun:test";
|
|
|
|
import { cancelAgentRunChatTurn, syncAgentRunChatResult } from "./code-agent-agentrun-adapter.ts";
|
|
import { createCodeAgentTraceStore } from "./code-agent-trace-store.ts";
|
|
|
|
test("AgentRun cancel downstream failure returns visible blocked disposition instead of throwing", async () => {
|
|
const traceId = "trc_cancel_downstream_blocked";
|
|
const codeAgentChatResults = new Map();
|
|
const traceStore = createCodeAgentTraceStore();
|
|
const currentResult = {
|
|
traceId,
|
|
status: "running",
|
|
conversationId: "cnv_cancel_downstream_blocked",
|
|
sessionId: "ses_cancel_downstream_blocked",
|
|
agentRun: {
|
|
runId: "run_cancel_downstream_blocked",
|
|
commandId: "cmd_cancel_downstream_blocked",
|
|
managerUrl: "http://127.0.0.1:65535",
|
|
status: "running",
|
|
commandState: "running"
|
|
}
|
|
};
|
|
const payload = await cancelAgentRunChatTurn({
|
|
traceId,
|
|
currentResult,
|
|
traceStore,
|
|
options: {
|
|
codeAgentChatResults,
|
|
env: {
|
|
HWLAB_CODE_AGENT_AGENTRUN_ALLOW_NON_K3S_URL: "1",
|
|
HWLAB_CODE_AGENT_AGENTRUN_HTTP_TIMEOUT_MS: "5000",
|
|
HWLAB_CODE_AGENT_CANCEL_TIMEOUT_MS: "5000"
|
|
},
|
|
async fetchImpl(url, init) {
|
|
assert.equal(url, "http://127.0.0.1:65535/api/v1/commands/cmd_cancel_downstream_blocked/cancel");
|
|
assert.equal(init.method, "POST");
|
|
return new Response(JSON.stringify({ ok: false, failureKind: "command_not_cancelable", message: "command is not cancelable" }), { status: 409 });
|
|
}
|
|
}
|
|
});
|
|
|
|
assert.equal(payload.status, "blocked");
|
|
assert.equal(payload.canceled, false);
|
|
assert.equal(payload.cancelStatus, "blocked");
|
|
assert.equal(payload.cancelDisposition.status, "blocked");
|
|
assert.equal(payload.cancelDisposition.code, "command_not_cancelable");
|
|
assert.equal(payload.cancelDisposition.terminal, false);
|
|
assert.equal(payload.error.route, "/v1/agent/chat/cancel");
|
|
assert.equal(payload.error.upstreamRoute, "/api/v1/commands/cmd_cancel_downstream_blocked/cancel");
|
|
assert.equal(codeAgentChatResults.get(traceId)?.cancelDisposition?.code, "command_not_cancelable");
|
|
assert.ok(traceStore.snapshot(traceId).events.some((event) => event.label === "agentrun:cancel:blocked" && event.status === "blocked"));
|
|
});
|
|
|
|
test("AgentRun result sync preserves a user-canceled payload instead of accepting late completed result", async () => {
|
|
const traceId = "trc_cancel_sealed_result";
|
|
const traceStore = createCodeAgentTraceStore();
|
|
const currentResult = {
|
|
traceId,
|
|
status: "canceled",
|
|
canceled: true,
|
|
cancelStatus: "canceled",
|
|
cancelDisposition: { status: "canceled", forwarded: true, terminal: true, traceId, valuesPrinted: false },
|
|
finalResponse: { text: "hwlab-user-cancel", status: "canceled", traceId, valuesPrinted: false },
|
|
agentRun: {
|
|
runId: "run_cancel_sealed_result",
|
|
commandId: "cmd_cancel_sealed_result",
|
|
managerUrl: "http://127.0.0.1:65535",
|
|
status: "cancelled",
|
|
commandState: "cancelled",
|
|
terminalStatus: "cancelled",
|
|
traceId,
|
|
valuesPrinted: false
|
|
},
|
|
valuesPrinted: false
|
|
};
|
|
|
|
const synced = await syncAgentRunChatResult({
|
|
traceId,
|
|
currentResult,
|
|
traceStore,
|
|
options: {
|
|
env: { HWLAB_CODE_AGENT_AGENTRUN_ALLOW_NON_K3S_URL: "1" },
|
|
fetchImpl() {
|
|
throw new Error("late AgentRun result must not be fetched after HWLAB user cancel is sealed");
|
|
}
|
|
}
|
|
});
|
|
|
|
assert.equal(synced.localCancelSealed, true);
|
|
assert.equal(synced.resultSynced, false);
|
|
assert.equal(synced.result.status, "canceled");
|
|
assert.equal(synced.result.finalResponse.text, "hwlab-user-cancel");
|
|
});
|