Files
tutti/packages/agent/gui/agent-message-center/workspaceAgentConsumerSelectors.spec.ts
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

1220 lines
36 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
createAgentSessionEngine,
normalizeAgentActivitySession,
type AgentActivitySession
} from "@tutti-os/agent-activity-core";
import { createTestEngineCommandPort } from "../shared/testing/createTestAgentSessionEngine";
import {
buildWorkspaceAgentMessageCenterModelFromEngine,
selectWorkspaceAgentAttentionItems,
selectWorkspaceAgentMessageCenterPresentation,
workspaceAgentAttentionItemsEqual,
workspaceAgentMessageCenterPromptStatus,
workspaceAgentMessageCenterPresentationEqual
} from "./workspaceAgentMessageCenterEngineModel";
import { selectMessageCenterAttentionDeckItems } from "./workspaceAgentMessageCenterModel";
import {
selectWorkspaceAgentConsumerCounts,
selectWorkspaceAgentConsumerSessions
} from "./workspaceAgentConsumerSelectors";
describe("workspaceAgentConsumerSelectors", () => {
it("projects every pending target with exact target-level identity", () => {
const engine = createEngine();
engine.dispatch({
type: "session/snapshotReceived",
sessions: [
session({
activeTurnId: "turn-1",
activeTurn: {
turnId: "turn-1",
agentSessionId: "session-1",
origin: "user_prompt",
phase: "waiting",
startedAtUnixMs: 10,
updatedAtUnixMs: 22
},
pendingInteractions: [
{
requestId: "request-approval",
agentSessionId: "session-1",
turnId: "turn-1",
kind: "approval",
status: "pending",
toolName: "Bash",
input: {
command: "pnpm test",
options: [{ optionId: "allow", label: "Allow" }]
},
createdAtUnixMs: 21,
updatedAtUnixMs: 21
},
{
requestId: "request-question",
agentSessionId: "session-1",
turnId: "turn-1",
kind: "question",
status: "pending",
toolName: "AskUserQuestion",
input: {
questions: [
{
question: "Which option?",
options: [{ label: "First" }]
}
]
},
createdAtUnixMs: 22,
updatedAtUnixMs: 22
}
]
})
]
});
const first = selectWorkspaceAgentAttentionItems(
selectWorkspaceAgentMessageCenterPresentation(engine.getSnapshot()),
{ workspaceId: "workspace-1", sessionMessagesById: {} }
);
const second = selectWorkspaceAgentAttentionItems(
selectWorkspaceAgentMessageCenterPresentation(engine.getSnapshot()),
{ workspaceId: "workspace-1", sessionMessagesById: {} }
);
expect(first).toHaveLength(2);
expect(first.map((entry) => entry.item.id)).toEqual([
"workspace-1\nsession-1\nturn-1\nrequest-approval",
"workspace-1\nsession-1\nturn-1\nrequest-question"
]);
expect(first.map((entry) => entry.target)).toEqual([
{
kind: "interaction",
workspaceId: "workspace-1",
agentSessionId: "session-1",
turnId: "turn-1",
requestId: "request-approval"
},
{
kind: "interaction",
workspaceId: "workspace-1",
agentSessionId: "session-1",
turnId: "turn-1",
requestId: "request-question"
}
]);
expect(workspaceAgentAttentionItemsEqual(first, second)).toBe(true);
});
it("normalizes canonical exit-plan interactions for the shared prompt surface", () => {
const engine = createEngine();
engine.dispatch({
type: "session/snapshotReceived",
sessions: [
session({
activeTurnId: "turn-1",
activeTurn: {
turnId: "turn-1",
agentSessionId: "session-1",
origin: "user_prompt",
phase: "waiting",
startedAtUnixMs: 10,
updatedAtUnixMs: 21
},
pendingInteractions: [
{
requestId: "request-exit-plan",
agentSessionId: "session-1",
turnId: "turn-1",
kind: "approval",
status: "pending",
toolName: "ExitPlanMode",
input: {
toolCall: { kind: "switch_mode" },
options: [
{ optionId: "acceptEdits", label: "Accept edits" },
{ optionId: "plan", label: "Keep planning" }
]
},
createdAtUnixMs: 21,
updatedAtUnixMs: 21
}
]
})
]
});
const [entry] = selectWorkspaceAgentAttentionItems(
selectWorkspaceAgentMessageCenterPresentation(engine.getSnapshot()),
{ workspaceId: "workspace-1", sessionMessagesById: {} }
);
expect(entry?.item.pendingPrompt).toEqual(
expect.objectContaining({
kind: "exit-plan",
requestId: "request-exit-plan",
keepPlanningOptionId: "plan",
options: [expect.objectContaining({ id: "acceptEdits" })]
})
);
});
it("projects an eligible completed plan turn as a canonical plan target", () => {
const engine = createEngine();
engine.dispatch({
type: "session/snapshotReceived",
sessions: [
session({
latestTurn: {
turnId: "turn-plan",
agentSessionId: "session-1",
origin: "user_prompt",
phase: "settled",
outcome: "completed",
startedAtUnixMs: 10,
settledAtUnixMs: 20,
updatedAtUnixMs: 20
},
capabilities: {
imageInput: false,
modelImageInputRequired: false,
modelPlanBinding: false,
modelSwitch: false,
skills: false,
compact: false,
tokenUsage: false,
rateLimits: false,
planMode: true,
interrupt: false,
activeTurnGuidance: false,
browserUse: false,
computerUse: false,
goalPause: false,
planImplementation: true,
permissionModeChangeDuringTurn: false,
permissionModeChangeDeferred: false,
review: false,
resumeRunningTurn: false
}
})
]
});
const [entry] = selectWorkspaceAgentAttentionItems(
selectWorkspaceAgentMessageCenterPresentation(engine.getSnapshot()),
{
workspaceId: "workspace-1",
sessionMessagesById: {
"session-1": [
{
workspaceId: "workspace-1",
agentSessionId: "session-1",
messageId: "plan-message",
version: 1,
turnId: "turn-plan",
role: "agent",
kind: "message",
payload: { messageKind: "plan" },
occurredAtUnixMs: 19
}
]
}
}
);
expect(entry).toMatchObject({
status: "idle",
target: {
kind: "plan-implementation",
workspaceId: "workspace-1",
agentSessionId: "session-1",
turnId: "turn-plan",
requestId: "turn-plan"
},
item: {
id: "workspace-1\nsession-1\nturn-plan\nturn-plan",
pendingPrompt: {
kind: "plan-implementation",
requestId: "turn-plan"
}
}
});
});
it("keeps a completed plan waiting in the production message center model when host messages are empty", () => {
const engine = createCompletedPlanEngine({
latestTurnId: "turn-plan",
planTurnId: "turn-plan",
capabilities: planImplementationCapabilities()
});
const model = buildWorkspaceAgentMessageCenterModelFromEngine(
selectWorkspaceAgentMessageCenterPresentation(engine.getSnapshot()),
{ workspaceId: "workspace-1", sessionMessagesById: {} }
);
expect(model.waitingCount).toBe(1);
expect(model.items[0]).toMatchObject({
id: "message-center-session-1",
agentSessionId: "session-1",
status: "waiting",
needsAttentionKind: "constraint",
pendingInteractionTarget: null,
pendingPrompt: {
kind: "plan-implementation",
requestId: "turn-plan"
},
latestTurnOutcome: null
});
});
it.each([
{
name: "the tagged plan belongs to an older turn",
latestTurnId: "turn-current",
planTurnId: "turn-old",
capabilities: planImplementationCapabilities()
},
{
name: "the session explicitly disables plan implementation",
latestTurnId: "turn-plan",
planTurnId: "turn-plan",
capabilities: {
...planImplementationCapabilities(),
planImplementation: false
}
}
])("does not synthesize plan waiting when $name", (input) => {
const engine = createCompletedPlanEngine(input);
const model = buildWorkspaceAgentMessageCenterModelFromEngine(
selectWorkspaceAgentMessageCenterPresentation(engine.getSnapshot()),
{ workspaceId: "workspace-1", sessionMessagesById: {} }
);
expect(model.waitingCount).toBe(0);
expect(model.items[0]).toMatchObject({
status: "completed",
pendingPrompt: null,
latestTurnOutcome: {
status: "completed",
turnId: input.latestTurnId
}
});
});
it("keeps the legacy presentation shape compatible and fails closed", () => {
const engine = createCompletedPlanEngine({
latestTurnId: "turn-plan",
planTurnId: "turn-plan",
capabilities: planImplementationCapabilities()
});
const {
awaitingPlanImplementationTurnIdBySessionId: _derivedPlanWait,
...legacyPresentation
} = selectWorkspaceAgentMessageCenterPresentation(engine.getSnapshot());
const model = buildWorkspaceAgentMessageCenterModelFromEngine(
legacyPresentation,
{
workspaceId: "workspace-1",
sessionMessagesById: { "session-1": [planMessage("turn-plan")] }
}
);
expect(model.waitingCount).toBe(0);
expect(model.items[0]).toMatchObject({
status: "completed",
pendingPrompt: null
});
});
it("keeps a durable interaction authoritative over a synthetic plan wait", () => {
const engine = createCompletedPlanEngine({
latestTurnId: "turn-plan",
planTurnId: "turn-plan",
capabilities: planImplementationCapabilities(),
pendingInteractions: [
{
requestId: "request-approval",
agentSessionId: "session-1",
turnId: "turn-plan",
kind: "approval",
status: "pending",
toolName: "Bash",
input: {
command: "pnpm test",
options: [{ optionId: "allow", label: "Allow" }]
},
createdAtUnixMs: 21,
updatedAtUnixMs: 21
}
]
});
const model = buildWorkspaceAgentMessageCenterModelFromEngine(
selectWorkspaceAgentMessageCenterPresentation(engine.getSnapshot()),
{ workspaceId: "workspace-1", sessionMessagesById: {} }
);
expect(model.waitingCount).toBe(1);
expect(model.items[0]).toMatchObject({
status: "waiting",
pendingInteractionTarget: {
agentSessionId: "session-1",
requestId: "request-approval",
turnId: "turn-plan"
},
pendingPrompt: {
kind: "approval",
requestId: "request-approval"
}
});
});
it("removes a skipped plan from the production message center model", () => {
const engine = createCompletedPlanEngine({
latestTurnId: "turn-plan",
planTurnId: "turn-plan",
capabilities: planImplementationCapabilities()
});
engine.dispatch({
type: "plan/skipped",
workspaceId: "workspace-1",
agentSessionId: "session-1",
turnId: "turn-plan",
requestId: "turn-plan"
});
const model = buildWorkspaceAgentMessageCenterModelFromEngine(
selectWorkspaceAgentMessageCenterPresentation(engine.getSnapshot()),
{ workspaceId: "workspace-1", sessionMessagesById: {} }
);
expect(model.waitingCount).toBe(0);
expect(model.items[0]).toMatchObject({
status: "completed",
pendingPrompt: null
});
});
it("tracks Plan feedback through explicit source identity instead of submit-id parsing", () => {
const engine = createEngine();
engine.dispatch({
type: "session/snapshotReceived",
sessions: [
session({
latestTurn: {
turnId: "turn-plan",
agentSessionId: "session-1",
origin: "user_prompt",
phase: "settled",
outcome: "completed",
startedAtUnixMs: 10,
settledAtUnixMs: 20,
updatedAtUnixMs: 20
}
})
]
});
engine.dispatch({
type: "plan/feedbackRequested",
agentSessionId: "session-1",
clientSubmitId: "opaque-feedback-id",
content: [{ type: "text", text: "Revise it" }],
expiresAtUnixMs: 120_000,
requestedAtUnixMs: 21,
requestId: "turn-plan",
turnId: "turn-plan",
workspaceId: "workspace-1"
});
const presentation = selectWorkspaceAgentMessageCenterPresentation(
engine.getSnapshot()
);
expect(
presentation.promptStatusByKey["session-1\0turn-plan\0turn-plan"]
).toBe("responding");
});
it("keeps message-center presentation equal across unrelated engine changes", () => {
const engine = createEngine();
engine.dispatch({
type: "session/snapshotReceived",
sessions: [session({})]
});
const before = selectWorkspaceAgentMessageCenterPresentation(
engine.getSnapshot()
);
engine.dispatch({ type: "engine/connectionChanged", status: "connected" });
const after = selectWorkspaceAgentMessageCenterPresentation(
engine.getSnapshot()
);
expect(workspaceAgentMessageCenterPresentationEqual(before, after)).toBe(
true
);
});
it("derives shared consumer state from canonical turn and interaction entities", () => {
const engine = createEngine();
engine.dispatch({
type: "session/snapshotReceived",
sessions: [
session({
activeTurnId: "turn-1",
activeTurn: {
turnId: "turn-1",
agentSessionId: "session-1",
origin: "user_prompt",
phase: "running",
startedAtUnixMs: 10,
updatedAtUnixMs: 20
},
pendingInteractions: [
{
requestId: "request-1",
agentSessionId: "session-1",
turnId: "turn-1",
kind: "question",
status: "pending",
input: { question: "Choose an option" },
createdAtUnixMs: 21,
updatedAtUnixMs: 21
}
]
})
]
});
const consumers = selectWorkspaceAgentConsumerSessions(
engine.getSnapshot()
);
expect(consumers).toHaveLength(1);
expect(consumers[0]?.displayStatus).toBe("waiting");
expect(selectWorkspaceAgentConsumerCounts(engine.getSnapshot())).toEqual({
canceled: 0,
completed: 0,
failed: 0,
idle: 0,
waiting: 1,
working: 0
});
const model = buildWorkspaceAgentMessageCenterModelFromEngine(
selectWorkspaceAgentMessageCenterPresentation(engine.getSnapshot()),
{ workspaceId: "workspace-1", sessionMessagesById: {} }
);
expect(model.items[0]).toMatchObject({
agentSessionId: "session-1",
needsAttentionKind: "question",
needsAttentionSummary: "Choose an option",
pendingPrompt: {
agentSessionId: "session-1",
kind: "ask-user",
requestId: "request-1",
turnId: "turn-1"
},
status: "waiting"
});
engine.dispatch({
type: "interaction/upserted",
interaction: {
requestId: "request-1",
agentSessionId: "session-1",
turnId: "turn-1",
kind: "question",
status: "answered",
input: { question: "Choose an option" },
createdAtUnixMs: 21,
updatedAtUnixMs: 30
}
});
const resolvedModel = buildWorkspaceAgentMessageCenterModelFromEngine(
selectWorkspaceAgentMessageCenterPresentation(engine.getSnapshot()),
{ workspaceId: "workspace-1", sessionMessagesById: {} }
);
expect(resolvedModel.items[0]?.pendingPrompt).toBeNull();
expect(selectMessageCenterAttentionDeckItems(resolvedModel.items)).toEqual(
[]
);
});
it("aggregates a child approval into its root conversation card", () => {
const engine = createEngine();
engine.dispatch({
type: "session/snapshotReceived",
sessions: [
session({
activeTurnId: "root-turn-1",
activeTurn: {
turnId: "root-turn-1",
agentSessionId: "session-1",
origin: "user_prompt",
phase: "running",
startedAtUnixMs: 10,
updatedAtUnixMs: 20
},
provider: "claude-code"
}),
session({
activeTurnId: "child-turn-1",
activeTurn: {
turnId: "child-turn-1",
agentSessionId: "child-1",
origin: "provider_initiated",
phase: "waiting",
startedAtUnixMs: 15,
updatedAtUnixMs: 25
},
agentSessionId: "child-1",
kind: "child",
parentAgentSessionId: "session-1",
parentToolCallId: "toolu-agent-1",
parentTurnId: "root-turn-1",
pendingInteractions: [
{
requestId: "child-approval-1",
agentSessionId: "child-1",
turnId: "child-turn-1",
kind: "approval",
status: "pending",
toolName: "Bash",
input: {
question: "Allow Bash?",
options: [{ optionId: "allow", label: "Allow" }]
},
createdAtUnixMs: 26,
updatedAtUnixMs: 26
}
],
provider: "claude-code",
providerSessionId: "agent-1",
rootAgentSessionId: "session-1",
rootTurnId: "root-turn-1",
title: "Child"
})
]
});
const presentation = selectWorkspaceAgentMessageCenterPresentation(
engine.getSnapshot()
);
const model = buildWorkspaceAgentMessageCenterModelFromEngine(
presentation,
{ workspaceId: "workspace-1", sessionMessagesById: {} }
);
expect(model.items).toHaveLength(1);
expect(model.items[0]).toMatchObject({
agentSessionId: "session-1",
status: "waiting",
pendingInteractionTarget: {
agentSessionId: "child-1",
requestId: "child-approval-1",
turnId: "child-turn-1"
},
pendingPrompt: {
kind: "approval",
requestId: "child-approval-1",
turnId: "child-turn-1"
}
});
expect(model.waitingCount).toBe(1);
expect(selectMessageCenterAttentionDeckItems(model.items)).toHaveLength(1);
engine.dispatch({
type: "interaction/responseRequested",
agentSessionId: "child-1",
commandId: "respond-child-approval-1",
requestId: "child-approval-1",
turnId: "child-turn-1",
workspaceId: "workspace-1",
optionId: "allow"
});
const respondingPresentation =
selectWorkspaceAgentMessageCenterPresentation(engine.getSnapshot());
expect(
workspaceAgentMessageCenterPromptStatus(
respondingPresentation,
model.items[0]!
)
).toBe("responding");
engine.dispatch({
type: "interaction/upserted",
interaction: {
requestId: "child-approval-1",
agentSessionId: "child-1",
turnId: "child-turn-1",
kind: "approval",
status: "answered",
toolName: "Bash",
input: { question: "Allow Bash?" },
createdAtUnixMs: 26,
updatedAtUnixMs: 30
}
});
engine.dispatch({
type: "session/snapshotReceived",
sessions: [
session({
activeTurnId: null,
latestTurn: {
turnId: "root-turn-1",
agentSessionId: "session-1",
origin: "user_prompt",
phase: "settled",
outcome: "completed",
startedAtUnixMs: 10,
settledAtUnixMs: 30,
updatedAtUnixMs: 30
},
provider: "claude-code"
}),
session({
activeTurnId: "child-turn-1",
activeTurn: {
turnId: "child-turn-1",
agentSessionId: "child-1",
origin: "provider_initiated",
phase: "running",
startedAtUnixMs: 15,
updatedAtUnixMs: 31
},
agentSessionId: "child-1",
kind: "child",
parentAgentSessionId: "session-1",
parentToolCallId: "toolu-agent-1",
parentTurnId: "root-turn-1",
provider: "claude-code",
providerSessionId: "agent-1",
rootAgentSessionId: "session-1",
rootTurnId: "root-turn-1",
title: "Child"
})
]
});
const resumedModel = buildWorkspaceAgentMessageCenterModelFromEngine(
selectWorkspaceAgentMessageCenterPresentation(engine.getSnapshot()),
{ workspaceId: "workspace-1", sessionMessagesById: {} }
);
expect(resumedModel.items).toHaveLength(1);
expect(resumedModel.items[0]).toMatchObject({
agentSessionId: "session-1",
latestTurnOutcome: null,
pendingPrompt: null,
status: "working"
});
});
it("projects signed Agent Target presentation for open-provider sessions", () => {
const engine = createEngine();
engine.dispatch({
type: "session/snapshotReceived",
sessions: [
session({
agentTargetId: "extension:gemini",
provider: "acp:gemini"
})
]
});
const model = buildWorkspaceAgentMessageCenterModelFromEngine(
selectWorkspaceAgentMessageCenterPresentation(engine.getSnapshot()),
{ workspaceId: "workspace-1", sessionMessagesById: {} },
{
agentPresentations: [
{
agentTargetId: "extension:gemini",
iconUrl: "data:image/svg+xml;base64,gemini",
name: "Gemini CLI"
}
]
}
);
expect(model.items[0]).toMatchObject({
agentTargetId: "extension:gemini",
agentName: "Gemini CLI",
agentAvatarUrl: "data:image/svg+xml;base64,gemini",
provider: "acp:gemini"
});
});
it("keeps canonical settled turn state authoritative over stale status messages", () => {
const engine = createEngine();
engine.dispatch({
type: "session/snapshotReceived",
sessions: [
session({
activeTurnId: null,
activeTurn: {
turnId: "turn-completed",
agentSessionId: "session-1",
origin: "user_prompt",
phase: "settled",
outcome: "completed",
startedAtUnixMs: 10,
settledAtUnixMs: 20,
updatedAtUnixMs: 20
}
})
]
});
const model = buildWorkspaceAgentMessageCenterModelFromEngine(
selectWorkspaceAgentMessageCenterPresentation(engine.getSnapshot()),
{
workspaceId: "workspace-1",
sessionMessagesById: {
"session-1": [
{
workspaceId: "workspace-1",
agentSessionId: "session-1",
messageId: "stale-question",
version: 1,
turnId: "turn-stale",
role: "agent",
kind: "question",
status: "failed",
payload: {
input: {
questions: [{ question: "Stale question" }]
}
},
occurredAtUnixMs: 5
}
]
}
}
);
expect(model.items[0]).toMatchObject({
status: "completed",
pendingPrompt: null,
needsAttentionKind: null,
latestTurnOutcome: {
status: "completed",
turnId: "turn-completed"
}
});
expect(model.waitingCount).toBe(0);
});
it("keeps the session title for a continued historical session", () => {
const engine = createEngine();
engine.dispatch({
type: "session/snapshotReceived",
sessions: [session({ title: "Original request" })]
});
const model = buildWorkspaceAgentMessageCenterModelFromEngine(
selectWorkspaceAgentMessageCenterPresentation(engine.getSnapshot()),
{
workspaceId: "workspace-1",
sessionMessagesById: {
"session-1": [
{
workspaceId: "workspace-1",
agentSessionId: "session-1",
messageId: "user-old",
version: 1,
turnId: "turn-old",
role: "user",
kind: "message",
payload: { text: "Original request" },
occurredAtUnixMs: 10
},
{
workspaceId: "workspace-1",
agentSessionId: "session-1",
messageId: "user-latest",
version: 2,
turnId: "turn-latest",
role: "user",
kind: "message",
payload: { text: "Continue with the latest request" },
occurredAtUnixMs: 20
}
]
}
}
);
expect(model.items[0]?.title).toBe("Original request");
});
it("keeps the session title and waiting plan prompt", () => {
const engine = createEngine();
engine.dispatch({
type: "session/snapshotReceived",
sessions: [
session({
title: "Original request",
activeTurnId: "turn-plan",
activeTurn: {
turnId: "turn-plan",
agentSessionId: "session-1",
origin: "user_prompt",
phase: "waiting",
startedAtUnixMs: 10,
updatedAtUnixMs: 20
},
pendingInteractions: [
{
requestId: "request-exit-plan",
agentSessionId: "session-1",
turnId: "turn-plan",
kind: "approval",
status: "pending",
toolName: "ExitPlanMode",
input: {
toolCall: { kind: "switch_mode" },
options: [{ optionId: "acceptEdits", label: "Accept edits" }]
},
createdAtUnixMs: 20,
updatedAtUnixMs: 20
}
]
})
]
});
const model = buildWorkspaceAgentMessageCenterModelFromEngine(
selectWorkspaceAgentMessageCenterPresentation(engine.getSnapshot()),
{
workspaceId: "workspace-1",
sessionMessagesById: {
"session-1": [
{
workspaceId: "workspace-1",
agentSessionId: "session-1",
messageId: "user-plan",
version: 1,
turnId: "turn-plan",
role: "user",
kind: "message",
payload: { text: "Implement the revised plan" },
occurredAtUnixMs: 19
}
]
}
}
);
expect(model.items[0]).toMatchObject({
title: "Original request",
status: "waiting",
pendingPrompt: {
kind: "exit-plan",
requestId: "request-exit-plan"
}
});
});
it("uses message version to select the latest reply when timestamps match", () => {
const engine = createEngine();
engine.dispatch({
type: "session/snapshotReceived",
sessions: [session({ title: "Original request" })]
});
const model = buildWorkspaceAgentMessageCenterModelFromEngine(
selectWorkspaceAgentMessageCenterPresentation(engine.getSnapshot()),
{
workspaceId: "workspace-1",
sessionMessagesById: {
"session-1": [
{
workspaceId: "workspace-1",
agentSessionId: "session-1",
messageId: "assistant-latest",
version: 2,
turnId: "turn-latest",
role: "assistant",
kind: "message",
payload: { text: "Current reply" },
occurredAtUnixMs: 20
},
{
workspaceId: "workspace-1",
agentSessionId: "session-1",
messageId: "assistant-previous",
version: 1,
turnId: "turn-previous",
role: "assistant",
kind: "message",
payload: { text: "Previous reply" },
occurredAtUnixMs: 20
}
]
}
}
);
expect(model.items[0]).toMatchObject({
title: "Original request",
lastAgentMessageSummary: "Current reply",
digest: {
primary: {
summary: "Current reply"
}
}
});
});
it("updates the recent summary only when a realtime reply becomes durable", () => {
const engine = createEngine();
engine.dispatch({
type: "session/snapshotReceived",
sessions: [session({ title: "Original request" })]
});
const previousReply = {
workspaceId: "workspace-1",
agentSessionId: "session-1",
messageId: "assistant-previous",
version: 1,
sequence: 1,
turnId: "turn-previous",
role: "assistant",
kind: "message",
payload: { text: "Previous reply" },
occurredAtUnixMs: 10
} as const;
const streamingReply = {
workspaceId: "workspace-1",
agentSessionId: "session-1",
messageId: "assistant-current",
version: 0,
turnId: "turn-current",
role: "assistant",
kind: "message",
status: "streaming",
payload: { text: "Current reply in progress" },
occurredAtUnixMs: 20
} as const;
const streamingModel = buildWorkspaceAgentMessageCenterModelFromEngine(
selectWorkspaceAgentMessageCenterPresentation(engine.getSnapshot()),
{
workspaceId: "workspace-1",
sessionMessagesById: {
"session-1": [previousReply, streamingReply]
}
}
);
expect(streamingModel.items[0]?.lastAgentMessageSummary).toBe(
"Previous reply"
);
const completedModel = buildWorkspaceAgentMessageCenterModelFromEngine(
selectWorkspaceAgentMessageCenterPresentation(engine.getSnapshot()),
{
workspaceId: "workspace-1",
sessionMessagesById: {
"session-1": [
previousReply,
{ ...streamingReply, sequence: 2, status: "completed", version: 2 }
]
}
}
);
expect(completedModel.items[0]).toMatchObject({
title: "Original request",
lastAgentMessageSummary: "Current reply in progress",
digest: { primary: { summary: "Current reply in progress" } }
});
});
it("omits hidden sessions from the message center model by default", () => {
const engine = createEngine();
engine.dispatch({
type: "session/snapshotReceived",
sessions: [session({ visible: false })]
});
const model = buildWorkspaceAgentMessageCenterModelFromEngine(
selectWorkspaceAgentMessageCenterPresentation(engine.getSnapshot()),
{ workspaceId: "workspace-1", sessionMessagesById: {} }
);
expect(model.items).toHaveLength(0);
});
it("does not treat a provider-native id as a hidden-session opt-in", () => {
const engine = createEngine();
engine.dispatch({
type: "session/snapshotReceived",
sessions: [
session({
visible: false,
providerSessionId: "provider-session-1"
})
]
});
const model = buildWorkspaceAgentMessageCenterModelFromEngine(
selectWorkspaceAgentMessageCenterPresentation(engine.getSnapshot()),
{ workspaceId: "workspace-1", sessionMessagesById: {} },
{ includeHiddenSessionIds: ["provider-session-1"] }
);
expect(model.items).toHaveLength(0);
});
it("keeps an allowlisted hidden delegate session and its pending prompt", () => {
const engine = createEngine();
engine.dispatch({
type: "session/snapshotReceived",
sessions: [
session({
visible: false,
activeTurnId: "turn-1",
activeTurn: {
turnId: "turn-1",
agentSessionId: "session-1",
origin: "user_prompt",
phase: "waiting",
startedAtUnixMs: 10,
updatedAtUnixMs: 21
},
pendingInteractions: [
{
requestId: "request-approval",
agentSessionId: "session-1",
turnId: "turn-1",
kind: "approval",
status: "pending",
toolName: "Bash",
input: {
command: "pnpm test",
options: [{ optionId: "allow", label: "Allow" }]
},
createdAtUnixMs: 21,
updatedAtUnixMs: 21
}
]
})
]
});
const model = buildWorkspaceAgentMessageCenterModelFromEngine(
selectWorkspaceAgentMessageCenterPresentation(engine.getSnapshot()),
{ workspaceId: "workspace-1", sessionMessagesById: {} },
{ includeHiddenSessionIds: ["session-1"] }
);
expect(model.items).toHaveLength(1);
expect(model.items[0]).toMatchObject({
agentSessionId: "session-1",
needsAttentionKind: "permission",
pendingInteractionTarget: {
agentSessionId: "session-1",
requestId: "request-approval",
turnId: "turn-1"
},
pendingPrompt: {
kind: "approval",
requestId: "request-approval"
}
});
});
});
function createEngine() {
return createAgentSessionEngine({
clock: { nowUnixMs: () => 1 },
commandPort: createTestEngineCommandPort({ execute: async () => ({}) }),
identity: { origin: "test", workspaceId: "workspace-1" },
scheduler: { schedule: () => ({ cancel() {} }) }
});
}
function session(
overrides: Partial<AgentActivitySession> = {}
): AgentActivitySession {
return normalizeAgentActivitySession({
activeTurnId: null,
latestTurnInteractions: [],
pendingInteractions: [],
workspaceId: "workspace-1",
agentSessionId: "session-1",
provider: "codex",
cwd: "/workspace",
title: "Canonical session",
...overrides
});
}
function planMessage(turnId: string) {
return {
workspaceId: "workspace-1",
agentSessionId: "session-1",
messageId: `plan-${turnId}`,
version: 1,
turnId,
role: "agent" as const,
kind: "message" as const,
payload: { messageKind: "plan" },
occurredAtUnixMs: 19
};
}
function planImplementationCapabilities() {
return {
imageInput: false,
modelImageInputRequired: false,
modelPlanBinding: false,
modelSwitch: false,
skills: false,
compact: false,
tokenUsage: false,
rateLimits: false,
planMode: true,
interrupt: false,
activeTurnGuidance: false,
browserUse: false,
computerUse: false,
goalPause: false,
planImplementation: true,
permissionModeChangeDuringTurn: false,
permissionModeChangeDeferred: false,
review: false,
resumeRunningTurn: false
};
}
function createCompletedPlanEngine(input: {
latestTurnId: string;
planTurnId: string;
capabilities: ReturnType<typeof planImplementationCapabilities>;
pendingInteractions?: AgentActivitySession["pendingInteractions"];
}) {
const engine = createEngine();
engine.dispatch({
type: "session/snapshotReceived",
sessions: [
session({
latestTurn: {
turnId: input.latestTurnId,
agentSessionId: "session-1",
origin: "user_prompt",
phase: "settled",
outcome: "completed",
startedAtUnixMs: 10,
settledAtUnixMs: 20,
updatedAtUnixMs: 20
},
capabilities: input.capabilities,
pendingInteractions: input.pendingInteractions ?? []
})
]
});
engine.dispatch({
type: "message/snapshotReceived",
workspaceId: "workspace-1",
messages: [planMessage(input.planTurnId)]
});
return engine;
}