@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,956 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reduce an array of ACP `session.event` payloads into the bubble structure
|
|
3
|
+
* the chat view renders.
|
|
4
|
+
*
|
|
5
|
+
* - `agent_message_chunk` (type=text) → concatenated into a single
|
|
6
|
+
* assistant bubble (one per turn).
|
|
7
|
+
* - `agent_thought_chunk` (type=text) → concatenated into an optional
|
|
8
|
+
* "Thinking" reasoning block above the assistant bubble.
|
|
9
|
+
* - `tool_call` → a new `ToolEntry` with status/title/etc, content[]
|
|
10
|
+
* blocks (diff / terminal / image / content), and locations[].
|
|
11
|
+
* - `tool_call_update` → PATCH onto an existing tool by toolCallId.
|
|
12
|
+
* - `plan` → REPLACE the current plan (no merging).
|
|
13
|
+
* - `available_commands_update` → REPLACE the per-session slash command
|
|
14
|
+
* list. The session store, not reduceTurn, owns this — it's
|
|
15
|
+
* session-scoped, not turn-scoped — but we surface it here so the
|
|
16
|
+
* reducer test can verify the dispatch path.
|
|
17
|
+
* - `current_mode_update` → REPLACE the agent's current mode id.
|
|
18
|
+
* - session-level metadata is handled by SessionStore before this reducer.
|
|
19
|
+
*
|
|
20
|
+
* Designed to be pure: pass an immutable event list, get a snapshot.
|
|
21
|
+
* Re-running on each render is cheap because events list grows linearly
|
|
22
|
+
* with the turn length (a few hundred at most).
|
|
23
|
+
*/
|
|
24
|
+
import { extractAcpSystemNotice } from "./acp-system-notices.js";
|
|
25
|
+
export { extractAcpSystemNotice } from "./acp-system-notices.js";
|
|
26
|
+
/** Internal transport context added when the ACP SDK gives OpenMA a
|
|
27
|
+
* notification-scoped `_meta` alongside `params.update`. The explicit key
|
|
28
|
+
* keeps wire-layer metadata separate from update/harness `_meta` while the
|
|
29
|
+
* existing flat update shape remains compatible with consumers. */
|
|
30
|
+
export const ACP_NOTIFICATION_CONTEXT_KEY = "_openma.acp.notification";
|
|
31
|
+
export function preserveAcpNotificationContext(params) {
|
|
32
|
+
if (!params || typeof params !== "object")
|
|
33
|
+
return params;
|
|
34
|
+
const notification = params;
|
|
35
|
+
if (!("update" in notification))
|
|
36
|
+
return params;
|
|
37
|
+
const update = notification.update;
|
|
38
|
+
if (!update || typeof update !== "object")
|
|
39
|
+
return update;
|
|
40
|
+
const notificationMeta = notification._meta;
|
|
41
|
+
if (!notificationMeta || typeof notificationMeta !== "object")
|
|
42
|
+
return update;
|
|
43
|
+
return {
|
|
44
|
+
...update,
|
|
45
|
+
[ACP_NOTIFICATION_CONTEXT_KEY]: {
|
|
46
|
+
...(typeof notification.sessionId === "string"
|
|
47
|
+
? { session_id: notification.sessionId }
|
|
48
|
+
: {}),
|
|
49
|
+
meta: notificationMeta,
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const SILENT_SESSION_UPDATES = new Set([
|
|
54
|
+
"current_mode_update",
|
|
55
|
+
"config_option_update",
|
|
56
|
+
"session_info_update",
|
|
57
|
+
"usage_update",
|
|
58
|
+
]);
|
|
59
|
+
const ACP_SESSION_UPDATE_TYPES = new Set([
|
|
60
|
+
"user_message_chunk",
|
|
61
|
+
"agent_message_chunk",
|
|
62
|
+
"agent_thought_chunk",
|
|
63
|
+
"tool_call",
|
|
64
|
+
"tool_call_update",
|
|
65
|
+
"plan",
|
|
66
|
+
"plan_update",
|
|
67
|
+
"plan_removed",
|
|
68
|
+
"available_commands_update",
|
|
69
|
+
...SILENT_SESSION_UPDATES,
|
|
70
|
+
]);
|
|
71
|
+
export function sessionUpdateInner(event) {
|
|
72
|
+
const ev = event;
|
|
73
|
+
const update = ev?.update;
|
|
74
|
+
return (update && typeof update === "object" ? update : ev ?? {});
|
|
75
|
+
}
|
|
76
|
+
export function sessionUpdateType(event) {
|
|
77
|
+
const inner = sessionUpdateInner(event);
|
|
78
|
+
const ev = event;
|
|
79
|
+
const rawType = typeof inner.type === "string" ? inner.type : undefined;
|
|
80
|
+
const innerUpdate = typeof inner.sessionUpdate === "string" ? inner.sessionUpdate : undefined;
|
|
81
|
+
const outerUpdate = typeof ev?.sessionUpdate === "string" ? ev.sessionUpdate : undefined;
|
|
82
|
+
return (innerUpdate ??
|
|
83
|
+
outerUpdate ??
|
|
84
|
+
(rawType && ACP_SESSION_UPDATE_TYPES.has(rawType) ? rawType : undefined));
|
|
85
|
+
}
|
|
86
|
+
function stringField(raw, names) {
|
|
87
|
+
for (const name of names) {
|
|
88
|
+
const value = raw[name];
|
|
89
|
+
if (typeof value === "string" && value.length > 0)
|
|
90
|
+
return value;
|
|
91
|
+
}
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
function normalizeToolCall(raw) {
|
|
95
|
+
const meta = objectField(raw._meta);
|
|
96
|
+
const claudeMeta = objectField(meta.claudeCode);
|
|
97
|
+
const toolCallId = raw.toolCallId ?? raw.tool_call_id ?? raw.id;
|
|
98
|
+
const entry = {
|
|
99
|
+
toolCallId: String(toolCallId ?? ""),
|
|
100
|
+
};
|
|
101
|
+
if (Object.keys(meta).length > 0)
|
|
102
|
+
entry.meta = meta;
|
|
103
|
+
const title = raw.title ?? raw.name ?? raw.toolName ?? raw.tool_name;
|
|
104
|
+
if (typeof title === "string")
|
|
105
|
+
entry.title = title;
|
|
106
|
+
if (typeof raw.kind === "string")
|
|
107
|
+
entry.kind = raw.kind;
|
|
108
|
+
if (typeof raw.status === "string")
|
|
109
|
+
entry.status = raw.status;
|
|
110
|
+
const rawInput = raw.rawInput ?? raw.raw_input ?? raw.input ?? raw.args;
|
|
111
|
+
const rawOutput = raw.rawOutput ?? raw.raw_output ?? raw.output ?? raw.result;
|
|
112
|
+
if (rawInput !== undefined && rawInput !== null)
|
|
113
|
+
entry.rawInput = rawInput;
|
|
114
|
+
if (rawOutput !== undefined && rawOutput !== null)
|
|
115
|
+
entry.rawOutput = rawOutput;
|
|
116
|
+
if (rawOutput === undefined || rawOutput === null) {
|
|
117
|
+
const terminalOutput = objectField(meta.terminal_output);
|
|
118
|
+
const terminalOutputDelta = objectField(meta.terminal_output_delta);
|
|
119
|
+
const mcpOutputDelta = objectField(meta.mcp_output_delta);
|
|
120
|
+
const terminalData = stringValue(terminalOutput.data) ?? stringValue(terminalOutputDelta.data);
|
|
121
|
+
const mcpData = stringValue(mcpOutputDelta.data);
|
|
122
|
+
if (terminalData !== undefined) {
|
|
123
|
+
entry.outputDelta = { data: terminalData, separator: "" };
|
|
124
|
+
}
|
|
125
|
+
else if (mcpData !== undefined) {
|
|
126
|
+
entry.outputDelta = { data: mcpData, separator: "\n" };
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (entry.status === undefined) {
|
|
130
|
+
const terminalExit = objectField(meta.terminal_exit);
|
|
131
|
+
const exitCode = terminalExit.exit_code ?? terminalExit.exitCode;
|
|
132
|
+
const signal = terminalExit.signal;
|
|
133
|
+
if (typeof exitCode === "number") {
|
|
134
|
+
entry.status = exitCode === 0 ? "completed" : "failed";
|
|
135
|
+
}
|
|
136
|
+
else if (typeof signal === "string" && signal.length > 0) {
|
|
137
|
+
entry.status = "failed";
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (Array.isArray(raw.content))
|
|
141
|
+
entry.content = raw.content;
|
|
142
|
+
if (Array.isArray(raw.locations))
|
|
143
|
+
entry.locations = raw.locations;
|
|
144
|
+
const toolName = claudeMeta.toolName ?? raw.toolName ?? raw.tool_name ?? raw.name;
|
|
145
|
+
if (typeof toolName === "string")
|
|
146
|
+
entry.toolName = toolName;
|
|
147
|
+
const parentToolUseId = stringValue(claudeMeta.parentToolUseId) ??
|
|
148
|
+
stringValue(raw.parentToolUseId) ??
|
|
149
|
+
stringValue(raw.parent_tool_use_id);
|
|
150
|
+
if (parentToolUseId)
|
|
151
|
+
entry.parentToolUseId = parentToolUseId;
|
|
152
|
+
return entry;
|
|
153
|
+
}
|
|
154
|
+
function normalizeCanonicalToolEvent(event) {
|
|
155
|
+
const type = stringValue(event.type);
|
|
156
|
+
if (type !== "tool.started"
|
|
157
|
+
&& type !== "tool.progress"
|
|
158
|
+
&& type !== "tool.completed"
|
|
159
|
+
&& type !== "tool.failed"
|
|
160
|
+
&& type !== "tool.cancelled")
|
|
161
|
+
return null;
|
|
162
|
+
const data = objectField(event.data);
|
|
163
|
+
const toolCallId = stringField(data, ["tool_call_id", "toolCallId", "id"]);
|
|
164
|
+
if (!toolCallId)
|
|
165
|
+
return null;
|
|
166
|
+
const tool = normalizeToolCall({
|
|
167
|
+
toolCallId,
|
|
168
|
+
...(data.title !== undefined ? { title: data.title } : {}),
|
|
169
|
+
...(data.kind !== undefined ? { kind: data.kind } : {}),
|
|
170
|
+
...(data.status !== undefined ? { status: data.status } : {}),
|
|
171
|
+
...(data.raw_input !== undefined ? { rawInput: data.raw_input } : {}),
|
|
172
|
+
...(data.rawInput !== undefined ? { rawInput: data.rawInput } : {}),
|
|
173
|
+
...(data.raw_output !== undefined ? { rawOutput: data.raw_output } : {}),
|
|
174
|
+
...(data.rawOutput !== undefined ? { rawOutput: data.rawOutput } : {}),
|
|
175
|
+
...(data.raw_output === undefined
|
|
176
|
+
&& data.rawOutput === undefined
|
|
177
|
+
&& typeof data.error === "string"
|
|
178
|
+
? { rawOutput: data.error }
|
|
179
|
+
: {}),
|
|
180
|
+
...(data.content !== undefined ? { content: data.content } : {}),
|
|
181
|
+
...(data.locations !== undefined ? { locations: data.locations } : {}),
|
|
182
|
+
...(data.tool_name !== undefined ? { toolName: data.tool_name } : {}),
|
|
183
|
+
...(data.adapter_meta !== undefined ? { _meta: data.adapter_meta } : {}),
|
|
184
|
+
...(event.parent_id !== undefined ? { parentToolUseId: event.parent_id } : {}),
|
|
185
|
+
});
|
|
186
|
+
if (type === "tool.completed")
|
|
187
|
+
tool.status = "completed";
|
|
188
|
+
if (type === "tool.failed")
|
|
189
|
+
tool.status = "failed";
|
|
190
|
+
if (type === "tool.cancelled")
|
|
191
|
+
tool.status = "cancelled";
|
|
192
|
+
const output = objectField(data.output);
|
|
193
|
+
const outputData = stringValue(output.data);
|
|
194
|
+
if (tool.rawOutput === undefined && outputData !== undefined) {
|
|
195
|
+
tool.outputDelta = {
|
|
196
|
+
data: outputData,
|
|
197
|
+
separator: typeof output.separator === "string"
|
|
198
|
+
? output.separator
|
|
199
|
+
: output.kind === "mcp"
|
|
200
|
+
? "\n"
|
|
201
|
+
: "",
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
return tool;
|
|
205
|
+
}
|
|
206
|
+
function objectField(value) {
|
|
207
|
+
return value && typeof value === "object" && !Array.isArray(value)
|
|
208
|
+
? value
|
|
209
|
+
: {};
|
|
210
|
+
}
|
|
211
|
+
function stringValue(value) {
|
|
212
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
213
|
+
}
|
|
214
|
+
function messageIdFrom(raw) {
|
|
215
|
+
return stringField(raw, ["messageId", "message_id"]);
|
|
216
|
+
}
|
|
217
|
+
function parentToolUseIdFrom(raw) {
|
|
218
|
+
const meta = objectField(raw._meta);
|
|
219
|
+
const claudeMeta = objectField(meta.claudeCode);
|
|
220
|
+
return (stringValue(claudeMeta.parentToolUseId) ??
|
|
221
|
+
stringValue(raw.parentToolUseId) ??
|
|
222
|
+
stringValue(raw.parent_tool_use_id));
|
|
223
|
+
}
|
|
224
|
+
function codexMessagePhase(raw) {
|
|
225
|
+
if (raw.phase === "commentary" || raw.phase === "final_answer") {
|
|
226
|
+
return raw.phase;
|
|
227
|
+
}
|
|
228
|
+
const codex = objectField(objectField(raw._meta).codex);
|
|
229
|
+
return codex.phase === "commentary" || codex.phase === "final_answer"
|
|
230
|
+
? codex.phase
|
|
231
|
+
: undefined;
|
|
232
|
+
}
|
|
233
|
+
function extractContentText(inner) {
|
|
234
|
+
if (typeof inner.text === "string")
|
|
235
|
+
return inner.text;
|
|
236
|
+
if (typeof inner.delta === "string")
|
|
237
|
+
return inner.delta;
|
|
238
|
+
if (typeof inner.content === "string")
|
|
239
|
+
return inner.content;
|
|
240
|
+
const content = inner.content;
|
|
241
|
+
if (typeof content?.text === "string")
|
|
242
|
+
return content.text;
|
|
243
|
+
if (typeof content?.content === "string")
|
|
244
|
+
return content.content;
|
|
245
|
+
if (content?.content && typeof content.content === "object") {
|
|
246
|
+
const nested = content.content;
|
|
247
|
+
if (typeof nested.text === "string")
|
|
248
|
+
return nested.text;
|
|
249
|
+
}
|
|
250
|
+
return undefined;
|
|
251
|
+
}
|
|
252
|
+
function extractTextBlocks(value) {
|
|
253
|
+
if (typeof value === "string")
|
|
254
|
+
return value;
|
|
255
|
+
if (Array.isArray(value)) {
|
|
256
|
+
const text = value
|
|
257
|
+
.map((part) => {
|
|
258
|
+
if (!part || typeof part !== "object")
|
|
259
|
+
return "";
|
|
260
|
+
const block = part;
|
|
261
|
+
if (typeof block.text === "string")
|
|
262
|
+
return block.text;
|
|
263
|
+
if (typeof block.content === "string")
|
|
264
|
+
return block.content;
|
|
265
|
+
return "";
|
|
266
|
+
})
|
|
267
|
+
.join("");
|
|
268
|
+
return text.length > 0 ? text : undefined;
|
|
269
|
+
}
|
|
270
|
+
if (!value || typeof value !== "object")
|
|
271
|
+
return undefined;
|
|
272
|
+
const block = value;
|
|
273
|
+
if (typeof block.text === "string")
|
|
274
|
+
return block.text;
|
|
275
|
+
if (typeof block.content === "string")
|
|
276
|
+
return block.content;
|
|
277
|
+
return undefined;
|
|
278
|
+
}
|
|
279
|
+
function isTransportDiagnosticText(text) {
|
|
280
|
+
return /^Falling back from WebSockets to HTTPS transport\./i.test(text.trim());
|
|
281
|
+
}
|
|
282
|
+
export function sanitizeThoughtText(text) {
|
|
283
|
+
return text.replace(/<!--[\s\S]*?-->/g, "");
|
|
284
|
+
}
|
|
285
|
+
function parsePlanEntries(rawEntries) {
|
|
286
|
+
if (!Array.isArray(rawEntries))
|
|
287
|
+
return [];
|
|
288
|
+
return rawEntries
|
|
289
|
+
.filter((entry) => Boolean(entry) && typeof entry === "object")
|
|
290
|
+
.map((entry) => ({
|
|
291
|
+
id: typeof entry.id === "string" && entry.id.length > 0
|
|
292
|
+
? entry.id
|
|
293
|
+
: undefined,
|
|
294
|
+
content: typeof entry.content === "string" ? entry.content : "",
|
|
295
|
+
priority: entry.priority === "high" ||
|
|
296
|
+
entry.priority === "medium" ||
|
|
297
|
+
entry.priority === "low"
|
|
298
|
+
? entry.priority
|
|
299
|
+
: undefined,
|
|
300
|
+
status: entry.status === "pending" ||
|
|
301
|
+
entry.status === "in_progress" ||
|
|
302
|
+
entry.status === "completed" ||
|
|
303
|
+
entry.status === "cancelled"
|
|
304
|
+
? entry.status
|
|
305
|
+
: "pending",
|
|
306
|
+
}));
|
|
307
|
+
}
|
|
308
|
+
function getEventSummary(event) {
|
|
309
|
+
try {
|
|
310
|
+
return JSON.stringify(event);
|
|
311
|
+
}
|
|
312
|
+
catch {
|
|
313
|
+
return undefined;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
export function parseAcpEvent(event) {
|
|
317
|
+
const eventRecord = objectField(event);
|
|
318
|
+
const isCanonicalOpenMAEvent = eventRecord.schema_version === "oma.event.v1";
|
|
319
|
+
const canonicalTool = isCanonicalOpenMAEvent
|
|
320
|
+
? normalizeCanonicalToolEvent(eventRecord)
|
|
321
|
+
: null;
|
|
322
|
+
if (canonicalTool)
|
|
323
|
+
return { kind: "tool_call", tool: canonicalTool, event };
|
|
324
|
+
const canonicalType = isCanonicalOpenMAEvent
|
|
325
|
+
? stringValue(eventRecord.type)
|
|
326
|
+
: undefined;
|
|
327
|
+
const canonicalData = objectField(eventRecord.data);
|
|
328
|
+
if (canonicalType === "agent.message" || canonicalType === "agent.message_chunk") {
|
|
329
|
+
const text = stringValue(canonicalData.text)
|
|
330
|
+
?? extractTextBlocks(canonicalData.content);
|
|
331
|
+
return text
|
|
332
|
+
? {
|
|
333
|
+
kind: "text",
|
|
334
|
+
text,
|
|
335
|
+
messageId: stringField(canonicalData, ["message_id", "messageId"]),
|
|
336
|
+
...(canonicalData.phase === "commentary"
|
|
337
|
+
|| canonicalData.phase === "final_answer"
|
|
338
|
+
? { phase: canonicalData.phase }
|
|
339
|
+
: {}),
|
|
340
|
+
parentToolUseId: stringValue(eventRecord.parent_id),
|
|
341
|
+
event,
|
|
342
|
+
}
|
|
343
|
+
: { kind: "silent", event };
|
|
344
|
+
}
|
|
345
|
+
if (canonicalType === "agent.thinking") {
|
|
346
|
+
const text = stringValue(canonicalData.text)
|
|
347
|
+
?? extractTextBlocks(canonicalData.content);
|
|
348
|
+
return text
|
|
349
|
+
? {
|
|
350
|
+
kind: "thought",
|
|
351
|
+
text: sanitizeThoughtText(text),
|
|
352
|
+
messageId: stringField(canonicalData, ["message_id", "messageId"]),
|
|
353
|
+
parentToolUseId: stringValue(eventRecord.parent_id),
|
|
354
|
+
event,
|
|
355
|
+
}
|
|
356
|
+
: { kind: "silent", event };
|
|
357
|
+
}
|
|
358
|
+
if (canonicalType === "plan.updated") {
|
|
359
|
+
if (Array.isArray(canonicalData.entries)) {
|
|
360
|
+
const document = objectField(canonicalData.document);
|
|
361
|
+
const markdown = stringValue(document.markdown)
|
|
362
|
+
?? stringValue(canonicalData.markdown);
|
|
363
|
+
const uri = stringValue(document.uri) ?? stringValue(canonicalData.uri);
|
|
364
|
+
const parsedDocument = markdown
|
|
365
|
+
? {
|
|
366
|
+
...(stringValue(document.id) ? { id: String(document.id) } : {}),
|
|
367
|
+
...(stringValue(document.title) ? { title: String(document.title) } : {}),
|
|
368
|
+
markdown,
|
|
369
|
+
}
|
|
370
|
+
: uri
|
|
371
|
+
? {
|
|
372
|
+
...(stringValue(document.id) ? { id: String(document.id) } : {}),
|
|
373
|
+
...(stringValue(document.title) ? { title: String(document.title) } : {}),
|
|
374
|
+
type: "file",
|
|
375
|
+
uri,
|
|
376
|
+
}
|
|
377
|
+
: undefined;
|
|
378
|
+
return {
|
|
379
|
+
kind: "plan",
|
|
380
|
+
planId: stringField(canonicalData, ["plan_id", "planId", "id"]),
|
|
381
|
+
updateMode: canonicalData.update_mode === "merge" ? "merge" : "replace",
|
|
382
|
+
plan: parsePlanEntries(canonicalData.entries),
|
|
383
|
+
...(parsedDocument ? { document: parsedDocument } : {}),
|
|
384
|
+
event,
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
const document = objectField(canonicalData.document);
|
|
388
|
+
const markdown = stringValue(document.markdown)
|
|
389
|
+
?? stringValue(canonicalData.markdown);
|
|
390
|
+
if (markdown) {
|
|
391
|
+
return {
|
|
392
|
+
kind: "plan_document",
|
|
393
|
+
document: {
|
|
394
|
+
...(stringValue(document.id) ? { id: String(document.id) } : {}),
|
|
395
|
+
...(stringValue(document.title) ? { title: String(document.title) } : {}),
|
|
396
|
+
markdown,
|
|
397
|
+
},
|
|
398
|
+
event,
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
const uri = stringValue(document.uri) ?? stringValue(canonicalData.uri);
|
|
402
|
+
if (uri) {
|
|
403
|
+
return {
|
|
404
|
+
kind: "plan_document",
|
|
405
|
+
document: {
|
|
406
|
+
...(stringValue(document.id) ? { id: String(document.id) } : {}),
|
|
407
|
+
...(stringValue(document.title) ? { title: String(document.title) } : {}),
|
|
408
|
+
type: "file",
|
|
409
|
+
uri,
|
|
410
|
+
},
|
|
411
|
+
event,
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
if (canonicalType === "plan.completed" || canonicalType === "plan.removed") {
|
|
416
|
+
return {
|
|
417
|
+
kind: "plan_removed",
|
|
418
|
+
planId: stringField(canonicalData, ["plan_id", "planId", "id"]),
|
|
419
|
+
event,
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
const inner = sessionUpdateInner(event);
|
|
423
|
+
const update = sessionUpdateType(event);
|
|
424
|
+
if (!update) {
|
|
425
|
+
if (inner.type === "agent.message_chunk" && typeof inner.delta === "string") {
|
|
426
|
+
return inner.delta.length > 0
|
|
427
|
+
? {
|
|
428
|
+
kind: "text",
|
|
429
|
+
text: inner.delta,
|
|
430
|
+
phase: codexMessagePhase(inner),
|
|
431
|
+
messageId: messageIdFrom(inner),
|
|
432
|
+
parentToolUseId: parentToolUseIdFrom(inner),
|
|
433
|
+
event,
|
|
434
|
+
}
|
|
435
|
+
: { kind: "silent", event };
|
|
436
|
+
}
|
|
437
|
+
if (inner.type === "agent.message") {
|
|
438
|
+
const text = extractTextBlocks(inner.content);
|
|
439
|
+
return typeof text === "string" && text.length > 0
|
|
440
|
+
? {
|
|
441
|
+
kind: "text",
|
|
442
|
+
text,
|
|
443
|
+
phase: codexMessagePhase(inner),
|
|
444
|
+
messageId: messageIdFrom(inner),
|
|
445
|
+
parentToolUseId: parentToolUseIdFrom(inner),
|
|
446
|
+
event,
|
|
447
|
+
}
|
|
448
|
+
: { kind: "silent", event };
|
|
449
|
+
}
|
|
450
|
+
if (inner.type === "agent.thinking_chunk" && typeof inner.delta === "string") {
|
|
451
|
+
const text = sanitizeThoughtText(inner.delta);
|
|
452
|
+
return inner.delta.length > 0
|
|
453
|
+
? text.length > 0
|
|
454
|
+
? {
|
|
455
|
+
kind: "thought",
|
|
456
|
+
text,
|
|
457
|
+
messageId: messageIdFrom(inner),
|
|
458
|
+
parentToolUseId: parentToolUseIdFrom(inner),
|
|
459
|
+
event,
|
|
460
|
+
}
|
|
461
|
+
: { kind: "silent", event }
|
|
462
|
+
: { kind: "silent", event };
|
|
463
|
+
}
|
|
464
|
+
if (inner.type === "agent.thinking") {
|
|
465
|
+
const rawText = typeof inner.text === "string" ? inner.text : extractTextBlocks(inner.content);
|
|
466
|
+
const text = typeof rawText === "string" ? sanitizeThoughtText(rawText) : rawText;
|
|
467
|
+
return typeof text === "string" && text.length > 0
|
|
468
|
+
? {
|
|
469
|
+
kind: "thought",
|
|
470
|
+
text,
|
|
471
|
+
messageId: messageIdFrom(inner),
|
|
472
|
+
parentToolUseId: parentToolUseIdFrom(inner),
|
|
473
|
+
event,
|
|
474
|
+
}
|
|
475
|
+
: { kind: "silent", event };
|
|
476
|
+
}
|
|
477
|
+
if (inner.type === "agent.tool_use" && typeof inner.id === "string") {
|
|
478
|
+
return {
|
|
479
|
+
kind: "tool_call",
|
|
480
|
+
tool: {
|
|
481
|
+
toolCallId: inner.id,
|
|
482
|
+
title: typeof inner.name === "string" ? inner.name : "tool",
|
|
483
|
+
toolName: typeof inner.name === "string" ? inner.name : undefined,
|
|
484
|
+
rawInput: inner.input ?? {},
|
|
485
|
+
status: "pending",
|
|
486
|
+
},
|
|
487
|
+
event,
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
if (inner.type === "agent.tool_result" && typeof inner.tool_use_id === "string") {
|
|
491
|
+
return {
|
|
492
|
+
kind: "tool_call",
|
|
493
|
+
tool: {
|
|
494
|
+
toolCallId: inner.tool_use_id,
|
|
495
|
+
rawOutput: extractTextBlocks(inner.content) ?? inner.content,
|
|
496
|
+
status: inner.is_error ? "failed" : "completed",
|
|
497
|
+
},
|
|
498
|
+
event,
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
if (inner.type === "agent.message_stream_start" ||
|
|
502
|
+
inner.type === "agent.message_stream_end" ||
|
|
503
|
+
inner.type === "agent.thinking_stream_start" ||
|
|
504
|
+
inner.type === "agent.thinking_stream_end" ||
|
|
505
|
+
inner.type === "agent.tool_use_input_stream_start" ||
|
|
506
|
+
inner.type === "agent.tool_use_input_chunk" ||
|
|
507
|
+
inner.type === "agent.tool_use_input_stream_end" ||
|
|
508
|
+
inner.type === "session.status_running" ||
|
|
509
|
+
inner.type === "session.status_idle" ||
|
|
510
|
+
inner.type === "session.warning") {
|
|
511
|
+
return { kind: "silent", event };
|
|
512
|
+
}
|
|
513
|
+
if (inner.type === "session.error" && typeof inner.error === "string" && inner.error.length > 0) {
|
|
514
|
+
return { kind: "note", note: inner.error, event };
|
|
515
|
+
}
|
|
516
|
+
if (inner.type === "text" && typeof inner.text === "string" && inner.text.length > 0) {
|
|
517
|
+
return {
|
|
518
|
+
kind: "text",
|
|
519
|
+
text: inner.text,
|
|
520
|
+
phase: codexMessagePhase(inner),
|
|
521
|
+
messageId: messageIdFrom(inner),
|
|
522
|
+
parentToolUseId: parentToolUseIdFrom(inner),
|
|
523
|
+
event,
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
if (inner.type === "thought" && typeof inner.text === "string" && inner.text.length > 0) {
|
|
527
|
+
const text = sanitizeThoughtText(inner.text);
|
|
528
|
+
return text.length > 0
|
|
529
|
+
? {
|
|
530
|
+
kind: "thought",
|
|
531
|
+
text,
|
|
532
|
+
messageId: messageIdFrom(inner),
|
|
533
|
+
parentToolUseId: parentToolUseIdFrom(inner),
|
|
534
|
+
event,
|
|
535
|
+
}
|
|
536
|
+
: { kind: "silent", event };
|
|
537
|
+
}
|
|
538
|
+
if (inner.type === "requestPermission") {
|
|
539
|
+
// Compatibility for sessions persisted before approval requests moved
|
|
540
|
+
// exclusively onto the broker channel. Approval is transient UI state,
|
|
541
|
+
// never a completed tool/activity row.
|
|
542
|
+
return { kind: "silent", event };
|
|
543
|
+
}
|
|
544
|
+
if ((inner.type === "tool_call" || inner.type === "tool_call_update") &&
|
|
545
|
+
(typeof inner.toolCallId === "string" ||
|
|
546
|
+
typeof inner.tool_call_id === "string" ||
|
|
547
|
+
typeof inner.id === "string")) {
|
|
548
|
+
return { kind: "tool_call", tool: normalizeToolCall(inner), event };
|
|
549
|
+
}
|
|
550
|
+
if (inner.type === "promptError" && typeof inner.error === "string" && inner.error.length > 0) {
|
|
551
|
+
return { kind: "text", text: inner.error, event };
|
|
552
|
+
}
|
|
553
|
+
if (inner.type === "promptComplete") {
|
|
554
|
+
return { kind: "note", note: "Turn complete", event };
|
|
555
|
+
}
|
|
556
|
+
return { kind: "raw", event };
|
|
557
|
+
}
|
|
558
|
+
if (update === "agent_message_chunk" || update === "agent_thought_chunk") {
|
|
559
|
+
const text = extractContentText(inner);
|
|
560
|
+
if (typeof text !== "string" || text.length === 0)
|
|
561
|
+
return { kind: "silent", event };
|
|
562
|
+
const notice = update === "agent_message_chunk" ? extractAcpSystemNotice(event) : null;
|
|
563
|
+
if (notice)
|
|
564
|
+
return { kind: "notice", notice: notice.message, event };
|
|
565
|
+
if (update === "agent_message_chunk" && isTransportDiagnosticText(text)) {
|
|
566
|
+
return { kind: "silent", event };
|
|
567
|
+
}
|
|
568
|
+
const visibleText = update === "agent_thought_chunk" ? sanitizeThoughtText(text) : text;
|
|
569
|
+
if (visibleText.length === 0)
|
|
570
|
+
return { kind: "silent", event };
|
|
571
|
+
return {
|
|
572
|
+
kind: update === "agent_thought_chunk" ? "thought" : "text",
|
|
573
|
+
text: visibleText,
|
|
574
|
+
...(update === "agent_thought_chunk"
|
|
575
|
+
? {
|
|
576
|
+
messageId: messageIdFrom(inner),
|
|
577
|
+
parentToolUseId: parentToolUseIdFrom(inner),
|
|
578
|
+
}
|
|
579
|
+
: {
|
|
580
|
+
phase: codexMessagePhase(inner),
|
|
581
|
+
messageId: messageIdFrom(inner),
|
|
582
|
+
parentToolUseId: parentToolUseIdFrom(inner),
|
|
583
|
+
}),
|
|
584
|
+
event,
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
if (update === "user_message_chunk")
|
|
588
|
+
return { kind: "silent", event };
|
|
589
|
+
if (update === "tool_call" || update === "tool_call_update") {
|
|
590
|
+
const toolCallId = stringField(inner, ["toolCallId", "tool_call_id", "id"]);
|
|
591
|
+
if (!toolCallId)
|
|
592
|
+
return { kind: "raw", event };
|
|
593
|
+
return { kind: "tool_call", tool: normalizeToolCall(inner), event };
|
|
594
|
+
}
|
|
595
|
+
if (update === "plan") {
|
|
596
|
+
const rawEntries = Array.isArray(inner.entries)
|
|
597
|
+
? inner.entries
|
|
598
|
+
: inner.plan &&
|
|
599
|
+
typeof inner.plan === "object" &&
|
|
600
|
+
Array.isArray(inner.plan.entries)
|
|
601
|
+
? inner.plan.entries
|
|
602
|
+
: [];
|
|
603
|
+
return { kind: "plan", plan: parsePlanEntries(rawEntries), event };
|
|
604
|
+
}
|
|
605
|
+
if (update === "plan_update") {
|
|
606
|
+
const plan = inner.plan && typeof inner.plan === "object"
|
|
607
|
+
? inner.plan
|
|
608
|
+
: inner;
|
|
609
|
+
const planId = stringField(plan, ["planId", "plan_id", "id"]);
|
|
610
|
+
const content = plan.content && typeof plan.content === "object"
|
|
611
|
+
? plan.content
|
|
612
|
+
: plan;
|
|
613
|
+
if (Array.isArray(content.entries)) {
|
|
614
|
+
return {
|
|
615
|
+
kind: "plan",
|
|
616
|
+
...(planId ? { planId } : {}),
|
|
617
|
+
plan: parsePlanEntries(content.entries),
|
|
618
|
+
event,
|
|
619
|
+
};
|
|
620
|
+
}
|
|
621
|
+
const markdown = typeof content.markdown === "string"
|
|
622
|
+
? content.markdown
|
|
623
|
+
: typeof content.content === "string"
|
|
624
|
+
? content.content
|
|
625
|
+
: undefined;
|
|
626
|
+
if (markdown) {
|
|
627
|
+
return {
|
|
628
|
+
kind: "plan_document",
|
|
629
|
+
document: {
|
|
630
|
+
...(planId ? { id: planId } : {}),
|
|
631
|
+
...(typeof plan.title === "string" ? { title: plan.title } : {}),
|
|
632
|
+
markdown,
|
|
633
|
+
},
|
|
634
|
+
event,
|
|
635
|
+
};
|
|
636
|
+
}
|
|
637
|
+
const uri = stringValue(plan.uri) ?? stringValue(content.uri);
|
|
638
|
+
if (uri) {
|
|
639
|
+
return {
|
|
640
|
+
kind: "plan_document",
|
|
641
|
+
document: {
|
|
642
|
+
...(planId ? { id: planId } : {}),
|
|
643
|
+
...(typeof plan.title === "string" ? { title: plan.title } : {}),
|
|
644
|
+
type: "file",
|
|
645
|
+
uri,
|
|
646
|
+
},
|
|
647
|
+
event,
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
const summary = getEventSummary(inner);
|
|
651
|
+
return {
|
|
652
|
+
kind: "note",
|
|
653
|
+
note: summary ? `Plan updated: ${summary}` : "Plan updated",
|
|
654
|
+
event,
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
if (update === "plan_removed") {
|
|
658
|
+
return {
|
|
659
|
+
kind: "plan_removed",
|
|
660
|
+
planId: stringField(inner, ["planId", "plan_id", "id"]),
|
|
661
|
+
event,
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
if (update === "available_commands_update") {
|
|
665
|
+
const availableCommands = Array.isArray(inner.availableCommands)
|
|
666
|
+
? inner.availableCommands
|
|
667
|
+
: Array.isArray(inner.available_commands)
|
|
668
|
+
? inner.available_commands
|
|
669
|
+
: null;
|
|
670
|
+
if (!availableCommands)
|
|
671
|
+
return { kind: "silent", event };
|
|
672
|
+
return {
|
|
673
|
+
kind: "commands",
|
|
674
|
+
commands: availableCommands,
|
|
675
|
+
event,
|
|
676
|
+
};
|
|
677
|
+
}
|
|
678
|
+
if (SILENT_SESSION_UPDATES.has(update))
|
|
679
|
+
return { kind: "silent", event };
|
|
680
|
+
return { kind: "raw", event };
|
|
681
|
+
}
|
|
682
|
+
function isEmptyObject(value) {
|
|
683
|
+
if (value === undefined || value === null)
|
|
684
|
+
return true;
|
|
685
|
+
if (typeof value !== "object")
|
|
686
|
+
return false;
|
|
687
|
+
return Object.keys(value).length === 0;
|
|
688
|
+
}
|
|
689
|
+
const MIN_OVERLAP = 8;
|
|
690
|
+
const SNAPSHOT_HEAD_PROBE = 16;
|
|
691
|
+
export function mergeStreamingText(accumulated, incoming) {
|
|
692
|
+
if (!accumulated)
|
|
693
|
+
return incoming;
|
|
694
|
+
if (!incoming)
|
|
695
|
+
return accumulated;
|
|
696
|
+
if (incoming === accumulated)
|
|
697
|
+
return accumulated;
|
|
698
|
+
if (incoming.startsWith(accumulated))
|
|
699
|
+
return incoming;
|
|
700
|
+
if (accumulated.endsWith(incoming))
|
|
701
|
+
return accumulated;
|
|
702
|
+
if (incoming.length >= accumulated.length) {
|
|
703
|
+
const head = Math.min(SNAPSHOT_HEAD_PROBE, accumulated.length);
|
|
704
|
+
if (head > 0 && incoming.slice(0, head) === accumulated.slice(0, head)) {
|
|
705
|
+
return incoming;
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
const maxOverlap = Math.min(accumulated.length, incoming.length);
|
|
709
|
+
for (let k = maxOverlap; k >= MIN_OVERLAP; k--) {
|
|
710
|
+
if (accumulated.endsWith(incoming.slice(0, k))) {
|
|
711
|
+
return accumulated + incoming.slice(k);
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
return accumulated + incoming;
|
|
715
|
+
}
|
|
716
|
+
export function reduceTurn(events) {
|
|
717
|
+
const out = {
|
|
718
|
+
thoughtText: "",
|
|
719
|
+
currentThoughtText: "",
|
|
720
|
+
assistantText: "",
|
|
721
|
+
tools: [],
|
|
722
|
+
plan: [],
|
|
723
|
+
notes: [],
|
|
724
|
+
timeline: [],
|
|
725
|
+
};
|
|
726
|
+
const toolById = new Map();
|
|
727
|
+
let toolsOrder = [];
|
|
728
|
+
// Running buffer for the current assistant_text segment. Flushed into
|
|
729
|
+
// out.timeline when a tool_call event arrives (which breaks the run)
|
|
730
|
+
// or at end-of-stream. Same chunk concatenation we used to do into
|
|
731
|
+
// assistantText, but segment-aware.
|
|
732
|
+
let textBuf = "";
|
|
733
|
+
let textPhase;
|
|
734
|
+
const flushText = () => {
|
|
735
|
+
if (textBuf) {
|
|
736
|
+
out.timeline.push({
|
|
737
|
+
kind: "assistant_text",
|
|
738
|
+
text: textBuf,
|
|
739
|
+
...(textPhase ? { phase: textPhase } : {}),
|
|
740
|
+
});
|
|
741
|
+
textBuf = "";
|
|
742
|
+
textPhase = undefined;
|
|
743
|
+
}
|
|
744
|
+
};
|
|
745
|
+
const thoughtIndexByMessageId = new Map();
|
|
746
|
+
let currentPlanId;
|
|
747
|
+
let anonymousThoughtIndex;
|
|
748
|
+
const appendThought = (parsed) => {
|
|
749
|
+
const id = parsed.messageId;
|
|
750
|
+
const existingIndex = id
|
|
751
|
+
? thoughtIndexByMessageId.get(id)
|
|
752
|
+
: anonymousThoughtIndex;
|
|
753
|
+
if (existingIndex !== undefined) {
|
|
754
|
+
const existing = out.timeline[existingIndex];
|
|
755
|
+
if (existing?.kind === "thought") {
|
|
756
|
+
existing.text = mergeStreamingText(existing.text, parsed.text);
|
|
757
|
+
out.currentThoughtText = latestThoughtSegment(existing.text);
|
|
758
|
+
return;
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
flushText();
|
|
762
|
+
const item = {
|
|
763
|
+
kind: "thought",
|
|
764
|
+
text: parsed.text,
|
|
765
|
+
...(id ? { messageId: id } : {}),
|
|
766
|
+
};
|
|
767
|
+
const index = out.timeline.push(item) - 1;
|
|
768
|
+
if (id)
|
|
769
|
+
thoughtIndexByMessageId.set(id, index);
|
|
770
|
+
else
|
|
771
|
+
anonymousThoughtIndex = index;
|
|
772
|
+
out.currentThoughtText = latestThoughtSegment(parsed.text);
|
|
773
|
+
};
|
|
774
|
+
const appendOutputDelta = (current, delta) => {
|
|
775
|
+
if (typeof current !== "string" || current.length === 0)
|
|
776
|
+
return delta.data;
|
|
777
|
+
if (delta.separator.length === 0
|
|
778
|
+
|| current.endsWith(delta.separator)
|
|
779
|
+
|| delta.data.startsWith(delta.separator)) {
|
|
780
|
+
return current + delta.data;
|
|
781
|
+
}
|
|
782
|
+
return current + delta.separator + delta.data;
|
|
783
|
+
};
|
|
784
|
+
const mergePlanEntries = (current, incoming) => {
|
|
785
|
+
const next = [...current];
|
|
786
|
+
const indexById = new Map();
|
|
787
|
+
next.forEach((entry, index) => {
|
|
788
|
+
if (entry.id)
|
|
789
|
+
indexById.set(entry.id, index);
|
|
790
|
+
});
|
|
791
|
+
for (const entry of incoming) {
|
|
792
|
+
const existingIndex = entry.id ? indexById.get(entry.id) : undefined;
|
|
793
|
+
if (existingIndex === undefined) {
|
|
794
|
+
if (entry.id)
|
|
795
|
+
indexById.set(entry.id, next.length);
|
|
796
|
+
next.push(entry);
|
|
797
|
+
}
|
|
798
|
+
else {
|
|
799
|
+
next[existingIndex] = entry;
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
return next;
|
|
803
|
+
};
|
|
804
|
+
const upsertTool = (incoming) => {
|
|
805
|
+
const id = incoming.toolCallId;
|
|
806
|
+
if (!id)
|
|
807
|
+
return;
|
|
808
|
+
const prev = toolById.get(id);
|
|
809
|
+
if (!prev) {
|
|
810
|
+
const entry = {
|
|
811
|
+
toolCallId: id,
|
|
812
|
+
title: incoming.title,
|
|
813
|
+
kind: incoming.kind,
|
|
814
|
+
status: incoming.status,
|
|
815
|
+
rawInput: incoming.rawInput,
|
|
816
|
+
rawOutput: incoming.rawOutput !== undefined
|
|
817
|
+
? incoming.rawOutput
|
|
818
|
+
: incoming.outputDelta?.data,
|
|
819
|
+
toolName: incoming.toolName,
|
|
820
|
+
meta: incoming.meta,
|
|
821
|
+
parentToolUseId: incoming.parentToolUseId,
|
|
822
|
+
content: incoming.content,
|
|
823
|
+
locations: incoming.locations,
|
|
824
|
+
};
|
|
825
|
+
if (entry.status === "in_progress" &&
|
|
826
|
+
entry.content?.some((b) => b.type === "content" && b.content?.type === "image")) {
|
|
827
|
+
entry.status = "completed";
|
|
828
|
+
}
|
|
829
|
+
toolById.set(id, entry);
|
|
830
|
+
if (!toolsOrder.includes(id)) {
|
|
831
|
+
toolsOrder.push(id);
|
|
832
|
+
flushText();
|
|
833
|
+
out.timeline.push({ kind: "tool", toolCallId: id });
|
|
834
|
+
}
|
|
835
|
+
return;
|
|
836
|
+
}
|
|
837
|
+
if (incoming.title !== undefined)
|
|
838
|
+
prev.title = incoming.title;
|
|
839
|
+
if (incoming.kind !== undefined)
|
|
840
|
+
prev.kind = incoming.kind;
|
|
841
|
+
if (incoming.status !== undefined)
|
|
842
|
+
prev.status = incoming.status;
|
|
843
|
+
if (incoming.toolName !== undefined)
|
|
844
|
+
prev.toolName = incoming.toolName;
|
|
845
|
+
if (incoming.meta !== undefined) {
|
|
846
|
+
prev.meta = {
|
|
847
|
+
...(prev.meta ?? {}),
|
|
848
|
+
...incoming.meta,
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
if (incoming.parentToolUseId !== undefined) {
|
|
852
|
+
prev.parentToolUseId = incoming.parentToolUseId;
|
|
853
|
+
}
|
|
854
|
+
if (incoming.rawInput !== undefined) {
|
|
855
|
+
const incEmpty = isEmptyObject(incoming.rawInput);
|
|
856
|
+
const prevHasContent = !isEmptyObject(prev.rawInput);
|
|
857
|
+
if (!(incEmpty && prevHasContent))
|
|
858
|
+
prev.rawInput = incoming.rawInput;
|
|
859
|
+
}
|
|
860
|
+
if (incoming.rawOutput !== undefined) {
|
|
861
|
+
// A native ACP rawOutput is a complete snapshot and therefore replaces
|
|
862
|
+
// any adapter deltas accumulated before it.
|
|
863
|
+
prev.rawOutput = incoming.rawOutput;
|
|
864
|
+
}
|
|
865
|
+
else if (incoming.outputDelta !== undefined) {
|
|
866
|
+
prev.rawOutput = appendOutputDelta(prev.rawOutput, incoming.outputDelta);
|
|
867
|
+
}
|
|
868
|
+
if (incoming.content !== undefined)
|
|
869
|
+
prev.content = incoming.content;
|
|
870
|
+
if (incoming.locations !== undefined)
|
|
871
|
+
prev.locations = incoming.locations;
|
|
872
|
+
if (prev.status === "in_progress" &&
|
|
873
|
+
prev.content?.some((b) => b.type === "content" && b.content?.type === "image")) {
|
|
874
|
+
prev.status = "completed";
|
|
875
|
+
}
|
|
876
|
+
};
|
|
877
|
+
for (const ev of events) {
|
|
878
|
+
const parsed = parseAcpEvent(ev.payload);
|
|
879
|
+
switch (parsed.kind) {
|
|
880
|
+
case "thought":
|
|
881
|
+
out.thoughtText = mergeStreamingText(out.thoughtText, parsed.text);
|
|
882
|
+
appendThought(parsed);
|
|
883
|
+
break;
|
|
884
|
+
case "text":
|
|
885
|
+
out.currentThoughtText = "";
|
|
886
|
+
if (textBuf && textPhase !== parsed.phase)
|
|
887
|
+
flushText();
|
|
888
|
+
textPhase = parsed.phase;
|
|
889
|
+
textBuf = mergeStreamingText(textBuf, parsed.text);
|
|
890
|
+
break;
|
|
891
|
+
case "tool_call":
|
|
892
|
+
out.currentThoughtText = "";
|
|
893
|
+
upsertTool(parsed.tool);
|
|
894
|
+
break;
|
|
895
|
+
case "plan":
|
|
896
|
+
out.plan = parsed.updateMode === "merge"
|
|
897
|
+
&& (currentPlanId === undefined
|
|
898
|
+
|| parsed.planId === undefined
|
|
899
|
+
|| parsed.planId === currentPlanId)
|
|
900
|
+
? mergePlanEntries(out.plan, parsed.plan)
|
|
901
|
+
: parsed.plan;
|
|
902
|
+
if (parsed.document)
|
|
903
|
+
out.planDocument = parsed.document;
|
|
904
|
+
currentPlanId = parsed.planId;
|
|
905
|
+
break;
|
|
906
|
+
case "plan_document":
|
|
907
|
+
out.planDocument = parsed.document;
|
|
908
|
+
if (parsed.document)
|
|
909
|
+
currentPlanId = parsed.document.id;
|
|
910
|
+
break;
|
|
911
|
+
case "plan_removed":
|
|
912
|
+
if (parsed.planId === undefined || parsed.planId === currentPlanId) {
|
|
913
|
+
out.plan = [];
|
|
914
|
+
out.planDocument = undefined;
|
|
915
|
+
currentPlanId = undefined;
|
|
916
|
+
}
|
|
917
|
+
break;
|
|
918
|
+
case "note":
|
|
919
|
+
out.notes.push(parsed.note);
|
|
920
|
+
break;
|
|
921
|
+
case "commands":
|
|
922
|
+
case "notice":
|
|
923
|
+
case "silent":
|
|
924
|
+
break;
|
|
925
|
+
case "raw":
|
|
926
|
+
// Drop raw events from the primary chat surface. They are still
|
|
927
|
+
// available in the persisted event stream for debugging.
|
|
928
|
+
break;
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
// Flush any trailing assistant text so the closing message segment
|
|
932
|
+
// makes it into the timeline.
|
|
933
|
+
flushText();
|
|
934
|
+
out.tools = toolsOrder
|
|
935
|
+
.map((id) => toolById.get(id))
|
|
936
|
+
.filter((e) => !!e);
|
|
937
|
+
// For back-compat with code still reading TurnRender.assistantText —
|
|
938
|
+
// the streaming track and a few legacy spots — concatenate the segments.
|
|
939
|
+
out.assistantText = out.timeline
|
|
940
|
+
.filter((t) => t.kind === "assistant_text")
|
|
941
|
+
.map((t) => t.text)
|
|
942
|
+
.join("");
|
|
943
|
+
return out;
|
|
944
|
+
}
|
|
945
|
+
export function latestThoughtSegment(text) {
|
|
946
|
+
if (/\n{2,}\s*$/.test(text))
|
|
947
|
+
return "";
|
|
948
|
+
const segments = text
|
|
949
|
+
.split(/\n{2,}/)
|
|
950
|
+
.map((segment) => segment.trim())
|
|
951
|
+
.filter(Boolean);
|
|
952
|
+
return segments.at(-1) ?? "";
|
|
953
|
+
}
|
|
954
|
+
/** @deprecated Use @openma/common/protocol/acp for the SDK codec. */
|
|
955
|
+
export * from "../protocol/acp/index.js";
|
|
956
|
+
//# sourceMappingURL=acp.js.map
|