@agentdeck/bridge 0.2.1 → 0.2.3

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 (383) hide show
  1. package/assets/fonts/IBMPlexSans-Bold.ttf +0 -0
  2. package/assets/fonts/IBMPlexSans-Regular.ttf +0 -0
  3. package/assets/fonts/JetBrainsMono-Bold.ttf +0 -0
  4. package/assets/fonts/JetBrainsMono-Regular.ttf +0 -0
  5. package/assets/fonts/LICENSES.md +22 -0
  6. package/dist/adapters/claude-code.d.ts +6 -0
  7. package/dist/adapters/claude-code.d.ts.map +1 -1
  8. package/dist/adapters/claude-code.js +8 -0
  9. package/dist/adapters/claude-code.js.map +1 -1
  10. package/dist/adapters/openclaw.d.ts +24 -0
  11. package/dist/adapters/openclaw.d.ts.map +1 -1
  12. package/dist/adapters/openclaw.js +291 -35
  13. package/dist/adapters/openclaw.js.map +1 -1
  14. package/dist/adapters/opencode-adapter.d.ts +59 -0
  15. package/dist/adapters/opencode-adapter.d.ts.map +1 -1
  16. package/dist/adapters/opencode-adapter.js +297 -35
  17. package/dist/adapters/opencode-adapter.js.map +1 -1
  18. package/dist/adb-reverse.d.ts +1 -1
  19. package/dist/adb-reverse.js +1 -1
  20. package/dist/antigravity-local.d.ts +1 -0
  21. package/dist/antigravity-local.d.ts.map +1 -1
  22. package/dist/antigravity-local.js +33 -0
  23. package/dist/antigravity-local.js.map +1 -1
  24. package/dist/apme/adapters/claude-hook.d.ts.map +1 -1
  25. package/dist/apme/adapters/claude-hook.js +5 -0
  26. package/dist/apme/adapters/claude-hook.js.map +1 -1
  27. package/dist/apme/adapters/codex-hook.d.ts +17 -0
  28. package/dist/apme/adapters/codex-hook.d.ts.map +1 -0
  29. package/dist/apme/adapters/codex-hook.js +95 -0
  30. package/dist/apme/adapters/codex-hook.js.map +1 -0
  31. package/dist/apme/adapters/codex-turn-manager.d.ts +86 -0
  32. package/dist/apme/adapters/codex-turn-manager.d.ts.map +1 -0
  33. package/dist/apme/adapters/codex-turn-manager.js +496 -0
  34. package/dist/apme/adapters/codex-turn-manager.js.map +1 -0
  35. package/dist/apme/adapters/openclaw-hook.d.ts +99 -0
  36. package/dist/apme/adapters/openclaw-hook.d.ts.map +1 -0
  37. package/dist/apme/adapters/openclaw-hook.js +234 -0
  38. package/dist/apme/adapters/openclaw-hook.js.map +1 -0
  39. package/dist/apme/adapters/opencode-hook.d.ts +56 -0
  40. package/dist/apme/adapters/opencode-hook.d.ts.map +1 -0
  41. package/dist/apme/adapters/opencode-hook.js +182 -0
  42. package/dist/apme/adapters/opencode-hook.js.map +1 -0
  43. package/dist/apme/adapters/timeline.d.ts.map +1 -1
  44. package/dist/apme/adapters/timeline.js +6 -1
  45. package/dist/apme/adapters/timeline.js.map +1 -1
  46. package/dist/apme/antigravity-transcript.d.ts +18 -0
  47. package/dist/apme/antigravity-transcript.d.ts.map +1 -0
  48. package/dist/apme/antigravity-transcript.js +94 -0
  49. package/dist/apme/antigravity-transcript.js.map +1 -0
  50. package/dist/apme/classify-turn.d.ts +13 -0
  51. package/dist/apme/classify-turn.d.ts.map +1 -0
  52. package/dist/apme/classify-turn.js +49 -0
  53. package/dist/apme/classify-turn.js.map +1 -0
  54. package/dist/apme/claude-transcript-reader.d.ts +10 -0
  55. package/dist/apme/claude-transcript-reader.d.ts.map +1 -1
  56. package/dist/apme/claude-transcript-reader.js +35 -0
  57. package/dist/apme/claude-transcript-reader.js.map +1 -1
  58. package/dist/apme/collector.d.ts +129 -6
  59. package/dist/apme/collector.d.ts.map +1 -1
  60. package/dist/apme/collector.js +470 -23
  61. package/dist/apme/collector.js.map +1 -1
  62. package/dist/apme/dashboard-html.d.ts.map +1 -1
  63. package/dist/apme/dashboard-html.js +87 -11
  64. package/dist/apme/dashboard-html.js.map +1 -1
  65. package/dist/apme/http.d.ts.map +1 -1
  66. package/dist/apme/http.js +43 -6
  67. package/dist/apme/http.js.map +1 -1
  68. package/dist/apme/index.d.ts +26 -5
  69. package/dist/apme/index.d.ts.map +1 -1
  70. package/dist/apme/index.js +135 -9
  71. package/dist/apme/index.js.map +1 -1
  72. package/dist/apme/pareto.d.ts +39 -0
  73. package/dist/apme/pareto.d.ts.map +1 -0
  74. package/dist/apme/pareto.js +59 -0
  75. package/dist/apme/pareto.js.map +1 -0
  76. package/dist/apme/recommend.d.ts +3 -0
  77. package/dist/apme/recommend.d.ts.map +1 -1
  78. package/dist/apme/recommend.js +43 -1
  79. package/dist/apme/recommend.js.map +1 -1
  80. package/dist/apme/runner.d.ts +92 -4
  81. package/dist/apme/runner.d.ts.map +1 -1
  82. package/dist/apme/runner.js +586 -70
  83. package/dist/apme/runner.js.map +1 -1
  84. package/dist/apme/sample-to-timeline.d.ts +26 -0
  85. package/dist/apme/sample-to-timeline.d.ts.map +1 -0
  86. package/dist/apme/sample-to-timeline.js +95 -0
  87. package/dist/apme/sample-to-timeline.js.map +1 -0
  88. package/dist/apme/scorers/index.d.ts +47 -0
  89. package/dist/apme/scorers/index.d.ts.map +1 -0
  90. package/dist/apme/scorers/index.js +96 -0
  91. package/dist/apme/scorers/index.js.map +1 -0
  92. package/dist/apme/settings.d.ts +14 -10
  93. package/dist/apme/settings.d.ts.map +1 -1
  94. package/dist/apme/settings.js +34 -8
  95. package/dist/apme/settings.js.map +1 -1
  96. package/dist/apme/store.d.ts +33 -1
  97. package/dist/apme/store.d.ts.map +1 -1
  98. package/dist/apme/store.js +334 -25
  99. package/dist/apme/store.js.map +1 -1
  100. package/dist/awaiting-overlay.d.ts +99 -0
  101. package/dist/awaiting-overlay.d.ts.map +1 -0
  102. package/dist/awaiting-overlay.js +148 -0
  103. package/dist/awaiting-overlay.js.map +1 -0
  104. package/dist/ble-sync-spawn.d.ts +63 -0
  105. package/dist/ble-sync-spawn.d.ts.map +1 -0
  106. package/dist/ble-sync-spawn.js +196 -0
  107. package/dist/ble-sync-spawn.js.map +1 -0
  108. package/dist/bridge-core.d.ts +24 -1
  109. package/dist/bridge-core.d.ts.map +1 -1
  110. package/dist/bridge-core.js +157 -24
  111. package/dist/bridge-core.js.map +1 -1
  112. package/dist/broadcast.d.ts +3 -0
  113. package/dist/broadcast.d.ts.map +1 -0
  114. package/dist/broadcast.js +122 -0
  115. package/dist/broadcast.js.map +1 -0
  116. package/dist/check-deps.d.ts.map +1 -1
  117. package/dist/check-deps.js +25 -9
  118. package/dist/check-deps.js.map +1 -1
  119. package/dist/cli.d.ts +15 -1
  120. package/dist/cli.d.ts.map +1 -1
  121. package/dist/cli.js +1025 -94
  122. package/dist/cli.js.map +1 -1
  123. package/dist/codex-auth.d.ts +21 -0
  124. package/dist/codex-auth.d.ts.map +1 -1
  125. package/dist/codex-auth.js +52 -1
  126. package/dist/codex-auth.js.map +1 -1
  127. package/dist/codex-output-parser.d.ts +8 -0
  128. package/dist/codex-output-parser.d.ts.map +1 -1
  129. package/dist/codex-output-parser.js +110 -25
  130. package/dist/codex-output-parser.js.map +1 -1
  131. package/dist/codex-rate-limits.d.ts +16 -0
  132. package/dist/codex-rate-limits.d.ts.map +1 -0
  133. package/dist/codex-rate-limits.js +197 -0
  134. package/dist/codex-rate-limits.js.map +1 -0
  135. package/dist/codex-rollout-response.d.ts +31 -0
  136. package/dist/codex-rollout-response.d.ts.map +1 -0
  137. package/dist/codex-rollout-response.js +135 -0
  138. package/dist/codex-rollout-response.js.map +1 -0
  139. package/dist/daemon-server.d.ts +85 -0
  140. package/dist/daemon-server.d.ts.map +1 -1
  141. package/dist/daemon-server.js +1627 -159
  142. package/dist/daemon-server.js.map +1 -1
  143. package/dist/daemon.js +15 -6
  144. package/dist/daemon.js.map +1 -1
  145. package/dist/display-dim.d.ts +9 -0
  146. package/dist/display-dim.d.ts.map +1 -0
  147. package/dist/display-dim.js +53 -0
  148. package/dist/display-dim.js.map +1 -0
  149. package/dist/display-monitor.d.ts +15 -2
  150. package/dist/display-monitor.d.ts.map +1 -1
  151. package/dist/display-monitor.js +104 -26
  152. package/dist/display-monitor.js.map +1 -1
  153. package/dist/esp32-serial.d.ts +160 -1
  154. package/dist/esp32-serial.d.ts.map +1 -1
  155. package/dist/esp32-serial.js +950 -153
  156. package/dist/esp32-serial.js.map +1 -1
  157. package/dist/fallback-task-timeline.d.ts +42 -0
  158. package/dist/fallback-task-timeline.d.ts.map +1 -0
  159. package/dist/fallback-task-timeline.js +112 -0
  160. package/dist/fallback-task-timeline.js.map +1 -0
  161. package/dist/foundation-models-helper.d.ts +11 -0
  162. package/dist/foundation-models-helper.d.ts.map +1 -0
  163. package/dist/foundation-models-helper.js +241 -0
  164. package/dist/foundation-models-helper.js.map +1 -0
  165. package/dist/hook-migration.js +1 -1
  166. package/dist/hook-migration.js.map +1 -1
  167. package/dist/hook-server.d.ts +2 -3
  168. package/dist/hook-server.d.ts.map +1 -1
  169. package/dist/hook-server.js +22 -10
  170. package/dist/hook-server.js.map +1 -1
  171. package/dist/idotmatrix/idotmatrix-daemon-sync.d.ts +33 -0
  172. package/dist/idotmatrix/idotmatrix-daemon-sync.d.ts.map +1 -0
  173. package/dist/idotmatrix/idotmatrix-daemon-sync.js +164 -0
  174. package/dist/idotmatrix/idotmatrix-daemon-sync.js.map +1 -0
  175. package/dist/idotmatrix/idotmatrix-discover.d.ts +18 -0
  176. package/dist/idotmatrix/idotmatrix-discover.d.ts.map +1 -0
  177. package/dist/idotmatrix/idotmatrix-discover.js +85 -0
  178. package/dist/idotmatrix/idotmatrix-discover.js.map +1 -0
  179. package/dist/idotmatrix/idotmatrix-settings.d.ts +20 -0
  180. package/dist/idotmatrix/idotmatrix-settings.d.ts.map +1 -0
  181. package/dist/idotmatrix/idotmatrix-settings.js +57 -0
  182. package/dist/idotmatrix/idotmatrix-settings.js.map +1 -0
  183. package/dist/index.d.ts.map +1 -1
  184. package/dist/index.js +215 -179
  185. package/dist/index.js.map +1 -1
  186. package/dist/log-stream.d.ts +15 -16
  187. package/dist/log-stream.d.ts.map +1 -1
  188. package/dist/log-stream.js +18 -96
  189. package/dist/log-stream.js.map +1 -1
  190. package/dist/logger.d.ts.map +1 -1
  191. package/dist/logger.js +12 -3
  192. package/dist/logger.js.map +1 -1
  193. package/dist/mdns.d.ts +17 -0
  194. package/dist/mdns.d.ts.map +1 -1
  195. package/dist/mdns.js +52 -18
  196. package/dist/mdns.js.map +1 -1
  197. package/dist/modules/adb-module.d.ts +1 -1
  198. package/dist/modules/adb-module.d.ts.map +1 -1
  199. package/dist/modules/adb-module.js +4 -3
  200. package/dist/modules/adb-module.js.map +1 -1
  201. package/dist/modules/broadcast-module.d.ts +17 -0
  202. package/dist/modules/broadcast-module.d.ts.map +1 -0
  203. package/dist/modules/broadcast-module.js +26 -0
  204. package/dist/modules/broadcast-module.js.map +1 -0
  205. package/dist/modules/idotmatrix-module.d.ts +9 -0
  206. package/dist/modules/idotmatrix-module.d.ts.map +1 -0
  207. package/dist/modules/idotmatrix-module.js +46 -0
  208. package/dist/modules/idotmatrix-module.js.map +1 -0
  209. package/dist/modules/index.d.ts +3 -1
  210. package/dist/modules/index.d.ts.map +1 -1
  211. package/dist/modules/index.js +9 -3
  212. package/dist/modules/index.js.map +1 -1
  213. package/dist/modules/pixoo-module.d.ts.map +1 -1
  214. package/dist/modules/pixoo-module.js +14 -4
  215. package/dist/modules/pixoo-module.js.map +1 -1
  216. package/dist/modules/serial-module.d.ts +4 -0
  217. package/dist/modules/serial-module.d.ts.map +1 -1
  218. package/dist/modules/serial-module.js +14 -12
  219. package/dist/modules/serial-module.js.map +1 -1
  220. package/dist/modules/timebox-module.d.ts +9 -0
  221. package/dist/modules/timebox-module.d.ts.map +1 -0
  222. package/dist/modules/timebox-module.js +46 -0
  223. package/dist/modules/timebox-module.js.map +1 -0
  224. package/dist/modules/types.d.ts +4 -2
  225. package/dist/modules/types.d.ts.map +1 -1
  226. package/dist/openclaw-session.d.ts +18 -0
  227. package/dist/openclaw-session.d.ts.map +1 -0
  228. package/dist/openclaw-session.js +34 -0
  229. package/dist/openclaw-session.js.map +1 -0
  230. package/dist/output-parser.d.ts +30 -0
  231. package/dist/output-parser.d.ts.map +1 -1
  232. package/dist/output-parser.js +125 -9
  233. package/dist/output-parser.js.map +1 -1
  234. package/dist/passive-observer.d.ts +26 -0
  235. package/dist/passive-observer.d.ts.map +1 -1
  236. package/dist/passive-observer.js +258 -49
  237. package/dist/passive-observer.js.map +1 -1
  238. package/dist/permission-resolver.d.ts +47 -0
  239. package/dist/permission-resolver.d.ts.map +1 -0
  240. package/dist/permission-resolver.js +103 -0
  241. package/dist/permission-resolver.js.map +1 -0
  242. package/dist/pixoo/micro-glyphs.d.ts +49 -0
  243. package/dist/pixoo/micro-glyphs.d.ts.map +1 -0
  244. package/dist/pixoo/micro-glyphs.js +276 -0
  245. package/dist/pixoo/micro-glyphs.js.map +1 -0
  246. package/dist/pixoo/pixoo-bridge.d.ts +2 -2
  247. package/dist/pixoo/pixoo-bridge.d.ts.map +1 -1
  248. package/dist/pixoo/pixoo-bridge.js +93 -25
  249. package/dist/pixoo/pixoo-bridge.js.map +1 -1
  250. package/dist/pixoo/pixoo-camera.d.ts +19 -3
  251. package/dist/pixoo/pixoo-camera.d.ts.map +1 -1
  252. package/dist/pixoo/pixoo-camera.js +62 -27
  253. package/dist/pixoo/pixoo-camera.js.map +1 -1
  254. package/dist/pixoo/pixoo-client.d.ts +13 -3
  255. package/dist/pixoo/pixoo-client.d.ts.map +1 -1
  256. package/dist/pixoo/pixoo-client.js +51 -22
  257. package/dist/pixoo/pixoo-client.js.map +1 -1
  258. package/dist/pixoo/pixoo-discover.d.ts +37 -0
  259. package/dist/pixoo/pixoo-discover.d.ts.map +1 -0
  260. package/dist/pixoo/pixoo-discover.js +105 -0
  261. package/dist/pixoo/pixoo-discover.js.map +1 -0
  262. package/dist/pixoo/pixoo-renderer.d.ts +8 -3
  263. package/dist/pixoo/pixoo-renderer.d.ts.map +1 -1
  264. package/dist/pixoo/pixoo-renderer.js +189 -60
  265. package/dist/pixoo/pixoo-renderer.js.map +1 -1
  266. package/dist/pixoo/pixoo-settings.d.ts +6 -0
  267. package/dist/pixoo/pixoo-settings.d.ts.map +1 -1
  268. package/dist/pixoo/pixoo-settings.js +9 -0
  269. package/dist/pixoo/pixoo-settings.js.map +1 -1
  270. package/dist/pixoo/pixoo-sprites.d.ts +60 -11
  271. package/dist/pixoo/pixoo-sprites.d.ts.map +1 -1
  272. package/dist/pixoo/pixoo-sprites.js +512 -209
  273. package/dist/pixoo/pixoo-sprites.js.map +1 -1
  274. package/dist/pty-manager.d.ts.map +1 -1
  275. package/dist/pty-manager.js +8 -2
  276. package/dist/pty-manager.js.map +1 -1
  277. package/dist/session-activity.d.ts +14 -0
  278. package/dist/session-activity.d.ts.map +1 -0
  279. package/dist/session-activity.js +160 -0
  280. package/dist/session-activity.js.map +1 -0
  281. package/dist/session-aggregator.d.ts +17 -0
  282. package/dist/session-aggregator.d.ts.map +1 -1
  283. package/dist/session-aggregator.js +48 -9
  284. package/dist/session-aggregator.js.map +1 -1
  285. package/dist/session-registry.d.ts +71 -3
  286. package/dist/session-registry.d.ts.map +1 -1
  287. package/dist/session-registry.js +137 -8
  288. package/dist/session-registry.js.map +1 -1
  289. package/dist/session-timeline-relay.d.ts.map +1 -1
  290. package/dist/session-timeline-relay.js +13 -4
  291. package/dist/session-timeline-relay.js.map +1 -1
  292. package/dist/session-transcript-timeline.d.ts +49 -0
  293. package/dist/session-transcript-timeline.d.ts.map +1 -0
  294. package/dist/session-transcript-timeline.js +276 -0
  295. package/dist/session-transcript-timeline.js.map +1 -0
  296. package/dist/state-machine.d.ts +6 -1
  297. package/dist/state-machine.d.ts.map +1 -1
  298. package/dist/state-machine.js +86 -28
  299. package/dist/state-machine.js.map +1 -1
  300. package/dist/timebox/timebox-daemon-sync.d.ts +19 -0
  301. package/dist/timebox/timebox-daemon-sync.d.ts.map +1 -0
  302. package/dist/timebox/timebox-daemon-sync.js +135 -0
  303. package/dist/timebox/timebox-daemon-sync.js.map +1 -0
  304. package/dist/timebox/timebox-discover.d.ts +19 -0
  305. package/dist/timebox/timebox-discover.d.ts.map +1 -0
  306. package/dist/timebox/timebox-discover.js +87 -0
  307. package/dist/timebox/timebox-discover.js.map +1 -0
  308. package/dist/timebox/timebox-settings.d.ts +32 -0
  309. package/dist/timebox/timebox-settings.d.ts.map +1 -0
  310. package/dist/timebox/timebox-settings.js +80 -0
  311. package/dist/timebox/timebox-settings.js.map +1 -0
  312. package/dist/timeline-store.d.ts +63 -3
  313. package/dist/timeline-store.d.ts.map +1 -1
  314. package/dist/timeline-store.js +292 -14
  315. package/dist/timeline-store.js.map +1 -1
  316. package/dist/timeline-summarizer.d.ts.map +1 -1
  317. package/dist/timeline-summarizer.js +29 -5
  318. package/dist/timeline-summarizer.js.map +1 -1
  319. package/dist/tui/ansi.d.ts +0 -4
  320. package/dist/tui/ansi.d.ts.map +1 -1
  321. package/dist/tui/ansi.js +14 -7
  322. package/dist/tui/ansi.js.map +1 -1
  323. package/dist/tui/dashboard.d.ts +1 -0
  324. package/dist/tui/dashboard.d.ts.map +1 -1
  325. package/dist/tui/dashboard.js +24 -7
  326. package/dist/tui/dashboard.js.map +1 -1
  327. package/dist/tui/renderer.d.ts +36 -0
  328. package/dist/tui/renderer.d.ts.map +1 -1
  329. package/dist/tui/renderer.js +303 -119
  330. package/dist/tui/renderer.js.map +1 -1
  331. package/dist/tui/terrarium.d.ts.map +1 -1
  332. package/dist/tui/terrarium.js +37 -49
  333. package/dist/tui/terrarium.js.map +1 -1
  334. package/dist/types.d.ts +2 -2
  335. package/dist/types.d.ts.map +1 -1
  336. package/dist/types.js +2 -2
  337. package/dist/types.js.map +1 -1
  338. package/dist/usage-api.d.ts.map +1 -1
  339. package/dist/usage-api.js +7 -1
  340. package/dist/usage-api.js.map +1 -1
  341. package/dist/usage-event.d.ts +10 -3
  342. package/dist/usage-event.d.ts.map +1 -1
  343. package/dist/usage-event.js +74 -12
  344. package/dist/usage-event.js.map +1 -1
  345. package/dist/utility-proxy.d.ts.map +1 -1
  346. package/dist/utility-proxy.js +8 -0
  347. package/dist/utility-proxy.js.map +1 -1
  348. package/dist/utils/project-name.d.ts +3 -0
  349. package/dist/utils/project-name.d.ts.map +1 -1
  350. package/dist/utils/project-name.js +44 -2
  351. package/dist/utils/project-name.js.map +1 -1
  352. package/dist/windows-service.d.ts +26 -0
  353. package/dist/windows-service.d.ts.map +1 -0
  354. package/dist/windows-service.js +145 -0
  355. package/dist/windows-service.js.map +1 -0
  356. package/dist/ws-server.d.ts +22 -1
  357. package/dist/ws-server.d.ts.map +1 -1
  358. package/dist/ws-server.js +89 -4
  359. package/dist/ws-server.js.map +1 -1
  360. package/fm-helper/AgentDeckFMHelper.swift +112 -0
  361. package/package.json +9 -3
  362. package/scripts/build-fm-helper.mjs +26 -0
  363. package/LICENSE +0 -21
  364. package/dist/apme/tuner.d.ts +0 -64
  365. package/dist/apme/tuner.d.ts.map +0 -1
  366. package/dist/apme/tuner.js +0 -297
  367. package/dist/apme/tuner.js.map +0 -1
  368. package/dist/d200h/hid-protocol.d.ts +0 -62
  369. package/dist/d200h/hid-protocol.d.ts.map +0 -1
  370. package/dist/d200h/hid-protocol.js +0 -124
  371. package/dist/d200h/hid-protocol.js.map +0 -1
  372. package/dist/d200h/image-renderer.d.ts +0 -36
  373. package/dist/d200h/image-renderer.d.ts.map +0 -1
  374. package/dist/d200h/image-renderer.js +0 -487
  375. package/dist/d200h/image-renderer.js.map +0 -1
  376. package/dist/modules/d200h-module.d.ts +0 -43
  377. package/dist/modules/d200h-module.d.ts.map +0 -1
  378. package/dist/modules/d200h-module.js +0 -360
  379. package/dist/modules/d200h-module.js.map +0 -1
  380. package/dist/modules/d200h-renderer.d.ts +0 -7
  381. package/dist/modules/d200h-renderer.d.ts.map +0 -1
  382. package/dist/modules/d200h-renderer.js +0 -321
  383. package/dist/modules/d200h-renderer.js.map +0 -1
@@ -0,0 +1,234 @@
1
+ /**
2
+ * OpenClaw Gateway event → TelemetrySpan adapter.
3
+ *
4
+ * OpenClaw is a chat-style remote agent reached over a WebSocket Gateway
5
+ * (`shared/src/gateway-protocol.ts`). Unlike Claude Code (Stop hook +
6
+ * PostToolUse TodoWrite) and Codex CLI (hook system), OpenClaw never emits a
7
+ * structured "task complete" signal — it streams `chat.delta` chunks during
8
+ * generation and a single `chat.final` per assistant turn. With nothing
9
+ * stronger to anchor a task to, OpenClaw previously fell back to
10
+ * `session_end` only, collapsing every chat session to a single APME task
11
+ * and defeating per-task evaluation.
12
+ *
13
+ * # Boundary signal: idle_gap (90 s)
14
+ *
15
+ * The chosen boundary is **idle_gap**: after `chat.final`, if the user
16
+ * doesn't send a new `chat.send` within 90 seconds, treat the conversation
17
+ * as one closed task. Rationale, derived from inspecting the chat-final /
18
+ * chat-delta fixture set (`tests/parity/gateway-frames/`) and the four
19
+ * scenario classes that ship in the audit plan:
20
+ *
21
+ * (a) Single Q/A → 1 final, no follow-up → idle_gap fires once.
22
+ * (b) Multi-turn collab → user keeps replying within 90 s → 1 task
23
+ * (collaboration stays together).
24
+ * (c) Long task w/ Qs → same as (b), user clarifications keep the
25
+ * idle timer reset until the agent fully closes
26
+ * the topic.
27
+ * (d) Abrupt new topic → if the pivot happens within 90 s of the
28
+ * previous final, this v1 will lump both into
29
+ * one task. Acceptable v1 limitation —
30
+ * user-driven `manual` boundary or longer
31
+ * silence between topics splits them. A future
32
+ * topic-shift embedder is the obvious next step.
33
+ *
34
+ * 90 s is conservative: long enough that genuine multi-turn debugging
35
+ * stays together, short enough that a real "I'm done, walking away"
36
+ * gesture closes the task within a normal coffee break. The threshold is
37
+ * exposed as `OPENCLAW_IDLE_GAP_MS` so a downstream consumer can override
38
+ * for a hot-research session if needed.
39
+ *
40
+ * # Alternative boundaries considered (rejected for v1)
41
+ *
42
+ * - `chat.final` per turn: too granular — every user/assistant turn pair
43
+ * would be its own task. Defeats the "what did the agent accomplish"
44
+ * framing — evaluation should span the work, not the words.
45
+ * - Embedding-based topic shift: cost-heavy + cold-start fragile. Not v1.
46
+ * - Gateway `taskCompleted` event: no such event in `GatewayEventPayload`
47
+ * union. Adding it requires the OpenClaw server to emit it, which the
48
+ * bridge can't unilaterally do.
49
+ *
50
+ * # Wiring
51
+ *
52
+ * `bridge/src/adapters/openclaw.ts` calls `openclawChatEventToSpans(ctx,
53
+ * payload)` from its `chat` event branch and forwards the resulting spans
54
+ * to `apme.collector.ingestSpan`. The idle timer is owned by the OpenClaw
55
+ * adapter (not this module) because it needs access to the active session
56
+ * id and an actual `setTimeout`. This module is pure — given a payload it
57
+ * returns the spans the adapter should currently emit, no side effects.
58
+ */
59
+ import { randomUUID } from 'crypto';
60
+ import { spanNameForKind } from '@agentdeck/shared';
61
+ /** Default idle-gap threshold after `chat.final` before we close the task. */
62
+ export const OPENCLAW_IDLE_GAP_MS = 90_000;
63
+ /**
64
+ * Convert a Gateway `chat` event payload into the spans the APME collector
65
+ * should ingest right now. Does NOT emit the idle-gap `task_boundary` —
66
+ * that's owned by the adapter's timer (it needs setTimeout + per-session
67
+ * state). Callers should also fire `emitIdleGapTaskBoundary(...)` when the
68
+ * idle timer expires.
69
+ */
70
+ export function openclawChatEventToSpans(ctx, payload) {
71
+ const ts = Date.now();
72
+ const baseAttrs = {
73
+ 'agentdeck.agent_type': ctx.agentType,
74
+ ...(ctx.cwd ? { 'agentdeck.cwd': ctx.cwd } : {}),
75
+ ...(payload.runId ? { 'agentdeck.run_id': payload.runId } : {}),
76
+ ...(payload.sessionKey ? { 'agentdeck.gateway_session_key': payload.sessionKey } : {}),
77
+ };
78
+ const make = (kind, attributes = {}) => ({
79
+ traceId: ctx.traceId,
80
+ spanId: randomUUID(),
81
+ parentSpanId: ctx.activeTurnId,
82
+ name: spanNameForKind(kind),
83
+ kind,
84
+ ts,
85
+ attributes: { ...baseAttrs, ...attributes },
86
+ });
87
+ if (payload.state === 'delta') {
88
+ // Deltas are streaming chunks — only the first delta of a new turn is
89
+ // load-bearing for APME (opens the turn). The OpenClaw adapter detects
90
+ // "first delta" via `chatStarted` and is responsible for emitting the
91
+ // turn_start when calling us. We don't emit on every delta — that
92
+ // would balloon the steps table and add no eval signal.
93
+ return [];
94
+ }
95
+ if (payload.state === 'final') {
96
+ const spans = [];
97
+ if (payload.response) {
98
+ spans.push(make('turn_response', { 'agentdeck.response_text': payload.response }));
99
+ }
100
+ if (Array.isArray(payload.tools)) {
101
+ for (const t of payload.tools) {
102
+ if (!t.name)
103
+ continue;
104
+ spans.push(make('tool_result', {
105
+ 'gen_ai.tool.name': t.name,
106
+ 'agentdeck.tool_name': t.name,
107
+ ...(t.status ? { 'agentdeck.tool_status': t.status } : {}),
108
+ }));
109
+ }
110
+ }
111
+ return spans;
112
+ }
113
+ if (payload.state === 'aborted') {
114
+ // Treat as a manual boundary — user explicitly stopped this turn. The
115
+ // composite outcome derivation will see the absence of a complete
116
+ // response and score accordingly.
117
+ return [make('task_boundary', { 'agentdeck.boundary_signal': 'manual' })];
118
+ }
119
+ if (payload.state === 'error') {
120
+ // Error doesn't close the task — agent might retry on the same prompt.
121
+ // The error is recorded for context but the idle timer continues to
122
+ // run. Returning empty array lets the adapter keep its lifecycle state.
123
+ return [];
124
+ }
125
+ return [];
126
+ }
127
+ /**
128
+ * Convert a Gateway `session.tool` event into spans. This granular per-tool
129
+ * stream carries the tool INPUT/OUTPUT that the coarse `chat.final` tools array
130
+ * lacks — and it was previously silently dropped (openclaw.ts default case), so
131
+ * the sample's tool trajectory had no detail. A `running`/`pending` status maps
132
+ * to a `tool_call` (opens a pending ToolEvent); a terminal status maps to a
133
+ * `tool_result` (resolves it). Pure — no side effects.
134
+ */
135
+ export function openclawSessionToolToSpans(ctx, payload) {
136
+ const name = payload.name ?? payload.tool;
137
+ if (!name)
138
+ return [];
139
+ const ts = typeof payload.ts === 'number' ? payload.ts : Date.now();
140
+ const status = (payload.status ?? '').toLowerCase();
141
+ const pending = status === '' || status === 'running' || status === 'pending' || status === 'started' || status === 'in_progress';
142
+ const kind = pending ? 'tool_call' : 'tool_result';
143
+ const attrs = {
144
+ 'agentdeck.agent_type': ctx.agentType,
145
+ ...(ctx.cwd ? { 'agentdeck.cwd': ctx.cwd } : {}),
146
+ 'gen_ai.tool.name': name,
147
+ 'agentdeck.tool_name': name,
148
+ 'agentdeck.raw_payload': {
149
+ ...(payload.status ? { status: payload.status } : {}),
150
+ ...(payload.input !== undefined ? { tool_input: payload.input } : {}),
151
+ ...(payload.output !== undefined ? { tool_response: payload.output } : {}),
152
+ },
153
+ };
154
+ return [{
155
+ traceId: ctx.traceId,
156
+ spanId: randomUUID(),
157
+ parentSpanId: ctx.activeTurnId,
158
+ name: spanNameForKind(kind),
159
+ kind,
160
+ ts,
161
+ attributes: attrs,
162
+ }];
163
+ }
164
+ /**
165
+ * Convert a Gateway `session.out-of-band message` into a turn span. User
166
+ * messages open a turn (turn_start); assistant messages set the response
167
+ * (turn_response). Previously dropped, so gateway-initiated turns (cron,
168
+ * automations) had no captured prompt/response in the sample.
169
+ */
170
+ export function openclawSessionMessageToSpans(ctx, payload) {
171
+ const text = (typeof payload.text === 'string' ? payload.text : undefined)
172
+ ?? (typeof payload.content === 'string' ? payload.content : undefined);
173
+ if (!text || !text.trim())
174
+ return [];
175
+ const ts = typeof payload.ts === 'number' ? payload.ts : Date.now();
176
+ const role = (payload.role ?? '').toLowerCase();
177
+ const kind = role === 'assistant' ? 'turn_response' : 'turn_start';
178
+ const attrs = {
179
+ 'agentdeck.agent_type': ctx.agentType,
180
+ ...(ctx.cwd ? { 'agentdeck.cwd': ctx.cwd } : {}),
181
+ ...(kind === 'turn_start' ? { 'agentdeck.prompt_text': text } : { 'agentdeck.response_text': text }),
182
+ };
183
+ return [{
184
+ traceId: ctx.traceId,
185
+ spanId: randomUUID(),
186
+ parentSpanId: ctx.activeTurnId,
187
+ name: spanNameForKind(kind),
188
+ kind,
189
+ ts,
190
+ attributes: attrs,
191
+ }];
192
+ }
193
+ /**
194
+ * Build the spans the adapter should emit when its idle-gap timer expires.
195
+ * Returned as a function (not a constant) because the timestamp is "now"
196
+ * at expiry, not "now" at adapter construction.
197
+ */
198
+ export function openclawIdleGapTaskBoundary(ctx) {
199
+ return {
200
+ traceId: ctx.traceId,
201
+ spanId: randomUUID(),
202
+ parentSpanId: ctx.activeTurnId,
203
+ name: spanNameForKind('task_boundary'),
204
+ kind: 'task_boundary',
205
+ ts: Date.now(),
206
+ attributes: {
207
+ 'agentdeck.agent_type': ctx.agentType,
208
+ ...(ctx.cwd ? { 'agentdeck.cwd': ctx.cwd } : {}),
209
+ 'agentdeck.boundary_signal': 'idle_gap',
210
+ },
211
+ };
212
+ }
213
+ /**
214
+ * Build the user-prompt span the adapter should emit on `chat.send`. Kept
215
+ * here for symmetry with `claude-hook.ts::claudeHookToSpans` and so future
216
+ * test fixtures can exercise the boundary detector without spinning a real
217
+ * Gateway connection.
218
+ */
219
+ export function openclawChatSendToSpan(ctx, prompt) {
220
+ return {
221
+ traceId: ctx.traceId,
222
+ spanId: randomUUID(),
223
+ parentSpanId: undefined,
224
+ name: spanNameForKind('turn_start'),
225
+ kind: 'turn_start',
226
+ ts: Date.now(),
227
+ attributes: {
228
+ 'agentdeck.agent_type': ctx.agentType,
229
+ ...(ctx.cwd ? { 'agentdeck.cwd': ctx.cwd } : {}),
230
+ 'agentdeck.prompt_text': prompt,
231
+ },
232
+ };
233
+ }
234
+ //# sourceMappingURL=openclaw-hook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openclaw-hook.js","sourceRoot":"","sources":["../../../src/apme/adapters/openclaw-hook.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * OpenCode SSE → TelemetrySpan adapter.
3
+ *
4
+ * OpenCode (https://github.com/sst/opencode) is the third coding agent
5
+ * AgentDeck monitors. Unlike Claude Code and Codex CLI, it has no command-
6
+ * level hook layer — its lifecycle is observed via the SSE stream emitted by
7
+ * `opencode serve` on its HTTP port. The OpenCode adapter
8
+ * (`bridge/src/adapters/opencode-adapter.ts`) subscribes to that stream and
9
+ * forwards `OpenCodeSSEEvent` payloads into the bridge.
10
+ *
11
+ * This helper takes those SSE payloads and produces the same `TelemetrySpan`
12
+ * shape that `claude-hook.ts` and `codex-hook.ts` emit, so the existing
13
+ * `ApmeCollector.ingestSpan` pipeline handles all three agents uniformly.
14
+ * Without this, OpenCode runs never reach APME — they fall back to
15
+ * `session_end`-only task boundaries (one task per session, defeating
16
+ * per-task evaluation).
17
+ *
18
+ * Detected boundary signals (priority order):
19
+ * 1. `todo_complete` — `message.part.updated` carrying a tool part whose
20
+ * tool name is "todowrite" and whose `state.output` reports every todo
21
+ * with `status === 'completed'`. OpenCode's todowrite tool is the
22
+ * analogue of Claude's TodoWrite + Codex's todo manager.
23
+ * 2. `idle_gap` — the adapter arms a timer on `session.idle` and fires
24
+ * `opencodeIdleGapTaskBoundary` after OPENCODE_IDLE_GAP_MS with no new
25
+ * work (mirrors the OpenClaw idle-gap segmentation). Without it,
26
+ * OpenCode tasks close only on `session_end` — one task per session,
27
+ * defeating per-task evaluation.
28
+ * 3. (`/clear` and `manual` are reserved for future direct integrations —
29
+ * OpenCode doesn't currently surface either via SSE.)
30
+ *
31
+ * Tool calls and tool results map to `tool_call` / `tool_result` spans for
32
+ * step-level parity with Claude / Codex (drives the timeline and the
33
+ * deterministic Layer 1 efficiency metrics).
34
+ */
35
+ import type { AdapterContext, TelemetrySpan } from '@agentdeck/shared';
36
+ import type { OpenCodeMessagePart, OpenCodeMessageInfo } from '../../opencode-client.js';
37
+ /**
38
+ * Convert a single OpenCode SSE `message.part.updated` payload into spans.
39
+ *
40
+ * Returns an empty array when the part isn't APME-relevant (text / step-finish
41
+ * are accumulated elsewhere). Caller is expected to drop empty arrays.
42
+ */
43
+ export declare function opencodePartToSpans(ctx: AdapterContext, part: OpenCodeMessagePart): TelemetrySpan[];
44
+ /**
45
+ * Spans for a `message.updated` SSE payload. OpenCode emits these on both
46
+ * user prompts (open a turn) and assistant turn-end signals (close it).
47
+ */
48
+ export declare function opencodeMessageToSpans(ctx: AdapterContext, info: OpenCodeMessageInfo, promptText: string | undefined, responseText: string | undefined): TelemetrySpan[];
49
+ /** How long a session must sit idle (no new work after `session.idle`)
50
+ * before the active task closes with an `idle_gap` boundary. Matches
51
+ * OPENCLAW_IDLE_GAP_MS — the two adapters segment on the same rhythm. */
52
+ export declare const OPENCODE_IDLE_GAP_MS = 90000;
53
+ /** Build the `task_boundary` (idle_gap) span the adapter emits when the
54
+ * idle-gap timer fires. Mirrors `openclawIdleGapTaskBoundary`. */
55
+ export declare function opencodeIdleGapTaskBoundary(ctx: AdapterContext): TelemetrySpan;
56
+ //# sourceMappingURL=opencode-hook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode-hook.d.ts","sourceRoot":"","sources":["../../../src/apme/adapters/opencode-hook.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAGH,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EAEd,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEzF;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,mBAAmB,GACxB,aAAa,EAAE,CAuCjB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,mBAAmB,EACzB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,YAAY,EAAE,MAAM,GAAG,SAAS,GAC/B,aAAa,EAAE,CAoCjB;AAED;;0EAE0E;AAC1E,eAAO,MAAM,oBAAoB,QAAS,CAAC;AAE3C;mEACmE;AACnE,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,cAAc,GAAG,aAAa,CAc9E"}
@@ -0,0 +1,182 @@
1
+ /**
2
+ * OpenCode SSE → TelemetrySpan adapter.
3
+ *
4
+ * OpenCode (https://github.com/sst/opencode) is the third coding agent
5
+ * AgentDeck monitors. Unlike Claude Code and Codex CLI, it has no command-
6
+ * level hook layer — its lifecycle is observed via the SSE stream emitted by
7
+ * `opencode serve` on its HTTP port. The OpenCode adapter
8
+ * (`bridge/src/adapters/opencode-adapter.ts`) subscribes to that stream and
9
+ * forwards `OpenCodeSSEEvent` payloads into the bridge.
10
+ *
11
+ * This helper takes those SSE payloads and produces the same `TelemetrySpan`
12
+ * shape that `claude-hook.ts` and `codex-hook.ts` emit, so the existing
13
+ * `ApmeCollector.ingestSpan` pipeline handles all three agents uniformly.
14
+ * Without this, OpenCode runs never reach APME — they fall back to
15
+ * `session_end`-only task boundaries (one task per session, defeating
16
+ * per-task evaluation).
17
+ *
18
+ * Detected boundary signals (priority order):
19
+ * 1. `todo_complete` — `message.part.updated` carrying a tool part whose
20
+ * tool name is "todowrite" and whose `state.output` reports every todo
21
+ * with `status === 'completed'`. OpenCode's todowrite tool is the
22
+ * analogue of Claude's TodoWrite + Codex's todo manager.
23
+ * 2. `idle_gap` — the adapter arms a timer on `session.idle` and fires
24
+ * `opencodeIdleGapTaskBoundary` after OPENCODE_IDLE_GAP_MS with no new
25
+ * work (mirrors the OpenClaw idle-gap segmentation). Without it,
26
+ * OpenCode tasks close only on `session_end` — one task per session,
27
+ * defeating per-task evaluation.
28
+ * 3. (`/clear` and `manual` are reserved for future direct integrations —
29
+ * OpenCode doesn't currently surface either via SSE.)
30
+ *
31
+ * Tool calls and tool results map to `tool_call` / `tool_result` spans for
32
+ * step-level parity with Claude / Codex (drives the timeline and the
33
+ * deterministic Layer 1 efficiency metrics).
34
+ */
35
+ import { randomUUID } from 'crypto';
36
+ import { spanNameForKind } from '@agentdeck/shared';
37
+ /**
38
+ * Convert a single OpenCode SSE `message.part.updated` payload into spans.
39
+ *
40
+ * Returns an empty array when the part isn't APME-relevant (text / step-finish
41
+ * are accumulated elsewhere). Caller is expected to drop empty arrays.
42
+ */
43
+ export function opencodePartToSpans(ctx, part) {
44
+ if (part.type !== 'tool')
45
+ return [];
46
+ const ts = Date.now();
47
+ const toolName = (part.tool ?? 'unknown').toLowerCase();
48
+ const status = part.state?.status ?? 'running';
49
+ const baseAttrs = {
50
+ 'agentdeck.agent_type': ctx.agentType,
51
+ ...(ctx.cwd ? { 'agentdeck.cwd': ctx.cwd } : {}),
52
+ 'gen_ai.tool.name': toolName,
53
+ 'agentdeck.tool_name': toolName,
54
+ 'agentdeck.raw_payload': part,
55
+ };
56
+ const make = (kind, attributes = {}) => ({
57
+ traceId: ctx.traceId,
58
+ spanId: randomUUID(),
59
+ parentSpanId: ctx.activeTurnId,
60
+ name: spanNameForKind(kind),
61
+ kind,
62
+ ts,
63
+ attributes: { ...baseAttrs, ...attributes },
64
+ });
65
+ const spans = [];
66
+ if (status === 'completed') {
67
+ spans.push(make('tool_result'));
68
+ // todowrite completion with every item marked 'completed' is the agent
69
+ // declaring the task done — same semantics as Claude's TodoWrite
70
+ // PostToolUse boundary check in `collector.ts::ingestHook`.
71
+ if (toolName === 'todowrite' && allTodosCompleted(part)) {
72
+ spans.push(make('task_boundary', { 'agentdeck.boundary_signal': 'todo_complete' }));
73
+ }
74
+ }
75
+ else {
76
+ spans.push(make('tool_call'));
77
+ }
78
+ return spans;
79
+ }
80
+ /**
81
+ * Spans for a `message.updated` SSE payload. OpenCode emits these on both
82
+ * user prompts (open a turn) and assistant turn-end signals (close it).
83
+ */
84
+ export function opencodeMessageToSpans(ctx, info, promptText, responseText) {
85
+ const ts = Date.now();
86
+ const baseAttrs = {
87
+ 'agentdeck.agent_type': ctx.agentType,
88
+ ...(ctx.cwd ? { 'agentdeck.cwd': ctx.cwd } : {}),
89
+ };
90
+ const make = (kind, attributes = {}) => ({
91
+ traceId: ctx.traceId,
92
+ spanId: randomUUID(),
93
+ parentSpanId: ctx.activeTurnId,
94
+ name: spanNameForKind(kind),
95
+ kind,
96
+ ts,
97
+ attributes: { ...baseAttrs, ...attributes },
98
+ });
99
+ const spans = [];
100
+ // Attribute the model as soon as an assistant message reveals it. OpenCode's
101
+ // SSE `message.updated` carries modelID/providerID, but that only ever
102
+ // reached the display StateMachine — the APME span pipeline never emitted a
103
+ // session_meta span, so every opencode run persisted model_id=NULL. Emitting
104
+ // it here routes through collector.ts (gen_ai.request.model -> updateModel),
105
+ // which writes directly to the bound APME session (no StateMachine reliance).
106
+ if (info.role === 'assistant' && info.modelID) {
107
+ const model = info.providerID ? `${info.providerID}/${info.modelID}` : info.modelID;
108
+ spans.push(make('session_meta', { 'gen_ai.request.model': model }));
109
+ }
110
+ if (info.role === 'user' && promptText) {
111
+ spans.push(make('turn_start', { 'agentdeck.prompt_text': promptText }));
112
+ }
113
+ else if (info.role === 'assistant' && responseText) {
114
+ spans.push(make('turn_response', { 'agentdeck.response_text': responseText }));
115
+ }
116
+ return spans;
117
+ }
118
+ /** How long a session must sit idle (no new work after `session.idle`)
119
+ * before the active task closes with an `idle_gap` boundary. Matches
120
+ * OPENCLAW_IDLE_GAP_MS — the two adapters segment on the same rhythm. */
121
+ export const OPENCODE_IDLE_GAP_MS = 90_000;
122
+ /** Build the `task_boundary` (idle_gap) span the adapter emits when the
123
+ * idle-gap timer fires. Mirrors `openclawIdleGapTaskBoundary`. */
124
+ export function opencodeIdleGapTaskBoundary(ctx) {
125
+ return {
126
+ traceId: ctx.traceId,
127
+ spanId: randomUUID(),
128
+ parentSpanId: ctx.activeTurnId,
129
+ name: spanNameForKind('task_boundary'),
130
+ kind: 'task_boundary',
131
+ ts: Date.now(),
132
+ attributes: {
133
+ 'agentdeck.agent_type': ctx.agentType,
134
+ ...(ctx.cwd ? { 'agentdeck.cwd': ctx.cwd } : {}),
135
+ 'agentdeck.boundary_signal': 'idle_gap',
136
+ },
137
+ };
138
+ }
139
+ /**
140
+ * Read the todos array out of an OpenCode todowrite tool part. OpenCode's
141
+ * todowrite stores its state under `part.state.output` as a JSON string of
142
+ * `{ todos: [{ status, ... }] }` (the same shape Claude Code's TodoWrite
143
+ * uses). Returns true when every entry is `completed`. Empty list returns
144
+ * false — we shouldn't treat "no todos" as task completion.
145
+ */
146
+ function allTodosCompleted(part) {
147
+ // Try input first (some OpenCode versions echo the final todos list there).
148
+ const inputTodos = readTodosFromUnknown(part.state?.input);
149
+ if (inputTodos && inputTodos.length > 0 && inputTodos.every((t) => t.status === 'completed')) {
150
+ return true;
151
+ }
152
+ // Output is usually a JSON-encoded string.
153
+ const output = part.state?.output;
154
+ if (typeof output === 'string') {
155
+ try {
156
+ const parsed = JSON.parse(output);
157
+ const todos = readTodosFromUnknown(parsed);
158
+ if (todos && todos.length > 0) {
159
+ return todos.every((t) => t.status === 'completed');
160
+ }
161
+ }
162
+ catch {
163
+ // ignore malformed output — treat as not-all-completed
164
+ }
165
+ }
166
+ return false;
167
+ }
168
+ function readTodosFromUnknown(value) {
169
+ if (!value || typeof value !== 'object')
170
+ return null;
171
+ const obj = value;
172
+ const candidates = [obj.todos, obj.tool_input?.todos];
173
+ for (const c of candidates) {
174
+ if (Array.isArray(c)) {
175
+ return c
176
+ .filter((it) => !!it && typeof it === 'object')
177
+ .map((it) => ({ status: String(it.status ?? '') }));
178
+ }
179
+ }
180
+ return null;
181
+ }
182
+ //# sourceMappingURL=opencode-hook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode-hook.js","sourceRoot":"","sources":["../../../src/apme/adapters/opencode-hook.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"timeline.d.ts","sourceRoot":"","sources":["../../../src/apme/adapters/timeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EAEb,aAAa,EACd,MAAM,mBAAmB,CAAC;AAG3B,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,aAAa,GACnB,aAAa,EAAE,CAmDjB"}
1
+ {"version":3,"file":"timeline.d.ts","sourceRoot":"","sources":["../../../src/apme/adapters/timeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EAEb,aAAa,EACd,MAAM,mBAAmB,CAAC;AAG3B,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,aAAa,GACnB,aAAa,EAAE,CAwDjB"}
@@ -48,7 +48,12 @@ export function timelineEntryToSpans(ctx, entry) {
48
48
  'agentdeck.fallback_to_last_closed': true,
49
49
  })];
50
50
  }
51
- case 'tool_request': {
51
+ // tool_request: Claude PreToolUse hook + Codex parser tool_action (after
52
+ // 2025-05 alignment) emit this. tool_exec: legacy OpenClaw parseLogLine
53
+ // and pre-alignment Codex emits — treated identically so APME counts
54
+ // every tool invocation regardless of source.
55
+ case 'tool_request':
56
+ case 'tool_exec': {
52
57
  // Some sources pack the tool name as the first whitespace-delimited token
53
58
  // in `raw`; when missing, the collector falls back to the literal 'tool'.
54
59
  const toolName = entry.raw?.split(' ')[0] ?? 'tool';
@@ -1 +1 @@
1
- {"version":3,"file":"timeline.js","sourceRoot":"","sources":["../../../src/apme/adapters/timeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAOpC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,UAAU,oBAAoB,CAClC,GAAmB,EACnB,KAAoB;IAEpB,MAAM,EAAE,GAAG,KAAK,CAAC,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;IAClC,MAAM,SAAS,GAAwB;QACrC,sBAAsB,EAAE,GAAG,CAAC,SAAS;QACrC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACjD,CAAC;IACF,MAAM,IAAI,GAAG,CACX,IAA2B,EAC3B,UAA+B,EAChB,EAAE,CAAC,CAAC;QACnB,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,MAAM,EAAE,UAAU,EAAE;QACpB,YAAY,EAAE,GAAG,CAAC,YAAY;QAC9B,IAAI,EAAE,eAAe,CAAC,IAAI,CAAC;QAC3B,IAAI;QACJ,EAAE;QACF,UAAU,EAAE,EAAE,GAAG,SAAS,EAAE,GAAG,UAAU,EAAE;KAC5C,CAAC,CAAC;IAEH,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,YAAY,CAAC,CAAC,CAAC;YAClB,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC;YAC/C,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,uBAAuB,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;QACnE,CAAC;QACD,KAAK,eAAe,CAAC,CAAC,CAAC;YACrB,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC;YACjD,IAAI,QAAQ,CAAC,MAAM,IAAI,CAAC;gBAAE,OAAO,EAAE,CAAC;YACpC,OAAO,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,yBAAyB,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;QAC1E,CAAC;QACD,KAAK,UAAU,CAAC,CAAC,CAAC;YAChB,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC;YACpC,IAAI,QAAQ,CAAC,MAAM,IAAI,CAAC;gBAAE,OAAO,EAAE,CAAC;YACpC,OAAO,CAAC,IAAI,CAAC,eAAe,EAAE;oBAC5B,yBAAyB,EAAE,QAAQ;oBACnC,mCAAmC,EAAE,IAAI;iBAC1C,CAAC,CAAC,CAAC;QACN,CAAC;QACD,KAAK,cAAc,CAAC,CAAC,CAAC;YACpB,0EAA0E;YAC1E,0EAA0E;YAC1E,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC;YACpD,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE;oBACxB,kBAAkB,EAAE,QAAQ;oBAC5B,qBAAqB,EAAE,QAAQ;iBAChC,CAAC,CAAC,CAAC;QACN,CAAC;QACD,KAAK,eAAe;YAClB,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,CAAC;QACnC;YACE,OAAO,EAAE,CAAC;IACd,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"timeline.js","sourceRoot":"","sources":["../../../src/apme/adapters/timeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAOpC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,UAAU,oBAAoB,CAClC,GAAmB,EACnB,KAAoB;IAEpB,MAAM,EAAE,GAAG,KAAK,CAAC,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;IAClC,MAAM,SAAS,GAAwB;QACrC,sBAAsB,EAAE,GAAG,CAAC,SAAS;QACrC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACjD,CAAC;IACF,MAAM,IAAI,GAAG,CACX,IAA2B,EAC3B,UAA+B,EAChB,EAAE,CAAC,CAAC;QACnB,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,MAAM,EAAE,UAAU,EAAE;QACpB,YAAY,EAAE,GAAG,CAAC,YAAY;QAC9B,IAAI,EAAE,eAAe,CAAC,IAAI,CAAC;QAC3B,IAAI;QACJ,EAAE;QACF,UAAU,EAAE,EAAE,GAAG,SAAS,EAAE,GAAG,UAAU,EAAE;KAC5C,CAAC,CAAC;IAEH,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,YAAY,CAAC,CAAC,CAAC;YAClB,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC;YAC/C,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,uBAAuB,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;QACnE,CAAC;QACD,KAAK,eAAe,CAAC,CAAC,CAAC;YACrB,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC;YACjD,IAAI,QAAQ,CAAC,MAAM,IAAI,CAAC;gBAAE,OAAO,EAAE,CAAC;YACpC,OAAO,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,yBAAyB,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;QAC1E,CAAC;QACD,KAAK,UAAU,CAAC,CAAC,CAAC;YAChB,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC;YACpC,IAAI,QAAQ,CAAC,MAAM,IAAI,CAAC;gBAAE,OAAO,EAAE,CAAC;YACpC,OAAO,CAAC,IAAI,CAAC,eAAe,EAAE;oBAC5B,yBAAyB,EAAE,QAAQ;oBACnC,mCAAmC,EAAE,IAAI;iBAC1C,CAAC,CAAC,CAAC;QACN,CAAC;QACD,yEAAyE;QACzE,wEAAwE;QACxE,qEAAqE;QACrE,8CAA8C;QAC9C,KAAK,cAAc,CAAC;QACpB,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,0EAA0E;YAC1E,0EAA0E;YAC1E,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC;YACpD,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE;oBACxB,kBAAkB,EAAE,QAAQ;oBAC5B,qBAAqB,EAAE,QAAQ;iBAChC,CAAC,CAAC,CAAC;QACN,CAAC;QACD,KAAK,eAAe;YAClB,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,CAAC;QACnC;YACE,OAAO,EAAE,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,18 @@
1
+ export interface AntigravityTranscriptSummary {
2
+ goal?: string;
3
+ state: 'idle' | 'processing';
4
+ currentTask?: string;
5
+ /** Human model label from the transcript's last USER_SETTINGS_CHANGE, if any
6
+ * (e.g. "GPT-OSS 120B (Medium)", "Gemini 3.5 Flash (Medium)"). */
7
+ model?: string;
8
+ }
9
+ export declare function antigravityRoot(): string;
10
+ /** Parse an agy transcript sample into goal / state / currentTask / model. */
11
+ export declare function parseAntigravityTranscript(raw: string): AntigravityTranscriptSummary;
12
+ /** Global default model from settings.json (fallback when a conversation never
13
+ * recorded an explicit model selection). */
14
+ export declare function antigravityDefaultModel(): string | undefined;
15
+ /** Resolve the conversationId for a workspace cwd via the last-opened cache. */
16
+ export declare function antigravityConversationId(cwd: string | undefined): string | undefined;
17
+ export declare function antigravityTranscriptPath(conversationId: string): string;
18
+ //# sourceMappingURL=antigravity-transcript.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"antigravity-transcript.d.ts","sourceRoot":"","sources":["../../src/apme/antigravity-transcript.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,4BAA4B;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,YAAY,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;uEACmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAgBD,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED,8EAA8E;AAC9E,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,GAAG,4BAA4B,CA8BpF;AAMD;6CAC6C;AAC7C,wBAAgB,uBAAuB,IAAI,MAAM,GAAG,SAAS,CAK5D;AAED,gFAAgF;AAChF,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAQrF;AAED,wBAAgB,yBAAyB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAExE"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Antigravity (`agy` CLI) transcript parsing.
3
+ *
4
+ * The agy CLI persists each conversation as a plain JSONL transcript at
5
+ * ~/.gemini/antigravity-cli/brain/<conversationId>/.system_generated/logs/transcript.jsonl
6
+ * one JSON object per step:
7
+ * { step_index, source, type, status, created_at, content?, thinking?, tool_calls? }
8
+ *
9
+ * Unlike Claude/Codex, the model id is NOT on each record. It surfaces in the
10
+ * first USER_INPUT's `<USER_SETTINGS_CHANGE>` tag ("...from None to <MODEL>.")
11
+ * when a model is selected for the conversation; otherwise the global default
12
+ * in `settings.json` applies. The session log carries a live override line too,
13
+ * but the per-conversation transcript is the cleanest attribution source.
14
+ *
15
+ * These pure functions are shared by the passive observer (creature + model
16
+ * display) and the APME ingester (run/turn model attribution) so agy gets the
17
+ * same scorecard treatment as the other agents.
18
+ */
19
+ import { readFileSync } from 'fs';
20
+ import { homedir } from 'os';
21
+ import { join } from 'path';
22
+ /** Step types that represent the agent doing tool work (drives currentTask). */
23
+ const TOOL_TYPES = new Set([
24
+ 'VIEW_FILE', 'RUN_COMMAND', 'GREP_SEARCH', 'LIST_DIRECTORY', 'CODE_ACTION', 'EDIT_FILE',
25
+ ]);
26
+ export function antigravityRoot() {
27
+ return join(homedir(), '.gemini', 'antigravity-cli');
28
+ }
29
+ /** Parse an agy transcript sample into goal / state / currentTask / model. */
30
+ export function parseAntigravityTranscript(raw) {
31
+ const records = [];
32
+ for (const line of raw.split('\n')) {
33
+ if (!line.trim())
34
+ continue;
35
+ try {
36
+ records.push(JSON.parse(line));
37
+ }
38
+ catch { /* skip malformed line */ }
39
+ }
40
+ let goal;
41
+ let model;
42
+ let currentTask;
43
+ let processing = false;
44
+ for (const rec of records) {
45
+ if (rec.type === 'USER_INPUT' && typeof rec.content === 'string') {
46
+ if (!goal) {
47
+ const req = rec.content.match(/<USER_REQUEST>\s*([\s\S]*?)\s*<\/USER_REQUEST>/);
48
+ if (req && req[1].trim())
49
+ goal = cleanGoal(req[1]);
50
+ }
51
+ // "The user changed setting `Model Selection` from None to GPT-OSS 120B (Medium)."
52
+ // Take the latest one seen → the model active for this conversation.
53
+ const change = rec.content.match(/Model Selection`?\s+from\s+.*?\s+to\s+(.+?)\.(?:\s|$)/);
54
+ if (change && change[1].trim())
55
+ model = change[1].trim();
56
+ }
57
+ if (rec.status === 'RUNNING')
58
+ processing = true;
59
+ if (rec.type && TOOL_TYPES.has(rec.type)) {
60
+ currentTask = rec.tool_calls?.[0]?.name ?? rec.type.toLowerCase();
61
+ }
62
+ }
63
+ return { goal, model, currentTask, state: processing ? 'processing' : 'idle' };
64
+ }
65
+ function cleanGoal(s) {
66
+ return s.replace(/\s+/g, ' ').trim().slice(0, 200);
67
+ }
68
+ /** Global default model from settings.json (fallback when a conversation never
69
+ * recorded an explicit model selection). */
70
+ export function antigravityDefaultModel() {
71
+ try {
72
+ const j = JSON.parse(readFileSync(join(antigravityRoot(), 'settings.json'), 'utf8'));
73
+ return typeof j.model === 'string' ? j.model : undefined;
74
+ }
75
+ catch {
76
+ return undefined;
77
+ }
78
+ }
79
+ /** Resolve the conversationId for a workspace cwd via the last-opened cache. */
80
+ export function antigravityConversationId(cwd) {
81
+ if (!cwd)
82
+ return undefined;
83
+ try {
84
+ const j = JSON.parse(readFileSync(join(antigravityRoot(), 'cache', 'last_conversations.json'), 'utf8'));
85
+ return typeof j[cwd] === 'string' ? j[cwd] : undefined;
86
+ }
87
+ catch {
88
+ return undefined;
89
+ }
90
+ }
91
+ export function antigravityTranscriptPath(conversationId) {
92
+ return join(antigravityRoot(), 'brain', conversationId, '.system_generated', 'logs', 'transcript.jsonl');
93
+ }
94
+ //# sourceMappingURL=antigravity-transcript.js.map