1import { assert } from "@effect/vitest";
2import type { ProviderReplayTranscript } from "@t3tools/contracts";
3
4import type { OrchestratorV2ScenarioResult } from "../../OrchestratorScenario.ts";
5import {
6 assertAssistantTextIncludes,
7 assertBaseProjection,
8 assertRuntimeRequestCounts,
9 assertSemanticProjectionIntegrity,
10 assertTurnItemTypes,
11 assertUserMessageInputIntents,
12 assertUserMessagesInclude,
13 assertVisibleTurnItemsMirrorLocalTurnItems,
14 MESSAGE_STEERING_INITIAL_PROMPT,
15 MESSAGE_STEERING_STEER_PROMPT,
16 projectionFor,
17} from "../shared.ts";
18
19function frameField(frame: unknown, key: string): unknown {
20 return typeof frame === "object" && frame !== null ? Reflect.get(frame, key) : undefined;
21}
22
23/**
24 * Pi steers through `prompt` with `streamingBehavior: "steer"`, which Pi
25 * queues into the running agent loop. The steer lands in the same provider
26 * turn: no interrupt, no second turn, one settled run.
27 */
28export function assertPiMessageSteeringOutput(
29 result: OrchestratorV2ScenarioResult,
30 transcript: ProviderReplayTranscript,
31) {
32 const outbound = transcript.entries.flatMap((entry) =>
33 entry.type === "expect_outbound" ? [entry.frame] : [],
34 );
35 const prompts = outbound.filter((frame) => frameField(frame, "type") === "prompt");
36 assert.deepEqual(
37 prompts.map((frame) => [frameField(frame, "message"), frameField(frame, "streamingBehavior")]),
38 [
39 [MESSAGE_STEERING_INITIAL_PROMPT, "steer"],
40 [MESSAGE_STEERING_STEER_PROMPT, "steer"],
41 ],
42 );
43 assert.isFalse(
44 outbound.some((frame) => frameField(frame, "type") === "abort"),
45 "steering must not abort the running Pi turn",
46 );
47
48 assertBaseProjection({ result, transcript, runCount: 1, runStatuses: ["completed"] });
49 const projection = projectionFor(result, transcript.scenario);
50 assertSemanticProjectionIntegrity(projection);
51 assertVisibleTurnItemsMirrorLocalTurnItems(projection);
52 assertTurnItemTypes(projection, ["user_message", "assistant_message"]);
53 assertRuntimeRequestCounts(projection, { total: 0 });
54 assertUserMessagesInclude(projection, [
55 MESSAGE_STEERING_INITIAL_PROMPT,
56 MESSAGE_STEERING_STEER_PROMPT,
57 ]);
58 assertUserMessageInputIntents(projection, ["turn_start", "steer"]);
59 assertAssistantTextIncludes(projection, "steering fixture observed");
60 assert.lengthOf(projection.providerTurns, 1, "active steering must not start a provider turn");
61 assert.equal(projection.providerTurns[0]?.status, "completed");
62}