@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.
Files changed (328) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +391 -2
  3. package/dist/acp-artifacts/binary.d.ts +35 -0
  4. package/dist/acp-artifacts/binary.d.ts.map +1 -0
  5. package/dist/acp-artifacts/binary.js +120 -0
  6. package/dist/acp-artifacts/binary.js.map +1 -0
  7. package/dist/acp-artifacts/index.d.ts +7 -0
  8. package/dist/acp-artifacts/index.d.ts.map +1 -0
  9. package/dist/acp-artifacts/index.js +7 -0
  10. package/dist/acp-artifacts/index.js.map +1 -0
  11. package/dist/acp-artifacts/node-abi.d.ts +3 -0
  12. package/dist/acp-artifacts/node-abi.d.ts.map +1 -0
  13. package/dist/acp-artifacts/node-abi.js +17 -0
  14. package/dist/acp-artifacts/node-abi.js.map +1 -0
  15. package/dist/acp-artifacts/npm-cli.d.ts +3 -0
  16. package/dist/acp-artifacts/npm-cli.d.ts.map +1 -0
  17. package/dist/acp-artifacts/npm-cli.js +9 -0
  18. package/dist/acp-artifacts/npm-cli.js.map +1 -0
  19. package/dist/acp-artifacts/npm.d.ts +37 -0
  20. package/dist/acp-artifacts/npm.d.ts.map +1 -0
  21. package/dist/acp-artifacts/npm.js +167 -0
  22. package/dist/acp-artifacts/npm.js.map +1 -0
  23. package/dist/acp-artifacts/registry.d.ts +45 -0
  24. package/dist/acp-artifacts/registry.d.ts.map +1 -0
  25. package/dist/acp-artifacts/registry.js +206 -0
  26. package/dist/acp-artifacts/registry.js.map +1 -0
  27. package/dist/acp-artifacts/shared.d.ts +45 -0
  28. package/dist/acp-artifacts/shared.d.ts.map +1 -0
  29. package/dist/acp-artifacts/shared.js +157 -0
  30. package/dist/acp-artifacts/shared.js.map +1 -0
  31. package/dist/acp-artifacts/uvx.d.ts +32 -0
  32. package/dist/acp-artifacts/uvx.d.ts.map +1 -0
  33. package/dist/acp-artifacts/uvx.js +95 -0
  34. package/dist/acp-artifacts/uvx.js.map +1 -0
  35. package/dist/acp-fork/index.d.ts +51 -0
  36. package/dist/acp-fork/index.d.ts.map +1 -0
  37. package/dist/acp-fork/index.js +116 -0
  38. package/dist/acp-fork/index.js.map +1 -0
  39. package/dist/acp-harnesses/agent-setup.d.ts +118 -0
  40. package/dist/acp-harnesses/agent-setup.d.ts.map +1 -0
  41. package/dist/acp-harnesses/agent-setup.js +717 -0
  42. package/dist/acp-harnesses/agent-setup.js.map +1 -0
  43. package/dist/acp-harnesses/custom-agents.d.ts +81 -0
  44. package/dist/acp-harnesses/custom-agents.d.ts.map +1 -0
  45. package/dist/acp-harnesses/custom-agents.js +361 -0
  46. package/dist/acp-harnesses/custom-agents.js.map +1 -0
  47. package/dist/acp-harnesses/headless-launch.d.ts +34 -0
  48. package/dist/acp-harnesses/headless-launch.d.ts.map +1 -0
  49. package/dist/acp-harnesses/headless-launch.js +67 -0
  50. package/dist/acp-harnesses/headless-launch.js.map +1 -0
  51. package/dist/acp-harnesses/index.d.ts +18 -0
  52. package/dist/acp-harnesses/index.d.ts.map +1 -0
  53. package/dist/acp-harnesses/index.js +58 -0
  54. package/dist/acp-harnesses/index.js.map +1 -0
  55. package/dist/acp-harnesses/install-state.d.ts +86 -0
  56. package/dist/acp-harnesses/install-state.d.ts.map +1 -0
  57. package/dist/acp-harnesses/install-state.js +322 -0
  58. package/dist/acp-harnesses/install-state.js.map +1 -0
  59. package/dist/acp-harnesses/installer.d.ts +145 -0
  60. package/dist/acp-harnesses/installer.d.ts.map +1 -0
  61. package/dist/acp-harnesses/installer.js +716 -0
  62. package/dist/acp-harnesses/installer.js.map +1 -0
  63. package/dist/acp-harnesses/known-agents.d.ts +154 -0
  64. package/dist/acp-harnesses/known-agents.d.ts.map +1 -0
  65. package/dist/acp-harnesses/known-agents.js +240 -0
  66. package/dist/acp-harnesses/known-agents.js.map +1 -0
  67. package/dist/acp-harnesses/launcher.d.ts +27 -0
  68. package/dist/acp-harnesses/launcher.d.ts.map +1 -0
  69. package/dist/acp-harnesses/launcher.js +64 -0
  70. package/dist/acp-harnesses/launcher.js.map +1 -0
  71. package/dist/acp-harnesses/registry-fetch.d.ts +42 -0
  72. package/dist/acp-harnesses/registry-fetch.d.ts.map +1 -0
  73. package/dist/acp-harnesses/registry-fetch.js +132 -0
  74. package/dist/acp-harnesses/registry-fetch.js.map +1 -0
  75. package/dist/acp-harnesses/registry.d.ts +36 -0
  76. package/dist/acp-harnesses/registry.d.ts.map +1 -0
  77. package/dist/acp-harnesses/registry.js +307 -0
  78. package/dist/acp-harnesses/registry.js.map +1 -0
  79. package/dist/acp-runtime/errors.d.ts +7 -0
  80. package/dist/acp-runtime/errors.d.ts.map +1 -0
  81. package/dist/acp-runtime/errors.js +17 -0
  82. package/dist/acp-runtime/errors.js.map +1 -0
  83. package/dist/acp-runtime/fork-support.d.ts +8 -0
  84. package/dist/acp-runtime/fork-support.d.ts.map +1 -0
  85. package/dist/acp-runtime/fork-support.js +20 -0
  86. package/dist/acp-runtime/fork-support.js.map +1 -0
  87. package/dist/acp-runtime/index.d.ts +11 -0
  88. package/dist/acp-runtime/index.d.ts.map +1 -0
  89. package/dist/acp-runtime/index.js +6 -0
  90. package/dist/acp-runtime/index.js.map +1 -0
  91. package/dist/acp-runtime/probe.d.ts +103 -0
  92. package/dist/acp-runtime/probe.d.ts.map +1 -0
  93. package/dist/acp-runtime/probe.js +881 -0
  94. package/dist/acp-runtime/probe.js.map +1 -0
  95. package/dist/acp-runtime/runtime.d.ts +7 -0
  96. package/dist/acp-runtime/runtime.d.ts.map +1 -0
  97. package/dist/acp-runtime/runtime.js +26 -0
  98. package/dist/acp-runtime/runtime.js.map +1 -0
  99. package/dist/acp-runtime/session.d.ts +87 -0
  100. package/dist/acp-runtime/session.d.ts.map +1 -0
  101. package/dist/acp-runtime/session.js +1071 -0
  102. package/dist/acp-runtime/session.js.map +1 -0
  103. package/dist/acp-runtime/spawners/node.d.ts +5 -0
  104. package/dist/acp-runtime/spawners/node.d.ts.map +1 -0
  105. package/dist/acp-runtime/spawners/node.js +244 -0
  106. package/dist/acp-runtime/spawners/node.js.map +1 -0
  107. package/dist/acp-runtime/types.d.ts +180 -0
  108. package/dist/acp-runtime/types.d.ts.map +1 -0
  109. package/dist/acp-runtime/types.js +2 -0
  110. package/dist/acp-runtime/types.js.map +1 -0
  111. package/dist/agent-contract/acp.d.ts +4 -0
  112. package/dist/agent-contract/acp.d.ts.map +1 -0
  113. package/dist/agent-contract/acp.js +273 -0
  114. package/dist/agent-contract/acp.js.map +1 -0
  115. package/dist/agent-contract/index.d.ts +125 -0
  116. package/dist/agent-contract/index.d.ts.map +1 -0
  117. package/dist/agent-contract/index.js +102 -0
  118. package/dist/agent-contract/index.js.map +1 -0
  119. package/dist/agent-contract/managed.d.ts +5 -0
  120. package/dist/agent-contract/managed.d.ts.map +1 -0
  121. package/dist/agent-contract/managed.js +242 -0
  122. package/dist/agent-contract/managed.js.map +1 -0
  123. package/dist/agent-ui/index.d.ts +170 -0
  124. package/dist/agent-ui/index.d.ts.map +1 -0
  125. package/dist/agent-ui/index.js +853 -0
  126. package/dist/agent-ui/index.js.map +1 -0
  127. package/dist/agent-ui/presentation.d.ts +30 -0
  128. package/dist/agent-ui/presentation.d.ts.map +1 -0
  129. package/dist/agent-ui/presentation.js +79 -0
  130. package/dist/agent-ui/presentation.js.map +1 -0
  131. package/dist/agent-ui/react.d.ts +50 -0
  132. package/dist/agent-ui/react.d.ts.map +1 -0
  133. package/dist/agent-ui/react.js +334 -0
  134. package/dist/agent-ui/react.js.map +1 -0
  135. package/dist/brand/index.d.ts +17 -0
  136. package/dist/brand/index.d.ts.map +1 -0
  137. package/dist/brand/index.js +119 -0
  138. package/dist/brand/index.js.map +1 -0
  139. package/dist/brand/openma-logo-mark.svg +7 -0
  140. package/dist/brand/tokens.css +77 -0
  141. package/dist/brand/website.css +67 -0
  142. package/dist/chat-ui/acp.d.ts +26 -0
  143. package/dist/chat-ui/acp.d.ts.map +1 -0
  144. package/dist/chat-ui/acp.js +166 -0
  145. package/dist/chat-ui/acp.js.map +1 -0
  146. package/dist/chat-ui/components.d.ts +230 -0
  147. package/dist/chat-ui/components.d.ts.map +1 -0
  148. package/dist/chat-ui/components.js +561 -0
  149. package/dist/chat-ui/components.js.map +1 -0
  150. package/dist/chat-ui/composer-drafts.d.ts +21 -0
  151. package/dist/chat-ui/composer-drafts.d.ts.map +1 -0
  152. package/dist/chat-ui/composer-drafts.js +58 -0
  153. package/dist/chat-ui/composer-drafts.js.map +1 -0
  154. package/dist/chat-ui/controller.d.ts +61 -0
  155. package/dist/chat-ui/controller.d.ts.map +1 -0
  156. package/dist/chat-ui/controller.js +218 -0
  157. package/dist/chat-ui/controller.js.map +1 -0
  158. package/dist/chat-ui/index.d.ts +8 -0
  159. package/dist/chat-ui/index.d.ts.map +1 -0
  160. package/dist/chat-ui/index.js +8 -0
  161. package/dist/chat-ui/index.js.map +1 -0
  162. package/dist/chat-ui/markdown.d.ts +37 -0
  163. package/dist/chat-ui/markdown.d.ts.map +1 -0
  164. package/dist/chat-ui/markdown.js +33 -0
  165. package/dist/chat-ui/markdown.js.map +1 -0
  166. package/dist/chat-ui/presentation.d.ts +34 -0
  167. package/dist/chat-ui/presentation.d.ts.map +1 -0
  168. package/dist/chat-ui/presentation.js +191 -0
  169. package/dist/chat-ui/presentation.js.map +1 -0
  170. package/dist/chat-ui/styles.css +815 -0
  171. package/dist/chat-ui/utils.d.ts +14 -0
  172. package/dist/chat-ui/utils.d.ts.map +1 -0
  173. package/dist/chat-ui/utils.js +71 -0
  174. package/dist/chat-ui/utils.js.map +1 -0
  175. package/dist/local-runtime/checkpoint.d.ts +28 -0
  176. package/dist/local-runtime/checkpoint.d.ts.map +1 -0
  177. package/dist/local-runtime/checkpoint.js +2 -0
  178. package/dist/local-runtime/checkpoint.js.map +1 -0
  179. package/dist/local-runtime/daemon-connection.d.ts +27 -0
  180. package/dist/local-runtime/daemon-connection.d.ts.map +1 -0
  181. package/dist/local-runtime/daemon-connection.js +161 -0
  182. package/dist/local-runtime/daemon-connection.js.map +1 -0
  183. package/dist/local-runtime/daemon-host.d.ts +39 -0
  184. package/dist/local-runtime/daemon-host.d.ts.map +1 -0
  185. package/dist/local-runtime/daemon-host.js +88 -0
  186. package/dist/local-runtime/daemon-host.js.map +1 -0
  187. package/dist/local-runtime/index.d.ts +6 -0
  188. package/dist/local-runtime/index.d.ts.map +1 -0
  189. package/dist/local-runtime/index.js +5 -0
  190. package/dist/local-runtime/index.js.map +1 -0
  191. package/dist/local-runtime/runtime.d.ts +36 -0
  192. package/dist/local-runtime/runtime.d.ts.map +1 -0
  193. package/dist/local-runtime/runtime.js +82 -0
  194. package/dist/local-runtime/runtime.js.map +1 -0
  195. package/dist/local-runtime/session-host.d.ts +62 -0
  196. package/dist/local-runtime/session-host.d.ts.map +1 -0
  197. package/dist/local-runtime/session-host.js +477 -0
  198. package/dist/local-runtime/session-host.js.map +1 -0
  199. package/dist/managed-runtime/acp-subagents.d.ts +14 -0
  200. package/dist/managed-runtime/acp-subagents.d.ts.map +1 -0
  201. package/dist/managed-runtime/acp-subagents.js +67 -0
  202. package/dist/managed-runtime/acp-subagents.js.map +1 -0
  203. package/dist/managed-runtime/claimed-environment-work.d.ts +61 -0
  204. package/dist/managed-runtime/claimed-environment-work.d.ts.map +1 -0
  205. package/dist/managed-runtime/claimed-environment-work.js +170 -0
  206. package/dist/managed-runtime/claimed-environment-work.js.map +1 -0
  207. package/dist/managed-runtime/contracts.d.ts +31 -0
  208. package/dist/managed-runtime/contracts.d.ts.map +1 -0
  209. package/dist/managed-runtime/contracts.js +2 -0
  210. package/dist/managed-runtime/contracts.js.map +1 -0
  211. package/dist/managed-runtime/http-control.d.ts +67 -0
  212. package/dist/managed-runtime/http-control.d.ts.map +1 -0
  213. package/dist/managed-runtime/http-control.js +465 -0
  214. package/dist/managed-runtime/http-control.js.map +1 -0
  215. package/dist/managed-runtime/index.d.ts +89 -0
  216. package/dist/managed-runtime/index.d.ts.map +1 -0
  217. package/dist/managed-runtime/index.js +215 -0
  218. package/dist/managed-runtime/index.js.map +1 -0
  219. package/dist/managed-runtime/input-identity.d.ts +2 -0
  220. package/dist/managed-runtime/input-identity.d.ts.map +1 -0
  221. package/dist/managed-runtime/input-identity.js +2 -0
  222. package/dist/managed-runtime/input-identity.js.map +1 -0
  223. package/dist/managed-runtime/managed-event-projector.d.ts +24 -0
  224. package/dist/managed-runtime/managed-event-projector.d.ts.map +1 -0
  225. package/dist/managed-runtime/managed-event-projector.js +333 -0
  226. package/dist/managed-runtime/managed-event-projector.js.map +1 -0
  227. package/dist/managed-runtime/semantic-recovery.d.ts +61 -0
  228. package/dist/managed-runtime/semantic-recovery.d.ts.map +1 -0
  229. package/dist/managed-runtime/semantic-recovery.js +167 -0
  230. package/dist/managed-runtime/semantic-recovery.js.map +1 -0
  231. package/dist/project-ui/CreateProjectDialog.d.ts +15 -0
  232. package/dist/project-ui/CreateProjectDialog.d.ts.map +1 -0
  233. package/dist/project-ui/CreateProjectDialog.js +87 -0
  234. package/dist/project-ui/CreateProjectDialog.js.map +1 -0
  235. package/dist/project-ui/ProjectComposer.d.ts +13 -0
  236. package/dist/project-ui/ProjectComposer.d.ts.map +1 -0
  237. package/dist/project-ui/ProjectComposer.js +70 -0
  238. package/dist/project-ui/ProjectComposer.js.map +1 -0
  239. package/dist/project-ui/ProjectConversation.d.ts +10 -0
  240. package/dist/project-ui/ProjectConversation.d.ts.map +1 -0
  241. package/dist/project-ui/ProjectConversation.js +28 -0
  242. package/dist/project-ui/ProjectConversation.js.map +1 -0
  243. package/dist/project-ui/ProjectMessageAttachments.d.ts +4 -0
  244. package/dist/project-ui/ProjectMessageAttachments.d.ts.map +1 -0
  245. package/dist/project-ui/ProjectMessageAttachments.js +28 -0
  246. package/dist/project-ui/ProjectMessageAttachments.js.map +1 -0
  247. package/dist/project-ui/ProjectSettings.d.ts +8 -0
  248. package/dist/project-ui/ProjectSettings.d.ts.map +1 -0
  249. package/dist/project-ui/ProjectSettings.js +65 -0
  250. package/dist/project-ui/ProjectSettings.js.map +1 -0
  251. package/dist/project-ui/Projects.d.ts +18 -0
  252. package/dist/project-ui/Projects.d.ts.map +1 -0
  253. package/dist/project-ui/Projects.js +377 -0
  254. package/dist/project-ui/Projects.js.map +1 -0
  255. package/dist/project-ui/client.d.ts +234 -0
  256. package/dist/project-ui/client.d.ts.map +1 -0
  257. package/dist/project-ui/client.js +42 -0
  258. package/dist/project-ui/client.js.map +1 -0
  259. package/dist/project-ui/controls.d.ts +15 -0
  260. package/dist/project-ui/controls.d.ts.map +1 -0
  261. package/dist/project-ui/controls.js +17 -0
  262. package/dist/project-ui/controls.js.map +1 -0
  263. package/dist/project-ui/index.d.ts +20 -0
  264. package/dist/project-ui/index.d.ts.map +1 -0
  265. package/dist/project-ui/index.js +17 -0
  266. package/dist/project-ui/index.js.map +1 -0
  267. package/dist/project-ui/project-coordinator.d.ts +3 -0
  268. package/dist/project-ui/project-coordinator.d.ts.map +1 -0
  269. package/dist/project-ui/project-coordinator.js +12 -0
  270. package/dist/project-ui/project-coordinator.js.map +1 -0
  271. package/dist/project-ui/project-goals.d.ts +48 -0
  272. package/dist/project-ui/project-goals.d.ts.map +1 -0
  273. package/dist/project-ui/project-goals.js +169 -0
  274. package/dist/project-ui/project-goals.js.map +1 -0
  275. package/dist/project-ui/projects-query.d.ts +19 -0
  276. package/dist/project-ui/projects-query.d.ts.map +1 -0
  277. package/dist/project-ui/projects-query.js +132 -0
  278. package/dist/project-ui/projects-query.js.map +1 -0
  279. package/dist/project-ui/styles.css +847 -0
  280. package/dist/protocol/acp/index.d.ts +52 -0
  281. package/dist/protocol/acp/index.d.ts.map +1 -0
  282. package/dist/protocol/acp/index.js +1056 -0
  283. package/dist/protocol/acp/index.js.map +1 -0
  284. package/dist/protocol/cursor-cloud/index.d.ts +74 -0
  285. package/dist/protocol/cursor-cloud/index.d.ts.map +1 -0
  286. package/dist/protocol/cursor-cloud/index.js +249 -0
  287. package/dist/protocol/cursor-cloud/index.js.map +1 -0
  288. package/dist/protocol/managed/index.d.ts +32 -0
  289. package/dist/protocol/managed/index.d.ts.map +1 -0
  290. package/dist/protocol/managed/index.js +646 -0
  291. package/dist/protocol/managed/index.js.map +1 -0
  292. package/dist/protocol/managed/input-identity.d.ts +3 -0
  293. package/dist/protocol/managed/input-identity.d.ts.map +1 -0
  294. package/dist/protocol/managed/input-identity.js +6 -0
  295. package/dist/protocol/managed/input-identity.js.map +1 -0
  296. package/dist/protocol/openai-agents/index.d.ts +102 -0
  297. package/dist/protocol/openai-agents/index.d.ts.map +1 -0
  298. package/dist/protocol/openai-agents/index.js +142 -0
  299. package/dist/protocol/openai-agents/index.js.map +1 -0
  300. package/dist/session-events/acp-system-notices.d.ts +10 -0
  301. package/dist/session-events/acp-system-notices.d.ts.map +1 -0
  302. package/dist/session-events/acp-system-notices.js +46 -0
  303. package/dist/session-events/acp-system-notices.js.map +1 -0
  304. package/dist/session-events/acp.d.ts +214 -0
  305. package/dist/session-events/acp.d.ts.map +1 -0
  306. package/dist/session-events/acp.js +956 -0
  307. package/dist/session-events/acp.js.map +1 -0
  308. package/dist/session-events/managed.d.ts +141 -0
  309. package/dist/session-events/managed.d.ts.map +1 -0
  310. package/dist/session-events/managed.js +324 -0
  311. package/dist/session-events/managed.js.map +1 -0
  312. package/dist/session-events/openma.d.ts +304 -0
  313. package/dist/session-events/openma.d.ts.map +1 -0
  314. package/dist/session-events/openma.js +438 -0
  315. package/dist/session-events/openma.js.map +1 -0
  316. package/dist/session-kernel/index.d.ts +118 -0
  317. package/dist/session-kernel/index.d.ts.map +1 -0
  318. package/dist/session-kernel/index.js +215 -0
  319. package/dist/session-kernel/index.js.map +1 -0
  320. package/dist/session-orchestrator/index.d.ts +71 -0
  321. package/dist/session-orchestrator/index.d.ts.map +1 -0
  322. package/dist/session-orchestrator/index.js +177 -0
  323. package/dist/session-orchestrator/index.js.map +1 -0
  324. package/dist/session-ui/index.d.ts +96 -0
  325. package/dist/session-ui/index.d.ts.map +1 -0
  326. package/dist/session-ui/index.js +277 -0
  327. package/dist/session-ui/index.js.map +1 -0
  328. 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