mirror of
https://github.com/murashit/codex-panel.git
synced 2026-07-22 06:57:10 +00:00
136 lines
4.5 KiB
TypeScript
136 lines
4.5 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
initialSubagentActivityState,
|
|
reduceSubagentActivitySlice,
|
|
} from "../../../../../src/features/chat/application/state/subagent-activity";
|
|
import type { ThreadStreamItem } from "../../../../../src/features/chat/domain/thread-stream/items";
|
|
|
|
describe("subagent activity state", () => {
|
|
it("tracks a child and accumulates its active reasoning summary", () => {
|
|
let state = reduceSubagentActivitySlice(initialSubagentActivityState("parent-turn"), {
|
|
type: "subagent-activity/tracked",
|
|
threadId: "child",
|
|
parentTurnId: "parent-turn",
|
|
});
|
|
state = reduceSubagentActivitySlice(state, {
|
|
type: "subagent-activity/turn-started",
|
|
threadId: "child",
|
|
childTurnId: "child-turn",
|
|
});
|
|
state = reduceSubagentActivitySlice(state, {
|
|
type: "subagent-activity/text-delta-appended",
|
|
threadId: "child",
|
|
childTurnId: "child-turn",
|
|
itemId: "reasoning",
|
|
label: "reasoning",
|
|
delta: "Inspecting ",
|
|
kind: "reasoning",
|
|
});
|
|
state = reduceSubagentActivitySlice(state, {
|
|
type: "subagent-activity/text-delta-appended",
|
|
threadId: "child",
|
|
childTurnId: "child-turn",
|
|
itemId: "reasoning",
|
|
label: "reasoning",
|
|
delta: "routing",
|
|
kind: "reasoning",
|
|
});
|
|
|
|
expect(state.byThreadId.get("child")).toMatchObject({
|
|
childTurnId: "child-turn",
|
|
latestItem: { id: "reasoning", kind: "reasoning", text: "reasoning: Inspecting routing" },
|
|
});
|
|
});
|
|
|
|
it("does not let an older item completion replace a newer activity", () => {
|
|
let state = trackedState();
|
|
state = observe(state, reasoningItem("older", "Reading files"), true);
|
|
state = observe(state, reasoningItem("newer", "Running tests"), true);
|
|
state = observe(state, { ...reasoningItem("older", "Finished reading"), executionState: "completed" }, false);
|
|
|
|
expect(state.byThreadId.get("child")?.latestItem).toMatchObject({
|
|
id: "newer",
|
|
text: "Running tests",
|
|
});
|
|
});
|
|
|
|
it("uses the last displayable canonical item when the child turn completes", () => {
|
|
let state = trackedState();
|
|
state = reduceSubagentActivitySlice(state, {
|
|
type: "subagent-activity/turn-completed",
|
|
threadId: "child",
|
|
childTurnId: "child-turn",
|
|
items: [
|
|
{ id: "user", kind: "dialogue", dialogueKind: "user", role: "user", text: "work" },
|
|
reasoningItem("reasoning", "Done checking"),
|
|
{
|
|
id: "answer",
|
|
kind: "dialogue",
|
|
dialogueKind: "assistantResponse",
|
|
dialogueState: "completed",
|
|
role: "assistant",
|
|
text: "Everything passes.",
|
|
},
|
|
],
|
|
executionState: "completed",
|
|
});
|
|
|
|
expect(state.byThreadId.get("child")?.latestItem).toMatchObject({
|
|
id: "answer",
|
|
text: "Everything passes.",
|
|
});
|
|
});
|
|
|
|
it("ignores delayed notifications from an older child turn", () => {
|
|
let state = trackedState();
|
|
state = reduceSubagentActivitySlice(state, {
|
|
type: "subagent-activity/turn-started",
|
|
threadId: "child",
|
|
childTurnId: "new-turn",
|
|
});
|
|
state = observe(state, reasoningItem("current", "Current work", "new-turn"), true);
|
|
state = reduceSubagentActivitySlice(state, {
|
|
type: "subagent-activity/text-delta-appended",
|
|
threadId: "child",
|
|
childTurnId: "old-turn",
|
|
itemId: "stale",
|
|
label: "reasoning",
|
|
delta: "Older work",
|
|
kind: "reasoning",
|
|
});
|
|
state = reduceSubagentActivitySlice(state, {
|
|
type: "subagent-activity/turn-completed",
|
|
threadId: "child",
|
|
childTurnId: "old-turn",
|
|
items: [reasoningItem("stale", "Older work", "old-turn")],
|
|
executionState: "completed",
|
|
});
|
|
|
|
expect(state.byThreadId.get("child")).toMatchObject({
|
|
childTurnId: "new-turn",
|
|
executionState: "running",
|
|
latestItem: { id: "current", text: "Current work" },
|
|
});
|
|
});
|
|
});
|
|
|
|
function trackedState() {
|
|
return reduceSubagentActivitySlice(initialSubagentActivityState("parent-turn"), {
|
|
type: "subagent-activity/tracked",
|
|
threadId: "child",
|
|
parentTurnId: "parent-turn",
|
|
});
|
|
}
|
|
|
|
function observe(state: ReturnType<typeof trackedState>, item: ThreadStreamItem, advance: boolean): ReturnType<typeof trackedState> {
|
|
return reduceSubagentActivitySlice(state, {
|
|
type: "subagent-activity/item-observed",
|
|
threadId: "child",
|
|
item,
|
|
advance,
|
|
});
|
|
}
|
|
|
|
function reasoningItem(id: string, text: string, turnId = "child-turn"): ThreadStreamItem {
|
|
return { id, kind: "reasoning", role: "tool", turnId, text };
|
|
}
|