Treat intentional cancellation as a non-failure terminal
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -40,7 +40,7 @@ export type TurnResult = "finished" | "paused";
|
||||
|
||||
export type InvokeKind = "user_send" | "notify" | "worker_event" | "system_reminder" | "wakeup";
|
||||
|
||||
export type RunResult = "finished" | "paused" | "limit_reached" | "rolled_back";
|
||||
export type RunResult = "finished" | "paused" | "limit_reached" | "cancelled" | "rolled_back";
|
||||
|
||||
export type ToolResultDisposition = "success" | "error" | "interrupted" | "cancelled" | "outcome_unknown";
|
||||
|
||||
@@ -142,7 +142,7 @@ export type RunResumeSource = "compaction" | "pause";
|
||||
|
||||
export type RunFailureKind = "engine" | "compaction";
|
||||
|
||||
export type SessionSnapshotEntryData = { "kind": "user_input", segments: Array<Segment>, } | { "kind": "message", role: SessionMessageRole, content: Array<SessionContentPart>, } | { "kind": "tool_call", call_id: string, name: string, arguments: string, } | { "kind": "tool_result", call_id: string, summary: string, content?: string | null, is_error: boolean, attachments?: Array<SessionToolAttachment>, } | { "kind": "system_item", item_kind: string, content: string, data?: unknown, } | { "kind": "run_yielded", reason: RunYieldReason, active_run_turn_count: number, } | { "kind": "run_resumed", source: RunResumeSource, active_run_turn_count: number, } | { "kind": "run_error", message: string, failure?: RunFailureKind | null, };
|
||||
export type SessionSnapshotEntryData = { "kind": "user_input", segments: Array<Segment>, } | { "kind": "message", role: SessionMessageRole, content: Array<SessionContentPart>, } | { "kind": "tool_call", call_id: string, name: string, arguments: string, } | { "kind": "tool_result", call_id: string, summary: string, content?: string | null, is_error: boolean, attachments?: Array<SessionToolAttachment>, } | { "kind": "system_item", item_kind: string, content: string, data?: unknown, } | { "kind": "run_yielded", reason: RunYieldReason, active_run_turn_count: number, } | { "kind": "run_resumed", source: RunResumeSource, active_run_turn_count: number, } | { "kind": "run_cancelled" } | { "kind": "run_error", message: string, failure?: RunFailureKind | null, };
|
||||
|
||||
export type SessionSnapshotEntry = {
|
||||
/**
|
||||
@@ -153,7 +153,7 @@ entry_id: string,
|
||||
/**
|
||||
* Timestamp copied from the durable log record that commits this entry.
|
||||
*/
|
||||
timestamp: number, provenance: SessionEntryProvenance, derived_from?: Array<string>, } & ({ "kind": "user_input", segments: Array<Segment>, } | { "kind": "message", role: SessionMessageRole, content: Array<SessionContentPart>, } | { "kind": "tool_call", call_id: string, name: string, arguments: string, } | { "kind": "tool_result", call_id: string, summary: string, content?: string | null, is_error: boolean, attachments?: Array<SessionToolAttachment>, } | { "kind": "system_item", item_kind: string, content: string, data?: unknown, } | { "kind": "run_yielded", reason: RunYieldReason, active_run_turn_count: number, } | { "kind": "run_resumed", source: RunResumeSource, active_run_turn_count: number, } | { "kind": "run_error", message: string, failure?: RunFailureKind | null, });
|
||||
timestamp: number, provenance: SessionEntryProvenance, derived_from?: Array<string>, } & ({ "kind": "user_input", segments: Array<Segment>, } | { "kind": "message", role: SessionMessageRole, content: Array<SessionContentPart>, } | { "kind": "tool_call", call_id: string, name: string, arguments: string, } | { "kind": "tool_result", call_id: string, summary: string, content?: string | null, is_error: boolean, attachments?: Array<SessionToolAttachment>, } | { "kind": "system_item", item_kind: string, content: string, data?: unknown, } | { "kind": "run_yielded", reason: RunYieldReason, active_run_turn_count: number, } | { "kind": "run_resumed", source: RunResumeSource, active_run_turn_count: number, } | { "kind": "run_cancelled" } | { "kind": "run_error", message: string, failure?: RunFailureKind | null, });
|
||||
|
||||
export type SessionConversationTurn = { turn_id: string, entries: Array<SessionSnapshotEntry>, };
|
||||
|
||||
|
||||
@@ -134,6 +134,7 @@ function canonicalSession(logEntries: unknown[]): Event extends {
|
||||
}
|
||||
case "run_yielded":
|
||||
case "run_resumed":
|
||||
case "run_cancelled":
|
||||
entries.push({
|
||||
entry_id: `legacy-test-${sequence++}`,
|
||||
provenance: "legacy_unknown",
|
||||
@@ -395,6 +396,43 @@ Deno.test("snapshot restores compaction terminal without reviving transition pro
|
||||
assertEquals(projection.lines[0].kind, "error");
|
||||
});
|
||||
|
||||
Deno.test("intentional cancellation stays non-error in live and snapshot projections", () => {
|
||||
const live = projectConsole([
|
||||
{
|
||||
eventId: "cancelled-terminal",
|
||||
event: {
|
||||
event: "session_entry_committed",
|
||||
data: {
|
||||
entry: {
|
||||
entry_id: "cancelled-entry",
|
||||
timestamp: 10,
|
||||
provenance: "legacy_unknown",
|
||||
kind: "run_cancelled",
|
||||
},
|
||||
},
|
||||
} as Event,
|
||||
},
|
||||
{
|
||||
eventId: "cancelled-run-end",
|
||||
event: {
|
||||
event: "run_end",
|
||||
data: { result: "cancelled" },
|
||||
} as Event,
|
||||
},
|
||||
]);
|
||||
assertEquals(live.lines.some((line) => line.kind === "error"), false);
|
||||
|
||||
const restored = projectConsole([{
|
||||
eventId: "snapshot",
|
||||
event: snapshotEvent("/repo", [{
|
||||
kind: "run_cancelled",
|
||||
timestamp: 10,
|
||||
}]),
|
||||
}]);
|
||||
assertEquals(restored.lines.some((line) => line.kind === "error"), false);
|
||||
assertEquals(restored.compaction, null);
|
||||
});
|
||||
|
||||
Deno.test("snapshot replaces a live error with one durable run_errored row", () => {
|
||||
const projector = createConsoleProjector();
|
||||
let projection = projector.append([
|
||||
|
||||
@@ -2190,8 +2190,9 @@ function applySessionEntry(
|
||||
}
|
||||
case "run_yielded":
|
||||
case "run_resumed":
|
||||
// Durable logical-Run transitions are replayable state, not Console
|
||||
// progress rows. Runtime compaction progress remains the spinner authority.
|
||||
case "run_cancelled":
|
||||
// Durable logical-Run transitions and intentional cancellation are
|
||||
// replayable lifecycle state, not errors or Console progress rows.
|
||||
break;
|
||||
case "run_error":
|
||||
appendDurableRunFailure(
|
||||
|
||||
Reference in New Issue
Block a user