@openma/common 0.0.0-stage → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/README.md +391 -2
- package/dist/acp-artifacts/binary.d.ts +35 -0
- package/dist/acp-artifacts/binary.d.ts.map +1 -0
- package/dist/acp-artifacts/binary.js +120 -0
- package/dist/acp-artifacts/binary.js.map +1 -0
- package/dist/acp-artifacts/index.d.ts +7 -0
- package/dist/acp-artifacts/index.d.ts.map +1 -0
- package/dist/acp-artifacts/index.js +7 -0
- package/dist/acp-artifacts/index.js.map +1 -0
- package/dist/acp-artifacts/node-abi.d.ts +3 -0
- package/dist/acp-artifacts/node-abi.d.ts.map +1 -0
- package/dist/acp-artifacts/node-abi.js +17 -0
- package/dist/acp-artifacts/node-abi.js.map +1 -0
- package/dist/acp-artifacts/npm-cli.d.ts +3 -0
- package/dist/acp-artifacts/npm-cli.d.ts.map +1 -0
- package/dist/acp-artifacts/npm-cli.js +9 -0
- package/dist/acp-artifacts/npm-cli.js.map +1 -0
- package/dist/acp-artifacts/npm.d.ts +37 -0
- package/dist/acp-artifacts/npm.d.ts.map +1 -0
- package/dist/acp-artifacts/npm.js +167 -0
- package/dist/acp-artifacts/npm.js.map +1 -0
- package/dist/acp-artifacts/registry.d.ts +45 -0
- package/dist/acp-artifacts/registry.d.ts.map +1 -0
- package/dist/acp-artifacts/registry.js +206 -0
- package/dist/acp-artifacts/registry.js.map +1 -0
- package/dist/acp-artifacts/shared.d.ts +45 -0
- package/dist/acp-artifacts/shared.d.ts.map +1 -0
- package/dist/acp-artifacts/shared.js +157 -0
- package/dist/acp-artifacts/shared.js.map +1 -0
- package/dist/acp-artifacts/uvx.d.ts +32 -0
- package/dist/acp-artifacts/uvx.d.ts.map +1 -0
- package/dist/acp-artifacts/uvx.js +95 -0
- package/dist/acp-artifacts/uvx.js.map +1 -0
- package/dist/acp-fork/index.d.ts +51 -0
- package/dist/acp-fork/index.d.ts.map +1 -0
- package/dist/acp-fork/index.js +116 -0
- package/dist/acp-fork/index.js.map +1 -0
- package/dist/acp-harnesses/agent-setup.d.ts +118 -0
- package/dist/acp-harnesses/agent-setup.d.ts.map +1 -0
- package/dist/acp-harnesses/agent-setup.js +717 -0
- package/dist/acp-harnesses/agent-setup.js.map +1 -0
- package/dist/acp-harnesses/custom-agents.d.ts +81 -0
- package/dist/acp-harnesses/custom-agents.d.ts.map +1 -0
- package/dist/acp-harnesses/custom-agents.js +361 -0
- package/dist/acp-harnesses/custom-agents.js.map +1 -0
- package/dist/acp-harnesses/headless-launch.d.ts +34 -0
- package/dist/acp-harnesses/headless-launch.d.ts.map +1 -0
- package/dist/acp-harnesses/headless-launch.js +67 -0
- package/dist/acp-harnesses/headless-launch.js.map +1 -0
- package/dist/acp-harnesses/index.d.ts +18 -0
- package/dist/acp-harnesses/index.d.ts.map +1 -0
- package/dist/acp-harnesses/index.js +58 -0
- package/dist/acp-harnesses/index.js.map +1 -0
- package/dist/acp-harnesses/install-state.d.ts +86 -0
- package/dist/acp-harnesses/install-state.d.ts.map +1 -0
- package/dist/acp-harnesses/install-state.js +322 -0
- package/dist/acp-harnesses/install-state.js.map +1 -0
- package/dist/acp-harnesses/installer.d.ts +145 -0
- package/dist/acp-harnesses/installer.d.ts.map +1 -0
- package/dist/acp-harnesses/installer.js +716 -0
- package/dist/acp-harnesses/installer.js.map +1 -0
- package/dist/acp-harnesses/known-agents.d.ts +154 -0
- package/dist/acp-harnesses/known-agents.d.ts.map +1 -0
- package/dist/acp-harnesses/known-agents.js +240 -0
- package/dist/acp-harnesses/known-agents.js.map +1 -0
- package/dist/acp-harnesses/launcher.d.ts +27 -0
- package/dist/acp-harnesses/launcher.d.ts.map +1 -0
- package/dist/acp-harnesses/launcher.js +64 -0
- package/dist/acp-harnesses/launcher.js.map +1 -0
- package/dist/acp-harnesses/registry-fetch.d.ts +42 -0
- package/dist/acp-harnesses/registry-fetch.d.ts.map +1 -0
- package/dist/acp-harnesses/registry-fetch.js +132 -0
- package/dist/acp-harnesses/registry-fetch.js.map +1 -0
- package/dist/acp-harnesses/registry.d.ts +36 -0
- package/dist/acp-harnesses/registry.d.ts.map +1 -0
- package/dist/acp-harnesses/registry.js +307 -0
- package/dist/acp-harnesses/registry.js.map +1 -0
- package/dist/acp-runtime/errors.d.ts +7 -0
- package/dist/acp-runtime/errors.d.ts.map +1 -0
- package/dist/acp-runtime/errors.js +17 -0
- package/dist/acp-runtime/errors.js.map +1 -0
- package/dist/acp-runtime/fork-support.d.ts +8 -0
- package/dist/acp-runtime/fork-support.d.ts.map +1 -0
- package/dist/acp-runtime/fork-support.js +20 -0
- package/dist/acp-runtime/fork-support.js.map +1 -0
- package/dist/acp-runtime/index.d.ts +11 -0
- package/dist/acp-runtime/index.d.ts.map +1 -0
- package/dist/acp-runtime/index.js +6 -0
- package/dist/acp-runtime/index.js.map +1 -0
- package/dist/acp-runtime/probe.d.ts +103 -0
- package/dist/acp-runtime/probe.d.ts.map +1 -0
- package/dist/acp-runtime/probe.js +881 -0
- package/dist/acp-runtime/probe.js.map +1 -0
- package/dist/acp-runtime/runtime.d.ts +7 -0
- package/dist/acp-runtime/runtime.d.ts.map +1 -0
- package/dist/acp-runtime/runtime.js +26 -0
- package/dist/acp-runtime/runtime.js.map +1 -0
- package/dist/acp-runtime/session.d.ts +87 -0
- package/dist/acp-runtime/session.d.ts.map +1 -0
- package/dist/acp-runtime/session.js +1071 -0
- package/dist/acp-runtime/session.js.map +1 -0
- package/dist/acp-runtime/spawners/node.d.ts +5 -0
- package/dist/acp-runtime/spawners/node.d.ts.map +1 -0
- package/dist/acp-runtime/spawners/node.js +244 -0
- package/dist/acp-runtime/spawners/node.js.map +1 -0
- package/dist/acp-runtime/types.d.ts +180 -0
- package/dist/acp-runtime/types.d.ts.map +1 -0
- package/dist/acp-runtime/types.js +2 -0
- package/dist/acp-runtime/types.js.map +1 -0
- package/dist/agent-contract/acp.d.ts +4 -0
- package/dist/agent-contract/acp.d.ts.map +1 -0
- package/dist/agent-contract/acp.js +273 -0
- package/dist/agent-contract/acp.js.map +1 -0
- package/dist/agent-contract/index.d.ts +125 -0
- package/dist/agent-contract/index.d.ts.map +1 -0
- package/dist/agent-contract/index.js +102 -0
- package/dist/agent-contract/index.js.map +1 -0
- package/dist/agent-contract/managed.d.ts +5 -0
- package/dist/agent-contract/managed.d.ts.map +1 -0
- package/dist/agent-contract/managed.js +242 -0
- package/dist/agent-contract/managed.js.map +1 -0
- package/dist/agent-ui/index.d.ts +170 -0
- package/dist/agent-ui/index.d.ts.map +1 -0
- package/dist/agent-ui/index.js +853 -0
- package/dist/agent-ui/index.js.map +1 -0
- package/dist/agent-ui/presentation.d.ts +30 -0
- package/dist/agent-ui/presentation.d.ts.map +1 -0
- package/dist/agent-ui/presentation.js +79 -0
- package/dist/agent-ui/presentation.js.map +1 -0
- package/dist/agent-ui/react.d.ts +50 -0
- package/dist/agent-ui/react.d.ts.map +1 -0
- package/dist/agent-ui/react.js +334 -0
- package/dist/agent-ui/react.js.map +1 -0
- package/dist/brand/index.d.ts +17 -0
- package/dist/brand/index.d.ts.map +1 -0
- package/dist/brand/index.js +119 -0
- package/dist/brand/index.js.map +1 -0
- package/dist/brand/openma-logo-mark.svg +7 -0
- package/dist/brand/tokens.css +77 -0
- package/dist/brand/website.css +67 -0
- package/dist/chat-ui/acp.d.ts +26 -0
- package/dist/chat-ui/acp.d.ts.map +1 -0
- package/dist/chat-ui/acp.js +166 -0
- package/dist/chat-ui/acp.js.map +1 -0
- package/dist/chat-ui/components.d.ts +230 -0
- package/dist/chat-ui/components.d.ts.map +1 -0
- package/dist/chat-ui/components.js +561 -0
- package/dist/chat-ui/components.js.map +1 -0
- package/dist/chat-ui/composer-drafts.d.ts +21 -0
- package/dist/chat-ui/composer-drafts.d.ts.map +1 -0
- package/dist/chat-ui/composer-drafts.js +58 -0
- package/dist/chat-ui/composer-drafts.js.map +1 -0
- package/dist/chat-ui/controller.d.ts +61 -0
- package/dist/chat-ui/controller.d.ts.map +1 -0
- package/dist/chat-ui/controller.js +218 -0
- package/dist/chat-ui/controller.js.map +1 -0
- package/dist/chat-ui/index.d.ts +8 -0
- package/dist/chat-ui/index.d.ts.map +1 -0
- package/dist/chat-ui/index.js +8 -0
- package/dist/chat-ui/index.js.map +1 -0
- package/dist/chat-ui/markdown.d.ts +37 -0
- package/dist/chat-ui/markdown.d.ts.map +1 -0
- package/dist/chat-ui/markdown.js +33 -0
- package/dist/chat-ui/markdown.js.map +1 -0
- package/dist/chat-ui/presentation.d.ts +34 -0
- package/dist/chat-ui/presentation.d.ts.map +1 -0
- package/dist/chat-ui/presentation.js +191 -0
- package/dist/chat-ui/presentation.js.map +1 -0
- package/dist/chat-ui/styles.css +815 -0
- package/dist/chat-ui/utils.d.ts +14 -0
- package/dist/chat-ui/utils.d.ts.map +1 -0
- package/dist/chat-ui/utils.js +71 -0
- package/dist/chat-ui/utils.js.map +1 -0
- package/dist/local-runtime/checkpoint.d.ts +28 -0
- package/dist/local-runtime/checkpoint.d.ts.map +1 -0
- package/dist/local-runtime/checkpoint.js +2 -0
- package/dist/local-runtime/checkpoint.js.map +1 -0
- package/dist/local-runtime/daemon-connection.d.ts +27 -0
- package/dist/local-runtime/daemon-connection.d.ts.map +1 -0
- package/dist/local-runtime/daemon-connection.js +161 -0
- package/dist/local-runtime/daemon-connection.js.map +1 -0
- package/dist/local-runtime/daemon-host.d.ts +39 -0
- package/dist/local-runtime/daemon-host.d.ts.map +1 -0
- package/dist/local-runtime/daemon-host.js +88 -0
- package/dist/local-runtime/daemon-host.js.map +1 -0
- package/dist/local-runtime/index.d.ts +6 -0
- package/dist/local-runtime/index.d.ts.map +1 -0
- package/dist/local-runtime/index.js +5 -0
- package/dist/local-runtime/index.js.map +1 -0
- package/dist/local-runtime/runtime.d.ts +36 -0
- package/dist/local-runtime/runtime.d.ts.map +1 -0
- package/dist/local-runtime/runtime.js +82 -0
- package/dist/local-runtime/runtime.js.map +1 -0
- package/dist/local-runtime/session-host.d.ts +62 -0
- package/dist/local-runtime/session-host.d.ts.map +1 -0
- package/dist/local-runtime/session-host.js +477 -0
- package/dist/local-runtime/session-host.js.map +1 -0
- package/dist/managed-runtime/acp-subagents.d.ts +14 -0
- package/dist/managed-runtime/acp-subagents.d.ts.map +1 -0
- package/dist/managed-runtime/acp-subagents.js +67 -0
- package/dist/managed-runtime/acp-subagents.js.map +1 -0
- package/dist/managed-runtime/claimed-environment-work.d.ts +61 -0
- package/dist/managed-runtime/claimed-environment-work.d.ts.map +1 -0
- package/dist/managed-runtime/claimed-environment-work.js +170 -0
- package/dist/managed-runtime/claimed-environment-work.js.map +1 -0
- package/dist/managed-runtime/contracts.d.ts +31 -0
- package/dist/managed-runtime/contracts.d.ts.map +1 -0
- package/dist/managed-runtime/contracts.js +2 -0
- package/dist/managed-runtime/contracts.js.map +1 -0
- package/dist/managed-runtime/http-control.d.ts +67 -0
- package/dist/managed-runtime/http-control.d.ts.map +1 -0
- package/dist/managed-runtime/http-control.js +465 -0
- package/dist/managed-runtime/http-control.js.map +1 -0
- package/dist/managed-runtime/index.d.ts +89 -0
- package/dist/managed-runtime/index.d.ts.map +1 -0
- package/dist/managed-runtime/index.js +215 -0
- package/dist/managed-runtime/index.js.map +1 -0
- package/dist/managed-runtime/input-identity.d.ts +2 -0
- package/dist/managed-runtime/input-identity.d.ts.map +1 -0
- package/dist/managed-runtime/input-identity.js +2 -0
- package/dist/managed-runtime/input-identity.js.map +1 -0
- package/dist/managed-runtime/managed-event-projector.d.ts +24 -0
- package/dist/managed-runtime/managed-event-projector.d.ts.map +1 -0
- package/dist/managed-runtime/managed-event-projector.js +333 -0
- package/dist/managed-runtime/managed-event-projector.js.map +1 -0
- package/dist/managed-runtime/semantic-recovery.d.ts +61 -0
- package/dist/managed-runtime/semantic-recovery.d.ts.map +1 -0
- package/dist/managed-runtime/semantic-recovery.js +167 -0
- package/dist/managed-runtime/semantic-recovery.js.map +1 -0
- package/dist/project-ui/CreateProjectDialog.d.ts +15 -0
- package/dist/project-ui/CreateProjectDialog.d.ts.map +1 -0
- package/dist/project-ui/CreateProjectDialog.js +87 -0
- package/dist/project-ui/CreateProjectDialog.js.map +1 -0
- package/dist/project-ui/ProjectComposer.d.ts +13 -0
- package/dist/project-ui/ProjectComposer.d.ts.map +1 -0
- package/dist/project-ui/ProjectComposer.js +70 -0
- package/dist/project-ui/ProjectComposer.js.map +1 -0
- package/dist/project-ui/ProjectConversation.d.ts +10 -0
- package/dist/project-ui/ProjectConversation.d.ts.map +1 -0
- package/dist/project-ui/ProjectConversation.js +28 -0
- package/dist/project-ui/ProjectConversation.js.map +1 -0
- package/dist/project-ui/ProjectMessageAttachments.d.ts +4 -0
- package/dist/project-ui/ProjectMessageAttachments.d.ts.map +1 -0
- package/dist/project-ui/ProjectMessageAttachments.js +28 -0
- package/dist/project-ui/ProjectMessageAttachments.js.map +1 -0
- package/dist/project-ui/ProjectSettings.d.ts +8 -0
- package/dist/project-ui/ProjectSettings.d.ts.map +1 -0
- package/dist/project-ui/ProjectSettings.js +65 -0
- package/dist/project-ui/ProjectSettings.js.map +1 -0
- package/dist/project-ui/Projects.d.ts +18 -0
- package/dist/project-ui/Projects.d.ts.map +1 -0
- package/dist/project-ui/Projects.js +377 -0
- package/dist/project-ui/Projects.js.map +1 -0
- package/dist/project-ui/client.d.ts +234 -0
- package/dist/project-ui/client.d.ts.map +1 -0
- package/dist/project-ui/client.js +42 -0
- package/dist/project-ui/client.js.map +1 -0
- package/dist/project-ui/controls.d.ts +15 -0
- package/dist/project-ui/controls.d.ts.map +1 -0
- package/dist/project-ui/controls.js +17 -0
- package/dist/project-ui/controls.js.map +1 -0
- package/dist/project-ui/index.d.ts +20 -0
- package/dist/project-ui/index.d.ts.map +1 -0
- package/dist/project-ui/index.js +17 -0
- package/dist/project-ui/index.js.map +1 -0
- package/dist/project-ui/project-coordinator.d.ts +3 -0
- package/dist/project-ui/project-coordinator.d.ts.map +1 -0
- package/dist/project-ui/project-coordinator.js +12 -0
- package/dist/project-ui/project-coordinator.js.map +1 -0
- package/dist/project-ui/project-goals.d.ts +48 -0
- package/dist/project-ui/project-goals.d.ts.map +1 -0
- package/dist/project-ui/project-goals.js +169 -0
- package/dist/project-ui/project-goals.js.map +1 -0
- package/dist/project-ui/projects-query.d.ts +19 -0
- package/dist/project-ui/projects-query.d.ts.map +1 -0
- package/dist/project-ui/projects-query.js +132 -0
- package/dist/project-ui/projects-query.js.map +1 -0
- package/dist/project-ui/styles.css +847 -0
- package/dist/protocol/acp/index.d.ts +52 -0
- package/dist/protocol/acp/index.d.ts.map +1 -0
- package/dist/protocol/acp/index.js +1056 -0
- package/dist/protocol/acp/index.js.map +1 -0
- package/dist/protocol/cursor-cloud/index.d.ts +74 -0
- package/dist/protocol/cursor-cloud/index.d.ts.map +1 -0
- package/dist/protocol/cursor-cloud/index.js +249 -0
- package/dist/protocol/cursor-cloud/index.js.map +1 -0
- package/dist/protocol/managed/index.d.ts +32 -0
- package/dist/protocol/managed/index.d.ts.map +1 -0
- package/dist/protocol/managed/index.js +646 -0
- package/dist/protocol/managed/index.js.map +1 -0
- package/dist/protocol/managed/input-identity.d.ts +3 -0
- package/dist/protocol/managed/input-identity.d.ts.map +1 -0
- package/dist/protocol/managed/input-identity.js +6 -0
- package/dist/protocol/managed/input-identity.js.map +1 -0
- package/dist/protocol/openai-agents/index.d.ts +102 -0
- package/dist/protocol/openai-agents/index.d.ts.map +1 -0
- package/dist/protocol/openai-agents/index.js +142 -0
- package/dist/protocol/openai-agents/index.js.map +1 -0
- package/dist/session-events/acp-system-notices.d.ts +10 -0
- package/dist/session-events/acp-system-notices.d.ts.map +1 -0
- package/dist/session-events/acp-system-notices.js +46 -0
- package/dist/session-events/acp-system-notices.js.map +1 -0
- package/dist/session-events/acp.d.ts +214 -0
- package/dist/session-events/acp.d.ts.map +1 -0
- package/dist/session-events/acp.js +956 -0
- package/dist/session-events/acp.js.map +1 -0
- package/dist/session-events/managed.d.ts +141 -0
- package/dist/session-events/managed.d.ts.map +1 -0
- package/dist/session-events/managed.js +324 -0
- package/dist/session-events/managed.js.map +1 -0
- package/dist/session-events/openma.d.ts +304 -0
- package/dist/session-events/openma.d.ts.map +1 -0
- package/dist/session-events/openma.js +438 -0
- package/dist/session-events/openma.js.map +1 -0
- package/dist/session-kernel/index.d.ts +118 -0
- package/dist/session-kernel/index.d.ts.map +1 -0
- package/dist/session-kernel/index.js +215 -0
- package/dist/session-kernel/index.js.map +1 -0
- package/dist/session-orchestrator/index.d.ts +71 -0
- package/dist/session-orchestrator/index.d.ts.map +1 -0
- package/dist/session-orchestrator/index.js +177 -0
- package/dist/session-orchestrator/index.js.map +1 -0
- package/dist/session-ui/index.d.ts +96 -0
- package/dist/session-ui/index.d.ts.map +1 -0
- package/dist/session-ui/index.js +277 -0
- package/dist/session-ui/index.js.map +1 -0
- package/package.json +222 -4
|
@@ -0,0 +1,853 @@
|
|
|
1
|
+
import { reduceWorkItemEvent, } from "../session-events/openma.js";
|
|
2
|
+
export const AGENT_UI_STATE_VERSION = "oma.agent-ui.v1";
|
|
3
|
+
export function createAgentUIState(sessionId) {
|
|
4
|
+
return {
|
|
5
|
+
version: AGENT_UI_STATE_VERSION,
|
|
6
|
+
sessionId,
|
|
7
|
+
status: "unknown",
|
|
8
|
+
sessionInfo: {},
|
|
9
|
+
commands: [],
|
|
10
|
+
capabilities: {},
|
|
11
|
+
turnOrder: [],
|
|
12
|
+
turns: {},
|
|
13
|
+
workItemOrder: [],
|
|
14
|
+
workItems: {},
|
|
15
|
+
planOrder: [],
|
|
16
|
+
plans: {},
|
|
17
|
+
callbackOrder: [],
|
|
18
|
+
callbacks: {},
|
|
19
|
+
outcomeOrder: [],
|
|
20
|
+
outcomes: {},
|
|
21
|
+
seenEventIds: {},
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function eventData(event) {
|
|
25
|
+
return event.data && typeof event.data === "object"
|
|
26
|
+
? event.data
|
|
27
|
+
: {};
|
|
28
|
+
}
|
|
29
|
+
function cloneState(state) {
|
|
30
|
+
return {
|
|
31
|
+
...state,
|
|
32
|
+
sessionInfo: { ...state.sessionInfo },
|
|
33
|
+
commands: [...state.commands],
|
|
34
|
+
capabilities: { ...state.capabilities },
|
|
35
|
+
turnOrder: [...state.turnOrder],
|
|
36
|
+
turns: Object.fromEntries(Object.entries(state.turns).map(([id, turn]) => [
|
|
37
|
+
id,
|
|
38
|
+
{
|
|
39
|
+
...turn,
|
|
40
|
+
items: turn.items.map((item) => item.kind === "tool"
|
|
41
|
+
? {
|
|
42
|
+
...item,
|
|
43
|
+
outputs: item.outputs.map((output) => ({ ...output })),
|
|
44
|
+
...(item.content ? { content: [...item.content] } : {}),
|
|
45
|
+
...(item.locations
|
|
46
|
+
? { locations: item.locations.map((location) => ({ ...location })) }
|
|
47
|
+
: {}),
|
|
48
|
+
...(item.adapterMeta
|
|
49
|
+
? { adapterMeta: { ...item.adapterMeta } }
|
|
50
|
+
: {}),
|
|
51
|
+
}
|
|
52
|
+
: { ...item }),
|
|
53
|
+
},
|
|
54
|
+
])),
|
|
55
|
+
workItemOrder: [...state.workItemOrder],
|
|
56
|
+
workItems: Object.fromEntries(Object.entries(state.workItems).map(([id, item]) => [
|
|
57
|
+
id,
|
|
58
|
+
{ ...item, output: [...item.output] },
|
|
59
|
+
])),
|
|
60
|
+
planOrder: [...state.planOrder],
|
|
61
|
+
plans: Object.fromEntries(Object.entries(state.plans).map(([id, plan]) => [
|
|
62
|
+
id,
|
|
63
|
+
{ ...plan, entries: plan.entries.map((entry) => ({ ...entry })) },
|
|
64
|
+
])),
|
|
65
|
+
callbackOrder: [...state.callbackOrder],
|
|
66
|
+
callbacks: Object.fromEntries(Object.entries(state.callbacks).map(([id, callback]) => [
|
|
67
|
+
id,
|
|
68
|
+
{ ...callback },
|
|
69
|
+
])),
|
|
70
|
+
...(state.usage ? { usage: { ...state.usage } } : {}),
|
|
71
|
+
outcomeOrder: [...state.outcomeOrder],
|
|
72
|
+
outcomes: Object.fromEntries(Object.entries(state.outcomes).map(([id, outcome]) => [id, { ...outcome }])),
|
|
73
|
+
seenEventIds: { ...state.seenEventIds },
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function toWorkItemSnapshot(item) {
|
|
77
|
+
return {
|
|
78
|
+
id: item.id,
|
|
79
|
+
kind: item.kind,
|
|
80
|
+
status: item.status,
|
|
81
|
+
output: [...item.output],
|
|
82
|
+
...(item.title !== undefined ? { title: item.title } : {}),
|
|
83
|
+
...(item.progress !== undefined ? { progress: item.progress } : {}),
|
|
84
|
+
...(item.result !== undefined ? { result: item.result } : {}),
|
|
85
|
+
...(item.error !== undefined ? { error: item.error } : {}),
|
|
86
|
+
...(item.reason !== undefined ? { reason: item.reason } : {}),
|
|
87
|
+
...(item.startedAt !== undefined ? { started_at: item.startedAt } : {}),
|
|
88
|
+
...(item.endedAt !== undefined ? { ended_at: item.endedAt } : {}),
|
|
89
|
+
...(item.missingStart !== undefined ? { missing_start: item.missingStart } : {}),
|
|
90
|
+
...(item.missingTerminal !== undefined
|
|
91
|
+
? { missing_terminal: item.missingTerminal }
|
|
92
|
+
: {}),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function toAgentUIWorkItem(item) {
|
|
96
|
+
return {
|
|
97
|
+
id: item.id,
|
|
98
|
+
kind: item.kind,
|
|
99
|
+
status: item.status,
|
|
100
|
+
output: [...item.output],
|
|
101
|
+
...(item.title !== undefined ? { title: item.title } : {}),
|
|
102
|
+
...(item.progress !== undefined ? { progress: item.progress } : {}),
|
|
103
|
+
...(item.result !== undefined ? { result: item.result } : {}),
|
|
104
|
+
...(item.error !== undefined ? { error: item.error } : {}),
|
|
105
|
+
...(item.reason !== undefined ? { reason: item.reason } : {}),
|
|
106
|
+
...(item.started_at !== undefined ? { startedAt: item.started_at } : {}),
|
|
107
|
+
...(item.ended_at !== undefined ? { endedAt: item.ended_at } : {}),
|
|
108
|
+
...(item.missing_start !== undefined ? { missingStart: item.missing_start } : {}),
|
|
109
|
+
...(item.missing_terminal !== undefined
|
|
110
|
+
? { missingTerminal: item.missing_terminal }
|
|
111
|
+
: {}),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function applyWorkItemProjection(state, previous, event) {
|
|
115
|
+
const registry = reduceWorkItemEvent({
|
|
116
|
+
items: new Map(Object.entries(previous.workItems).map(([id, item]) => [
|
|
117
|
+
id,
|
|
118
|
+
toWorkItemSnapshot(item),
|
|
119
|
+
])),
|
|
120
|
+
seen_event_ids: new Set(Object.keys(previous.seenEventIds)),
|
|
121
|
+
}, event);
|
|
122
|
+
const ids = [...registry.items.keys()];
|
|
123
|
+
const present = new Set(ids);
|
|
124
|
+
state.workItemOrder = previous.workItemOrder.filter((id) => present.has(id));
|
|
125
|
+
for (const id of ids) {
|
|
126
|
+
if (!state.workItemOrder.includes(id))
|
|
127
|
+
state.workItemOrder.push(id);
|
|
128
|
+
}
|
|
129
|
+
state.workItems = Object.fromEntries([...registry.items].map(([id, item]) => [id, toAgentUIWorkItem(item)]));
|
|
130
|
+
}
|
|
131
|
+
function planId(event) {
|
|
132
|
+
if (!event.data || typeof event.data !== "object")
|
|
133
|
+
return undefined;
|
|
134
|
+
const value = event.data.plan_id;
|
|
135
|
+
return typeof value === "string" && value.length > 0
|
|
136
|
+
? value
|
|
137
|
+
: event.turn_id;
|
|
138
|
+
}
|
|
139
|
+
function mergePlanEntries(previous, incoming) {
|
|
140
|
+
const merged = previous.map((entry) => ({ ...entry }));
|
|
141
|
+
for (const entry of incoming) {
|
|
142
|
+
const index = entry.id
|
|
143
|
+
? merged.findIndex((candidate) => candidate.id === entry.id)
|
|
144
|
+
: -1;
|
|
145
|
+
if (index >= 0)
|
|
146
|
+
merged[index] = { ...merged[index], ...entry };
|
|
147
|
+
else
|
|
148
|
+
merged.push({ ...entry });
|
|
149
|
+
}
|
|
150
|
+
return merged;
|
|
151
|
+
}
|
|
152
|
+
function applyPlanProjection(state, event) {
|
|
153
|
+
const id = planId(event);
|
|
154
|
+
if (!id)
|
|
155
|
+
return;
|
|
156
|
+
if (event.type === "plan.updated") {
|
|
157
|
+
const data = event.data;
|
|
158
|
+
if (data.representation !== "items"
|
|
159
|
+
&& data.representation !== "markdown"
|
|
160
|
+
&& data.representation !== "file") {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
const previous = state.plans[id];
|
|
164
|
+
const incoming = data.entries ?? [];
|
|
165
|
+
state.plans[id] = {
|
|
166
|
+
id,
|
|
167
|
+
representation: data.representation,
|
|
168
|
+
status: "active",
|
|
169
|
+
entries: data.update_mode === "merge" && previous
|
|
170
|
+
? mergePlanEntries(previous.entries, incoming)
|
|
171
|
+
: incoming.map((entry) => ({ ...entry })),
|
|
172
|
+
};
|
|
173
|
+
if (!state.planOrder.includes(id))
|
|
174
|
+
state.planOrder.push(id);
|
|
175
|
+
}
|
|
176
|
+
else if (event.type === "plan.completed") {
|
|
177
|
+
const previous = state.plans[id];
|
|
178
|
+
if (previous)
|
|
179
|
+
state.plans[id] = { ...previous, status: "completed" };
|
|
180
|
+
}
|
|
181
|
+
else if (event.type === "plan.removed") {
|
|
182
|
+
delete state.plans[id];
|
|
183
|
+
state.planOrder = state.planOrder.filter((planId) => planId !== id);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
function applyCallbackProjection(state, event) {
|
|
187
|
+
if (event.type !== "callback.requested"
|
|
188
|
+
&& event.type !== "callback.completed"
|
|
189
|
+
&& event.type !== "callback.failed"
|
|
190
|
+
&& event.type !== "callback.notification") {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
if (!event.data || typeof event.data !== "object")
|
|
194
|
+
return;
|
|
195
|
+
const data = event.data;
|
|
196
|
+
const callbackId = (typeof data.callback_id === "string" && data.callback_id.length > 0) || typeof data.callback_id === "number"
|
|
197
|
+
? String(data.callback_id)
|
|
198
|
+
: data.callback_id === null
|
|
199
|
+
? "null"
|
|
200
|
+
: event.type === "callback.notification"
|
|
201
|
+
? event.event_id
|
|
202
|
+
: undefined;
|
|
203
|
+
if (!callbackId) {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
if (typeof data.method !== "string" || data.method.length === 0)
|
|
207
|
+
return;
|
|
208
|
+
const id = callbackId;
|
|
209
|
+
const previous = state.callbacks[id];
|
|
210
|
+
const callback = {
|
|
211
|
+
id,
|
|
212
|
+
category: data.category,
|
|
213
|
+
method: data.method,
|
|
214
|
+
status: event.type === "callback.requested"
|
|
215
|
+
? "pending"
|
|
216
|
+
: event.type === "callback.failed"
|
|
217
|
+
? "failed"
|
|
218
|
+
: event.type === "callback.notification"
|
|
219
|
+
? "notification"
|
|
220
|
+
: "completed",
|
|
221
|
+
...(previous?.params !== undefined ? { params: previous.params } : {}),
|
|
222
|
+
...(data.params !== undefined ? { params: data.params } : {}),
|
|
223
|
+
...(data.result !== undefined ? { result: data.result } : {}),
|
|
224
|
+
...(data.error !== undefined ? { error: data.error } : {}),
|
|
225
|
+
};
|
|
226
|
+
state.callbacks[id] = callback;
|
|
227
|
+
if (!state.callbackOrder.includes(id))
|
|
228
|
+
state.callbackOrder.push(id);
|
|
229
|
+
}
|
|
230
|
+
function applyOutcomeProjection(state, event) {
|
|
231
|
+
if (event.type !== "outcome.defined"
|
|
232
|
+
&& event.type !== "outcome.evaluation_started"
|
|
233
|
+
&& event.type !== "outcome.evaluation_progress"
|
|
234
|
+
&& event.type !== "outcome.evaluation_completed") {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
if (!event.data || typeof event.data !== "object")
|
|
238
|
+
return;
|
|
239
|
+
const data = event.data;
|
|
240
|
+
const id = typeof data.outcome_id === "string" && data.outcome_id.length > 0
|
|
241
|
+
? data.outcome_id
|
|
242
|
+
: event.event_id;
|
|
243
|
+
const previous = state.outcomes[id];
|
|
244
|
+
const status = event.type === "outcome.defined"
|
|
245
|
+
? "defined"
|
|
246
|
+
: event.type === "outcome.evaluation_completed"
|
|
247
|
+
? data.result ?? "completed"
|
|
248
|
+
: "evaluating";
|
|
249
|
+
state.outcomes[id] = {
|
|
250
|
+
id,
|
|
251
|
+
status,
|
|
252
|
+
...(previous?.description !== undefined
|
|
253
|
+
? { description: previous.description }
|
|
254
|
+
: {}),
|
|
255
|
+
...(previous?.rubric !== undefined ? { rubric: previous.rubric } : {}),
|
|
256
|
+
...(previous?.maxIterations !== undefined
|
|
257
|
+
? { maxIterations: previous.maxIterations }
|
|
258
|
+
: {}),
|
|
259
|
+
...(data.description !== undefined ? { description: data.description } : {}),
|
|
260
|
+
...(data.rubric !== undefined ? { rubric: data.rubric } : {}),
|
|
261
|
+
...(data.max_iterations !== undefined
|
|
262
|
+
? { maxIterations: data.max_iterations }
|
|
263
|
+
: {}),
|
|
264
|
+
...(data.iteration !== undefined ? { iteration: data.iteration } : {}),
|
|
265
|
+
...(data.explanation !== undefined ? { explanation: data.explanation } : {}),
|
|
266
|
+
...(data.usage !== undefined ? { usage: data.usage } : {}),
|
|
267
|
+
updatedAt: event.occurred_at,
|
|
268
|
+
};
|
|
269
|
+
if (!state.outcomeOrder.includes(id))
|
|
270
|
+
state.outcomeOrder.push(id);
|
|
271
|
+
}
|
|
272
|
+
function requireTurn(state, event) {
|
|
273
|
+
const turnId = event.turn_id;
|
|
274
|
+
if (!turnId)
|
|
275
|
+
return undefined;
|
|
276
|
+
const existing = state.turns[turnId];
|
|
277
|
+
if (existing)
|
|
278
|
+
return existing;
|
|
279
|
+
const created = {
|
|
280
|
+
id: turnId,
|
|
281
|
+
status: "unknown",
|
|
282
|
+
items: [],
|
|
283
|
+
};
|
|
284
|
+
state.turns[turnId] = created;
|
|
285
|
+
state.turnOrder.push(turnId);
|
|
286
|
+
return created;
|
|
287
|
+
}
|
|
288
|
+
function upsertMessage(turn, event, input) {
|
|
289
|
+
const data = eventData(event);
|
|
290
|
+
const id = typeof data.message_id === "string" && data.message_id.length > 0
|
|
291
|
+
? data.message_id
|
|
292
|
+
: event.event_id;
|
|
293
|
+
const text = typeof data.text === "string" ? data.text : "";
|
|
294
|
+
const tail = turn.items.at(-1);
|
|
295
|
+
const existing = tail
|
|
296
|
+
&& tail.kind !== "tool"
|
|
297
|
+
&& tail.kind === input.kind
|
|
298
|
+
&& tail.role === input.role
|
|
299
|
+
&& (data.message_id === undefined
|
|
300
|
+
|| (tail.messageId ?? tail.id) === data.message_id)
|
|
301
|
+
? tail
|
|
302
|
+
: undefined;
|
|
303
|
+
if (existing) {
|
|
304
|
+
existing.kind = input.kind;
|
|
305
|
+
existing.role = input.role;
|
|
306
|
+
existing.text = input.streaming
|
|
307
|
+
? mergeAgentUIStreamingText(existing.text, text)
|
|
308
|
+
: text;
|
|
309
|
+
existing.status = input.streaming ? "streaming" : "complete";
|
|
310
|
+
if (data.content !== undefined)
|
|
311
|
+
existing.content = data.content;
|
|
312
|
+
if (data.phase !== undefined)
|
|
313
|
+
existing.phase = data.phase;
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
const segmentId = uniqueMessageItemId(turn, id);
|
|
317
|
+
turn.items.push({
|
|
318
|
+
id: segmentId,
|
|
319
|
+
...(segmentId !== id ? { messageId: id } : {}),
|
|
320
|
+
kind: input.kind,
|
|
321
|
+
...(input.kind === "thinking" ? { startedAt: event.occurred_at } : {}),
|
|
322
|
+
role: input.role,
|
|
323
|
+
text,
|
|
324
|
+
status: input.streaming ? "streaming" : "complete",
|
|
325
|
+
...(data.content !== undefined ? { content: data.content } : {}),
|
|
326
|
+
...(data.phase !== undefined ? { phase: data.phase } : {}),
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
function uniqueMessageItemId(turn, sourceId) {
|
|
330
|
+
if (!turn.items.some((item) => item.id === sourceId))
|
|
331
|
+
return sourceId;
|
|
332
|
+
let segment = 2;
|
|
333
|
+
while (turn.items.some((item) => item.id === `${sourceId}:segment:${segment}`)) {
|
|
334
|
+
segment += 1;
|
|
335
|
+
}
|
|
336
|
+
return `${sourceId}:segment:${segment}`;
|
|
337
|
+
}
|
|
338
|
+
function mergeAdapterMeta(current, incoming) {
|
|
339
|
+
const next = { ...(current ?? {}) };
|
|
340
|
+
for (const [key, value] of Object.entries(incoming)) {
|
|
341
|
+
const previous = next[key];
|
|
342
|
+
next[key] = value
|
|
343
|
+
&& typeof value === "object"
|
|
344
|
+
&& !Array.isArray(value)
|
|
345
|
+
&& previous
|
|
346
|
+
&& typeof previous === "object"
|
|
347
|
+
&& !Array.isArray(previous)
|
|
348
|
+
? mergeAdapterMeta(previous, value)
|
|
349
|
+
: value;
|
|
350
|
+
}
|
|
351
|
+
return next;
|
|
352
|
+
}
|
|
353
|
+
const MIN_STREAM_OVERLAP = 8;
|
|
354
|
+
export function mergeAgentUIStreamingText(accumulated, incoming) {
|
|
355
|
+
if (!accumulated)
|
|
356
|
+
return incoming;
|
|
357
|
+
if (!incoming || incoming === accumulated)
|
|
358
|
+
return accumulated;
|
|
359
|
+
if (incoming.startsWith(accumulated))
|
|
360
|
+
return incoming;
|
|
361
|
+
if (incoming.length >= MIN_STREAM_OVERLAP && accumulated.endsWith(incoming)) {
|
|
362
|
+
return accumulated;
|
|
363
|
+
}
|
|
364
|
+
const maxOverlap = Math.min(accumulated.length, incoming.length);
|
|
365
|
+
for (let size = maxOverlap; size >= MIN_STREAM_OVERLAP; size -= 1) {
|
|
366
|
+
if (accumulated.endsWith(incoming.slice(0, size))) {
|
|
367
|
+
return accumulated + incoming.slice(size);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return accumulated + incoming;
|
|
371
|
+
}
|
|
372
|
+
function upsertTool(turn, event, status) {
|
|
373
|
+
if (!event.data || typeof event.data !== "object")
|
|
374
|
+
return;
|
|
375
|
+
const data = event.data;
|
|
376
|
+
if (typeof data.tool_call_id !== "string" || data.tool_call_id.length === 0) {
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
let item = turn.items.find((candidate) => candidate.kind === "tool" && candidate.id === data.tool_call_id);
|
|
380
|
+
if (!item) {
|
|
381
|
+
item = {
|
|
382
|
+
id: data.tool_call_id,
|
|
383
|
+
kind: "tool",
|
|
384
|
+
status,
|
|
385
|
+
outputs: [],
|
|
386
|
+
};
|
|
387
|
+
turn.items.push(item);
|
|
388
|
+
}
|
|
389
|
+
item.status = status;
|
|
390
|
+
if (data.tool_name !== undefined)
|
|
391
|
+
item.name = data.tool_name;
|
|
392
|
+
if (data.title !== undefined)
|
|
393
|
+
item.title = data.title;
|
|
394
|
+
if (data.kind !== undefined)
|
|
395
|
+
item.toolKind = data.kind;
|
|
396
|
+
if (data.raw_input !== undefined)
|
|
397
|
+
item.rawInput = data.raw_input;
|
|
398
|
+
if (data.raw_output !== undefined)
|
|
399
|
+
item.rawOutput = data.raw_output;
|
|
400
|
+
if (data.content !== undefined)
|
|
401
|
+
item.content = [...data.content];
|
|
402
|
+
if (data.locations !== undefined) {
|
|
403
|
+
item.locations = data.locations.map((location) => ({ ...location }));
|
|
404
|
+
}
|
|
405
|
+
if (data.adapter_meta !== undefined) {
|
|
406
|
+
item.adapterMeta = mergeAdapterMeta(item.adapterMeta, data.adapter_meta);
|
|
407
|
+
}
|
|
408
|
+
if (data.error !== undefined)
|
|
409
|
+
item.error = data.error;
|
|
410
|
+
if (data.reason !== undefined)
|
|
411
|
+
item.reason = data.reason;
|
|
412
|
+
if (data.output !== undefined) {
|
|
413
|
+
if (data.output.append)
|
|
414
|
+
item.outputs.push(data.output);
|
|
415
|
+
else
|
|
416
|
+
item.outputs = [data.output];
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
function errorMessage(event) {
|
|
420
|
+
if (!event.data || typeof event.data !== "object")
|
|
421
|
+
return undefined;
|
|
422
|
+
const data = event.data;
|
|
423
|
+
for (const value of [data.error, data.message, data.reason]) {
|
|
424
|
+
if (typeof value === "string" && value.length > 0)
|
|
425
|
+
return value;
|
|
426
|
+
}
|
|
427
|
+
return undefined;
|
|
428
|
+
}
|
|
429
|
+
function stopReasonType(event) {
|
|
430
|
+
if (!event.data || typeof event.data !== "object")
|
|
431
|
+
return undefined;
|
|
432
|
+
const stopReason = event.data.stop_reason;
|
|
433
|
+
if (typeof stopReason === "string")
|
|
434
|
+
return stopReason;
|
|
435
|
+
if (!stopReason || typeof stopReason !== "object")
|
|
436
|
+
return undefined;
|
|
437
|
+
const type = stopReason.type;
|
|
438
|
+
return typeof type === "string" ? type : undefined;
|
|
439
|
+
}
|
|
440
|
+
/** Match ACP chat projection: first thought chunk through the following
|
|
441
|
+
* activity (or turn termination), rounded up to whole seconds. Metadata and
|
|
442
|
+
* unrelated turns must not stop a thought's clock. */
|
|
443
|
+
function settleThoughtTiming(turn, event) {
|
|
444
|
+
if (!turn)
|
|
445
|
+
return;
|
|
446
|
+
const thought = [...turn.items].reverse().find((item) => item.kind === "thinking" && !item.endedAt);
|
|
447
|
+
if (!thought?.startedAt)
|
|
448
|
+
return;
|
|
449
|
+
const data = eventData(event);
|
|
450
|
+
const continuesThought = event.type === "agent.thinking"
|
|
451
|
+
&& turn.items.at(-1) === thought
|
|
452
|
+
&& (data.message_id === undefined || data.message_id === (thought.messageId ?? thought.id));
|
|
453
|
+
if (continuesThought)
|
|
454
|
+
return;
|
|
455
|
+
const boundary = event.type === "agent.thinking"
|
|
456
|
+
|| event.type === "agent.message_chunk"
|
|
457
|
+
|| event.type === "agent.message"
|
|
458
|
+
|| event.type.startsWith("tool.")
|
|
459
|
+
|| ["turn.completed", "turn.failed", "turn.cancelled", "session.error", "session.terminated"].includes(event.type)
|
|
460
|
+
|| (event.type === "session.idle" && stopReasonType(event) === "end_turn");
|
|
461
|
+
if (!boundary)
|
|
462
|
+
return;
|
|
463
|
+
const elapsed = Date.parse(event.occurred_at) - Date.parse(thought.startedAt);
|
|
464
|
+
if (!Number.isFinite(elapsed))
|
|
465
|
+
return;
|
|
466
|
+
thought.endedAt = event.occurred_at;
|
|
467
|
+
thought.content = {
|
|
468
|
+
...(thought.content && typeof thought.content === "object" && !Array.isArray(thought.content)
|
|
469
|
+
? thought.content : {}),
|
|
470
|
+
durationSeconds: Math.max(1, Math.ceil(elapsed / 1_000)),
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
export function reduceAgentUIEvent(state, event) {
|
|
474
|
+
if (event.session_id !== state.sessionId || state.seenEventIds[event.event_id]) {
|
|
475
|
+
return state;
|
|
476
|
+
}
|
|
477
|
+
const next = cloneState(state);
|
|
478
|
+
applyWorkItemProjection(next, state, event);
|
|
479
|
+
applyPlanProjection(next, event);
|
|
480
|
+
applyCallbackProjection(next, event);
|
|
481
|
+
applyOutcomeProjection(next, event);
|
|
482
|
+
next.seenEventIds[event.event_id] = true;
|
|
483
|
+
const turn = requireTurn(next, event);
|
|
484
|
+
settleThoughtTiming(turn ?? (event.type.startsWith("session.") && next.activeTurnId ? next.turns[next.activeTurnId] : undefined), event);
|
|
485
|
+
switch (event.type) {
|
|
486
|
+
case "session.updated": {
|
|
487
|
+
const data = event.data;
|
|
488
|
+
next.sessionInfo = {
|
|
489
|
+
...next.sessionInfo,
|
|
490
|
+
...(Object.prototype.hasOwnProperty.call(data, "title")
|
|
491
|
+
? { title: data.title }
|
|
492
|
+
: {}),
|
|
493
|
+
...(Object.prototype.hasOwnProperty.call(data, "updated_at")
|
|
494
|
+
? { updatedAt: data.updated_at }
|
|
495
|
+
: {}),
|
|
496
|
+
};
|
|
497
|
+
break;
|
|
498
|
+
}
|
|
499
|
+
case "command_catalog.updated": {
|
|
500
|
+
const data = event.data;
|
|
501
|
+
if (Array.isArray(data.commands))
|
|
502
|
+
next.commands = [...data.commands];
|
|
503
|
+
break;
|
|
504
|
+
}
|
|
505
|
+
case "capability.updated": {
|
|
506
|
+
const data = event.data;
|
|
507
|
+
if (typeof data.capability === "string" && data.capability.length > 0) {
|
|
508
|
+
next.capabilities[data.capability] = data.value;
|
|
509
|
+
}
|
|
510
|
+
break;
|
|
511
|
+
}
|
|
512
|
+
case "session.running":
|
|
513
|
+
next.status = "running";
|
|
514
|
+
if (turn) {
|
|
515
|
+
turn.status = "running";
|
|
516
|
+
turn.startedAt ??= event.occurred_at;
|
|
517
|
+
next.activeTurnId = turn.id;
|
|
518
|
+
}
|
|
519
|
+
break;
|
|
520
|
+
case "session.rescheduled":
|
|
521
|
+
next.status = "rescheduled";
|
|
522
|
+
break;
|
|
523
|
+
case "session.idle": {
|
|
524
|
+
next.status = "idle";
|
|
525
|
+
const idleTurn = turn
|
|
526
|
+
?? (next.activeTurnId ? next.turns[next.activeTurnId] : undefined);
|
|
527
|
+
if (idleTurn && stopReasonType(event) === "end_turn") {
|
|
528
|
+
idleTurn.status = "completed";
|
|
529
|
+
idleTurn.endedAt = event.occurred_at;
|
|
530
|
+
}
|
|
531
|
+
next.activeTurnId = undefined;
|
|
532
|
+
break;
|
|
533
|
+
}
|
|
534
|
+
case "session.terminated":
|
|
535
|
+
next.status = "terminated";
|
|
536
|
+
next.activeTurnId = undefined;
|
|
537
|
+
break;
|
|
538
|
+
case "session.error": {
|
|
539
|
+
const message = errorMessage(event);
|
|
540
|
+
const failedTurn = turn
|
|
541
|
+
?? (next.activeTurnId ? next.turns[next.activeTurnId] : undefined);
|
|
542
|
+
next.status = "error";
|
|
543
|
+
next.lastError = message;
|
|
544
|
+
if (failedTurn) {
|
|
545
|
+
failedTurn.status = "failed";
|
|
546
|
+
failedTurn.error = message;
|
|
547
|
+
failedTurn.endedAt = event.occurred_at;
|
|
548
|
+
}
|
|
549
|
+
next.activeTurnId = undefined;
|
|
550
|
+
break;
|
|
551
|
+
}
|
|
552
|
+
case "usage.updated": {
|
|
553
|
+
const data = event.data;
|
|
554
|
+
if (data.usage !== undefined) {
|
|
555
|
+
next.usage = {
|
|
556
|
+
snapshot: data.usage,
|
|
557
|
+
...(data.budget !== undefined ? { budget: data.budget } : {}),
|
|
558
|
+
updatedAt: event.occurred_at,
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
break;
|
|
562
|
+
}
|
|
563
|
+
case "turn.queued":
|
|
564
|
+
if (turn)
|
|
565
|
+
turn.status = "queued";
|
|
566
|
+
break;
|
|
567
|
+
case "turn.completed":
|
|
568
|
+
if (turn) {
|
|
569
|
+
turn.status = "completed";
|
|
570
|
+
turn.endedAt = event.occurred_at;
|
|
571
|
+
}
|
|
572
|
+
if (next.activeTurnId === event.turn_id)
|
|
573
|
+
next.activeTurnId = undefined;
|
|
574
|
+
break;
|
|
575
|
+
case "turn.failed":
|
|
576
|
+
if (turn) {
|
|
577
|
+
turn.status = "failed";
|
|
578
|
+
turn.error = errorMessage(event);
|
|
579
|
+
turn.endedAt = event.occurred_at;
|
|
580
|
+
}
|
|
581
|
+
if (next.activeTurnId === event.turn_id)
|
|
582
|
+
next.activeTurnId = undefined;
|
|
583
|
+
break;
|
|
584
|
+
case "turn.cancelled":
|
|
585
|
+
if (turn) {
|
|
586
|
+
turn.status = "cancelled";
|
|
587
|
+
turn.reason = errorMessage(event);
|
|
588
|
+
turn.endedAt = event.occurred_at;
|
|
589
|
+
}
|
|
590
|
+
if (next.activeTurnId === event.turn_id)
|
|
591
|
+
next.activeTurnId = undefined;
|
|
592
|
+
break;
|
|
593
|
+
case "user.message_chunk":
|
|
594
|
+
if (turn) {
|
|
595
|
+
if (turn.status === "unknown")
|
|
596
|
+
turn.status = "queued";
|
|
597
|
+
upsertMessage(turn, event, {
|
|
598
|
+
kind: "message",
|
|
599
|
+
role: "user",
|
|
600
|
+
streaming: true,
|
|
601
|
+
});
|
|
602
|
+
}
|
|
603
|
+
break;
|
|
604
|
+
case "user.message":
|
|
605
|
+
if (turn) {
|
|
606
|
+
if (turn.status === "unknown")
|
|
607
|
+
turn.status = "queued";
|
|
608
|
+
upsertMessage(turn, event, {
|
|
609
|
+
kind: "message",
|
|
610
|
+
role: "user",
|
|
611
|
+
streaming: false,
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
break;
|
|
615
|
+
case "agent.message_chunk":
|
|
616
|
+
if (turn) {
|
|
617
|
+
if (turn.status === "unknown" || turn.status === "queued") {
|
|
618
|
+
turn.status = "running";
|
|
619
|
+
}
|
|
620
|
+
upsertMessage(turn, event, {
|
|
621
|
+
kind: "message",
|
|
622
|
+
role: "assistant",
|
|
623
|
+
streaming: true,
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
break;
|
|
627
|
+
case "agent.message":
|
|
628
|
+
if (turn) {
|
|
629
|
+
upsertMessage(turn, event, {
|
|
630
|
+
kind: "message",
|
|
631
|
+
role: "assistant",
|
|
632
|
+
streaming: false,
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
break;
|
|
636
|
+
case "agent.thinking":
|
|
637
|
+
if (turn) {
|
|
638
|
+
const data = eventData(event);
|
|
639
|
+
upsertMessage(turn, event, {
|
|
640
|
+
kind: "thinking",
|
|
641
|
+
role: "assistant",
|
|
642
|
+
streaming: typeof data.text === "string" && data.text.length > 0,
|
|
643
|
+
});
|
|
644
|
+
}
|
|
645
|
+
break;
|
|
646
|
+
case "system.message":
|
|
647
|
+
if (turn) {
|
|
648
|
+
upsertMessage(turn, event, {
|
|
649
|
+
kind: "message",
|
|
650
|
+
role: "system",
|
|
651
|
+
streaming: false,
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
break;
|
|
655
|
+
case "system.notice":
|
|
656
|
+
if (turn) {
|
|
657
|
+
upsertMessage(turn, event, {
|
|
658
|
+
kind: "notice",
|
|
659
|
+
role: "system",
|
|
660
|
+
streaming: false,
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
break;
|
|
664
|
+
case "tool.started":
|
|
665
|
+
if (turn)
|
|
666
|
+
upsertTool(turn, event, "in_progress");
|
|
667
|
+
break;
|
|
668
|
+
case "tool.progress":
|
|
669
|
+
if (turn)
|
|
670
|
+
upsertTool(turn, event, "in_progress");
|
|
671
|
+
break;
|
|
672
|
+
case "tool.completed":
|
|
673
|
+
if (turn)
|
|
674
|
+
upsertTool(turn, event, "completed");
|
|
675
|
+
break;
|
|
676
|
+
case "tool.failed":
|
|
677
|
+
if (turn)
|
|
678
|
+
upsertTool(turn, event, "failed");
|
|
679
|
+
break;
|
|
680
|
+
case "tool.cancelled":
|
|
681
|
+
if (turn)
|
|
682
|
+
upsertTool(turn, event, "cancelled");
|
|
683
|
+
break;
|
|
684
|
+
case "raw.event":
|
|
685
|
+
case "vendor.event":
|
|
686
|
+
if (turn)
|
|
687
|
+
turn.items.push({ id: event.event_id, kind: "raw", event });
|
|
688
|
+
break;
|
|
689
|
+
}
|
|
690
|
+
return next;
|
|
691
|
+
}
|
|
692
|
+
export function replayAgentUIEvents(sessionId, events) {
|
|
693
|
+
const ordered = events
|
|
694
|
+
.map((event, index) => ({ event, index }))
|
|
695
|
+
.sort((left, right) => {
|
|
696
|
+
if (left.event.seq === undefined && right.event.seq === undefined) {
|
|
697
|
+
return left.index - right.index;
|
|
698
|
+
}
|
|
699
|
+
if (left.event.seq === undefined)
|
|
700
|
+
return 1;
|
|
701
|
+
if (right.event.seq === undefined)
|
|
702
|
+
return -1;
|
|
703
|
+
return left.event.seq - right.event.seq || left.index - right.index;
|
|
704
|
+
});
|
|
705
|
+
return ordered.reduce((state, entry) => reduceAgentUIEvent(state, entry.event), createAgentUIState(sessionId));
|
|
706
|
+
}
|
|
707
|
+
/** Rebuild a live Agent UI store from persisted host events. Stable seq
|
|
708
|
+
* ordering and the store's event-id dedupe make repeated hydration safe. */
|
|
709
|
+
export function replayAgentUIEventLog(store, rows, decode) {
|
|
710
|
+
const ordered = rows
|
|
711
|
+
.map((row, index) => ({ row, index }))
|
|
712
|
+
.sort((left, right) => left.row.seq - right.row.seq || left.index - right.index);
|
|
713
|
+
for (const { row } of ordered) {
|
|
714
|
+
const decoded = decode(row);
|
|
715
|
+
if (!decoded)
|
|
716
|
+
continue;
|
|
717
|
+
for (const event of Array.isArray(decoded) ? decoded : [decoded]) {
|
|
718
|
+
store.dispatch(event);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
return store.getState();
|
|
722
|
+
}
|
|
723
|
+
export function createAgentUISessionRegistry() {
|
|
724
|
+
const stores = new Map();
|
|
725
|
+
return {
|
|
726
|
+
get(sessionId) {
|
|
727
|
+
const existing = stores.get(sessionId);
|
|
728
|
+
if (existing)
|
|
729
|
+
return existing;
|
|
730
|
+
const created = createAgentUIStore(sessionId);
|
|
731
|
+
stores.set(sessionId, created);
|
|
732
|
+
return created;
|
|
733
|
+
},
|
|
734
|
+
has(sessionId) {
|
|
735
|
+
return stores.has(sessionId);
|
|
736
|
+
},
|
|
737
|
+
remove(sessionId) {
|
|
738
|
+
return stores.delete(sessionId);
|
|
739
|
+
},
|
|
740
|
+
clear() {
|
|
741
|
+
stores.clear();
|
|
742
|
+
},
|
|
743
|
+
};
|
|
744
|
+
}
|
|
745
|
+
export function createAgentUIStore(sessionId) {
|
|
746
|
+
let state = createAgentUIState(sessionId);
|
|
747
|
+
const listeners = new Set();
|
|
748
|
+
const streamSubscribers = new Map();
|
|
749
|
+
const getState = () => state;
|
|
750
|
+
return {
|
|
751
|
+
getState,
|
|
752
|
+
getSnapshot: getState,
|
|
753
|
+
dispatch: (event) => {
|
|
754
|
+
const stream = streamProjection(event);
|
|
755
|
+
const beforeText = stream
|
|
756
|
+
? accumulatedTurnStream(state, event.turn_id, stream.kind)
|
|
757
|
+
: "";
|
|
758
|
+
const opensSegment = stream ? opensStreamSegment(state, event, stream.kind) : false;
|
|
759
|
+
const next = reduceAgentUIEvent(state, event);
|
|
760
|
+
if (next !== state) {
|
|
761
|
+
state = next;
|
|
762
|
+
if (stream) {
|
|
763
|
+
const afterText = accumulatedTurnStream(state, event.turn_id, stream.kind);
|
|
764
|
+
const delta = afterText.startsWith(beforeText)
|
|
765
|
+
? afterText.slice(beforeText.length)
|
|
766
|
+
: "";
|
|
767
|
+
if (delta && event.turn_id) {
|
|
768
|
+
for (const subscriber of streamSubscribers.get(event.turn_id) ?? []) {
|
|
769
|
+
subscriber({ kind: stream.kind, text: delta });
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
if (!stream || opensSegment) {
|
|
774
|
+
for (const listener of listeners)
|
|
775
|
+
listener(state);
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
return state;
|
|
779
|
+
},
|
|
780
|
+
subscribe: (listener) => {
|
|
781
|
+
listeners.add(listener);
|
|
782
|
+
return () => listeners.delete(listener);
|
|
783
|
+
},
|
|
784
|
+
subscribeTurnStream: (turnId, listener) => {
|
|
785
|
+
let subscribers = streamSubscribers.get(turnId);
|
|
786
|
+
if (!subscribers) {
|
|
787
|
+
subscribers = new Set();
|
|
788
|
+
streamSubscribers.set(turnId, subscribers);
|
|
789
|
+
}
|
|
790
|
+
subscribers.add(listener);
|
|
791
|
+
const thought = accumulatedTurnStream(state, turnId, "thought");
|
|
792
|
+
if (thought)
|
|
793
|
+
listener({ kind: "thought", text: thought });
|
|
794
|
+
const assistant = accumulatedTurnStream(state, turnId, "assistant");
|
|
795
|
+
if (assistant)
|
|
796
|
+
listener({ kind: "assistant", text: assistant });
|
|
797
|
+
return () => {
|
|
798
|
+
const current = streamSubscribers.get(turnId);
|
|
799
|
+
if (!current)
|
|
800
|
+
return;
|
|
801
|
+
current.delete(listener);
|
|
802
|
+
if (current.size === 0)
|
|
803
|
+
streamSubscribers.delete(turnId);
|
|
804
|
+
};
|
|
805
|
+
},
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
function streamProjection(event) {
|
|
809
|
+
if (event.type === "agent.message_chunk")
|
|
810
|
+
return { kind: "assistant" };
|
|
811
|
+
if (event.type === "agent.thinking") {
|
|
812
|
+
const data = eventData(event);
|
|
813
|
+
return typeof data.text === "string" && data.text.length > 0
|
|
814
|
+
? { kind: "thought" }
|
|
815
|
+
: undefined;
|
|
816
|
+
}
|
|
817
|
+
return undefined;
|
|
818
|
+
}
|
|
819
|
+
function accumulatedTurnStream(state, turnId, kind) {
|
|
820
|
+
if (!turnId)
|
|
821
|
+
return "";
|
|
822
|
+
const turn = state.turns[turnId];
|
|
823
|
+
if (!turn)
|
|
824
|
+
return "";
|
|
825
|
+
return turn.items.flatMap((item) => {
|
|
826
|
+
if (item.kind === "tool")
|
|
827
|
+
return [];
|
|
828
|
+
if (kind === "thought")
|
|
829
|
+
return item.kind === "thinking" ? [item.text] : [];
|
|
830
|
+
return item.kind === "message" && item.role === "assistant" ? [item.text] : [];
|
|
831
|
+
}).join("");
|
|
832
|
+
}
|
|
833
|
+
function opensStreamSegment(state, event, kind) {
|
|
834
|
+
if (!event.turn_id)
|
|
835
|
+
return false;
|
|
836
|
+
const tail = state.turns[event.turn_id]?.items.at(-1);
|
|
837
|
+
if (!tail || tail.kind === "tool")
|
|
838
|
+
return true;
|
|
839
|
+
if (kind === "thought") {
|
|
840
|
+
if (tail.kind !== "thinking")
|
|
841
|
+
return true;
|
|
842
|
+
}
|
|
843
|
+
else if (tail.kind !== "message" || tail.role !== "assistant") {
|
|
844
|
+
return true;
|
|
845
|
+
}
|
|
846
|
+
const data = eventData(event);
|
|
847
|
+
if (typeof data.message_id !== "string" || data.message_id.length === 0) {
|
|
848
|
+
return false;
|
|
849
|
+
}
|
|
850
|
+
return (tail.messageId ?? tail.id) !== data.message_id;
|
|
851
|
+
}
|
|
852
|
+
export * from "./presentation.js";
|
|
853
|
+
//# sourceMappingURL=index.js.map
|