mirror of
https://github.com/murashit/codex-panel.git
synced 2026-07-22 06:57:10 +00:00
99 lines
4 KiB
TypeScript
99 lines
4 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { type ChatAction, type ChatState, chatReducer } from "../../../../../src/features/chat/application/state/root-reducer";
|
|
import { planTurnRuntimeEvents } from "../../../../../src/features/chat/application/turns/runtime-event-plan";
|
|
import type { TurnRuntimeEvent } from "../../../../../src/features/chat/application/turns/runtime-events";
|
|
import type { ThreadStreamItem } from "../../../../../src/features/chat/domain/thread-stream/items";
|
|
import { chatStateFixture, chatStateWith } from "../../support/state";
|
|
import { chatStateThreadStreamItems, withChatStateThreadStreamItems } from "../../support/thread-stream";
|
|
|
|
function activeRunningState(): ChatState {
|
|
let state = chatStateFixture();
|
|
state = chatStateWith(state, { activeThread: { id: "thread-active" } });
|
|
return chatStateWith(state, { turn: { lifecycle: { kind: "running", turnId: "turn-active" } } });
|
|
}
|
|
|
|
function applyActions(state: ChatState, actions: readonly ChatAction[]): ChatState {
|
|
return actions.reduce(chatReducer, state);
|
|
}
|
|
|
|
describe("TurnRuntimeEvent planner", () => {
|
|
it("reports turn starts as turn-runtime outcomes", () => {
|
|
const state = chatStateWith(chatStateFixture(), { activeThread: { id: "thread-active" } });
|
|
|
|
const plan = planTurnRuntimeEvents(state, [{ type: "turnStarted", threadId: "thread-active", turnId: "turn-active", recencyAt: 123 }]);
|
|
|
|
expect(plan.outcomes).toEqual([{ type: "turn-started", threadId: "thread-active", turnId: "turn-active", recencyAt: 123 }]);
|
|
});
|
|
|
|
it("reconciles completed turn snapshots with optimistic local user dialogues", () => {
|
|
let state = activeRunningState();
|
|
state = withChatStateThreadStreamItems(state, [
|
|
{ id: "local-user-1", kind: "dialogue", dialogueKind: "user", role: "user", text: "hello", turnId: "turn-active" },
|
|
]);
|
|
const events: TurnRuntimeEvent[] = [
|
|
{
|
|
type: "turnCompleted",
|
|
threadId: "thread-active",
|
|
turnId: "turn-active",
|
|
status: "completed",
|
|
completedTurnTranscriptSummary: { userText: "hello", assistantText: "done" },
|
|
completedItems: [
|
|
{
|
|
id: "u1",
|
|
sourceItemId: "u1",
|
|
kind: "dialogue",
|
|
dialogueKind: "user",
|
|
role: "user",
|
|
text: "hello",
|
|
clientId: "local-user-1",
|
|
turnId: "turn-active",
|
|
},
|
|
{
|
|
id: "a1",
|
|
sourceItemId: "a1",
|
|
kind: "dialogue",
|
|
dialogueKind: "assistantResponse",
|
|
role: "assistant",
|
|
text: "done",
|
|
dialogueState: "completed",
|
|
turnId: "turn-active",
|
|
},
|
|
],
|
|
},
|
|
];
|
|
|
|
const plan = planTurnRuntimeEvents(state, events);
|
|
const next = applyActions(state, plan.actions);
|
|
|
|
expect(chatStateThreadStreamItems(next).map((item) => item.id)).toEqual(["u1", "a1"]);
|
|
expect(plan.outcomes).toEqual([
|
|
{
|
|
type: "turn-completed",
|
|
threadId: "thread-active",
|
|
turnId: "turn-active",
|
|
completedTurnTranscriptSummary: { userText: "hello", assistantText: "done" },
|
|
},
|
|
]);
|
|
});
|
|
|
|
it("upserts structured auto-review results without dropping unrelated stream items", () => {
|
|
let state = activeRunningState();
|
|
state = withChatStateThreadStreamItems(state, [
|
|
{ id: "m1", kind: "dialogue", dialogueKind: "assistantResponse", role: "assistant", text: "working", dialogueState: "completed" },
|
|
{ id: "warning-1", kind: "reviewResult", role: "tool", text: "Auto-review warning", executionState: "completed" },
|
|
]);
|
|
const item: ThreadStreamItem = {
|
|
id: "review-1",
|
|
kind: "reviewResult",
|
|
role: "tool",
|
|
text: "Auto-review approved",
|
|
turnId: "turn-active",
|
|
executionState: "completed",
|
|
};
|
|
|
|
const plan = planTurnRuntimeEvents(state, [{ type: "autoReviewUpdated", item }]);
|
|
const next = applyActions(state, plan.actions);
|
|
|
|
expect(chatStateThreadStreamItems(next).map((streamItem) => streamItem.id)).toEqual(["m1", "review-1"]);
|
|
});
|
|
});
|