1import { assert } from "@effect/vitest";
2import type { ProviderReplayTranscript } from "@t3tools/contracts";
3
4import type { OrchestratorV2ScenarioResult } from "../../OrchestratorScenario.ts";
5import {
6 assertBaseProjection,
7 assertSemanticProjectionIntegrity,
8 assertTurnItemTypes,
9 assertUserMessagesInclude,
10 assertVisibleTurnItemsMirrorLocalTurnItems,
11 projectionFor,
12 TURN_INTERRUPT_PROMPT,
13} from "../shared.ts";
14
15export function assertTurnInterruptClaudeOutput(
16 result: OrchestratorV2ScenarioResult,
17 transcript: ProviderReplayTranscript,
18) {
19 assert.equal(transcript.provider, "claudeAgent");
20 assertBaseProjection({ result, transcript, runCount: 1, runStatuses: ["interrupted"] });
21
22 const projection = projectionFor(result, transcript.scenario);
23 assertSemanticProjectionIntegrity(projection);
24 assertVisibleTurnItemsMirrorLocalTurnItems(projection);
25 assertTurnItemTypes(projection, [
26 "user_message",
27 "run_interrupt_request",
28 "run_interrupt_result",
29 ]);
30 assertUserMessagesInclude(projection, [TURN_INTERRUPT_PROMPT]);
31
32 const interruptRequest = projection.turnItems.find(
33 (item) => item.type === "run_interrupt_request",
34 );
35 const interruptResult = projection.turnItems.find((item) => item.type === "run_interrupt_result");
36 assert.isDefined(interruptRequest);
37 assert.isDefined(interruptResult);
38 assert.equal(interruptRequest.status, "completed");
39 assert.equal(interruptResult.status, "interrupted");
40 assert.equal(interruptResult.parentItemId, interruptRequest.id);
41 assert.deepEqual(
42 projection.attempts.map((attempt) => attempt.status),
43 ["interrupted"],
44 );
45 assert.deepEqual(
46 projection.nodes.map((node) => node.status),
47 ["interrupted"],
48 );
49 assert.equal(projection.providerThreads[0]?.status, "idle");
50 assert.equal(projection.providerTurns[0]?.status, "interrupted");
51}