@agentdeck/bridge 0.2.2 → 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 +1021 -93
  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
@@ -6,12 +6,21 @@
6
6
  * Callers should check `store.enabled` before assuming persistence.
7
7
  */
8
8
  import type { ApmeRunRow, ApmeStepRow, ApmeArtifactRow, ApmeEvalRowDb, ApmeRubricRow, ApmeVibeRow, ApmeScorecardRow, ApmeTaskRow } from './types.js';
9
+ import type { ApmeSampleEventRow, ApmeSampleScorecardRow, SessionSample, TrajectoryEvent } from '@agentdeck/shared';
9
10
  export declare class ApmeStore {
10
11
  private db;
11
12
  enabled: boolean;
12
13
  readonly dbPath: string;
14
+ /** Populated when init() returns false. Surfaced in daemon startup logs so
15
+ * silent APME outages (the failure mode that left ~/.agentdeck/apme.sqlite
16
+ * stale for 11 days in 2026-04 user data) become diagnosable. */
17
+ lastInitError: string | null;
13
18
  constructor(dbPath?: string);
14
- /** Attempt to open the DB. Returns false if better-sqlite3 is unavailable. */
19
+ /** Attempt to open the DB. Returns false on failure; check `lastInitError`
20
+ * for the reason. The two common failure modes are:
21
+ * 1. better-sqlite3 native binding missing (CI / setups without build tools)
22
+ * 2. DB file unreadable / DDL fails (disk full, permissions, WAL lock from a
23
+ * crashed prior process). */
15
24
  init(): Promise<boolean>;
16
25
  close(): void;
17
26
  /** Add columns that may be missing from databases created before this version. */
@@ -43,6 +52,12 @@ export declare class ApmeStore {
43
52
  updateTask(id: string, patch: Partial<ApmeTaskRow>): void;
44
53
  getTask(id: string): ApmeTaskRow | null;
45
54
  listTasksForRun(runId: string): ApmeTaskRow[];
55
+ /** All tasks across runs, newest first. Used by `agentdeck apme export --by task`
56
+ * to dump a flat dataset of meaningful task units (one row per closed task). */
57
+ listAllTasks(opts?: {
58
+ limit?: number;
59
+ closedOnly?: boolean;
60
+ }): ApmeTaskRow[];
46
61
  listTurnsForTask(taskId: string): Array<Record<string, unknown>>;
47
62
  /** Ended tasks (boundary hit) that haven't been judged yet — backfill candidates. */
48
63
  listTasksNeedingSummary(limit?: number): Array<{
@@ -86,6 +101,23 @@ export declare class ApmeStore {
86
101
  /** Orphaned runs: started long ago, never closed, no turns.
87
102
  * Typically from session bridges that crashed without cleanup. */
88
103
  listOrphanedRuns(staleSec?: number): string[];
104
+ /** Append one typed trajectory event. INSERT OR IGNORE on the UNIQUE
105
+ * (task_id, dedup_key) index makes storage-time dedup atomic — duplicates
106
+ * never persist. Returns true if a row was actually inserted. */
107
+ insertSampleEvent(row: ApmeSampleEventRow): boolean;
108
+ /** Update a previously-inserted event (e.g. a tool pending→resolved) by id. */
109
+ updateSampleEvent(id: number, fields: Partial<ApmeSampleEventRow>): void;
110
+ /** Find a tool event still pending for (task, turn, toolName), to resolve it. */
111
+ findPendingToolEvent(taskId: string, turnIndex: number, toolName: string): ApmeSampleEventRow | null;
112
+ listSampleEventRows(taskId: string): ApmeSampleEventRow[];
113
+ listSampleEvents(taskId: string): TrajectoryEvent[];
114
+ /** Next monotonic seq within a task. */
115
+ nextSampleSeq(taskId: string): number;
116
+ /** Assemble the full SessionSample (header + cost + typed trajectory). */
117
+ getSample(taskId: string): SessionSample | null;
118
+ /** Recompute the task's cost aggregate by summing its ModelEvents. */
119
+ recomputeSampleCost(taskId: string): void;
120
+ sampleScorecard(): ApmeSampleScorecardRow[];
89
121
  scorecard(): ApmeScorecardRow[];
90
122
  categoryScorecard(): Array<{
91
123
  taskCategory: string;
@@ -1 +1 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/apme/store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/apme/store.ts"],"names":[],"mappings":"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"}
@@ -88,11 +88,43 @@ CREATE TABLE IF NOT EXISTS tasks (
88
88
  outcome TEXT,
89
89
  composite_score REAL,
90
90
  task_category TEXT,
91
- notes_json TEXT
91
+ notes_json TEXT,
92
+ model_id TEXT,
93
+ model_config TEXT,
94
+ input_tokens INTEGER,
95
+ output_tokens INTEGER,
96
+ cost_usd REAL,
97
+ latency_ms INTEGER
92
98
  );
93
99
 
94
100
  CREATE INDEX IF NOT EXISTS idx_tasks_run ON tasks(run_id);
95
101
 
102
+ -- Typed trajectory events — the SessionSample.events projection. The single
103
+ -- source of truth that BOTH the timeline and APME eval derive from. Storage-
104
+ -- time dedup via the UNIQUE index + INSERT OR IGNORE (no race-sensitive window).
105
+ CREATE TABLE IF NOT EXISTS sample_events (
106
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
107
+ task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
108
+ run_id TEXT NOT NULL REFERENCES runs(id) ON DELETE CASCADE,
109
+ turn_index INTEGER,
110
+ seq INTEGER NOT NULL,
111
+ ts INTEGER NOT NULL,
112
+ kind TEXT NOT NULL,
113
+ model TEXT,
114
+ input_tokens INTEGER,
115
+ output_tokens INTEGER,
116
+ cost_usd REAL,
117
+ latency_ms INTEGER,
118
+ tool_name TEXT,
119
+ tool_status TEXT,
120
+ tool_error TEXT,
121
+ payload TEXT,
122
+ dedup_key TEXT
123
+ );
124
+
125
+ CREATE INDEX IF NOT EXISTS idx_sevents_task ON sample_events(task_id, seq);
126
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_sevents_dedup ON sample_events(task_id, dedup_key);
127
+
96
128
  CREATE TABLE IF NOT EXISTS artifacts (
97
129
  id INTEGER PRIMARY KEY AUTOINCREMENT,
98
130
  run_id TEXT NOT NULL REFERENCES runs(id) ON DELETE CASCADE,
@@ -179,6 +211,28 @@ FROM runs r
179
211
  LEFT JOIN v_run_metrics m ON m.run_id = r.id
180
212
  WHERE r.task_category IS NOT NULL AND r.task_category != 'unknown'
181
213
  GROUP BY r.task_category, r.model_id;
214
+
215
+ -- Sample-granularity scorecard: quality vs cost per (agent, model, category).
216
+ -- The recommender + Pareto frontier read this. Uses the task's own model_id /
217
+ -- cost (the sample header), falling back to the run's model when unset.
218
+ CREATE VIEW IF NOT EXISTS v_sample_scorecard AS
219
+ SELECT
220
+ r.agent_type AS agent_type,
221
+ COALESCE(t.model_id, r.model_id, 'unknown') AS model_id,
222
+ t.task_category AS task_category,
223
+ COUNT(*) AS samples,
224
+ AVG(t.composite_score) AS avg_quality,
225
+ SUM(t.cost_usd) AS total_cost,
226
+ AVG(t.latency_ms) AS avg_latency_ms,
227
+ CASE
228
+ WHEN AVG(t.composite_score) > 0
229
+ THEN SUM(t.cost_usd) / AVG(t.composite_score)
230
+ ELSE NULL
231
+ END AS cost_per_quality
232
+ FROM tasks t
233
+ JOIN runs r ON r.id = t.run_id
234
+ WHERE t.ended_at IS NOT NULL AND t.composite_score IS NOT NULL
235
+ GROUP BY r.agent_type, COALESCE(t.model_id, r.model_id, 'unknown'), t.task_category;
182
236
  `;
183
237
  // ─── Default rubric v1 (seeded on first boot) ──────────────────────────────────
184
238
  const DEFAULT_RUBRIC_V1 = {
@@ -323,29 +377,50 @@ Return strict JSON: {"correctness":N,"safety":N,"completeness":N,"overall":N,"re
323
377
  },
324
378
  task_rollup: {
325
379
  purpose: 'task_rollup',
326
- prompt: `You are evaluating a multi-turn AI agent task that the agent itself has just signaled as complete
327
- (for example: every TodoWrite item was marked \`completed\`, or the user issued \`/clear\` to reset context).
380
+ prompt: `You are evaluating a multi-turn AI agent task that has just ended.
381
+ The boundary signal that closed the task tells you HOW it ended:
382
+ - todo_complete : the agent itself marked every TodoWrite item as completed (self-declared done)
383
+ - clear : the user typed /clear to reset context (often: user gave up or moved on)
384
+ - session_end : the agent process exited (could be done, could be interrupted)
385
+ - manual : a human marked the boundary explicitly
328
386
 
329
- You will be given the full sequence of turns (user prompt → agent response) that make up this task.
330
- Produce a concise rollup: a single-sentence summary plus axis scores.
387
+ You receive: the task's category (coding/planning/research/…), the number of turns,
388
+ the boundary signal, and the full Turn 0..N transcript (user prompt → agent response).
331
389
 
332
- Score each axis as a float in [0,1] where 0=failed and 1=excellent.
390
+ Your job is a one-sentence rollup PLUS axis scores in [0,1].
333
391
 
334
- Axes:
335
- - completion: Did the agent actually finish what the task was about? A high score means the task was
336
- delivered end-to-end; low if large pieces were skipped or declared done without evidence.
337
- - coherence: Did the turns build on each other toward a single goal? Penalize incoherent jumps,
338
- redundant re-planning, or lost context between turns.
339
- - efficiency: Were the turns appropriately scoped? Penalize unnecessary back-and-forth, repeated
340
- tool calls with the same inputs, or churn. Reward focused, decisive progress.
341
- - overall: Holistic judgment. Weight completion most heavily an efficient, coherent task that
342
- never actually finishes is worse than a slightly messier task that delivered.
343
-
344
- Summary guidance: one sentence, 140 characters, past tense, describing what the task accomplished.
345
- Start with a verb (e.g. "Added", "Fixed", "Investigated", "Refactored"). No hedging.
346
-
347
- Return strict JSON exactly:
348
- {"summary":"<one sentence>","completion":N,"coherence":N,"efficiency":N,"overall":N,"reasoning":"...","done":["item1"],"missed":["item1"]}.`,
392
+ Identify FIRST: what was the user actually trying to accomplish? Read Turn 0's prompt and any
393
+ later prompts that pivot or refine. The task's success is measured against THAT goal not
394
+ against how busy the turns look.
395
+
396
+ Axes (each in [0,1], 0=failed, 1=excellent):
397
+ - completion: Did the agent actually deliver against the user's identified goal? High = goal
398
+ reached with evidence in the final turns. Low = goal half-done, abandoned, or only declared
399
+ done (e.g. "I've completed all the items" with nothing visible). For boundary=clear, completion
400
+ is usually low the user reset before satisfaction.
401
+ - coherence: Did the turns build on each other toward the goal? Penalize incoherent jumps,
402
+ redundant re-planning, lost context, or the agent forgetting earlier decisions.
403
+ - efficiency: Were the turns appropriately scoped? Penalize repeated tool calls with the same
404
+ inputs, long discovery loops the agent could have shortcut, or churn. Reward focused progress.
405
+ - overall: Holistic judgment. Weight completion most heavily — an efficient coherent task
406
+ that never finishes is worse than a slightly messier task that delivered.
407
+
408
+ Summary guidance: one sentence, ≤ 280 characters, past tense, describing what the task ACCOMPLISHED
409
+ (not what the agent attempted). Start with a verb: "Added", "Fixed", "Investigated", "Refactored",
410
+ "Failed to". Be specific about the artefact when possible. No hedging, no "the agent…" preamble.
411
+
412
+ reasoning: 1-3 sentences explaining the key evidence behind the overall score. Cite turn numbers.
413
+ done: list the concrete deliverables visible in the turns (≤5 short items).
414
+ missed: list what the user asked for but the agent did NOT deliver (≤5 items, empty array if none).
415
+
416
+ Return strict JSON exactly, no prose before or after:
417
+ {"summary":"<one sentence>","completion":N,"coherence":N,"efficiency":N,"overall":N,"reasoning":"...","done":["…"],"missed":["…"]}
418
+
419
+ Examples of well-calibrated overall scores:
420
+ 0.9 — User asked to add a feature; final turns show the feature implemented + test passing.
421
+ 0.6 — User asked for a feature; agent built most of it but left a TODO they self-declared "done".
422
+ 0.3 — User asked a question; agent rambled across 5 turns without ever answering.
423
+ 0.1 — User asked to fix a bug; agent introduced two more bugs and called /clear.`,
349
424
  weights: JSON.stringify({ completion: 0.5, coherence: 0.25, efficiency: 0.25 }),
350
425
  notes: 'task-unit rollup (TodoWrite all-completed / /clear / session_end)',
351
426
  },
@@ -354,19 +429,28 @@ export class ApmeStore {
354
429
  db = null;
355
430
  enabled = false;
356
431
  dbPath;
432
+ /** Populated when init() returns false. Surfaced in daemon startup logs so
433
+ * silent APME outages (the failure mode that left ~/.agentdeck/apme.sqlite
434
+ * stale for 11 days in 2026-04 user data) become diagnosable. */
435
+ lastInitError = null;
357
436
  constructor(dbPath) {
358
437
  const dataDir = process.env.AGENTDECK_DATA_DIR || join(homedir(), '.agentdeck');
359
438
  this.dbPath = dbPath ?? join(dataDir, 'apme.sqlite');
360
439
  }
361
- /** Attempt to open the DB. Returns false if better-sqlite3 is unavailable. */
440
+ /** Attempt to open the DB. Returns false on failure; check `lastInitError`
441
+ * for the reason. The two common failure modes are:
442
+ * 1. better-sqlite3 native binding missing (CI / setups without build tools)
443
+ * 2. DB file unreadable / DDL fails (disk full, permissions, WAL lock from a
444
+ * crashed prior process). */
362
445
  async init() {
363
446
  try {
364
447
  let Ctor = null;
365
448
  try {
366
449
  Ctor = require('better-sqlite3');
367
450
  }
368
- catch {
369
- debug('APME', 'better-sqlite3 not installed APME store disabled');
451
+ catch (err) {
452
+ this.lastInitError = `better-sqlite3 native binding unavailable (${String(err).slice(0, 200)}). Run \`pnpm install\` in bridge/.`;
453
+ debug('APME', this.lastInitError);
370
454
  return false;
371
455
  }
372
456
  const dir = dirname(this.dbPath);
@@ -379,11 +463,13 @@ export class ApmeStore {
379
463
  this.migrateSchema();
380
464
  this.seedDefaultRubric();
381
465
  this.enabled = true;
466
+ this.lastInitError = null;
382
467
  debug('APME', `store ready at ${this.dbPath}`);
383
468
  return true;
384
469
  }
385
470
  catch (err) {
386
- debug('APME', `store init failed: ${String(err)}`);
471
+ this.lastInitError = `store init failed at ${this.dbPath}: ${String(err).slice(0, 300)}`;
472
+ debug('APME', this.lastInitError);
387
473
  return false;
388
474
  }
389
475
  }
@@ -439,6 +525,26 @@ export class ApmeStore {
439
525
  }
440
526
  catch { /* ignore */ }
441
527
  }
528
+ // Tasks sample-header columns (model identity + cost) — added for the
529
+ // SessionSample rebuild. Older DBs get them via ALTER.
530
+ const taskCols = this.db.prepare("PRAGMA table_info(tasks)").all().map(c => c.name);
531
+ for (const [col, sql] of [
532
+ ['model_id', 'ALTER TABLE tasks ADD COLUMN model_id TEXT'],
533
+ ['model_config', 'ALTER TABLE tasks ADD COLUMN model_config TEXT'],
534
+ ['input_tokens', 'ALTER TABLE tasks ADD COLUMN input_tokens INTEGER'],
535
+ ['output_tokens', 'ALTER TABLE tasks ADD COLUMN output_tokens INTEGER'],
536
+ ['cost_usd', 'ALTER TABLE tasks ADD COLUMN cost_usd REAL'],
537
+ ['latency_ms', 'ALTER TABLE tasks ADD COLUMN latency_ms INTEGER'],
538
+ ]) {
539
+ if (!taskCols.includes(col)) {
540
+ try {
541
+ this.db.exec(sql);
542
+ }
543
+ catch { /* ignore */ }
544
+ }
545
+ }
546
+ // sample_events table + indexes are created via CREATE TABLE IF NOT EXISTS
547
+ // in DDL; nothing to ALTER. The v_sample_scorecard view likewise.
442
548
  }
443
549
  seedDefaultRubric() {
444
550
  if (!this.db)
@@ -605,6 +711,12 @@ export class ApmeStore {
605
711
  taskCategory: 'task_category',
606
712
  notesJson: 'notes_json',
607
713
  boundarySignal: 'boundary_signal',
714
+ modelId: 'model_id',
715
+ modelConfig: 'model_config',
716
+ inputTokens: 'input_tokens',
717
+ outputTokens: 'output_tokens',
718
+ costUsd: 'cost_usd',
719
+ latencyMs: 'latency_ms',
608
720
  };
609
721
  const sets = [];
610
722
  const vals = [];
@@ -632,6 +744,18 @@ export class ApmeStore {
632
744
  const rows = this.db.prepare('SELECT * FROM tasks WHERE run_id = ? ORDER BY task_index ASC').all(runId);
633
745
  return rows.map(rowToTask);
634
746
  }
747
+ /** All tasks across runs, newest first. Used by `agentdeck apme export --by task`
748
+ * to dump a flat dataset of meaningful task units (one row per closed task). */
749
+ listAllTasks(opts = {}) {
750
+ if (!this.db)
751
+ return [];
752
+ const limit = opts.limit ?? 100;
753
+ const sql = opts.closedOnly
754
+ ? `SELECT * FROM tasks WHERE ended_at IS NOT NULL ORDER BY started_at DESC LIMIT ?`
755
+ : `SELECT * FROM tasks ORDER BY started_at DESC LIMIT ?`;
756
+ const rows = this.db.prepare(sql).all(limit);
757
+ return rows.map(rowToTask);
758
+ }
635
759
  listTurnsForTask(taskId) {
636
760
  if (!this.db)
637
761
  return [];
@@ -782,6 +906,7 @@ export class ApmeStore {
782
906
  return [];
783
907
  const rows = this.db.prepare(`SELECT r.id, r.project_path FROM runs r
784
908
  WHERE r.ended_at IS NOT NULL
909
+ AND (r.task_category IS NULL OR r.task_category != '_empty')
785
910
  AND NOT EXISTS (SELECT 1 FROM evals e WHERE e.run_id = r.id)
786
911
  ORDER BY r.ended_at DESC
787
912
  LIMIT ?`).all(limit);
@@ -823,6 +948,136 @@ export class ApmeStore {
823
948
  LIMIT 20`).all(cutoff);
824
949
  return rows.map((r) => r.id);
825
950
  }
951
+ // ─── Sample events (typed trajectory) ────────────────────────────────────────
952
+ /** Append one typed trajectory event. INSERT OR IGNORE on the UNIQUE
953
+ * (task_id, dedup_key) index makes storage-time dedup atomic — duplicates
954
+ * never persist. Returns true if a row was actually inserted. */
955
+ insertSampleEvent(row) {
956
+ if (!this.db)
957
+ return false;
958
+ const res = this.db.prepare(`INSERT OR IGNORE INTO sample_events
959
+ (task_id, run_id, turn_index, seq, ts, kind, model, input_tokens, output_tokens,
960
+ cost_usd, latency_ms, tool_name, tool_status, tool_error, payload, dedup_key)
961
+ VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`).run(row.taskId, row.runId, row.turnIndex ?? null, row.seq, row.ts, row.kind, row.model ?? null, row.inputTokens ?? null, row.outputTokens ?? null, row.costUsd ?? null, row.latencyMs ?? null, row.toolName ?? null, row.toolStatus ?? null, row.toolError ?? null, row.payload ?? null, row.dedupKey ?? null);
962
+ return res.changes > 0;
963
+ }
964
+ /** Update a previously-inserted event (e.g. a tool pending→resolved) by id. */
965
+ updateSampleEvent(id, fields) {
966
+ if (!this.db)
967
+ return;
968
+ const map = {
969
+ toolStatus: 'tool_status', toolError: 'tool_error', payload: 'payload',
970
+ costUsd: 'cost_usd', latencyMs: 'latency_ms', model: 'model',
971
+ inputTokens: 'input_tokens', outputTokens: 'output_tokens', ts: 'ts',
972
+ };
973
+ const sets = [];
974
+ const vals = [];
975
+ for (const [k, v] of Object.entries(fields)) {
976
+ const col = map[k];
977
+ if (!col || v === undefined)
978
+ continue;
979
+ sets.push(`${col} = ?`);
980
+ vals.push(v);
981
+ }
982
+ if (sets.length === 0)
983
+ return;
984
+ vals.push(id);
985
+ this.db.prepare(`UPDATE sample_events SET ${sets.join(', ')} WHERE id = ?`).run(...vals);
986
+ }
987
+ /** Find a tool event still pending for (task, turn, toolName), to resolve it. */
988
+ findPendingToolEvent(taskId, turnIndex, toolName) {
989
+ if (!this.db)
990
+ return null;
991
+ const row = this.db.prepare(`SELECT * FROM sample_events
992
+ WHERE task_id = ? AND turn_index = ? AND kind = 'tool' AND tool_name = ?
993
+ AND (tool_status IS NULL OR tool_status = 'pending')
994
+ ORDER BY seq DESC LIMIT 1`).get(taskId, turnIndex, toolName);
995
+ return row ? rowToSampleEvent(row) : null;
996
+ }
997
+ listSampleEventRows(taskId) {
998
+ if (!this.db)
999
+ return [];
1000
+ const rows = this.db.prepare('SELECT * FROM sample_events WHERE task_id = ? ORDER BY seq ASC').all(taskId);
1001
+ return rows.map(rowToSampleEvent);
1002
+ }
1003
+ listSampleEvents(taskId) {
1004
+ return this.listSampleEventRows(taskId).map(sampleEventRowToTrajectory).filter((e) => e !== null);
1005
+ }
1006
+ /** Next monotonic seq within a task. */
1007
+ nextSampleSeq(taskId) {
1008
+ if (!this.db)
1009
+ return 0;
1010
+ const row = this.db.prepare('SELECT COALESCE(MAX(seq),-1)+1 AS s FROM sample_events WHERE task_id = ?').get(taskId);
1011
+ return row.s;
1012
+ }
1013
+ /** Assemble the full SessionSample (header + cost + typed trajectory). */
1014
+ getSample(taskId) {
1015
+ if (!this.db)
1016
+ return null;
1017
+ const task = this.getTask(taskId);
1018
+ if (!task)
1019
+ return null;
1020
+ const run = this.getRun(task.runId);
1021
+ const events = this.listSampleEvents(taskId);
1022
+ let modelConfig = null;
1023
+ if (task.modelConfig) {
1024
+ try {
1025
+ modelConfig = JSON.parse(task.modelConfig);
1026
+ }
1027
+ catch { /* ignore */ }
1028
+ }
1029
+ const modelId = task.modelId ?? run?.modelId ?? modelConfig?.modelId ?? 'unknown';
1030
+ return {
1031
+ id: task.id,
1032
+ runId: task.runId,
1033
+ sessionId: run?.sessionId ?? '',
1034
+ agentType: (run?.agentType ?? 'claude-code'),
1035
+ index: task.taskIndex,
1036
+ boundarySignal: task.boundarySignal,
1037
+ startedAt: task.startedAt,
1038
+ endedAt: task.endedAt ?? null,
1039
+ model: modelConfig ?? { modelId },
1040
+ projectName: run?.projectName ?? null,
1041
+ projectPath: run?.projectPath ?? null,
1042
+ events,
1043
+ cost: {
1044
+ inputTokens: task.inputTokens ?? 0,
1045
+ outputTokens: task.outputTokens ?? 0,
1046
+ costUsd: task.costUsd ?? 0,
1047
+ latencyMs: task.latencyMs ?? 0,
1048
+ },
1049
+ summary: task.summary ?? null,
1050
+ outcome: task.outcome ?? null,
1051
+ compositeScore: task.compositeScore ?? null,
1052
+ taskCategory: task.taskCategory ?? null,
1053
+ };
1054
+ }
1055
+ /** Recompute the task's cost aggregate by summing its ModelEvents. */
1056
+ recomputeSampleCost(taskId) {
1057
+ if (!this.db)
1058
+ return;
1059
+ const row = this.db.prepare(`SELECT COALESCE(SUM(input_tokens),0) AS it, COALESCE(SUM(output_tokens),0) AS ot,
1060
+ COALESCE(SUM(cost_usd),0) AS cu, COALESCE(SUM(latency_ms),0) AS lm
1061
+ FROM sample_events WHERE task_id = ? AND kind = 'model'`).get(taskId);
1062
+ this.updateTask(taskId, {
1063
+ inputTokens: row.it, outputTokens: row.ot, costUsd: row.cu, latencyMs: row.lm,
1064
+ });
1065
+ }
1066
+ sampleScorecard() {
1067
+ if (!this.db)
1068
+ return [];
1069
+ const rows = this.db.prepare('SELECT * FROM v_sample_scorecard').all();
1070
+ return rows.map((r) => ({
1071
+ agentType: r.agent_type,
1072
+ modelId: r.model_id,
1073
+ taskCategory: r.task_category ?? null,
1074
+ samples: r.samples,
1075
+ avgQuality: r.avg_quality ?? null,
1076
+ totalCost: r.total_cost ?? null,
1077
+ avgLatencyMs: r.avg_latency_ms ?? null,
1078
+ costPerQuality: r.cost_per_quality ?? null,
1079
+ }));
1080
+ }
826
1081
  // ─── Scorecard ───────────────────────────────────────────────────────────────
827
1082
  scorecard() {
828
1083
  if (!this.db)
@@ -895,8 +1150,62 @@ function rowToTask(r) {
895
1150
  compositeScore: r.composite_score ?? null,
896
1151
  taskCategory: r.task_category ?? null,
897
1152
  notesJson: r.notes_json ?? null,
1153
+ modelId: r.model_id ?? null,
1154
+ modelConfig: r.model_config ?? null,
1155
+ inputTokens: r.input_tokens ?? null,
1156
+ outputTokens: r.output_tokens ?? null,
1157
+ costUsd: r.cost_usd ?? null,
1158
+ latencyMs: r.latency_ms ?? null,
898
1159
  };
899
1160
  }
1161
+ function rowToSampleEvent(r) {
1162
+ return {
1163
+ id: r.id,
1164
+ taskId: r.task_id,
1165
+ runId: r.run_id,
1166
+ turnIndex: r.turn_index ?? null,
1167
+ seq: r.seq,
1168
+ ts: r.ts,
1169
+ kind: r.kind,
1170
+ model: r.model ?? null,
1171
+ inputTokens: r.input_tokens ?? null,
1172
+ outputTokens: r.output_tokens ?? null,
1173
+ costUsd: r.cost_usd ?? null,
1174
+ latencyMs: r.latency_ms ?? null,
1175
+ toolName: r.tool_name ?? null,
1176
+ toolStatus: r.tool_status ?? null,
1177
+ toolError: r.tool_error ?? null,
1178
+ payload: r.payload ?? null,
1179
+ dedupKey: r.dedup_key ?? null,
1180
+ };
1181
+ }
1182
+ /** Decode a stored sample_events row back into a typed TrajectoryEvent. */
1183
+ function sampleEventRowToTrajectory(r) {
1184
+ const base = { ts: r.ts, turnIndex: r.turnIndex ?? 0 };
1185
+ let p = {};
1186
+ if (r.payload) {
1187
+ try {
1188
+ p = JSON.parse(r.payload);
1189
+ }
1190
+ catch { /* ignore */ }
1191
+ }
1192
+ switch (r.kind) {
1193
+ case 'user_message':
1194
+ return { ...base, kind: 'user_message', text: p.text ?? '' };
1195
+ case 'assistant_message':
1196
+ return { ...base, kind: 'assistant_message', text: p.text ?? '', responseKind: (p.responseKind ?? 'text') };
1197
+ case 'model':
1198
+ return { ...base, kind: 'model', model: r.model ?? 'unknown', inputTokens: r.inputTokens ?? 0, outputTokens: r.outputTokens ?? 0, costUsd: r.costUsd ?? 0, latencyMs: r.latencyMs ?? 0 };
1199
+ case 'tool':
1200
+ return { ...base, kind: 'tool', name: r.toolName ?? 'tool', input: p.input, output: p.output, error: r.toolError ?? null, status: r.toolStatus ?? undefined };
1201
+ case 'state':
1202
+ return { ...base, kind: 'state', from: p.from ?? null, to: p.to ?? 'unknown' };
1203
+ case 'info':
1204
+ return { ...base, kind: 'info', label: p.label ?? 'info', detail: p.detail ?? null };
1205
+ default:
1206
+ return null;
1207
+ }
1208
+ }
900
1209
  function rowToRubric(r) {
901
1210
  return {
902
1211
  version: r.version,