cli-jaw 2.0.1 → 2.0.2

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 (607) hide show
  1. package/README.ko.md +3 -2
  2. package/README.md +41 -12
  3. package/dist/bin/_http-client.js +34 -0
  4. package/dist/bin/_http-client.js.map +1 -0
  5. package/dist/bin/cli-jaw.js +10 -5
  6. package/dist/bin/cli-jaw.js.map +1 -1
  7. package/dist/bin/commands/browser-web-ai.js +155 -38
  8. package/dist/bin/commands/browser-web-ai.js.map +1 -1
  9. package/dist/bin/commands/browser.js +265 -37
  10. package/dist/bin/commands/browser.js.map +1 -1
  11. package/dist/bin/commands/chat.js +18 -14
  12. package/dist/bin/commands/chat.js.map +1 -1
  13. package/dist/bin/commands/clone.js +3 -2
  14. package/dist/bin/commands/clone.js.map +1 -1
  15. package/dist/bin/commands/dashboard.js +22 -18
  16. package/dist/bin/commands/dashboard.js.map +1 -1
  17. package/dist/bin/commands/dispatch.js +9 -11
  18. package/dist/bin/commands/dispatch.js.map +1 -1
  19. package/dist/bin/commands/doctor.js +26 -14
  20. package/dist/bin/commands/doctor.js.map +1 -1
  21. package/dist/bin/commands/employee.js +12 -7
  22. package/dist/bin/commands/employee.js.map +1 -1
  23. package/dist/bin/commands/init.js +9 -9
  24. package/dist/bin/commands/init.js.map +1 -1
  25. package/dist/bin/commands/launchd.js +17 -7
  26. package/dist/bin/commands/launchd.js.map +1 -1
  27. package/dist/bin/commands/mcp.js +7 -4
  28. package/dist/bin/commands/mcp.js.map +1 -1
  29. package/dist/bin/commands/memory.js +7 -5
  30. package/dist/bin/commands/memory.js.map +1 -1
  31. package/dist/bin/commands/orchestrate.js +6 -3
  32. package/dist/bin/commands/orchestrate.js.map +1 -1
  33. package/dist/bin/commands/reset.js +4 -3
  34. package/dist/bin/commands/reset.js.map +1 -1
  35. package/dist/bin/commands/serve.js +3 -2
  36. package/dist/bin/commands/serve.js.map +1 -1
  37. package/dist/bin/commands/service.js +2 -2
  38. package/dist/bin/commands/service.js.map +1 -1
  39. package/dist/bin/commands/status.js +10 -9
  40. package/dist/bin/commands/status.js.map +1 -1
  41. package/dist/bin/commands/tui/api.js +26 -18
  42. package/dist/bin/commands/tui/api.js.map +1 -1
  43. package/dist/bin/commands/tui/overlays.js +3 -1
  44. package/dist/bin/commands/tui/overlays.js.map +1 -1
  45. package/dist/bin/commands/tui/simple-mode.js +1 -1
  46. package/dist/bin/commands/tui/simple-mode.js.map +1 -1
  47. package/dist/bin/commands/tui/types.js.map +1 -1
  48. package/dist/bin/postinstall.js +153 -65
  49. package/dist/bin/postinstall.js.map +1 -1
  50. package/dist/bin/star-prompt.js +4 -3
  51. package/dist/bin/star-prompt.js.map +1 -1
  52. package/dist/lib/mcp/format-converters.js +15 -10
  53. package/dist/lib/mcp/format-converters.js.map +1 -1
  54. package/dist/lib/mcp/mcp-install.js +2 -2
  55. package/dist/lib/mcp/mcp-install.js.map +1 -1
  56. package/dist/lib/mcp/skills-distribution.js +2 -2
  57. package/dist/lib/mcp/skills-distribution.js.map +1 -1
  58. package/dist/lib/mcp/skills-reset.js +5 -4
  59. package/dist/lib/mcp/skills-reset.js.map +1 -1
  60. package/dist/lib/mcp/skills-symlinks.js +9 -9
  61. package/dist/lib/mcp/skills-symlinks.js.map +1 -1
  62. package/dist/lib/mcp/skills-utils.js +5 -4
  63. package/dist/lib/mcp/skills-utils.js.map +1 -1
  64. package/dist/lib/mcp/unified-config.js +3 -2
  65. package/dist/lib/mcp/unified-config.js.map +1 -1
  66. package/dist/lib/mime-detect.js +65 -0
  67. package/dist/lib/mime-detect.js.map +1 -0
  68. package/dist/lib/quota-copilot.js +12 -10
  69. package/dist/lib/quota-copilot.js.map +1 -1
  70. package/dist/lib/stt.js +3 -3
  71. package/dist/lib/stt.js.map +1 -1
  72. package/dist/lib/upload.js +14 -5
  73. package/dist/lib/upload.js.map +1 -1
  74. package/dist/scripts/i18n-registry.js +4 -4
  75. package/dist/scripts/i18n-registry.js.map +1 -1
  76. package/dist/server.js +61 -57
  77. package/dist/server.js.map +1 -1
  78. package/dist/src/agent/alert-escalation.js +61 -0
  79. package/dist/src/agent/alert-escalation.js.map +1 -0
  80. package/dist/src/agent/args.js +71 -2
  81. package/dist/src/agent/args.js.map +1 -1
  82. package/dist/src/agent/error-classifier.js +9 -4
  83. package/dist/src/agent/error-classifier.js.map +1 -1
  84. package/dist/src/agent/events.js +130 -101
  85. package/dist/src/agent/events.js.map +1 -1
  86. package/dist/src/agent/lifecycle-handler.js +44 -19
  87. package/dist/src/agent/lifecycle-handler.js.map +1 -1
  88. package/dist/src/agent/live-run-state.js +7 -3
  89. package/dist/src/agent/live-run-state.js.map +1 -1
  90. package/dist/src/agent/memory-flush-controller.js +6 -4
  91. package/dist/src/agent/memory-flush-controller.js.map +1 -1
  92. package/dist/src/agent/opencode-diagnostics.js +7 -6
  93. package/dist/src/agent/opencode-diagnostics.js.map +1 -1
  94. package/dist/src/agent/session-persistence.js +1 -1
  95. package/dist/src/agent/session-persistence.js.map +1 -1
  96. package/dist/src/agent/spawn-env.js +33 -16
  97. package/dist/src/agent/spawn-env.js.map +1 -1
  98. package/dist/src/agent/spawn.js +176 -110
  99. package/dist/src/agent/spawn.js.map +1 -1
  100. package/dist/src/agent/watchdog.js +56 -0
  101. package/dist/src/agent/watchdog.js.map +1 -0
  102. package/dist/src/browser/actions.js +179 -70
  103. package/dist/src/browser/actions.js.map +1 -1
  104. package/dist/src/browser/connection.js +296 -19
  105. package/dist/src/browser/connection.js.map +1 -1
  106. package/dist/src/browser/index.js +4 -1
  107. package/dist/src/browser/index.js.map +1 -1
  108. package/dist/src/browser/launch-policy.js +1 -1
  109. package/dist/src/browser/launch-policy.js.map +1 -1
  110. package/dist/src/browser/primitives.js +11 -7
  111. package/dist/src/browser/primitives.js.map +1 -1
  112. package/dist/src/browser/runtime-diagnostics.js +45 -0
  113. package/dist/src/browser/runtime-diagnostics.js.map +1 -0
  114. package/dist/src/browser/runtime-orphans.js +127 -0
  115. package/dist/src/browser/runtime-orphans.js.map +1 -0
  116. package/dist/src/browser/runtime-owner-store.js +51 -0
  117. package/dist/src/browser/runtime-owner-store.js.map +1 -0
  118. package/dist/src/browser/runtime-owner.js +2 -2
  119. package/dist/src/browser/runtime-owner.js.map +1 -1
  120. package/dist/src/browser/tab-lifecycle.js +157 -0
  121. package/dist/src/browser/tab-lifecycle.js.map +1 -0
  122. package/dist/src/browser/vision.js +35 -11
  123. package/dist/src/browser/vision.js.map +1 -1
  124. package/dist/src/browser/web-ai/action-breadth.js +56 -0
  125. package/dist/src/browser/web-ai/action-breadth.js.map +1 -0
  126. package/dist/src/browser/web-ai/action-cache.js +9 -8
  127. package/dist/src/browser/web-ai/action-cache.js.map +1 -1
  128. package/dist/src/browser/web-ai/action-intent.js +64 -0
  129. package/dist/src/browser/web-ai/action-intent.js.map +1 -0
  130. package/dist/src/browser/web-ai/action-memory.js +82 -0
  131. package/dist/src/browser/web-ai/action-memory.js.map +1 -0
  132. package/dist/src/browser/web-ai/action-trace.js +11 -6
  133. package/dist/src/browser/web-ai/action-trace.js.map +1 -1
  134. package/dist/src/browser/web-ai/annotated-screenshot.js +2 -1
  135. package/dist/src/browser/web-ai/annotated-screenshot.js.map +1 -1
  136. package/dist/src/browser/web-ai/answer-artifact.js +97 -0
  137. package/dist/src/browser/web-ai/answer-artifact.js.map +1 -0
  138. package/dist/src/browser/web-ai/ax-snapshot.js +3 -2
  139. package/dist/src/browser/web-ai/ax-snapshot.js.map +1 -1
  140. package/dist/src/browser/web-ai/browser-primitives.js +10 -7
  141. package/dist/src/browser/web-ai/browser-primitives.js.map +1 -1
  142. package/dist/src/browser/web-ai/capability-registry.js +1 -1
  143. package/dist/src/browser/web-ai/capability-registry.js.map +1 -1
  144. package/dist/src/browser/web-ai/chatgpt-composer.js +12 -12
  145. package/dist/src/browser/web-ai/chatgpt-composer.js.map +1 -1
  146. package/dist/src/browser/web-ai/chatgpt-model.js +469 -50
  147. package/dist/src/browser/web-ai/chatgpt-model.js.map +1 -1
  148. package/dist/src/browser/web-ai/chatgpt-response.js +82 -10
  149. package/dist/src/browser/web-ai/chatgpt-response.js.map +1 -1
  150. package/dist/src/browser/web-ai/chatgpt.js +325 -49
  151. package/dist/src/browser/web-ai/chatgpt.js.map +1 -1
  152. package/dist/src/browser/web-ai/churn-log.js +1 -1
  153. package/dist/src/browser/web-ai/churn-log.js.map +1 -1
  154. package/dist/src/browser/web-ai/cli-sessions.js +42 -26
  155. package/dist/src/browser/web-ai/cli-sessions.js.map +1 -1
  156. package/dist/src/browser/web-ai/context-pack/builder.js +1 -1
  157. package/dist/src/browser/web-ai/context-pack/builder.js.map +1 -1
  158. package/dist/src/browser/web-ai/context-pack/file-selector.js +2 -2
  159. package/dist/src/browser/web-ai/context-pack/file-selector.js.map +1 -1
  160. package/dist/src/browser/web-ai/context-pack/report.js +1 -1
  161. package/dist/src/browser/web-ai/context-pack/report.js.map +1 -1
  162. package/dist/src/browser/web-ai/copy-markdown.js +25 -5
  163. package/dist/src/browser/web-ai/copy-markdown.js.map +1 -1
  164. package/dist/src/browser/web-ai/diagnostics.js +17 -14
  165. package/dist/src/browser/web-ai/diagnostics.js.map +1 -1
  166. package/dist/src/browser/web-ai/doctor.js +10 -6
  167. package/dist/src/browser/web-ai/doctor.js.map +1 -1
  168. package/dist/src/browser/web-ai/dom-hash.js.map +1 -1
  169. package/dist/src/browser/web-ai/errors.js +5 -22
  170. package/dist/src/browser/web-ai/errors.js.map +1 -1
  171. package/dist/src/browser/web-ai/gemini-live.js +7 -6
  172. package/dist/src/browser/web-ai/gemini-live.js.map +1 -1
  173. package/dist/src/browser/web-ai/grok-live.js +9 -5
  174. package/dist/src/browser/web-ai/grok-live.js.map +1 -1
  175. package/dist/src/browser/web-ai/index.js +5 -0
  176. package/dist/src/browser/web-ai/index.js.map +1 -1
  177. package/dist/src/browser/web-ai/observation-bundle.js +90 -0
  178. package/dist/src/browser/web-ai/observation-bundle.js.map +1 -0
  179. package/dist/src/browser/web-ai/observe-actions.js +186 -0
  180. package/dist/src/browser/web-ai/observe-actions.js.map +1 -0
  181. package/dist/src/browser/web-ai/observe-targets.js +6 -1
  182. package/dist/src/browser/web-ai/observe-targets.js.map +1 -1
  183. package/dist/src/browser/web-ai/planner-contract.js +18 -0
  184. package/dist/src/browser/web-ai/planner-contract.js.map +1 -0
  185. package/dist/src/browser/web-ai/post-action-assert.js +8 -7
  186. package/dist/src/browser/web-ai/post-action-assert.js.map +1 -1
  187. package/dist/src/browser/web-ai/product-surfaces.js +2 -1
  188. package/dist/src/browser/web-ai/product-surfaces.js.map +1 -1
  189. package/dist/src/browser/web-ai/provider-adapter.js.map +1 -1
  190. package/dist/src/browser/web-ai/question.js +14 -7
  191. package/dist/src/browser/web-ai/question.js.map +1 -1
  192. package/dist/src/browser/web-ai/ref-registry.js.map +1 -1
  193. package/dist/src/browser/web-ai/self-heal.js +20 -14
  194. package/dist/src/browser/web-ai/self-heal.js.map +1 -1
  195. package/dist/src/browser/web-ai/session-store.js +61 -1
  196. package/dist/src/browser/web-ai/session-store.js.map +1 -1
  197. package/dist/src/browser/web-ai/session.js +43 -2
  198. package/dist/src/browser/web-ai/session.js.map +1 -1
  199. package/dist/src/browser/web-ai/source-audit.js +116 -0
  200. package/dist/src/browser/web-ai/source-audit.js.map +1 -0
  201. package/dist/src/browser/web-ai/tab-finalizer.js +18 -0
  202. package/dist/src/browser/web-ai/tab-finalizer.js.map +1 -0
  203. package/dist/src/browser/web-ai/tab-lease-store.js +390 -0
  204. package/dist/src/browser/web-ai/tab-lease-store.js.map +1 -0
  205. package/dist/src/browser/web-ai/tab-pool.js +44 -0
  206. package/dist/src/browser/web-ai/tab-pool.js.map +1 -0
  207. package/dist/src/browser/web-ai/target-resolver.js +31 -0
  208. package/dist/src/browser/web-ai/target-resolver.js.map +1 -0
  209. package/dist/src/browser/web-ai/trace-persistence.js +4 -2
  210. package/dist/src/browser/web-ai/trace-persistence.js.map +1 -1
  211. package/dist/src/browser/web-ai/vendor-editor-contract.js.map +1 -1
  212. package/dist/src/browser/web-ai/watcher.js +8 -7
  213. package/dist/src/browser/web-ai/watcher.js.map +1 -1
  214. package/dist/src/cli/acp-client.js +40 -26
  215. package/dist/src/cli/acp-client.js.map +1 -1
  216. package/dist/src/cli/command-context.js +3 -3
  217. package/dist/src/cli/command-context.js.map +1 -1
  218. package/dist/src/cli/commands.js +25 -16
  219. package/dist/src/cli/commands.js.map +1 -1
  220. package/dist/src/cli/compact.js.map +1 -1
  221. package/dist/src/cli/handlers-completions.js +6 -4
  222. package/dist/src/cli/handlers-completions.js.map +1 -1
  223. package/dist/src/cli/handlers-runtime.js +45 -38
  224. package/dist/src/cli/handlers-runtime.js.map +1 -1
  225. package/dist/src/cli/handlers.js +44 -36
  226. package/dist/src/cli/handlers.js.map +1 -1
  227. package/dist/src/cli/readiness.js +3 -1
  228. package/dist/src/cli/readiness.js.map +1 -1
  229. package/dist/src/cli/registry.js +1 -1
  230. package/dist/src/cli/registry.js.map +1 -1
  231. package/dist/src/cli/tui/overlay.js +4 -1
  232. package/dist/src/cli/tui/overlay.js.map +1 -1
  233. package/dist/src/cli/types.js +4 -0
  234. package/dist/src/cli/types.js.map +1 -0
  235. package/dist/src/command-contract/catalog.js +1 -1
  236. package/dist/src/command-contract/catalog.js.map +1 -1
  237. package/dist/src/command-contract/help-renderer.js +1 -1
  238. package/dist/src/command-contract/help-renderer.js.map +1 -1
  239. package/dist/src/core/browser-open-default.js +13 -0
  240. package/dist/src/core/browser-open-default.js.map +1 -0
  241. package/dist/src/core/browser-open.js +41 -0
  242. package/dist/src/core/browser-open.js.map +1 -0
  243. package/dist/src/core/bus.js +13 -2
  244. package/dist/src/core/bus.js.map +1 -1
  245. package/dist/src/core/compact.js +5 -4
  246. package/dist/src/core/compact.js.map +1 -1
  247. package/dist/src/core/config.js +51 -52
  248. package/dist/src/core/config.js.map +1 -1
  249. package/dist/src/core/db.js +48 -6
  250. package/dist/src/core/db.js.map +1 -1
  251. package/dist/src/core/employees.js +9 -8
  252. package/dist/src/core/employees.js.map +1 -1
  253. package/dist/src/core/instance.js +7 -6
  254. package/dist/src/core/instance.js.map +1 -1
  255. package/dist/src/core/logger.js +1 -1
  256. package/dist/src/core/logger.js.map +1 -1
  257. package/dist/src/core/main-session.js +7 -7
  258. package/dist/src/core/main-session.js.map +1 -1
  259. package/dist/src/core/path-expand.js +10 -0
  260. package/dist/src/core/path-expand.js.map +1 -0
  261. package/dist/src/core/runtime-path.js +1 -1
  262. package/dist/src/core/runtime-path.js.map +1 -1
  263. package/dist/src/core/runtime-settings.js +13 -13
  264. package/dist/src/core/runtime-settings.js.map +1 -1
  265. package/dist/src/core/settings-merge.js +14 -14
  266. package/dist/src/core/settings-merge.js.map +1 -1
  267. package/dist/src/core/strip-undefined.js +13 -0
  268. package/dist/src/core/strip-undefined.js.map +1 -0
  269. package/dist/src/core/tcc.js +1 -1
  270. package/dist/src/core/tcc.js.map +1 -1
  271. package/dist/src/discord/bot.js +19 -18
  272. package/dist/src/discord/bot.js.map +1 -1
  273. package/dist/src/discord/channel-types.js +14 -0
  274. package/dist/src/discord/channel-types.js.map +1 -0
  275. package/dist/src/discord/commands.js +7 -6
  276. package/dist/src/discord/commands.js.map +1 -1
  277. package/dist/src/discord/discord-file.js.map +1 -1
  278. package/dist/src/discord/forwarder.js +3 -3
  279. package/dist/src/discord/forwarder.js.map +1 -1
  280. package/dist/src/http/error-middleware.js +3 -3
  281. package/dist/src/http/error-middleware.js.map +1 -1
  282. package/dist/src/http/response.js +2 -2
  283. package/dist/src/http/response.js.map +1 -1
  284. package/dist/src/ide/diff.js +7 -7
  285. package/dist/src/ide/diff.js.map +1 -1
  286. package/dist/src/manager/board/routes.js +28 -27
  287. package/dist/src/manager/board/routes.js.map +1 -1
  288. package/dist/src/manager/dashboard-home.js +3 -5
  289. package/dist/src/manager/dashboard-home.js.map +1 -1
  290. package/dist/src/manager/dashboard-service.js +2 -2
  291. package/dist/src/manager/dashboard-service.js.map +1 -1
  292. package/dist/src/manager/health-history.js +10 -9
  293. package/dist/src/manager/health-history.js.map +1 -1
  294. package/dist/src/manager/launchd-service.js +2 -2
  295. package/dist/src/manager/launchd-service.js.map +1 -1
  296. package/dist/src/manager/lifecycle-helpers.js +7 -6
  297. package/dist/src/manager/lifecycle-helpers.js.map +1 -1
  298. package/dist/src/manager/lifecycle.js +7 -6
  299. package/dist/src/manager/lifecycle.js.map +1 -1
  300. package/dist/src/manager/logs.js +18 -18
  301. package/dist/src/manager/logs.js.map +1 -1
  302. package/dist/src/manager/metadata.js +10 -2
  303. package/dist/src/manager/metadata.js.map +1 -1
  304. package/dist/src/manager/notes/assets.js +216 -0
  305. package/dist/src/manager/notes/assets.js.map +1 -0
  306. package/dist/src/manager/notes/capabilities.js +56 -0
  307. package/dist/src/manager/notes/capabilities.js.map +1 -0
  308. package/dist/src/manager/notes/constants.js +11 -0
  309. package/dist/src/manager/notes/constants.js.map +1 -0
  310. package/dist/src/manager/notes/frontmatter.js +120 -0
  311. package/dist/src/manager/notes/frontmatter.js.map +1 -0
  312. package/dist/src/manager/notes/link-resolver.js +96 -0
  313. package/dist/src/manager/notes/link-resolver.js.map +1 -0
  314. package/dist/src/manager/notes/path-guards.js +4 -0
  315. package/dist/src/manager/notes/path-guards.js.map +1 -1
  316. package/dist/src/manager/notes/remote-assets.js +128 -0
  317. package/dist/src/manager/notes/remote-assets.js.map +1 -0
  318. package/dist/src/manager/notes/routes.js +63 -13
  319. package/dist/src/manager/notes/routes.js.map +1 -1
  320. package/dist/src/manager/notes/store.js +3 -2
  321. package/dist/src/manager/notes/store.js.map +1 -1
  322. package/dist/src/manager/notes/system-trash.js +3 -3
  323. package/dist/src/manager/notes/system-trash.js.map +1 -1
  324. package/dist/src/manager/notes/vault-index.js +220 -0
  325. package/dist/src/manager/notes/vault-index.js.map +1 -0
  326. package/dist/src/manager/notes/watcher.js +27 -0
  327. package/dist/src/manager/notes/watcher.js.map +1 -0
  328. package/dist/src/manager/notes/wiki-links.js +109 -0
  329. package/dist/src/manager/notes/wiki-links.js.map +1 -0
  330. package/dist/src/manager/process-verify.js +29 -0
  331. package/dist/src/manager/process-verify.js.map +1 -1
  332. package/dist/src/manager/profiles.js +3 -2
  333. package/dist/src/manager/profiles.js.map +1 -1
  334. package/dist/src/manager/registry.js +60 -58
  335. package/dist/src/manager/registry.js.map +1 -1
  336. package/dist/src/manager/routes/electron-metrics.js +22 -22
  337. package/dist/src/manager/routes/electron-metrics.js.map +1 -1
  338. package/dist/src/manager/scan.js +2 -2
  339. package/dist/src/manager/scan.js.map +1 -1
  340. package/dist/src/manager/schedule/routes.js +24 -23
  341. package/dist/src/manager/schedule/routes.js.map +1 -1
  342. package/dist/src/manager/server.js +28 -28
  343. package/dist/src/manager/server.js.map +1 -1
  344. package/dist/src/manager/systemd-service.js +1 -1
  345. package/dist/src/manager/systemd-service.js.map +1 -1
  346. package/dist/src/memory/bootstrap.js +5 -4
  347. package/dist/src/memory/bootstrap.js.map +1 -1
  348. package/dist/src/memory/heartbeat-schedule.js +10 -10
  349. package/dist/src/memory/heartbeat-schedule.js.map +1 -1
  350. package/dist/src/memory/heartbeat.js +23 -22
  351. package/dist/src/memory/heartbeat.js.map +1 -1
  352. package/dist/src/memory/indexing.js.map +1 -1
  353. package/dist/src/memory/keyword-expand.js +1 -1
  354. package/dist/src/memory/keyword-expand.js.map +1 -1
  355. package/dist/src/memory/memory.js +2 -2
  356. package/dist/src/memory/memory.js.map +1 -1
  357. package/dist/src/memory/runtime.js +6 -5
  358. package/dist/src/memory/runtime.js.map +1 -1
  359. package/dist/src/memory/shared.js +2 -1
  360. package/dist/src/memory/shared.js.map +1 -1
  361. package/dist/src/memory/worklog.js +1 -1
  362. package/dist/src/memory/worklog.js.map +1 -1
  363. package/dist/src/messaging/runtime.js +13 -10
  364. package/dist/src/messaging/runtime.js.map +1 -1
  365. package/dist/src/messaging/send.js +16 -15
  366. package/dist/src/messaging/send.js.map +1 -1
  367. package/dist/src/orchestrator/collect.js +6 -6
  368. package/dist/src/orchestrator/collect.js.map +1 -1
  369. package/dist/src/orchestrator/distribute.js +112 -77
  370. package/dist/src/orchestrator/distribute.js.map +1 -1
  371. package/dist/src/orchestrator/gateway.js +6 -5
  372. package/dist/src/orchestrator/gateway.js.map +1 -1
  373. package/dist/src/orchestrator/pipeline.js +42 -42
  374. package/dist/src/orchestrator/pipeline.js.map +1 -1
  375. package/dist/src/orchestrator/state-machine.js +3 -3
  376. package/dist/src/orchestrator/state-machine.js.map +1 -1
  377. package/dist/src/orchestrator/worker-registry.js +4 -3
  378. package/dist/src/orchestrator/worker-registry.js.map +1 -1
  379. package/dist/src/prompt/builder.js +24 -19
  380. package/dist/src/prompt/builder.js.map +1 -1
  381. package/dist/src/prompt/templates/a1-system.md +15 -10
  382. package/dist/src/prompt/templates/control-system.md +9 -7
  383. package/dist/src/prompt/templates/employee.md +5 -4
  384. package/dist/src/prompt/templates/vision-click.md +1 -1
  385. package/dist/src/routes/_http-error.js +15 -0
  386. package/dist/src/routes/_http-error.js.map +1 -0
  387. package/dist/src/routes/avatar.js +6 -5
  388. package/dist/src/routes/avatar.js.map +1 -1
  389. package/dist/src/routes/browser.js +132 -45
  390. package/dist/src/routes/browser.js.map +1 -1
  391. package/dist/src/routes/employees.js +28 -21
  392. package/dist/src/routes/employees.js.map +1 -1
  393. package/dist/src/routes/heartbeat.js +12 -9
  394. package/dist/src/routes/heartbeat.js.map +1 -1
  395. package/dist/src/routes/i18n.js +13 -7
  396. package/dist/src/routes/i18n.js.map +1 -1
  397. package/dist/src/routes/jaw-memory.js +15 -11
  398. package/dist/src/routes/jaw-memory.js.map +1 -1
  399. package/dist/src/routes/memory.js +25 -20
  400. package/dist/src/routes/memory.js.map +1 -1
  401. package/dist/src/routes/messaging.js +50 -29
  402. package/dist/src/routes/messaging.js.map +1 -1
  403. package/dist/src/routes/orchestrate.js +38 -24
  404. package/dist/src/routes/orchestrate.js.map +1 -1
  405. package/dist/src/routes/quota.js +81 -17
  406. package/dist/src/routes/quota.js.map +1 -1
  407. package/dist/src/routes/settings.js +28 -18
  408. package/dist/src/routes/settings.js.map +1 -1
  409. package/dist/src/routes/skills.js +22 -13
  410. package/dist/src/routes/skills.js.map +1 -1
  411. package/dist/src/routes/traces.js +77 -0
  412. package/dist/src/routes/traces.js.map +1 -0
  413. package/dist/src/security/path-guards.js +2 -1
  414. package/dist/src/security/path-guards.js.map +1 -1
  415. package/dist/src/shared/tool-log-sanitize.js +191 -0
  416. package/dist/src/shared/tool-log-sanitize.js.map +1 -0
  417. package/dist/src/telegram/bot.js +65 -55
  418. package/dist/src/telegram/bot.js.map +1 -1
  419. package/dist/src/telegram/forwarder.js +5 -9
  420. package/dist/src/telegram/forwarder.js.map +1 -1
  421. package/dist/src/telegram/telegram-file.js +28 -24
  422. package/dist/src/telegram/telegram-file.js.map +1 -1
  423. package/dist/src/telegram/voice.js +4 -3
  424. package/dist/src/telegram/voice.js.map +1 -1
  425. package/dist/src/trace/redact.js +50 -0
  426. package/dist/src/trace/redact.js.map +1 -0
  427. package/dist/src/trace/store.js +162 -0
  428. package/dist/src/trace/store.js.map +1 -0
  429. package/dist/src/trace/types.js +2 -0
  430. package/dist/src/trace/types.js.map +1 -0
  431. package/dist/src/types/cli-engine.js +34 -0
  432. package/dist/src/types/cli-engine.js.map +1 -0
  433. package/dist/src/types/cli-events.js +31 -0
  434. package/dist/src/types/cli-events.js.map +1 -0
  435. package/package.json +22 -2
  436. package/public/css/tool-ui.css +3 -1
  437. package/public/css/trace-drawer.css +48 -0
  438. package/public/dist/assets/{AdvancedExport-3WAYIabE.js → AdvancedExport-DJZ2VmBR.js} +1 -1
  439. package/public/dist/assets/Agent-CgpLT8IY.js +1 -0
  440. package/public/dist/assets/Browser-CrkiQoB8.js +1 -0
  441. package/public/dist/assets/{ChannelsDiscord-UzFPlWT4.js → ChannelsDiscord-CVUC22D4.js} +1 -1
  442. package/public/dist/assets/{ChannelsTelegram-DNWtPX0w.js → ChannelsTelegram-DEatIQNM.js} +1 -1
  443. package/public/dist/assets/{DashboardMeta-Y_6nVeJO.js → DashboardMeta-BKoxRc7i.js} +1 -1
  444. package/public/dist/assets/{Display-D8vGOl4s.js → Display-DnNGV9Km.js} +1 -1
  445. package/public/dist/assets/{Employees-YR_sIRK4.js → Employees-DZ2iJYKy.js} +1 -1
  446. package/public/dist/assets/{HealthBadge-CPePajyU.js → HealthBadge-Cq2c7G9s.js} +1 -1
  447. package/public/dist/assets/{Heartbeat-DTpAULQR.js → Heartbeat-BML6eTXZ.js} +1 -1
  448. package/public/dist/assets/{Mcp-DM-PgG6z.js → Mcp-BlEviQ3h.js} +1 -1
  449. package/public/dist/assets/{Memory-C_LvJnkn.js → Memory-BRyH80He.js} +1 -1
  450. package/public/dist/assets/MilkdownWysiwygEditor-Cm3uXfWf.js +52 -0
  451. package/public/dist/assets/ModelProvider-DxyR7EL9.js +1 -0
  452. package/public/dist/assets/Network-DDOOESh1.js +1 -0
  453. package/public/dist/assets/{Permissions-B1naJjjw.js → Permissions-Br0eSbKb.js} +1 -1
  454. package/public/dist/assets/{Permissions-BKffrMJD.js → Permissions-QHkzStqQ.js} +1 -1
  455. package/public/dist/assets/{Profile-DIqjSe2C.js → Profile-C79NKumk.js} +1 -1
  456. package/public/dist/assets/{Prompts-BMfbV6Y4.js → Prompts-BmiIDiXW.js} +1 -1
  457. package/public/dist/assets/{SpeechKeys-DjiQTzSL.js → SpeechKeys-B8304XJK.js} +1 -1
  458. package/public/dist/assets/app-Be58Cs3Y.js +32 -0
  459. package/public/dist/assets/{app-BzvwJJiv.css → app-CphocJzo.css} +1 -1
  460. package/public/dist/assets/{dist-DTvxN3ux.js → dist-BD0UXfgF2.js} +1 -1
  461. package/public/dist/assets/{dist-CASeq-Tl.js → dist-BNfXO3Yr.js} +1 -1
  462. package/public/dist/assets/{dist-BMPiaUzF.js → dist-BUnPYbK3.js} +1 -1
  463. package/public/dist/assets/{dist-CT_X3hVT.js → dist-BZosRD2u.js} +1 -1
  464. package/public/dist/assets/{dist-4J6YbNXv.js → dist-Bd9PlnQm.js} +1 -1
  465. package/public/dist/assets/{dist-BcZjyn5g.js → dist-BsT5UdNP.js} +1 -1
  466. package/public/dist/assets/{dist-BfBhOPR-.js → dist-CIuXW-sc.js} +1 -1
  467. package/public/dist/assets/{dist-BMiCig3A2.js → dist-CL4PTYWf.js} +1 -1
  468. package/public/dist/assets/{dist-VyP6-HLb.js → dist-Ch5VAlV9.js} +1 -1
  469. package/public/dist/assets/dist-ClqO40BE.js +1 -0
  470. package/public/dist/assets/{dist-c98Tp7bP.js → dist-Cp42cMcI.js} +1 -1
  471. package/public/dist/assets/{dist-CIlYL1qe.js → dist-CpUK8ypo.js} +1 -1
  472. package/public/dist/assets/dist-CxeLAw2Y.js +1 -0
  473. package/public/dist/assets/dist-D2SH8nxa.js +1 -0
  474. package/public/dist/assets/{dist-84fwQ7bO.js → dist-D6cUXP7K.js} +1 -1
  475. package/public/dist/assets/{dist-BOCcQAyF.js → dist-D7bCuS3f.js} +1 -1
  476. package/public/dist/assets/{dist-DMmpfLVP.js → dist-DFYRUAjN.js} +1 -1
  477. package/public/dist/assets/{dist-DdY6pTJr.js → dist-DZsFVYF4.js} +1 -1
  478. package/public/dist/assets/{dist-B0p3Eyme.js → dist-Db16ogVk.js} +1 -1
  479. package/public/dist/assets/{dist-DlnNtr6L.js → dist-DfodGES_.js} +1 -1
  480. package/public/dist/assets/{dist-DO9so2a2.js → dist-SU-YTAIg.js} +1 -1
  481. package/public/dist/assets/{dist-DUjXiMLP.js → dist-UYn7T-GH.js} +1 -1
  482. package/public/dist/assets/{dist-BW1409rz.js → dist-W51oDoeA.js} +1 -1
  483. package/public/dist/assets/{dist-BimBQZx1.js → dist-eU7TyC86.js} +1 -1
  484. package/public/dist/assets/dist-l9HH00ip.js +1 -0
  485. package/public/dist/assets/{dist-BrOPNxdH.js → dist-urPTQzXL.js} +1 -1
  486. package/public/dist/assets/{dist-AloEV3J52.js → dist-yHP6L0Ty.js} +1 -1
  487. package/public/dist/assets/{employees-Bbabvbyx.js → employees-CxdghzoD.js} +7 -7
  488. package/public/dist/assets/{error-normalize-DdvKGLt_.js → error-normalize-5n-zlEQ3.js} +1 -1
  489. package/public/dist/assets/insert-image-markdown-DIEa-zjk.js +22 -0
  490. package/public/dist/assets/{manager-DyB2ZUr9.css → manager-DEiyrWDP.css} +1 -1
  491. package/public/dist/assets/manager-UEXd1_9T.js +25 -0
  492. package/public/dist/assets/{memory-B_plvcuQ.js → memory-CsMNkYtv.js} +9 -9
  493. package/public/dist/assets/memory-DXad_DPO.js +1 -0
  494. package/public/dist/assets/{page-shell-DML_HneX.js → page-shell-D5tbivHH.js} +1 -1
  495. package/public/dist/assets/{render-DEhbfUAW.js → render-DGQX46ei.js} +2 -2
  496. package/public/dist/assets/{settings-D7F-_kYG.js → settings-BH213Yv3.js} +14 -14
  497. package/public/dist/assets/settings-DXT87G2U.js +1 -0
  498. package/public/dist/assets/settings-client-ajlwI-oK.js +1 -0
  499. package/public/dist/assets/skills-5o_1v0nz.js +1 -0
  500. package/public/dist/assets/{skills-DoGJOc0D.js → skills-CQtCtHPA.js} +6 -6
  501. package/public/dist/assets/slash-commands-D4-hrrmh.js +1 -0
  502. package/public/dist/assets/{slash-commands-khNFPOyF.js → slash-commands-Dzk1xHWS.js} +1 -1
  503. package/public/dist/assets/trace-drawer-SRKcfm2S.js +15 -0
  504. package/public/dist/assets/ui-CdRKN2S6.js +141 -0
  505. package/public/dist/assets/ui-n43jmg_f.js +1 -0
  506. package/public/dist/assets/{ws-B2aJ-nD2.js → ws-CTHQFzM1.js} +8 -8
  507. package/public/dist/index.html +2 -2
  508. package/public/dist/manager/index.html +2 -2
  509. package/public/index.html +1 -0
  510. package/public/js/constants.ts +5 -5
  511. package/public/js/diagram/iframe-renderer.ts +11 -11
  512. package/public/js/features/chat.ts +1 -1
  513. package/public/js/features/memory.ts +10 -10
  514. package/public/js/features/pending-queue.ts +2 -2
  515. package/public/js/features/process-block.ts +257 -29
  516. package/public/js/features/process-step-match.ts +18 -0
  517. package/public/js/features/settings-cli-status.ts +1 -1
  518. package/public/js/features/settings-stt.ts +37 -11
  519. package/public/js/features/settings-templates.ts +2 -2
  520. package/public/js/features/slash-commands.ts +1 -1
  521. package/public/js/features/tool-ui.ts +13 -7
  522. package/public/js/features/trace-drawer.ts +122 -0
  523. package/public/js/icons.ts +1 -1
  524. package/public/js/main.ts +28 -28
  525. package/public/js/provider-icons.ts +1 -1
  526. package/public/js/render.ts +29 -27
  527. package/public/js/sanitizer.ts +4 -0
  528. package/public/js/ui.ts +234 -68
  529. package/public/js/virtual-scroll.ts +19 -33
  530. package/public/js/ws.ts +22 -10
  531. package/public/manager/src/App.tsx +34 -6
  532. package/public/manager/src/api.ts +55 -1
  533. package/public/manager/src/components/ActivityTimeline.tsx +1 -1
  534. package/public/manager/src/components/InstanceDetailPanel.tsx +2 -2
  535. package/public/manager/src/components/InstanceGroups.tsx +5 -5
  536. package/public/manager/src/components/InstanceListContent.tsx +1 -1
  537. package/public/manager/src/dashboard-features.ts +1 -1
  538. package/public/manager/src/manager-notes.css +49 -2
  539. package/public/manager/src/notes/MarkdownEditor.tsx +7 -3
  540. package/public/manager/src/notes/NotesFileTree.tsx +45 -6
  541. package/public/manager/src/notes/NotesSidebar.tsx +24 -55
  542. package/public/manager/src/notes/NotesWorkspace.tsx +50 -3
  543. package/public/manager/src/notes/image-assets/clipboard-images.ts +100 -0
  544. package/public/manager/src/notes/image-assets/insert-image-markdown.ts +85 -0
  545. package/public/manager/src/notes/notes-api.ts +2 -0
  546. package/public/manager/src/notes/notes-types.ts +8 -1
  547. package/public/manager/src/notes/rendering/MarkdownRenderer.tsx +6 -0
  548. package/public/manager/src/notes/rendering/markdown-render-security.ts +19 -1
  549. package/public/manager/src/notes/rich-markdown/paste-policy.ts +6 -2
  550. package/public/manager/src/notes/rich-markdown/rich-markdown-extension.ts +5 -5
  551. package/public/manager/src/notes/rich-markdown/rich-widget.ts +8 -8
  552. package/public/manager/src/notes/useNotesExternalSync.ts +37 -0
  553. package/public/manager/src/notes/useNotesModel.ts +91 -0
  554. package/public/manager/src/notes/wysiwyg/MilkdownWysiwygEditor.tsx +157 -17
  555. package/public/manager/src/notes/wysiwyg/milkdown-block-keymap.ts +14 -2
  556. package/public/manager/src/notes/wysiwyg/milkdown-code-block-view.ts +20 -20
  557. package/public/manager/src/notes/wysiwyg/milkdown-heading-source-view.ts +8 -8
  558. package/public/manager/src/notes/wysiwyg/milkdown-math.ts +25 -25
  559. package/public/manager/src/settings/pages/Browser.tsx +38 -20
  560. package/public/manager/src/settings/pages/ModelProvider.tsx +11 -9
  561. package/public/manager/src/settings/pages/Network.tsx +10 -10
  562. package/public/manager/src/settings/pages/components/HealthBadge.tsx +12 -12
  563. package/public/manager/src/settings/pages/components/agent/runtime-employees-helpers.ts +12 -10
  564. package/public/manager/src/settings/pages/components/employees-helpers.ts +9 -9
  565. package/public/manager/src/settings/pages/components/heartbeat-helpers.ts +13 -13
  566. package/public/manager/src/settings/pages/components/memory-helpers.ts +4 -4
  567. package/public/manager/src/settings/pages/mcp-helpers.ts +7 -7
  568. package/public/manager/src/settings/settings-client.ts +4 -3
  569. package/public/manager/src/sync/IframeBridge.tsx +29 -0
  570. package/public/manager/src/sync/VisibilityBridge.tsx +24 -0
  571. package/public/manager/src/sync/invalidation-bus.ts +30 -0
  572. package/public/manager/src/sync/useInvalidationSubscription.ts +19 -0
  573. package/public/manager/src/types.ts +101 -0
  574. package/scripts/check-strict-baseline.mjs +255 -0
  575. package/scripts/claim-audit.mjs +159 -0
  576. package/scripts/i18n-registry.ts +4 -4
  577. package/scripts/install-officecli.sh +2 -2
  578. package/scripts/install-wsl.sh +2 -1
  579. package/scripts/release-gates.mjs +347 -0
  580. package/scripts/release-preview.sh +3 -0
  581. package/scripts/release.sh +4 -0
  582. package/scripts/smoke/opencode-external-dir-smoke.ts +14 -5
  583. package/public/dist/assets/Agent-BYdzZwD0.js +0 -1
  584. package/public/dist/assets/Browser-CkGeczuN.js +0 -1
  585. package/public/dist/assets/MilkdownWysiwygEditor-B7k9bAey.js +0 -52
  586. package/public/dist/assets/ModelProvider-CX3Qhowu.js +0 -1
  587. package/public/dist/assets/Network-DfPLFAvw.js +0 -1
  588. package/public/dist/assets/app-DLYoRkU9.js +0 -32
  589. package/public/dist/assets/dist-8zNAQAIa.js +0 -1
  590. package/public/dist/assets/dist-BgeY6nvK.js +0 -1
  591. package/public/dist/assets/dist-BzDGGxHQ.js +0 -1
  592. package/public/dist/assets/dist-D3YKbVi-.js +0 -1
  593. package/public/dist/assets/manager-CUSgFbMO.js +0 -25
  594. package/public/dist/assets/markdown-render-security-DJfJPWO-.js +0 -22
  595. package/public/dist/assets/memory-DQ6dU0qs.js +0 -1
  596. package/public/dist/assets/settings-DxLPUbpj.js +0 -1
  597. package/public/dist/assets/settings-client-CGf3uPPf.js +0 -1
  598. package/public/dist/assets/skills-yMfNYJ8m.js +0 -1
  599. package/public/dist/assets/slash-commands-CZcwr1W6.js +0 -1
  600. package/public/dist/assets/ui-04YlOMgn.js +0 -136
  601. package/public/dist/assets/ui-D6hlMjRq.js +0 -1
  602. /package/public/dist/assets/{InlineWarn-CqgWEC41.js → InlineWarn-BooBRm7o.js} +0 -0
  603. /package/public/dist/assets/{agent-meta-puNn13DV.js → agent-meta-DHddpWHQ.js} +0 -0
  604. /package/public/dist/assets/{fields-DH9JS3mb.js → fields-BtncIZYA.js} +0 -0
  605. /package/public/dist/assets/{mermaid-loader-6XC0y10y.js → mermaid-loader-BEFIOoJn.js} +0 -0
  606. /package/public/dist/assets/{path-utils-CtsDDGZg.js → path-utils-BuEEtj9w.js} +0 -0
  607. /package/public/dist/assets/{w3c-keyname-VSld09PZ.js → w3c-keyname-IiiZScED.js} +0 -0
@@ -1,10 +1,14 @@
1
1
  // ─── Event Extraction (NDJSON parser) ────────────────
2
2
  import { broadcast } from '../core/bus.js';
3
+ import { stripUndefined } from '../core/strip-undefined.js';
4
+ import { asCliEventArray, asCliEventRecord, fieldNumber, fieldString, isCliEventRecord, } from '../types/cli-events.js';
3
5
  import { appendLiveRunText, replaceLiveRunTools, appendLiveRunTool } from './live-run-state.js';
6
+ import { stampTraceToolEntries } from '../trace/store.js';
4
7
  function liveScopeOf(ctx) {
5
8
  return ctx.liveScope ?? null;
6
9
  }
7
10
  function syncLiveTools(ctx) {
11
+ stampTraceToolEntries(ctx);
8
12
  const scope = liveScopeOf(ctx);
9
13
  if (scope)
10
14
  replaceLiveRunTools(scope, ctx.toolLog);
@@ -17,6 +21,9 @@ function syncLiveTools(ctx) {
17
21
  ctx._parentSyncedCount = total;
18
22
  }
19
23
  }
24
+ function emitAgentTool(ctx, agentLabel, tool, empTag) {
25
+ broadcast('agent_tool', { agentId: agentLabel, ...tool, ...empTag }, ctx.traceAudience === 'internal' ? 'internal' : 'public');
26
+ }
20
27
  /** Flush Claude-specific stream buffers (thinking + input_json).
21
28
  * Call on stream close to avoid data loss if content_block_stop never arrives. */
22
29
  export function flushClaudeBuffers(ctx, agentLabel, empTag = {}) {
@@ -31,7 +38,7 @@ export function flushClaudeBuffers(ctx, agentLabel, empTag = {}) {
31
38
  };
32
39
  ctx.toolLog.push(tool);
33
40
  syncLiveTools(ctx);
34
- broadcast('agent_tool', { agentId: agentLabel, ...tool, ...empTag });
41
+ emitAgentTool(ctx, agentLabel, tool, empTag);
35
42
  pushTrace(ctx, `[${agentLabel || 'agent'}] 💭 ${merged.slice(0, 200)}`);
36
43
  }
37
44
  ctx.claudeThinkingBuf = '';
@@ -46,7 +53,7 @@ export function flushClaudeBuffers(ctx, agentLabel, empTag = {}) {
46
53
  if (existing) {
47
54
  existing.detail = detail;
48
55
  syncLiveTools(ctx);
49
- broadcast('agent_tool', { agentId: agentLabel, ...existing, ...empTag });
56
+ emitAgentTool(ctx, agentLabel, existing, empTag);
50
57
  }
51
58
  }
52
59
  }
@@ -133,18 +140,19 @@ function emitGeminiThought(ctx, agentLabel, empTag, text) {
133
140
  };
134
141
  ctx.toolLog.push(tool);
135
142
  syncLiveTools(ctx);
136
- broadcast('agent_tool', { agentId: agentLabel, ...tool, ...empTag });
143
+ emitAgentTool(ctx, agentLabel, tool, empTag);
137
144
  }
138
145
  function extractGeminiThoughtText(content) {
139
146
  if (typeof content === 'string')
140
147
  return content;
141
148
  if (Array.isArray(content)) {
142
149
  return content
143
- .filter((p) => p?.type === 'thought' || p?.type === 'thinking')
150
+ .filter(isCliEventRecord)
151
+ .filter((p) => p.type === 'thought' || p.type === 'thinking')
144
152
  .map((p) => String(p.thought || p.text || p.content || ''))
145
153
  .join('');
146
154
  }
147
- if (content && typeof content === 'object') {
155
+ if (isCliEventRecord(content)) {
148
156
  return String(content.thought || content.text || content.content || '');
149
157
  }
150
158
  return '';
@@ -157,7 +165,7 @@ function toIndentedPreview(text, max = 200) {
157
165
  return clipped.replace(/\n/g, '\n ');
158
166
  }
159
167
  function isOpencodeToolFailure(part) {
160
- const exitCode = part?.state?.metadata?.exit;
168
+ const exitCode = part?.state?.metadata?.["exit"];
161
169
  if (exitCode != null && exitCode !== 0)
162
170
  return true;
163
171
  const status = String(part?.state?.status || '').toLowerCase();
@@ -177,10 +185,11 @@ function formatOpenCodeTaskDetail(part) {
177
185
  const state = part?.state || {};
178
186
  const input = state.input || {};
179
187
  const meta = state.metadata || {};
188
+ const modelInfo = asCliEventRecord(meta.model);
180
189
  const model = meta.model
181
- ? [meta.model.providerID, meta.model.modelID].filter(Boolean).join('/')
190
+ ? [modelInfo["providerID"], modelInfo["modelID"]].filter(Boolean).join('/')
182
191
  : '';
183
- return appendDetail(input.prompt ? `prompt: ${clipText(String(input.prompt), 300)}` : '', model ? `model: ${model}` : '', meta.sessionId ? `child_session: ${meta.sessionId}` : '', cleanOpencodeTaskResult(state.output) ? `result: ${cleanOpencodeTaskResult(state.output)}` : '');
192
+ return appendDetail(input.prompt ? `prompt: ${clipText(String(input.prompt), 300)}` : '', model ? `model: ${model}` : '', meta["sessionId"] ? `child_session: ${meta["sessionId"]}` : '', cleanOpencodeTaskResult(state.output) ? `result: ${cleanOpencodeTaskResult(state.output)}` : '');
184
193
  }
185
194
  function finalizeOpencodePendingTools(ctx, agentLabel, empTag) {
186
195
  const pendingRefs = ctx.opencodePendingToolRefs || [];
@@ -194,15 +203,15 @@ function finalizeOpencodePendingTools(ctx, agentLabel, empTag) {
194
203
  existing.status = failed ? 'error' : 'done';
195
204
  existing.icon = failed ? '❌' : '✅';
196
205
  syncLiveTools(ctx);
197
- broadcast('agent_tool', { agentId: agentLabel, ...existing, ...empTag });
206
+ emitAgentTool(ctx, agentLabel, existing, empTag);
198
207
  }
199
208
  }
200
209
  export function extractSessionId(cli, event) {
201
210
  switch (cli) {
202
- case 'claude': return event.type === 'system' ? event.session_id : null;
203
- case 'codex': return event.type === 'thread.started' ? event.thread_id : null;
204
- case 'gemini': return event.type === 'init' ? event.session_id : null;
205
- case 'opencode': return event.sessionID || null;
211
+ case 'claude': return event.type === 'system' ? event.session_id ?? null : null;
212
+ case 'codex': return event.type === 'thread.started' ? event.thread_id ?? null : null;
213
+ case 'gemini': return event.type === 'init' ? event.session_id ?? null : null;
214
+ case 'opencode': return event.sessionID ?? null;
206
215
  default: return null;
207
216
  }
208
217
  }
@@ -219,8 +228,8 @@ export function extractOutputChunk(cli, event, ctx) {
219
228
  if (event.type === 'message' && event.role === 'assistant' && event.content) {
220
229
  // Skip message events with thought content parts (ACP path)
221
230
  if (Array.isArray(event.content)) {
222
- const textParts = event.content.filter((p) => p?.type === 'text');
223
- return textParts.map((p) => String(p?.text || '')).join('');
231
+ const textParts = asCliEventArray(event.content).filter((p) => p.type === 'text');
232
+ return textParts.map((p) => String(p.text || '')).join('');
224
233
  }
225
234
  return String(event.content);
226
235
  }
@@ -256,11 +265,11 @@ export function extractFromEvent(cli, event, ctx, agentLabel, empTag = {}) {
256
265
  if (!ctx.metadata)
257
266
  ctx.metadata = {};
258
267
  if (event.tools)
259
- ctx.metadata.tools = event.tools;
268
+ ctx.metadata["tools"] = event.tools;
260
269
  if (event.mcp_servers)
261
- ctx.metadata.mcp_servers = event.mcp_servers;
270
+ ctx.metadata["mcp_servers"] = event.mcp_servers;
262
271
  if (event.version)
263
- ctx.metadata.version = event.version;
272
+ ctx.metadata["version"] = event.version;
264
273
  }
265
274
  // ── Claude stream buffer: thinking_delta + input_json_delta ──
266
275
  if (cli === 'claude' && event.type === 'stream_event') {
@@ -278,7 +287,7 @@ export function extractFromEvent(cli, event, ctx, agentLabel, empTag = {}) {
278
287
  if (inner?.type === 'message_start' && inner.message?.usage) {
279
288
  if (!ctx.tokens)
280
289
  ctx.tokens = { input_tokens: 0, output_tokens: 0 };
281
- ctx.tokens.input_tokens = inner.message.usage.input_tokens ?? ctx.tokens.input_tokens;
290
+ ctx.tokens["input_tokens"] = inner.message.usage.input_tokens ?? ctx.tokens["input_tokens"] ?? 0;
282
291
  }
283
292
  // Buffer thinking deltas
284
293
  if (inner?.type === 'content_block_delta' && inner.delta?.type === 'thinking_delta') {
@@ -310,7 +319,7 @@ export function extractFromEvent(cli, event, ctx, agentLabel, empTag = {}) {
310
319
  if (inner.usage.output_tokens != null) {
311
320
  if (!ctx.tokens)
312
321
  ctx.tokens = { input_tokens: 0, output_tokens: 0 };
313
- ctx.tokens.output_tokens = inner.usage.output_tokens;
322
+ ctx.tokens["output_tokens"] = inner.usage.output_tokens;
314
323
  }
315
324
  }
316
325
  // content_block_stop → flush both buffers
@@ -327,7 +336,7 @@ export function extractFromEvent(cli, event, ctx, agentLabel, empTag = {}) {
327
336
  };
328
337
  ctx.toolLog.push(tool);
329
338
  syncLiveTools(ctx);
330
- broadcast('agent_tool', { agentId: agentLabel, ...tool, ...empTag });
339
+ emitAgentTool(ctx, agentLabel, tool, empTag);
331
340
  }
332
341
  ctx.claudeThinkingBuf = '';
333
342
  }
@@ -346,7 +355,7 @@ export function extractFromEvent(cli, event, ctx, agentLabel, empTag = {}) {
346
355
  };
347
356
  ctx.toolLog.push(tool);
348
357
  syncLiveTools(ctx);
349
- broadcast('agent_tool', { agentId: agentLabel, ...tool, ...empTag });
358
+ emitAgentTool(ctx, agentLabel, tool, empTag);
350
359
  pushTrace(ctx, `[${agentLabel || 'agent'}] 🔒 encrypted thinking (sig ${sigLen}B)`);
351
360
  }
352
361
  if (ctx.claudeThinkingBlockOpen) {
@@ -367,7 +376,7 @@ export function extractFromEvent(cli, event, ctx, agentLabel, empTag = {}) {
367
376
  existing.detail = detail;
368
377
  syncLiveTools(ctx);
369
378
  // Re-broadcast with detail
370
- broadcast('agent_tool', { agentId: agentLabel, ...existing, ...empTag });
379
+ emitAgentTool(ctx, agentLabel, existing, empTag);
371
380
  }
372
381
  }
373
382
  }
@@ -388,7 +397,7 @@ export function extractFromEvent(cli, event, ctx, agentLabel, empTag = {}) {
388
397
  };
389
398
  ctx.toolLog.push(tool);
390
399
  syncLiveTools(ctx);
391
- broadcast('agent_tool', { agentId: agentLabel, ...tool, ...empTag });
400
+ emitAgentTool(ctx, agentLabel, tool, empTag);
392
401
  }
393
402
  ctx.claudeThinkingBuf = '';
394
403
  }
@@ -415,7 +424,7 @@ export function extractFromEvent(cli, event, ctx, agentLabel, empTag = {}) {
415
424
  ctx.opencodePendingToolRefs = ctx.opencodePendingToolRefs.filter(ref => ref !== toolLabel.stepRef);
416
425
  }
417
426
  syncLiveTools(ctx);
418
- broadcast('agent_tool', { agentId: agentLabel, ...toolLabel, ...empTag });
427
+ emitAgentTool(ctx, agentLabel, toolLabel, empTag);
419
428
  continue;
420
429
  }
421
430
  }
@@ -427,7 +436,7 @@ export function extractFromEvent(cli, event, ctx, agentLabel, empTag = {}) {
427
436
  ctx.opencodePendingToolRefs.push(toolLabel.stepRef);
428
437
  }
429
438
  syncLiveTools(ctx);
430
- broadcast('agent_tool', { agentId: agentLabel, ...toolLabel, ...empTag });
439
+ emitAgentTool(ctx, agentLabel, toolLabel, empTag);
431
440
  }
432
441
  switch (cli) {
433
442
  case 'claude':
@@ -442,16 +451,16 @@ export function extractFromEvent(cli, event, ctx, agentLabel, empTag = {}) {
442
451
  }
443
452
  }
444
453
  else if (event.type === 'result') {
445
- ctx.cost = event.total_cost_usd;
446
- ctx.turns = event.num_turns;
447
- ctx.duration = event.duration_ms;
454
+ ctx.cost = event.total_cost_usd ?? null;
455
+ ctx.turns = event.num_turns ?? null;
456
+ ctx.duration = event.duration_ms ?? null;
448
457
  if (event.session_id)
449
458
  ctx.sessionId = event.session_id;
450
459
  // [P1-2.3] Store modelUsage for per-model token/cache breakdown
451
460
  if (event.usage) {
452
461
  ctx.tokens = {
453
462
  input_tokens: event.usage.input_tokens ?? 0,
454
- output_tokens: event.usage.output_tokens ?? ctx.tokens?.output_tokens ?? 0,
463
+ output_tokens: event.usage.output_tokens ?? ctx.tokens?.["output_tokens"] ?? 0,
455
464
  cache_read: event.usage.cache_read_input_tokens ?? 0,
456
465
  cache_creation: event.usage.cache_creation_input_tokens ?? 0,
457
466
  };
@@ -463,7 +472,7 @@ export function extractFromEvent(cli, event, ctx, agentLabel, empTag = {}) {
463
472
  const tool = { icon: '⚠️', label: buildPreview(msg, 60), toolType: 'tool', status: 'warning' };
464
473
  ctx.toolLog.push(tool);
465
474
  syncLiveTools(ctx);
466
- broadcast('agent_tool', { agentId: agentLabel, ...tool, ...empTag });
475
+ emitAgentTool(ctx, agentLabel, tool, empTag);
467
476
  // [P0-1.2] Parse user/tool_result feedback (stdout/stderr/is_error)
468
477
  }
469
478
  else if (event.type === 'user' && event.message?.content) {
@@ -471,13 +480,13 @@ export function extractFromEvent(cli, event, ctx, agentLabel, empTag = {}) {
471
480
  if (block.type === 'tool_result' && block.tool_use_id) {
472
481
  const existing = [...ctx.toolLog].reverse().find((t) => t.stepRef === `claude:tooluse:${block.tool_use_id}`);
473
482
  if (existing) {
474
- existing.status = block.is_error ? 'error' : 'done';
475
- existing.icon = block.is_error ? '❌' : '✅';
483
+ existing.status = block["is_error"] ? 'error' : 'done';
484
+ existing.icon = block["is_error"] ? '❌' : '✅';
476
485
  const resultText = extractText(block.content);
477
486
  if (resultText)
478
487
  existing.detail = (existing.detail || '') + '\n' + resultText;
479
488
  syncLiveTools(ctx);
480
- broadcast('agent_tool', { agentId: agentLabel, ...existing, ...empTag });
489
+ emitAgentTool(ctx, agentLabel, existing, empTag);
481
490
  }
482
491
  }
483
492
  }
@@ -500,21 +509,21 @@ export function extractFromEvent(cli, event, ctx, agentLabel, empTag = {}) {
500
509
  // least one toolLog step. Dedup is handled by seenToolKeys via stepRef.
501
510
  if (segment.trim()) {
502
511
  const itemId = event.item.id || '';
503
- const tool = {
512
+ const tool = stripUndefined({
504
513
  icon: '💬',
505
514
  label: buildPreview(segment, 80) || 'message',
506
515
  toolType: 'tool',
507
516
  detail: segment,
508
517
  stepRef: itemId ? `codex:item:${itemId}` : undefined,
509
518
  status: 'done',
510
- };
519
+ });
511
520
  const key = tool.stepRef || `codex:msg:${ctx.toolLog.length}:${segment.slice(0, 30)}`;
512
521
  if (!ctx.seenToolKeys || !ctx.seenToolKeys.has(key)) {
513
522
  if (ctx.seenToolKeys)
514
523
  ctx.seenToolKeys.add(key);
515
524
  ctx.toolLog.push(tool);
516
525
  syncLiveTools(ctx);
517
- broadcast('agent_tool', { agentId: agentLabel, ...tool, ...empTag });
526
+ emitAgentTool(ctx, agentLabel, tool, empTag);
518
527
  }
519
528
  }
520
529
  }
@@ -535,7 +544,7 @@ export function extractFromEvent(cli, event, ctx, agentLabel, empTag = {}) {
535
544
  ctx.seenToolKeys?.add(doneKey);
536
545
  ctx.toolLog.push(doneTool);
537
546
  syncLiveTools(ctx);
538
- broadcast('agent_tool', { agentId: agentLabel, ...doneTool, ...empTag });
547
+ emitAgentTool(ctx, agentLabel, doneTool, empTag);
539
548
  }
540
549
  }
541
550
  if (event.item?.type === 'collab_tool_call'
@@ -547,19 +556,19 @@ export function extractFromEvent(cli, event, ctx, agentLabel, empTag = {}) {
547
556
  if (event.item?.type === 'command_execution') {
548
557
  const cmd = (event.item.command || '').slice(0, 120);
549
558
  const itemId = event.item.id || '';
550
- const tool = {
559
+ const tool = stripUndefined({
551
560
  icon: '⚡',
552
561
  label: buildPreview(cmd, 80) || 'command',
553
562
  toolType: 'tool',
554
563
  detail: cmd,
555
564
  stepRef: itemId ? `codex:cmd:${itemId}` : undefined,
556
- };
565
+ });
557
566
  const key = `${tool.icon}:${tool.label}:${tool.stepRef || ''}:`;
558
567
  if (!ctx.seenToolKeys?.has(key)) {
559
568
  ctx.seenToolKeys?.add(key);
560
569
  ctx.toolLog.push(tool);
561
570
  syncLiveTools(ctx);
562
- broadcast('agent_tool', { agentId: agentLabel, ...tool, ...empTag });
571
+ emitAgentTool(ctx, agentLabel, tool, empTag);
563
572
  }
564
573
  }
565
574
  if (event.item?.type === 'collab_tool_call'
@@ -594,7 +603,7 @@ export function extractFromEvent(cli, event, ctx, agentLabel, empTag = {}) {
594
603
  };
595
604
  ctx.toolLog.push(tool);
596
605
  syncLiveTools(ctx);
597
- broadcast('agent_tool', { agentId: agentLabel, ...tool, ...empTag });
606
+ emitAgentTool(ctx, agentLabel, tool, empTag);
598
607
  pushTrace(ctx, `[${agentLabel}] codex ${event.type}: ${msg.slice(0, 200)}`);
599
608
  }
600
609
  break;
@@ -624,8 +633,9 @@ export function extractFromEvent(cli, event, ctx, agentLabel, empTag = {}) {
624
633
  emitGeminiThought(ctx, agentLabel, empTag, extractGeminiThoughtText(event.content));
625
634
  }
626
635
  const textOnly = event.content
627
- .filter((p) => p?.type === 'text')
628
- .map((p) => String(p?.text || ''))
636
+ .filter(isCliEventRecord)
637
+ .filter((p) => p.type === 'text')
638
+ .map((p) => String(p.text || ''))
629
639
  .join('');
630
640
  if (textOnly) {
631
641
  const segment = appendGeminiAssistantTextSegment(ctx, textOnly, !!event.delta);
@@ -644,8 +654,8 @@ export function extractFromEvent(cli, event, ctx, agentLabel, empTag = {}) {
644
654
  else if (event.type === 'result') {
645
655
  ctx.geminiDeltaActive = false;
646
656
  ctx.geminiResultSeen = true;
647
- ctx.duration = event.stats?.duration_ms;
648
- ctx.turns = event.stats?.tool_calls;
657
+ ctx.duration = event.stats?.duration_ms ?? null;
658
+ ctx.turns = event.stats?.tool_calls ?? null;
649
659
  // [P0-1.6] Store Gemini token stats
650
660
  if (event.stats) {
651
661
  ctx.tokens = {
@@ -693,7 +703,7 @@ export function extractFromEvent(cli, event, ctx, agentLabel, empTag = {}) {
693
703
  };
694
704
  ctx.toolLog.push(thinkingTool);
695
705
  syncLiveTools(ctx);
696
- broadcast('agent_tool', { agentId: agentLabel, ...thinkingTool, ...empTag });
706
+ emitAgentTool(ctx, agentLabel, thinkingTool, empTag);
697
707
  ctx.opencodeStepThinkingToolEmitted = true;
698
708
  pushTrace(ctx, `[${agentLabel}] opencode reasoning (${text.length} chars)`);
699
709
  }
@@ -708,28 +718,28 @@ export function extractFromEvent(cli, event, ctx, agentLabel, empTag = {}) {
708
718
  }
709
719
  else if (event.type === 'tool_use') {
710
720
  ctx.opencodeSawToolInStep = true;
711
- if (isOpencodeToolFailure(event.part))
721
+ if (isOpencodeToolFailure(asCliEventRecord(event.part)))
712
722
  ctx.opencodeHadToolErrorInStep = true;
713
723
  }
714
724
  else if (event.type === 'step_finish' && event.part) {
715
- ctx.sessionId = event.sessionID;
725
+ ctx.sessionId = event.sessionID ?? null;
716
726
  // [P0-1.7] Accumulate tokens across steps (not overwrite)
717
727
  if (event.part.tokens) {
718
728
  if (!ctx.tokens)
719
729
  ctx.tokens = { input_tokens: 0, output_tokens: 0, cached_read: 0, cached_write: 0 };
720
- ctx.tokens.input_tokens += event.part.tokens.input ?? 0;
721
- ctx.tokens.output_tokens += event.part.tokens.output ?? 0;
730
+ ctx.tokens["input_tokens"] = (ctx.tokens["input_tokens"] ?? 0) + (event.part.tokens.input ?? 0);
731
+ ctx.tokens["output_tokens"] = (ctx.tokens["output_tokens"] ?? 0) + (event.part.tokens.output ?? 0);
722
732
  // [P0-1.8] Cache token accumulation
723
733
  if (event.part.tokens.cache) {
724
- ctx.tokens.cached_read += event.part.tokens.cache.read ?? 0;
725
- ctx.tokens.cached_write += event.part.tokens.cache.write ?? 0;
734
+ ctx.tokens["cached_read"] = (ctx.tokens["cached_read"] ?? 0) + (event.part.tokens.cache.read ?? 0);
735
+ ctx.tokens["cached_write"] = (ctx.tokens["cached_write"] ?? 0) + (event.part.tokens.cache.write ?? 0);
726
736
  }
727
737
  // [P2-3.13] Accumulate total tokens across steps
728
738
  if (event.part.tokens.total != null) {
729
- ctx.tokens.total_tokens = (ctx.tokens.total_tokens ?? 0) + event.part.tokens.total;
739
+ ctx.tokens["total_tokens"] = (ctx.tokens["total_tokens"] ?? 0) + event.part.tokens.total;
730
740
  }
731
741
  if (event.part.tokens.reasoning != null) {
732
- ctx.tokens.reasoning_tokens = (ctx.tokens.reasoning_tokens ?? 0) + event.part.tokens.reasoning;
742
+ ctx.tokens["reasoning_tokens"] = (ctx.tokens["reasoning_tokens"] ?? 0) + event.part.tokens.reasoning;
733
743
  }
734
744
  }
735
745
  // Accumulate cost across steps
@@ -759,7 +769,7 @@ export function extractFromEvent(cli, event, ctx, agentLabel, empTag = {}) {
759
769
  };
760
770
  ctx.toolLog.push(thinkingTool);
761
771
  syncLiveTools(ctx);
762
- broadcast('agent_tool', { agentId: agentLabel, ...thinkingTool, ...empTag });
772
+ emitAgentTool(ctx, agentLabel, thinkingTool, empTag);
763
773
  ctx.opencodeStepThinkingToolEmitted = true;
764
774
  pushTrace(ctx, `[${agentLabel}] opencode pre-tool intermediate text (${suppressedText.length} chars)`);
765
775
  }
@@ -778,7 +788,7 @@ export function extractFromEvent(cli, event, ctx, agentLabel, empTag = {}) {
778
788
  };
779
789
  ctx.toolLog.push(thinkingTool);
780
790
  syncLiveTools(ctx);
781
- broadcast('agent_tool', { agentId: agentLabel, ...thinkingTool, ...empTag });
791
+ emitAgentTool(ctx, agentLabel, thinkingTool, empTag);
782
792
  ctx.opencodeStepThinkingToolEmitted = true;
783
793
  pushTrace(ctx, `[${agentLabel}] opencode reasoning token fallback (${reasoningTokens} tokens)`);
784
794
  }
@@ -790,10 +800,10 @@ export function extractFromEvent(cli, event, ctx, agentLabel, empTag = {}) {
790
800
  ctx.opencodePendingToolRefs = [];
791
801
  ctx.opencodeStepThinkingToolEmitted = false;
792
802
  // [P2-3.12] Store step timing
793
- if (event.part.time) {
803
+ if (event.part["time"]) {
794
804
  if (!ctx.metadata)
795
805
  ctx.metadata = {};
796
- ctx.metadata.lastStepTime = event.part.time;
806
+ ctx.metadata["lastStepTime"] = event.part["time"];
797
807
  }
798
808
  }
799
809
  break;
@@ -905,7 +915,7 @@ function makeClaudeToolKey(event, label) {
905
915
  if (label.stepRef)
906
916
  return `claude:ref:${label.stepRef}:${label.icon}:${label.label}`;
907
917
  const msgId = event.message?.id || '';
908
- const idx = event.event?.index;
918
+ const idx = event.event?.["index"];
909
919
  if (msgId && idx !== undefined && idx !== null)
910
920
  return `claude:msg:${msgId}:${idx}:${label.icon}:${label.label}`;
911
921
  if (idx !== undefined && idx !== null)
@@ -978,7 +988,7 @@ function extractToolLabels(cli, event, ctx = null) {
978
988
  const ref = `codex:collab:${item.id || tool}`;
979
989
  const isStarted = event.type === 'item.started' || item.status === 'in_progress';
980
990
  const receiverIds = Array.isArray(item.receiver_thread_ids) ? item.receiver_thread_ids.join(', ') : '';
981
- const detail = appendDetail(item.sender_thread_id ? `sender: ${item.sender_thread_id}` : '', receiverIds ? `receivers: ${receiverIds}` : '', formatJsonDetail('agents', item.agents_states), item.prompt ? `prompt: ${clipText(String(item.prompt), 300)}` : '');
991
+ const detail = appendDetail(item["sender_thread_id"] ? `sender: ${item["sender_thread_id"]}` : '', receiverIds ? `receivers: ${receiverIds}` : '', formatJsonDetail('agents', item.agents_states), item.prompt ? `prompt: ${clipText(String(item.prompt), 300)}` : '');
982
992
  labels.push({
983
993
  icon: isStarted ? '🤖' : '✅',
984
994
  label: isStarted ? `${tool}...` : `${tool} done`,
@@ -1022,7 +1032,7 @@ function extractToolLabels(cli, event, ctx = null) {
1022
1032
  const usage = event.usage || {};
1023
1033
  const usageDetail = [
1024
1034
  usage.total_tokens != null ? `${usage.total_tokens} tok` : '',
1025
- usage.tool_uses != null ? `${usage.tool_uses} tools` : '',
1035
+ usage["tool_uses"] != null ? `${usage["tool_uses"]} tools` : '',
1026
1036
  usage.duration_ms != null ? `${(Number(usage.duration_ms) / 1000).toFixed(1)}s` : '',
1027
1037
  ].filter(Boolean).join(' · ');
1028
1038
  const detail = appendDetail(event.summary ? `summary: ${event.summary}` : '', event.output_file ? `output_file: ${event.output_file}` : '', usageDetail);
@@ -1050,12 +1060,12 @@ function extractToolLabels(cli, event, ctx = null) {
1050
1060
  const cb = event.event.content_block;
1051
1061
  if (cb?.type === 'tool_use') {
1052
1062
  const isAgent = cb.name === 'Agent';
1053
- pushToolLabel(labels, {
1063
+ pushToolLabel(labels, stripUndefined({
1054
1064
  icon: isAgent ? '🤖' : '🔧',
1055
1065
  label: isAgent ? 'subagent' : (cb.name || 'tool'),
1056
1066
  toolType: isAgent ? 'subagent' : 'tool',
1057
1067
  stepRef: cb.id ? `claude:tooluse:${cb.id}` : undefined,
1058
- }, cli, event, ctx);
1068
+ }), cli, event, ctx);
1059
1069
  }
1060
1070
  // thinking: don't emit placeholder — buffer in extractFromEvent will emit with real content
1061
1071
  }
@@ -1063,14 +1073,14 @@ function extractToolLabels(cli, event, ctx = null) {
1063
1073
  for (const block of event.message.content) {
1064
1074
  if (block.type === 'tool_use') {
1065
1075
  const isAgent = block.name === 'Agent';
1066
- const description = block.input?.description || block.input?.subagent_type || 'subagent';
1067
- pushToolLabel(labels, {
1076
+ const description = block.input?.description || block.input?.["subagent_type"] || 'subagent';
1077
+ pushToolLabel(labels, stripUndefined({
1068
1078
  icon: isAgent ? '🤖' : '🔧',
1069
1079
  label: isAgent ? `subagent: ${buildPreview(description, 60)}` : (block.name || 'tool'),
1070
1080
  toolType: isAgent ? 'subagent' : 'tool',
1071
1081
  stepRef: block.id ? `claude:tooluse:${block.id}` : undefined,
1072
1082
  ...(isAgent && block.input?.prompt ? { detail: `prompt: ${clipText(String(block.input.prompt), 300)}` } : {}),
1073
- }, cli, event, ctx);
1083
+ }), cli, event, ctx);
1074
1084
  }
1075
1085
  if (block.type === 'thinking') {
1076
1086
  const text = (block.thinking || '').trim();
@@ -1110,7 +1120,7 @@ function extractToolLabels(cli, event, ctx = null) {
1110
1120
  && event.part?.callID
1111
1121
  && ctx?.opencodeTaskCallIds?.has(event.part.callID);
1112
1122
  if (isTaskToolUse || isTaskToolResult) {
1113
- const part = event.part;
1123
+ const part = asCliEventRecord(event.part);
1114
1124
  const callID = part.callID || part.id || 'task';
1115
1125
  if (isTaskToolResult && !part.state)
1116
1126
  return labels;
@@ -1123,7 +1133,7 @@ function extractToolLabels(cli, event, ctx = null) {
1123
1133
  const input = state.input || {};
1124
1134
  const status = String(state.status || (event.type === 'tool_result' ? 'completed' : 'completed'));
1125
1135
  const failed = isOpencodeToolFailure(part) || ['error', 'failed', 'cancelled', 'canceled'].includes(status);
1126
- const subagentType = input.subagent_type || 'general';
1136
+ const subagentType = input["subagent_type"] || 'general';
1127
1137
  const description = input.description || state.title || part.tool || 'task';
1128
1138
  const resultText = event.type === 'tool_result'
1129
1139
  ? extractText(part.content || part.output || state.output)
@@ -1146,10 +1156,10 @@ function extractToolLabels(cli, event, ctx = null) {
1146
1156
  const detail = summarizeToolInput(event.part.tool || '', event.part.state?.input || {}, 0)
1147
1157
  || String(event.part.state?.output || '').trim();
1148
1158
  const isDone = event.part.state?.status === 'completed';
1149
- const exitCode = event.part.state?.metadata?.exit;
1159
+ const exitCode = fieldNumber(event.part.state?.metadata?.["exit"]);
1150
1160
  const isFailed = isOpencodeToolFailure(event.part);
1151
- const displayLabel = event.part.state?.title || event.part.tool || 'tool';
1152
- labels.push({
1161
+ const displayLabel = fieldString(event.part.state?.title || event.part.tool, 'tool');
1162
+ labels.push(stripUndefined({
1153
1163
  icon: isFailed ? '❌' : (isDone ? '✅' : '🔧'),
1154
1164
  label: displayLabel,
1155
1165
  toolType: 'tool',
@@ -1157,13 +1167,13 @@ function extractToolLabels(cli, event, ctx = null) {
1157
1167
  detail,
1158
1168
  status: isFailed ? 'error' : (isDone ? 'done' : undefined),
1159
1169
  ...(exitCode != null ? { exitCode } : {}),
1160
- });
1170
+ }));
1161
1171
  }
1162
1172
  if (event.type === 'tool_result' && event.part) {
1163
1173
  const ref = event.part.callID
1164
1174
  ? `opencode:call:${event.part.callID}`
1165
1175
  : `opencode:tool:${event.part.tool || 'tool'}`;
1166
- labels.push({ icon: '✅', label: event.part.tool || 'done', toolType: 'tool', stepRef: ref, status: 'done' });
1176
+ labels.push({ icon: '✅', label: fieldString(event.part.tool, 'done'), toolType: 'tool', stepRef: ref, status: 'done' });
1167
1177
  }
1168
1178
  }
1169
1179
  return labels;
@@ -1187,23 +1197,24 @@ export function summarizeToolInput(toolName, input, max = 0) {
1187
1197
  return '';
1188
1198
  if (typeof input !== 'object')
1189
1199
  return max ? clipText(String(input), max) : String(input);
1200
+ const data = asCliEventRecord(input);
1190
1201
  const s = (v) => (typeof v === 'string' ? v : v != null ? String(v) : '');
1191
1202
  const name = (toolName || '').toLowerCase();
1192
1203
  let result = '';
1193
1204
  if (name.includes('bash') || name.includes('terminal') || name === 'execute_command')
1194
- result = s(input.command || input.cmd);
1205
+ result = s(data.command || data.cmd);
1195
1206
  else if (name.includes('read') || name === 'read_file' || name === 'view') {
1196
- const fullPath = s(input.path || input.file_path || input.filename);
1207
+ const fullPath = s(data["path"] || data["file_path"] || data["filename"]);
1197
1208
  result = max ? (fullPath.split('/').pop() || fullPath) : fullPath;
1198
1209
  }
1199
1210
  else if (name.includes('write') || name.includes('edit') || name === 'create_file') {
1200
- const fullPath = s(input.path || input.file_path);
1211
+ const fullPath = s(data["path"] || data["file_path"]);
1201
1212
  result = max ? (fullPath.split('/').pop() || fullPath) : fullPath;
1202
1213
  }
1203
1214
  else if (name.includes('search') || name.includes('grep') || name === 'codebase_search')
1204
- result = s(input.query || input.pattern || input.search_query);
1215
+ result = s(data.query || data["pattern"] || data["search_query"]);
1205
1216
  else if (name.includes('web') || name === 'web_search')
1206
- result = s(input.query);
1217
+ result = s(data.query);
1207
1218
  // Fallback: show first meaningful key-value if specific extraction yielded nothing
1208
1219
  if (!result) {
1209
1220
  try {
@@ -1216,10 +1227,22 @@ export function summarizeToolInput(toolName, input, max = 0) {
1216
1227
  // Backward-compat: return first label or null
1217
1228
  export function extractToolLabel(cli, event) {
1218
1229
  const labels = extractToolLabels(cli, event);
1219
- return labels.length ? labels[0] : null;
1230
+ return labels[0] ?? null;
1220
1231
  }
1221
1232
  // Test-only helpers (keep parser logic private for runtime flow)
1222
- export function extractToolLabelsForTest(cli, event, ctx = {}) {
1233
+ export function extractToolLabelsForTest(cli, event, ctx = {
1234
+ fullText: '',
1235
+ traceLog: [],
1236
+ toolLog: [],
1237
+ seenToolKeys: new Set(),
1238
+ hasClaudeStreamEvents: false,
1239
+ sessionId: null,
1240
+ cost: null,
1241
+ turns: null,
1242
+ duration: null,
1243
+ tokens: null,
1244
+ stderrBuf: '',
1245
+ }) {
1223
1246
  return extractToolLabels(cli, event, ctx);
1224
1247
  }
1225
1248
  export function makeClaudeToolKeyForTest(event, label) {
@@ -1233,19 +1256,21 @@ function extractText(content) {
1233
1256
  return content;
1234
1257
  if (Array.isArray(content)) {
1235
1258
  return content
1259
+ .filter(isCliEventRecord)
1236
1260
  .filter(c => c.type === 'text')
1237
1261
  .map(c => c.text || '')
1238
1262
  .join('');
1239
1263
  }
1240
1264
  // Single content object: {type: 'text', text: '...'}
1241
- if (content && typeof content === 'object' && content.type === 'text') {
1265
+ if (isCliEventRecord(content) && content.type === 'text') {
1242
1266
  return content.text || '';
1243
1267
  }
1244
1268
  return '';
1245
1269
  }
1246
1270
  export function extractFromAcpUpdate(params, ctx = null) {
1247
- const update = params?.update;
1248
- if (!update)
1271
+ const envelope = asCliEventRecord(params);
1272
+ const update = asCliEventRecord(envelope["update"]);
1273
+ if (!isCliEventRecord(envelope["update"]))
1249
1274
  return null;
1250
1275
  const type = update.sessionUpdate;
1251
1276
  switch (type) {
@@ -1261,9 +1286,9 @@ export function extractFromAcpUpdate(params, ctx = null) {
1261
1286
  };
1262
1287
  }
1263
1288
  case 'tool_call': {
1264
- const toolName = update.name || 'tool';
1265
- const rawInput = update.rawInput || update.input || {};
1266
- const isSubagentTask = rawInput?.agent_type === 'task' || rawInput?.agentType === 'task';
1289
+ const toolName = fieldString(update.name, 'tool');
1290
+ const rawInput = asCliEventRecord(update.rawInput || update.input);
1291
+ const isSubagentTask = rawInput?.["agent_type"] === 'task' || rawInput?.["agentType"] === 'task';
1267
1292
  const displayLabel = isSubagentTask
1268
1293
  ? `subagent: ${update.title || rawInput.description || rawInput.name || toolName}`
1269
1294
  : update.title || toolName;
@@ -1273,7 +1298,7 @@ export function extractFromAcpUpdate(params, ctx = null) {
1273
1298
  if (!ctx.acpSubagentLabels)
1274
1299
  ctx.acpSubagentLabels = new Map();
1275
1300
  ctx.acpSubagentToolCallIds.add(update.toolCallId);
1276
- ctx.acpSubagentLabels.set(update.toolCallId, displayLabel);
1301
+ ctx.acpSubagentLabels.set(update.toolCallId, fieldString(displayLabel));
1277
1302
  }
1278
1303
  const fullInput = update.input != null
1279
1304
  ? (typeof update.input === 'object' ? JSON.stringify(update.input, null, 2) : String(update.input))
@@ -1281,12 +1306,12 @@ export function extractFromAcpUpdate(params, ctx = null) {
1281
1306
  ? (typeof update.rawInput === 'object' ? JSON.stringify(update.rawInput, null, 2) : String(update.rawInput))
1282
1307
  : '';
1283
1308
  // [P1-2.10] Semantic icon from tool kind/title
1284
- const kindIcon = toolKindIcon(update.kind);
1309
+ const kindIcon = toolKindIcon(fieldString(update["kind"]) || undefined);
1285
1310
  // [P0-1.11] Use toolCallId for unique stepRef
1286
1311
  return {
1287
1312
  tool: {
1288
1313
  icon: isSubagentTask ? '🤖' : (kindIcon || '🔧'),
1289
- label: displayLabel,
1314
+ label: fieldString(displayLabel),
1290
1315
  toolType: isSubagentTask ? 'subagent' : 'tool',
1291
1316
  detail: fullInput,
1292
1317
  stepRef: `acp:callid:${update.toolCallId || update.id || toolName}`,
@@ -1303,8 +1328,9 @@ export function extractFromAcpUpdate(params, ctx = null) {
1303
1328
  completed: { icon: '✅', status: 'done' },
1304
1329
  failed: { icon: '❌', status: 'error' },
1305
1330
  };
1306
- const mapped = statusMap[update.status] || { icon: '❔', status: update.status || 'unknown' };
1307
- const toolCallId = update.toolCallId || update.id || update.name || 'done';
1331
+ const statusKey = fieldString(update.status);
1332
+ const mapped = statusMap[statusKey] || { icon: '❔', status: statusKey || 'unknown' };
1333
+ const toolCallId = fieldString(update.toolCallId || update.id || update.name, 'done');
1308
1334
  const isSubagentTask = !!(toolCallId && ctx?.acpSubagentToolCallIds?.has(toolCallId));
1309
1335
  const subagentLabel = toolCallId ? ctx?.acpSubagentLabels?.get(toolCallId) : '';
1310
1336
  // [P1-2.9] Extract content from tool result
@@ -1312,7 +1338,7 @@ export function extractFromAcpUpdate(params, ctx = null) {
1312
1338
  return {
1313
1339
  tool: {
1314
1340
  icon: mapped.icon,
1315
- label: isSubagentTask ? (subagentLabel || `subagent: ${update.name || update.title || 'task'}`) : update.name || update.id || 'done',
1341
+ label: isSubagentTask ? (subagentLabel || `subagent: ${update.name || update.title || 'task'}`) : fieldString(update.name || update.id, 'done'),
1316
1342
  toolType: isSubagentTask ? 'subagent' : 'tool',
1317
1343
  stepRef: `acp:callid:${toolCallId}`,
1318
1344
  status: mapped.status,
@@ -1358,19 +1384,20 @@ export function extractFromAcpUpdate(params, ctx = null) {
1358
1384
  };
1359
1385
  }
1360
1386
  default:
1361
- if (process.env.DEBUG) {
1387
+ if (process.env["DEBUG"]) {
1362
1388
  console.log(`[acp] unknown sessionUpdate: ${type}`, JSON.stringify(update).slice(0, 100));
1363
1389
  }
1364
1390
  return null;
1365
1391
  }
1366
1392
  }
1367
1393
  export function extractFromAcpSubagent(event) {
1368
- if (!event?.type || !String(event.type).startsWith('subagent.'))
1394
+ const record = asCliEventRecord(event);
1395
+ if (!record.type || !String(record.type).startsWith('subagent.'))
1369
1396
  return null;
1370
- const data = event.data || {};
1371
- const display = data.agentDisplayName || data.agentName || 'subagent';
1372
- const agentName = data.agentName || display;
1373
- switch (event.type) {
1397
+ const data = asCliEventRecord(record["data"]);
1398
+ const display = fieldString(data.agentDisplayName || data.agentName, 'subagent');
1399
+ const agentName = fieldString(data.agentName, display);
1400
+ switch (record.type) {
1374
1401
  case 'subagent.selected':
1375
1402
  return {
1376
1403
  tool: {
@@ -1392,7 +1419,8 @@ export function extractFromAcpSubagent(event) {
1392
1419
  status: 'done',
1393
1420
  },
1394
1421
  };
1395
- case 'subagent.started':
1422
+ case 'subagent.started': {
1423
+ const agentDescription = fieldString(data["agentDescription"]);
1396
1424
  return {
1397
1425
  tool: {
1398
1426
  icon: '🤖',
@@ -1400,9 +1428,10 @@ export function extractFromAcpSubagent(event) {
1400
1428
  toolType: 'subagent',
1401
1429
  stepRef: `acp:subagent:${data.toolCallId || agentName}`,
1402
1430
  status: 'running',
1403
- ...(data.agentDescription ? { detail: data.agentDescription } : {}),
1431
+ ...(agentDescription ? { detail: agentDescription } : {}),
1404
1432
  },
1405
1433
  };
1434
+ }
1406
1435
  case 'subagent.completed':
1407
1436
  return {
1408
1437
  tool: {