@agentdeck/bridge 0.2.2 → 1.0.0

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 (435) hide show
  1. package/assets/fm-helper/agentdeck-fm-helper +0 -0
  2. package/assets/fonts/IBMPlexSans-Bold.ttf +0 -0
  3. package/assets/fonts/IBMPlexSans-Regular.ttf +0 -0
  4. package/assets/fonts/JetBrainsMono-Bold.ttf +0 -0
  5. package/assets/fonts/JetBrainsMono-Regular.ttf +0 -0
  6. package/assets/fonts/LICENSES.md +22 -0
  7. package/dist/adapters/claude-code.d.ts +6 -0
  8. package/dist/adapters/claude-code.d.ts.map +1 -1
  9. package/dist/adapters/claude-code.js +8 -0
  10. package/dist/adapters/claude-code.js.map +1 -1
  11. package/dist/adapters/openclaw.d.ts +24 -0
  12. package/dist/adapters/openclaw.d.ts.map +1 -1
  13. package/dist/adapters/openclaw.js +291 -35
  14. package/dist/adapters/openclaw.js.map +1 -1
  15. package/dist/adapters/opencode-adapter.d.ts +59 -0
  16. package/dist/adapters/opencode-adapter.d.ts.map +1 -1
  17. package/dist/adapters/opencode-adapter.js +297 -35
  18. package/dist/adapters/opencode-adapter.js.map +1 -1
  19. package/dist/adb-reverse.d.ts +1 -1
  20. package/dist/adb-reverse.js +1 -1
  21. package/dist/antigravity-local.d.ts +1 -0
  22. package/dist/antigravity-local.d.ts.map +1 -1
  23. package/dist/antigravity-local.js +33 -0
  24. package/dist/antigravity-local.js.map +1 -1
  25. package/dist/apme/adapters/claude-hook.d.ts.map +1 -1
  26. package/dist/apme/adapters/claude-hook.js +5 -0
  27. package/dist/apme/adapters/claude-hook.js.map +1 -1
  28. package/dist/apme/adapters/codex-hook.d.ts +17 -0
  29. package/dist/apme/adapters/codex-hook.d.ts.map +1 -0
  30. package/dist/apme/adapters/codex-hook.js +95 -0
  31. package/dist/apme/adapters/codex-hook.js.map +1 -0
  32. package/dist/apme/adapters/codex-turn-manager.d.ts +86 -0
  33. package/dist/apme/adapters/codex-turn-manager.d.ts.map +1 -0
  34. package/dist/apme/adapters/codex-turn-manager.js +496 -0
  35. package/dist/apme/adapters/codex-turn-manager.js.map +1 -0
  36. package/dist/apme/adapters/openclaw-hook.d.ts +99 -0
  37. package/dist/apme/adapters/openclaw-hook.d.ts.map +1 -0
  38. package/dist/apme/adapters/openclaw-hook.js +234 -0
  39. package/dist/apme/adapters/openclaw-hook.js.map +1 -0
  40. package/dist/apme/adapters/opencode-hook.d.ts +56 -0
  41. package/dist/apme/adapters/opencode-hook.d.ts.map +1 -0
  42. package/dist/apme/adapters/opencode-hook.js +182 -0
  43. package/dist/apme/adapters/opencode-hook.js.map +1 -0
  44. package/dist/apme/adapters/timeline.d.ts.map +1 -1
  45. package/dist/apme/adapters/timeline.js +6 -1
  46. package/dist/apme/adapters/timeline.js.map +1 -1
  47. package/dist/apme/antigravity-transcript.d.ts +18 -0
  48. package/dist/apme/antigravity-transcript.d.ts.map +1 -0
  49. package/dist/apme/antigravity-transcript.js +94 -0
  50. package/dist/apme/antigravity-transcript.js.map +1 -0
  51. package/dist/apme/classify-turn.d.ts +13 -0
  52. package/dist/apme/classify-turn.d.ts.map +1 -0
  53. package/dist/apme/classify-turn.js +49 -0
  54. package/dist/apme/classify-turn.js.map +1 -0
  55. package/dist/apme/claude-transcript-reader.d.ts +10 -0
  56. package/dist/apme/claude-transcript-reader.d.ts.map +1 -1
  57. package/dist/apme/claude-transcript-reader.js +35 -0
  58. package/dist/apme/claude-transcript-reader.js.map +1 -1
  59. package/dist/apme/collector.d.ts +133 -6
  60. package/dist/apme/collector.d.ts.map +1 -1
  61. package/dist/apme/collector.js +471 -23
  62. package/dist/apme/collector.js.map +1 -1
  63. package/dist/apme/dashboard-html.d.ts.map +1 -1
  64. package/dist/apme/dashboard-html.js +117 -11
  65. package/dist/apme/dashboard-html.js.map +1 -1
  66. package/dist/apme/http.d.ts.map +1 -1
  67. package/dist/apme/http.js +52 -6
  68. package/dist/apme/http.js.map +1 -1
  69. package/dist/apme/index.d.ts +26 -5
  70. package/dist/apme/index.d.ts.map +1 -1
  71. package/dist/apme/index.js +146 -9
  72. package/dist/apme/index.js.map +1 -1
  73. package/dist/apme/judge-detect.d.ts +26 -0
  74. package/dist/apme/judge-detect.d.ts.map +1 -0
  75. package/dist/apme/judge-detect.js +69 -0
  76. package/dist/apme/judge-detect.js.map +1 -0
  77. package/dist/apme/pareto.d.ts +39 -0
  78. package/dist/apme/pareto.d.ts.map +1 -0
  79. package/dist/apme/pareto.js +59 -0
  80. package/dist/apme/pareto.js.map +1 -0
  81. package/dist/apme/recommend.d.ts +3 -0
  82. package/dist/apme/recommend.d.ts.map +1 -1
  83. package/dist/apme/recommend.js +43 -1
  84. package/dist/apme/recommend.js.map +1 -1
  85. package/dist/apme/runner.d.ts +99 -4
  86. package/dist/apme/runner.d.ts.map +1 -1
  87. package/dist/apme/runner.js +743 -72
  88. package/dist/apme/runner.js.map +1 -1
  89. package/dist/apme/sample-to-timeline.d.ts +26 -0
  90. package/dist/apme/sample-to-timeline.d.ts.map +1 -0
  91. package/dist/apme/sample-to-timeline.js +95 -0
  92. package/dist/apme/sample-to-timeline.js.map +1 -0
  93. package/dist/apme/scorers/index.d.ts +47 -0
  94. package/dist/apme/scorers/index.d.ts.map +1 -0
  95. package/dist/apme/scorers/index.js +96 -0
  96. package/dist/apme/scorers/index.js.map +1 -0
  97. package/dist/apme/settings.d.ts +17 -11
  98. package/dist/apme/settings.d.ts.map +1 -1
  99. package/dist/apme/settings.js +30 -9
  100. package/dist/apme/settings.js.map +1 -1
  101. package/dist/apme/store.d.ts +33 -1
  102. package/dist/apme/store.d.ts.map +1 -1
  103. package/dist/apme/store.js +334 -25
  104. package/dist/apme/store.js.map +1 -1
  105. package/dist/awaiting-overlay.d.ts +112 -0
  106. package/dist/awaiting-overlay.d.ts.map +1 -0
  107. package/dist/awaiting-overlay.js +179 -0
  108. package/dist/awaiting-overlay.js.map +1 -0
  109. package/dist/ble-sync-spawn.d.ts +63 -0
  110. package/dist/ble-sync-spawn.d.ts.map +1 -0
  111. package/dist/ble-sync-spawn.js +196 -0
  112. package/dist/ble-sync-spawn.js.map +1 -0
  113. package/dist/bridge-core.d.ts +34 -1
  114. package/dist/bridge-core.d.ts.map +1 -1
  115. package/dist/bridge-core.js +207 -24
  116. package/dist/bridge-core.js.map +1 -1
  117. package/dist/broadcast.d.ts +3 -0
  118. package/dist/broadcast.d.ts.map +1 -0
  119. package/dist/broadcast.js +122 -0
  120. package/dist/broadcast.js.map +1 -0
  121. package/dist/check-deps.d.ts.map +1 -1
  122. package/dist/check-deps.js +25 -9
  123. package/dist/check-deps.js.map +1 -1
  124. package/dist/claude-permission-rules.d.ts +55 -0
  125. package/dist/claude-permission-rules.d.ts.map +1 -0
  126. package/dist/claude-permission-rules.js +197 -0
  127. package/dist/claude-permission-rules.js.map +1 -0
  128. package/dist/cli.d.ts +15 -1
  129. package/dist/cli.d.ts.map +1 -1
  130. package/dist/cli.js +1030 -93
  131. package/dist/cli.js.map +1 -1
  132. package/dist/codex-auth.d.ts +21 -0
  133. package/dist/codex-auth.d.ts.map +1 -1
  134. package/dist/codex-auth.js +52 -1
  135. package/dist/codex-auth.js.map +1 -1
  136. package/dist/codex-output-parser.d.ts +8 -0
  137. package/dist/codex-output-parser.d.ts.map +1 -1
  138. package/dist/codex-output-parser.js +110 -25
  139. package/dist/codex-output-parser.js.map +1 -1
  140. package/dist/codex-rate-limits.d.ts +16 -0
  141. package/dist/codex-rate-limits.d.ts.map +1 -0
  142. package/dist/codex-rate-limits.js +197 -0
  143. package/dist/codex-rate-limits.js.map +1 -0
  144. package/dist/codex-rollout-response.d.ts +31 -0
  145. package/dist/codex-rollout-response.d.ts.map +1 -0
  146. package/dist/codex-rollout-response.js +135 -0
  147. package/dist/codex-rollout-response.js.map +1 -0
  148. package/dist/d200h/image-renderer.d.ts +4 -16
  149. package/dist/d200h/image-renderer.d.ts.map +1 -1
  150. package/dist/d200h/image-renderer.js +46 -212
  151. package/dist/d200h/image-renderer.js.map +1 -1
  152. package/dist/daemon-server.d.ts +85 -0
  153. package/dist/daemon-server.d.ts.map +1 -1
  154. package/dist/daemon-server.js +1975 -159
  155. package/dist/daemon-server.js.map +1 -1
  156. package/dist/daemon.js +15 -6
  157. package/dist/daemon.js.map +1 -1
  158. package/dist/display-dim.d.ts +9 -0
  159. package/dist/display-dim.d.ts.map +1 -0
  160. package/dist/display-dim.js +53 -0
  161. package/dist/display-dim.js.map +1 -0
  162. package/dist/display-monitor.d.ts +15 -2
  163. package/dist/display-monitor.d.ts.map +1 -1
  164. package/dist/display-monitor.js +104 -26
  165. package/dist/display-monitor.js.map +1 -1
  166. package/dist/esp32-serial.d.ts +190 -1
  167. package/dist/esp32-serial.d.ts.map +1 -1
  168. package/dist/esp32-serial.js +1090 -156
  169. package/dist/esp32-serial.js.map +1 -1
  170. package/dist/fallback-task-timeline.d.ts +42 -0
  171. package/dist/fallback-task-timeline.d.ts.map +1 -0
  172. package/dist/fallback-task-timeline.js +119 -0
  173. package/dist/fallback-task-timeline.js.map +1 -0
  174. package/dist/foundation-models-helper.d.ts +11 -0
  175. package/dist/foundation-models-helper.d.ts.map +1 -0
  176. package/dist/foundation-models-helper.js +241 -0
  177. package/dist/foundation-models-helper.js.map +1 -0
  178. package/dist/hook-migration.js +1 -1
  179. package/dist/hook-migration.js.map +1 -1
  180. package/dist/hook-server.d.ts +2 -3
  181. package/dist/hook-server.d.ts.map +1 -1
  182. package/dist/hook-server.js +23 -10
  183. package/dist/hook-server.js.map +1 -1
  184. package/dist/idotmatrix/idotmatrix-daemon-sync.d.ts +33 -0
  185. package/dist/idotmatrix/idotmatrix-daemon-sync.d.ts.map +1 -0
  186. package/dist/idotmatrix/idotmatrix-daemon-sync.js +164 -0
  187. package/dist/idotmatrix/idotmatrix-daemon-sync.js.map +1 -0
  188. package/dist/idotmatrix/idotmatrix-discover.d.ts +18 -0
  189. package/dist/idotmatrix/idotmatrix-discover.d.ts.map +1 -0
  190. package/dist/idotmatrix/idotmatrix-discover.js +85 -0
  191. package/dist/idotmatrix/idotmatrix-discover.js.map +1 -0
  192. package/dist/idotmatrix/idotmatrix-settings.d.ts +20 -0
  193. package/dist/idotmatrix/idotmatrix-settings.d.ts.map +1 -0
  194. package/dist/idotmatrix/idotmatrix-settings.js +57 -0
  195. package/dist/idotmatrix/idotmatrix-settings.js.map +1 -0
  196. package/dist/index.d.ts.map +1 -1
  197. package/dist/index.js +217 -179
  198. package/dist/index.js.map +1 -1
  199. package/dist/log-stream.d.ts +15 -16
  200. package/dist/log-stream.d.ts.map +1 -1
  201. package/dist/log-stream.js +18 -96
  202. package/dist/log-stream.js.map +1 -1
  203. package/dist/logger.d.ts +3 -1
  204. package/dist/logger.d.ts.map +1 -1
  205. package/dist/logger.js +18 -5
  206. package/dist/logger.js.map +1 -1
  207. package/dist/mdns.d.ts +17 -0
  208. package/dist/mdns.d.ts.map +1 -1
  209. package/dist/mdns.js +52 -18
  210. package/dist/mdns.js.map +1 -1
  211. package/dist/model-catalog.d.ts +1 -1
  212. package/dist/model-catalog.d.ts.map +1 -1
  213. package/dist/model-catalog.js +2 -4
  214. package/dist/model-catalog.js.map +1 -1
  215. package/dist/modules/adb-module.d.ts +1 -1
  216. package/dist/modules/adb-module.d.ts.map +1 -1
  217. package/dist/modules/adb-module.js +4 -3
  218. package/dist/modules/adb-module.js.map +1 -1
  219. package/dist/modules/broadcast-module.d.ts +17 -0
  220. package/dist/modules/broadcast-module.d.ts.map +1 -0
  221. package/dist/modules/broadcast-module.js +26 -0
  222. package/dist/modules/broadcast-module.js.map +1 -0
  223. package/dist/modules/d200h-module.d.ts +22 -0
  224. package/dist/modules/d200h-module.d.ts.map +1 -1
  225. package/dist/modules/d200h-module.js +200 -65
  226. package/dist/modules/d200h-module.js.map +1 -1
  227. package/dist/modules/idotmatrix-module.d.ts +9 -0
  228. package/dist/modules/idotmatrix-module.d.ts.map +1 -0
  229. package/dist/modules/idotmatrix-module.js +46 -0
  230. package/dist/modules/idotmatrix-module.js.map +1 -0
  231. package/dist/modules/index.d.ts +3 -1
  232. package/dist/modules/index.d.ts.map +1 -1
  233. package/dist/modules/index.js +9 -3
  234. package/dist/modules/index.js.map +1 -1
  235. package/dist/modules/pixoo-module.d.ts.map +1 -1
  236. package/dist/modules/pixoo-module.js +14 -4
  237. package/dist/modules/pixoo-module.js.map +1 -1
  238. package/dist/modules/serial-module.d.ts +4 -0
  239. package/dist/modules/serial-module.d.ts.map +1 -1
  240. package/dist/modules/serial-module.js +14 -12
  241. package/dist/modules/serial-module.js.map +1 -1
  242. package/dist/modules/timebox-module.d.ts +9 -0
  243. package/dist/modules/timebox-module.d.ts.map +1 -0
  244. package/dist/modules/timebox-module.js +46 -0
  245. package/dist/modules/timebox-module.js.map +1 -0
  246. package/dist/modules/trmnl-module.d.ts +38 -0
  247. package/dist/modules/trmnl-module.d.ts.map +1 -0
  248. package/dist/modules/trmnl-module.js +111 -0
  249. package/dist/modules/trmnl-module.js.map +1 -0
  250. package/dist/modules/types.d.ts +4 -2
  251. package/dist/modules/types.d.ts.map +1 -1
  252. package/dist/observed-steering.d.ts +93 -0
  253. package/dist/observed-steering.d.ts.map +1 -0
  254. package/dist/observed-steering.js +247 -0
  255. package/dist/observed-steering.js.map +1 -0
  256. package/dist/openclaw-session.d.ts +18 -0
  257. package/dist/openclaw-session.d.ts.map +1 -0
  258. package/dist/openclaw-session.js +34 -0
  259. package/dist/openclaw-session.js.map +1 -0
  260. package/dist/opencode-steering.d.ts +36 -0
  261. package/dist/opencode-steering.d.ts.map +1 -0
  262. package/dist/opencode-steering.js +84 -0
  263. package/dist/opencode-steering.js.map +1 -0
  264. package/dist/output-parser.d.ts +30 -0
  265. package/dist/output-parser.d.ts.map +1 -1
  266. package/dist/output-parser.js +172 -18
  267. package/dist/output-parser.js.map +1 -1
  268. package/dist/passive-observer.d.ts +32 -0
  269. package/dist/passive-observer.d.ts.map +1 -1
  270. package/dist/passive-observer.js +288 -49
  271. package/dist/passive-observer.js.map +1 -1
  272. package/dist/permission-resolver.d.ts +55 -0
  273. package/dist/permission-resolver.d.ts.map +1 -0
  274. package/dist/permission-resolver.js +112 -0
  275. package/dist/permission-resolver.js.map +1 -0
  276. package/dist/pixoo/micro-glyphs.d.ts +18 -0
  277. package/dist/pixoo/micro-glyphs.d.ts.map +1 -0
  278. package/dist/pixoo/micro-glyphs.js +143 -0
  279. package/dist/pixoo/micro-glyphs.js.map +1 -0
  280. package/dist/pixoo/official-dot-glyphs.generated.d.ts +8 -0
  281. package/dist/pixoo/official-dot-glyphs.generated.d.ts.map +1 -0
  282. package/dist/pixoo/official-dot-glyphs.generated.js +247 -0
  283. package/dist/pixoo/official-dot-glyphs.generated.js.map +1 -0
  284. package/dist/pixoo/pixoo-bridge.d.ts +16 -8
  285. package/dist/pixoo/pixoo-bridge.d.ts.map +1 -1
  286. package/dist/pixoo/pixoo-bridge.js +127 -35
  287. package/dist/pixoo/pixoo-bridge.js.map +1 -1
  288. package/dist/pixoo/pixoo-camera.d.ts +19 -3
  289. package/dist/pixoo/pixoo-camera.d.ts.map +1 -1
  290. package/dist/pixoo/pixoo-camera.js +62 -27
  291. package/dist/pixoo/pixoo-camera.js.map +1 -1
  292. package/dist/pixoo/pixoo-client.d.ts +13 -3
  293. package/dist/pixoo/pixoo-client.d.ts.map +1 -1
  294. package/dist/pixoo/pixoo-client.js +51 -22
  295. package/dist/pixoo/pixoo-client.js.map +1 -1
  296. package/dist/pixoo/pixoo-discover.d.ts +37 -0
  297. package/dist/pixoo/pixoo-discover.d.ts.map +1 -0
  298. package/dist/pixoo/pixoo-discover.js +105 -0
  299. package/dist/pixoo/pixoo-discover.js.map +1 -0
  300. package/dist/pixoo/pixoo-renderer.d.ts +27 -3
  301. package/dist/pixoo/pixoo-renderer.d.ts.map +1 -1
  302. package/dist/pixoo/pixoo-renderer.js +533 -135
  303. package/dist/pixoo/pixoo-renderer.js.map +1 -1
  304. package/dist/pixoo/pixoo-settings.d.ts +6 -0
  305. package/dist/pixoo/pixoo-settings.d.ts.map +1 -1
  306. package/dist/pixoo/pixoo-settings.js +9 -0
  307. package/dist/pixoo/pixoo-settings.js.map +1 -1
  308. package/dist/pixoo/pixoo-sprites.d.ts +84 -11
  309. package/dist/pixoo/pixoo-sprites.d.ts.map +1 -1
  310. package/dist/pixoo/pixoo-sprites.js +620 -209
  311. package/dist/pixoo/pixoo-sprites.js.map +1 -1
  312. package/dist/pty-manager.d.ts.map +1 -1
  313. package/dist/pty-manager.js +8 -2
  314. package/dist/pty-manager.js.map +1 -1
  315. package/dist/review-runner.d.ts +113 -0
  316. package/dist/review-runner.d.ts.map +1 -0
  317. package/dist/review-runner.js +428 -0
  318. package/dist/review-runner.js.map +1 -0
  319. package/dist/session-activity.d.ts +14 -0
  320. package/dist/session-activity.d.ts.map +1 -0
  321. package/dist/session-activity.js +160 -0
  322. package/dist/session-activity.js.map +1 -0
  323. package/dist/session-aggregator.d.ts +25 -0
  324. package/dist/session-aggregator.d.ts.map +1 -1
  325. package/dist/session-aggregator.js +48 -9
  326. package/dist/session-aggregator.js.map +1 -1
  327. package/dist/session-focus-relay.d.ts.map +1 -1
  328. package/dist/session-focus-relay.js +7 -1
  329. package/dist/session-focus-relay.js.map +1 -1
  330. package/dist/session-registry.d.ts +74 -3
  331. package/dist/session-registry.d.ts.map +1 -1
  332. package/dist/session-registry.js +140 -8
  333. package/dist/session-registry.js.map +1 -1
  334. package/dist/session-timeline-relay.d.ts.map +1 -1
  335. package/dist/session-timeline-relay.js +13 -4
  336. package/dist/session-timeline-relay.js.map +1 -1
  337. package/dist/session-transcript-timeline.d.ts +49 -0
  338. package/dist/session-transcript-timeline.d.ts.map +1 -0
  339. package/dist/session-transcript-timeline.js +276 -0
  340. package/dist/session-transcript-timeline.js.map +1 -0
  341. package/dist/state-machine.d.ts +6 -1
  342. package/dist/state-machine.d.ts.map +1 -1
  343. package/dist/state-machine.js +86 -28
  344. package/dist/state-machine.js.map +1 -1
  345. package/dist/timebox/timebox-daemon-sync.d.ts +19 -0
  346. package/dist/timebox/timebox-daemon-sync.d.ts.map +1 -0
  347. package/dist/timebox/timebox-daemon-sync.js +135 -0
  348. package/dist/timebox/timebox-daemon-sync.js.map +1 -0
  349. package/dist/timebox/timebox-discover.d.ts +19 -0
  350. package/dist/timebox/timebox-discover.d.ts.map +1 -0
  351. package/dist/timebox/timebox-discover.js +87 -0
  352. package/dist/timebox/timebox-discover.js.map +1 -0
  353. package/dist/timebox/timebox-settings.d.ts +32 -0
  354. package/dist/timebox/timebox-settings.d.ts.map +1 -0
  355. package/dist/timebox/timebox-settings.js +80 -0
  356. package/dist/timebox/timebox-settings.js.map +1 -0
  357. package/dist/timeline-store.d.ts +112 -3
  358. package/dist/timeline-store.d.ts.map +1 -1
  359. package/dist/timeline-store.js +460 -14
  360. package/dist/timeline-store.js.map +1 -1
  361. package/dist/timeline-summarizer.d.ts.map +1 -1
  362. package/dist/timeline-summarizer.js +29 -5
  363. package/dist/timeline-summarizer.js.map +1 -1
  364. package/dist/trmnl/byos-server.d.ts +39 -0
  365. package/dist/trmnl/byos-server.d.ts.map +1 -0
  366. package/dist/trmnl/byos-server.js +301 -0
  367. package/dist/trmnl/byos-server.js.map +1 -0
  368. package/dist/trmnl/frame-cache.d.ts +37 -0
  369. package/dist/trmnl/frame-cache.d.ts.map +1 -0
  370. package/dist/trmnl/frame-cache.js +157 -0
  371. package/dist/trmnl/frame-cache.js.map +1 -0
  372. package/dist/trmnl/image-renderer.d.ts +27 -0
  373. package/dist/trmnl/image-renderer.d.ts.map +1 -0
  374. package/dist/trmnl/image-renderer.js +235 -0
  375. package/dist/trmnl/image-renderer.js.map +1 -0
  376. package/dist/trmnl/trmnl-settings.d.ts +96 -0
  377. package/dist/trmnl/trmnl-settings.d.ts.map +1 -0
  378. package/dist/trmnl/trmnl-settings.js +177 -0
  379. package/dist/trmnl/trmnl-settings.js.map +1 -0
  380. package/dist/trmnl/trmnl-telemetry.d.ts +47 -0
  381. package/dist/trmnl/trmnl-telemetry.d.ts.map +1 -0
  382. package/dist/trmnl/trmnl-telemetry.js +56 -0
  383. package/dist/trmnl/trmnl-telemetry.js.map +1 -0
  384. package/dist/tui/ansi.d.ts +0 -4
  385. package/dist/tui/ansi.d.ts.map +1 -1
  386. package/dist/tui/ansi.js +14 -7
  387. package/dist/tui/ansi.js.map +1 -1
  388. package/dist/tui/dashboard.d.ts +1 -0
  389. package/dist/tui/dashboard.d.ts.map +1 -1
  390. package/dist/tui/dashboard.js +38 -11
  391. package/dist/tui/dashboard.js.map +1 -1
  392. package/dist/tui/renderer.d.ts +36 -0
  393. package/dist/tui/renderer.d.ts.map +1 -1
  394. package/dist/tui/renderer.js +355 -121
  395. package/dist/tui/renderer.js.map +1 -1
  396. package/dist/tui/terrarium.d.ts.map +1 -1
  397. package/dist/tui/terrarium.js +44 -51
  398. package/dist/tui/terrarium.js.map +1 -1
  399. package/dist/types.d.ts +2 -2
  400. package/dist/types.d.ts.map +1 -1
  401. package/dist/types.js +2 -2
  402. package/dist/types.js.map +1 -1
  403. package/dist/usage-api.d.ts.map +1 -1
  404. package/dist/usage-api.js +7 -1
  405. package/dist/usage-api.js.map +1 -1
  406. package/dist/usage-event.d.ts +10 -3
  407. package/dist/usage-event.d.ts.map +1 -1
  408. package/dist/usage-event.js +98 -13
  409. package/dist/usage-event.js.map +1 -1
  410. package/dist/utility-proxy.d.ts.map +1 -1
  411. package/dist/utility-proxy.js +8 -0
  412. package/dist/utility-proxy.js.map +1 -1
  413. package/dist/utils/project-name.d.ts +3 -0
  414. package/dist/utils/project-name.d.ts.map +1 -1
  415. package/dist/utils/project-name.js +44 -2
  416. package/dist/utils/project-name.js.map +1 -1
  417. package/dist/version-check.d.ts.map +1 -1
  418. package/dist/version-check.js +1 -17
  419. package/dist/version-check.js.map +1 -1
  420. package/dist/windows-service.d.ts +26 -0
  421. package/dist/windows-service.d.ts.map +1 -0
  422. package/dist/windows-service.js +145 -0
  423. package/dist/windows-service.js.map +1 -0
  424. package/dist/ws-server.d.ts +17 -3
  425. package/dist/ws-server.d.ts.map +1 -1
  426. package/dist/ws-server.js +78 -8
  427. package/dist/ws-server.js.map +1 -1
  428. package/fm-helper/AgentDeckFMHelper.swift +112 -0
  429. package/package.json +10 -4
  430. package/scripts/build-fm-helper.mjs +26 -0
  431. package/LICENSE +0 -21
  432. package/dist/apme/tuner.d.ts +0 -64
  433. package/dist/apme/tuner.d.ts.map +0 -1
  434. package/dist/apme/tuner.js +0 -297
  435. package/dist/apme/tuner.js.map +0 -1
@@ -13,43 +13,175 @@
13
13
  import { writeFileSync } from 'fs';
14
14
  import { join } from 'path';
15
15
  import { homedir } from 'os';
16
- import { debug } from '../logger.js';
16
+ import { logError } from '../logger.js';
17
17
  import { ApmeStore } from './store.js';
18
18
  import { apmeDashboardHtml } from './dashboard-html.js';
19
19
  import { ApmeCollector } from './collector.js';
20
20
  import { ApmeRunner } from './runner.js';
21
- import { ApmeTuner } from './tuner.js';
22
21
  import { ApmeHwSampler } from './hw-sampler.js';
23
22
  import { ApmeRecommender } from './recommend.js';
23
+ import { sampleEventToTimeline } from './sample-to-timeline.js';
24
+ import { formatDurationSec } from '@agentdeck/shared';
25
+ /** Task boundary rows read "<signal> · <N> turns · <duration>" — the turn
26
+ * count says what the boundary covered, the human duration replaces the
27
+ * raw "3672s" second counts. */
28
+ function taskEndRowText(signalLabel, turns, durationSec) {
29
+ const parts = [signalLabel];
30
+ if (turns && turns > 0)
31
+ parts.push(turns === 1 ? '1 turn' : `${turns} turns`);
32
+ parts.push(formatDurationSec(durationSec));
33
+ return parts.join(' · ');
34
+ }
24
35
  let singleton = null;
25
- /** Initialize the APME subsystem. Returns null if the SQLite store can't open. */
26
- export async function initApme(dbPath) {
36
+ /** Initialize the APME subsystem. Returns null if the SQLite store can't open.
37
+ * When null, the failure reason is logged at ERROR level — silent disable was
38
+ * the dominant cause of multi-day data outages observed in user telemetry. */
39
+ export async function initApme(dbPath, opts = {}) {
27
40
  if (singleton)
28
41
  return singleton;
29
42
  const store = new ApmeStore(dbPath);
30
43
  const ok = await store.init();
31
44
  if (!ok) {
32
- debug('APME', 'initApme skipped (store disabled)');
45
+ logError(`APME disabled — ${store.lastInitError ?? 'unknown init failure'}. Agent runs will not be measured.`);
33
46
  return null;
34
47
  }
35
48
  const hwSampler = new ApmeHwSampler();
36
49
  const collector = new ApmeCollector(store, hwSampler);
37
50
  const runner = new ApmeRunner(store);
38
- const tuner = new ApmeTuner(store);
39
51
  const recommender = new ApmeRecommender(store);
40
- singleton = { store, collector, runner, tuner, hwSampler, recommender };
52
+ singleton = { store, collector, runner, hwSampler, recommender };
53
+ const emitTimeline = opts.emitTimeline;
54
+ // Task headers are DEFERRED (collector emits `task_start` only once a task
55
+ // proves itself multi-turn). Track which task ids actually reached the
56
+ // timeline so the async judge re-emit (`onTaskEvaluated`, below) can skip
57
+ // unpromoted single-turn tasks — otherwise it would insert an orphan
58
+ // `task_end` with a score badge under no header. `onTaskOpened` fires at the
59
+ // deferred promotion moment, so membership here == "header is on the timeline".
60
+ const promotedTaskIds = new Set();
41
61
  // Wire task-level judge: whenever the collector closes a task (TodoWrite
42
62
  // all-completed / /clear / session_end), enqueue a task_rollup judge call.
43
63
  // Kept here — not in the collector constructor — so the collector has no
44
64
  // hard dependency on the runner.
45
- collector.onTaskClosed = ({ taskId, runId, boundarySignal, taskCategory }) => {
65
+ collector.onTaskClosed = ({ taskId, runId, sessionId, agentType, projectName, startedAt, endedAt, boundarySignal, taskCategory, turns, timelineEmitted, }) => {
46
66
  runner.enqueueTask({
47
67
  runId,
48
68
  taskId,
49
69
  category: taskCategory ?? undefined,
50
70
  boundarySignal,
51
71
  });
72
+ // Gate the `task_end` row on the header having been emitted — an
73
+ // unpromoted single-turn task shows only its chat rows, never a bare
74
+ // "Task end" marker. The eval enqueue above runs regardless.
75
+ if (emitTimeline && timelineEmitted) {
76
+ const durationSec = Math.max(0, Math.round((endedAt - startedAt) / 1000));
77
+ const signalLabel = boundarySignal === 'todo_complete' ? 'TODO done'
78
+ : boundarySignal === 'clear' ? '/clear'
79
+ : boundarySignal === 'session_end' ? 'Session end'
80
+ : 'Task end';
81
+ emitTimeline({
82
+ ts: endedAt,
83
+ type: 'task_end',
84
+ raw: taskEndRowText(signalLabel, turns, durationSec),
85
+ agentType: agentType ?? undefined,
86
+ projectName: projectName ?? undefined,
87
+ sessionId,
88
+ runId,
89
+ taskId,
90
+ boundarySignal,
91
+ startedAt,
92
+ endedAt,
93
+ });
94
+ }
52
95
  };
96
+ // Wire the SessionSample → Timeline projection. When enabled, the timeline
97
+ // is a projection of the canonical sample (one row per typed trajectory
98
+ // event), replacing display-time grouping + the race-sensitive dedup window.
99
+ if (emitTimeline && opts.projectSampleTimeline) {
100
+ const emitProjected = opts.emitProjectedTimeline ?? emitTimeline;
101
+ collector.onSampleEvent = ({ event, sessionId, runId, taskId, agentType, projectName }) => {
102
+ const entry = sampleEventToTimeline(event, { sessionId, runId, taskId, agentType, projectName });
103
+ if (entry)
104
+ emitProjected(entry);
105
+ };
106
+ }
107
+ // Wire task-start emission. The runner has no opinion on opens — only the
108
+ // dashboard does — so we keep this strictly local to the timeline path.
109
+ if (emitTimeline) {
110
+ collector.onTaskOpened = ({ taskId, runId, sessionId, agentType, projectName, taskIndex, startedAt, }) => {
111
+ promotedTaskIds.add(taskId);
112
+ emitTimeline({
113
+ ts: startedAt,
114
+ type: 'task_start',
115
+ raw: `Task ${taskIndex + 1}`,
116
+ agentType: agentType ?? undefined,
117
+ projectName: projectName ?? undefined,
118
+ sessionId,
119
+ runId,
120
+ taskId,
121
+ startedAt,
122
+ });
123
+ };
124
+ }
125
+ // Wire the mid-task completion milestone. TodoWrite-all-completed is a
126
+ // non-segmenting soft hint (fires ~18% of the time on Claude Code v2.1), so
127
+ // it must not split the task — but when it DOES fire it is a strong "the
128
+ // agent declared this chunk done" signal, and long sessions otherwise show
129
+ // no completion marks until /clear or session_end.
130
+ if (emitTimeline) {
131
+ collector.onTaskMilestone = ({ taskId, runId, sessionId, agentType, projectName, todoCount, at, }) => {
132
+ emitTimeline({
133
+ ts: at,
134
+ type: 'task_milestone',
135
+ raw: todoCount ? `Todos done (${todoCount})` : 'Todos done',
136
+ agentType: agentType ?? undefined,
137
+ projectName: projectName ?? undefined,
138
+ sessionId,
139
+ runId,
140
+ taskId,
141
+ });
142
+ };
143
+ }
144
+ // Wire task-eval completion → re-emit `task_end` with score + outcome.
145
+ // The original `task_end` (above) fires synchronously on closeTask so the
146
+ // boundary is visible immediately; the judge runs async and may take
147
+ // 5-30 s. When it resolves, this listener emits a second `task_end` with
148
+ // the same `taskId`. Timeline stores upsert by (type='task_end', taskId)
149
+ // and merge the new score fields onto the existing row, so dashboard task
150
+ // headers get the score badge as soon as the judge returns.
151
+ if (emitTimeline) {
152
+ runner.onTaskEvaluated((e) => {
153
+ // Skip the score re-emit for tasks whose header never reached the
154
+ // timeline (single-turn Q&A). Without this the merge-or-insert
155
+ // timeline store would insert a fresh orphan `task_end` here. Consume
156
+ // the id so the set doesn't grow unbounded across a long-lived daemon.
157
+ if (!promotedTaskIds.delete(e.taskId))
158
+ return;
159
+ const durationSec = Math.max(0, Math.round((e.endedAt - e.startedAt) / 1000));
160
+ const signalLabel = e.boundarySignal === 'todo_complete' ? 'TODO done'
161
+ : e.boundarySignal === 'clear' ? '/clear'
162
+ : e.boundarySignal === 'session_end' ? 'Session end'
163
+ : e.boundarySignal === 'manual' ? 'Manual'
164
+ : e.boundarySignal === 'idle_gap' ? 'Idle gap'
165
+ : 'Task end';
166
+ emitTimeline({
167
+ ts: e.endedAt,
168
+ type: 'task_end',
169
+ raw: taskEndRowText(signalLabel, e.turns, durationSec),
170
+ agentType: e.agentType,
171
+ projectName: e.projectName,
172
+ sessionId: e.sessionId,
173
+ runId: e.runId,
174
+ taskId: e.taskId,
175
+ boundarySignal: e.boundarySignal,
176
+ startedAt: e.startedAt,
177
+ endedAt: e.endedAt,
178
+ taskScore: e.compositeScore ?? undefined,
179
+ taskOutcome: e.outcome,
180
+ taskCategory: e.taskCategory,
181
+ taskSummary: e.summary,
182
+ });
183
+ });
184
+ }
53
185
  // Write dashboard HTML for Swift daemon to pick up.
54
186
  try {
55
187
  const dataDir = process.env.AGENTDECK_DATA_DIR || join(homedir(), '.agentdeck');
@@ -63,11 +195,16 @@ export async function initApme(dbPath) {
63
195
  export function getApme() {
64
196
  return singleton;
65
197
  }
198
+ /** Phase 6 cutover switch (default OFF). Set `AGENTDECK_TIMELINE_PROJECTION=1`
199
+ * to make the timeline a projection of the canonical SessionSample. Read at
200
+ * daemon/session-bridge startup so it can be flipped without a recompile. */
201
+ export function isTimelineProjectionEnabled() {
202
+ return process.env.AGENTDECK_TIMELINE_PROJECTION === '1';
203
+ }
66
204
  export { loadApmeConfig, shouldJudge, DEFAULT_APME_CONFIG } from './settings.js';
67
205
  export { ApmeStore } from './store.js';
68
206
  export { ApmeCollector } from './collector.js';
69
207
  export { ApmeRunner } from './runner.js';
70
- export { ApmeTuner } from './tuner.js';
71
208
  export { ApmeHwSampler } from './hw-sampler.js';
72
209
  export { ApmeRecommender } from './recommend.js';
73
210
  export { classifyRun, classifyRunSmart, classifyWithLlm, classify, computeSignals, TASK_CATEGORIES } from './classifier.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/apme/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACnC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAWjD,IAAI,SAAS,GAAsB,IAAI,CAAC;AAExC,kFAAkF;AAClF,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,MAAe;IAC5C,IAAI,SAAS;QAAE,OAAO,SAAS,CAAC;IAChC,MAAM,KAAK,GAAG,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,KAAK,CAAC,MAAM,EAAE,mCAAmC,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,aAAa,EAAE,CAAC;IACtC,MAAM,SAAS,GAAG,IAAI,aAAa,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;IACrC,MAAM,KAAK,GAAG,IAAI,SAAS,CAAC,KAAK,CAAC,CAAC;IACnC,MAAM,WAAW,GAAG,IAAI,eAAe,CAAC,KAAK,CAAC,CAAC;IAC/C,SAAS,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC;IAExE,yEAAyE;IACzE,2EAA2E;IAC3E,yEAAyE;IACzE,iCAAiC;IACjC,SAAS,CAAC,YAAY,GAAG,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,EAAE,EAAE;QAC3E,MAAM,CAAC,WAAW,CAAC;YACjB,KAAK;YACL,MAAM;YACN,QAAQ,EAAE,YAAY,IAAI,SAAS;YACnC,cAAc;SACf,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,oDAAoD;IACpD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAC;QAChF,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,qBAAqB,CAAC,EAAE,iBAAiB,EAAE,EAAE,OAAO,CAAC,CAAC;IACpF,CAAC;IAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;IAE7B,sEAAsE;IACtE,8DAA8D;IAE9D,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,OAAO;IACrB,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEjF,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,eAAe,EAAE,QAAQ,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC5H,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/apme/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * HTTP-only detection of locally-running, de-facto-standard inference servers
3
+ * so onboarding + the REVIEW judge-setup guide can offer "use what you already
4
+ * have" instead of asking the user to configure an endpoint by hand.
5
+ *
6
+ * App Store safety: this is pure network I/O against loopback ports — NO
7
+ * subprocess, NO CLI probe (`ollama list` etc.). The macOS sandbox's
8
+ * `com.apple.security.network.client` covers loopback HTTP, so this runs
9
+ * unchanged in the signed App Store daemon. Mirror: apple ApmeJudgeDetect.swift.
10
+ */
11
+ export interface DetectedProvider {
12
+ /** Stable key: 'ollama' | 'lmstudio' | 'mlx' | 'openai-generic'. */
13
+ provider: string;
14
+ label: string;
15
+ /** OpenAI-compatible base to store as apme.judge.endpoint. */
16
+ endpoint: string;
17
+ /** Chat model ids advertised by the server (first is a sensible default). */
18
+ models: string[];
19
+ }
20
+ /**
21
+ * Probe the standard local endpoints concurrently. Returns only servers that
22
+ * are reachable AND advertise at least one usable chat model. De-duplicated by
23
+ * (provider, endpoint) so the two MLX ports don't both show when one answers.
24
+ */
25
+ export declare function detectLocalJudgeProviders(timeoutMs?: number): Promise<DetectedProvider[]>;
26
+ //# sourceMappingURL=judge-detect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"judge-detect.d.ts","sourceRoot":"","sources":["../../src/apme/judge-detect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,oEAAoE;IACpE,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,QAAQ,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AA2CD;;;;GAIG;AACH,wBAAsB,yBAAyB,CAAC,SAAS,SAAO,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAgB7F"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * HTTP-only detection of locally-running, de-facto-standard inference servers
3
+ * so onboarding + the REVIEW judge-setup guide can offer "use what you already
4
+ * have" instead of asking the user to configure an endpoint by hand.
5
+ *
6
+ * App Store safety: this is pure network I/O against loopback ports — NO
7
+ * subprocess, NO CLI probe (`ollama list` etc.). The macOS sandbox's
8
+ * `com.apple.security.network.client` covers loopback HTTP, so this runs
9
+ * unchanged in the signed App Store daemon. Mirror: apple ApmeJudgeDetect.swift.
10
+ */
11
+ const CANDIDATES = [
12
+ { provider: 'ollama', label: 'Ollama', base: 'http://127.0.0.1:11434', endpoint: 'http://127.0.0.1:11434/v1', tags: true },
13
+ { provider: 'lmstudio', label: 'LM Studio', base: 'http://127.0.0.1:1234', endpoint: 'http://127.0.0.1:1234/v1' },
14
+ { provider: 'mlx', label: 'Local MLX server', base: 'http://127.0.0.1:8800', endpoint: 'http://127.0.0.1:8800/v1' },
15
+ { provider: 'mlx', label: 'Local MLX server', base: 'http://127.0.0.1:8080', endpoint: 'http://127.0.0.1:8080/v1' },
16
+ ];
17
+ const NANO = 'nanollava';
18
+ async function modelsFor(c, timeoutMs) {
19
+ // Ollama's canonical list is /api/tags; every OpenAI-compatible server
20
+ // (LM Studio, MLX, vLLM, Ollama's compat shim) exposes /v1/models.
21
+ if (c.tags) {
22
+ try {
23
+ const r = await fetch(`${c.base}/api/tags`, { signal: AbortSignal.timeout(timeoutMs) }).catch(() => null);
24
+ if (r?.ok) {
25
+ const j = await r.json();
26
+ const names = (j.models ?? []).map((m) => m.name).filter((n) => !!n);
27
+ if (names.length)
28
+ return names;
29
+ }
30
+ }
31
+ catch { /* fall through to /v1/models */ }
32
+ }
33
+ try {
34
+ const r = await fetch(`${c.base}/v1/models`, { signal: AbortSignal.timeout(timeoutMs) }).catch(() => null);
35
+ if (r?.ok) {
36
+ const j = await r.json();
37
+ const ids = (j.data ?? []).map((m) => m.id).filter((id) => !!id && !id.toLowerCase().includes(NANO));
38
+ return ids; // empty array = reachable but no usable model
39
+ }
40
+ }
41
+ catch { /* unreachable */ }
42
+ return null;
43
+ }
44
+ /**
45
+ * Probe the standard local endpoints concurrently. Returns only servers that
46
+ * are reachable AND advertise at least one usable chat model. De-duplicated by
47
+ * (provider, endpoint) so the two MLX ports don't both show when one answers.
48
+ */
49
+ export async function detectLocalJudgeProviders(timeoutMs = 1200) {
50
+ const results = await Promise.all(CANDIDATES.map(async (c) => {
51
+ const models = await modelsFor(c, timeoutMs);
52
+ if (!models || models.length === 0)
53
+ return null;
54
+ return { provider: c.provider, label: c.label, endpoint: c.endpoint, models: models.slice(0, 12) };
55
+ }));
56
+ const seen = new Set();
57
+ const out = [];
58
+ for (const r of results) {
59
+ if (!r)
60
+ continue;
61
+ const key = `${r.provider}:${r.endpoint}`;
62
+ if (seen.has(key))
63
+ continue;
64
+ seen.add(key);
65
+ out.push(r);
66
+ }
67
+ return out;
68
+ }
69
+ //# sourceMappingURL=judge-detect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"judge-detect.js","sourceRoot":"","sources":["../../src/apme/judge-detect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Pareto frontier over (quality, cost) for model orchestration.
3
+ *
4
+ * A model is on the frontier if no other model dominates it — i.e. no other
5
+ * model is BOTH higher quality AND lower (or equal) cost per sample. Dominated
6
+ * models are strictly worse on both axes and should never be recommended; the
7
+ * frontier is the real menu of quality/cost tradeoffs.
8
+ *
9
+ * "Same quality, 40% cheaper" decisions fall straight out of this: walk the
10
+ * frontier from cheapest to best and pick the knee that fits the budget.
11
+ *
12
+ * Pure + synchronous + unit-testable. Input is the sample-granularity
13
+ * scorecard; output partitions candidates into frontier vs dominated.
14
+ */
15
+ import type { ApmeSampleScorecardRow } from '@agentdeck/shared';
16
+ export interface ParetoPoint {
17
+ agentType: string;
18
+ modelId: string;
19
+ taskCategory: string | null;
20
+ /** Quality axis (avg composite, [0,1]). Higher is better. */
21
+ quality: number;
22
+ /** Cost axis: average USD per sample. Lower is better. */
23
+ costPerSample: number;
24
+ avgLatencyMs: number | null;
25
+ samples: number;
26
+ }
27
+ export interface ParetoResult {
28
+ frontier: ParetoPoint[];
29
+ dominated: ParetoPoint[];
30
+ }
31
+ /**
32
+ * Partition scorecard rows into the Pareto frontier and the dominated set.
33
+ * @param rows sample scorecard rows (optionally pre-filtered by category)
34
+ * @param minSamples ignore models with too little data to trust
35
+ */
36
+ export declare function computePareto(rows: ApmeSampleScorecardRow[], minSamples?: number): ParetoResult;
37
+ /** Convenience: filter scorecard to a category before computing the frontier. */
38
+ export declare function paretoForCategory(rows: ApmeSampleScorecardRow[], category: string | null | undefined, minSamples?: number): ParetoResult;
39
+ //# sourceMappingURL=pareto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pareto.d.ts","sourceRoot":"","sources":["../../src/apme/pareto.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAEhE,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,6DAA6D;IAC7D,OAAO,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,SAAS,EAAE,WAAW,EAAE,CAAC;CAC1B;AAsBD;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,sBAAsB,EAAE,EAC9B,UAAU,SAAI,GACb,YAAY,CAcd;AAED,iFAAiF;AACjF,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,sBAAsB,EAAE,EAC9B,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACnC,UAAU,SAAI,GACb,YAAY,CAGd"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Pareto frontier over (quality, cost) for model orchestration.
3
+ *
4
+ * A model is on the frontier if no other model dominates it — i.e. no other
5
+ * model is BOTH higher quality AND lower (or equal) cost per sample. Dominated
6
+ * models are strictly worse on both axes and should never be recommended; the
7
+ * frontier is the real menu of quality/cost tradeoffs.
8
+ *
9
+ * "Same quality, 40% cheaper" decisions fall straight out of this: walk the
10
+ * frontier from cheapest to best and pick the knee that fits the budget.
11
+ *
12
+ * Pure + synchronous + unit-testable. Input is the sample-granularity
13
+ * scorecard; output partitions candidates into frontier vs dominated.
14
+ */
15
+ function toPoint(r) {
16
+ return {
17
+ agentType: r.agentType,
18
+ modelId: r.modelId,
19
+ taskCategory: r.taskCategory,
20
+ quality: r.avgQuality ?? 0,
21
+ costPerSample: r.samples > 0 ? (r.totalCost ?? 0) / r.samples : 0,
22
+ avgLatencyMs: r.avgLatencyMs,
23
+ samples: r.samples,
24
+ };
25
+ }
26
+ /** True when `b` dominates `a`: at least as good on both axes and strictly
27
+ * better on at least one (higher quality, lower cost). */
28
+ function dominates(b, a) {
29
+ const betterOrEqual = b.quality >= a.quality && b.costPerSample <= a.costPerSample;
30
+ const strictlyBetter = b.quality > a.quality || b.costPerSample < a.costPerSample;
31
+ return betterOrEqual && strictlyBetter;
32
+ }
33
+ /**
34
+ * Partition scorecard rows into the Pareto frontier and the dominated set.
35
+ * @param rows sample scorecard rows (optionally pre-filtered by category)
36
+ * @param minSamples ignore models with too little data to trust
37
+ */
38
+ export function computePareto(rows, minSamples = 3) {
39
+ const points = rows
40
+ .filter((r) => r.samples >= minSamples && (r.avgQuality ?? 0) > 0)
41
+ .map(toPoint);
42
+ const frontier = [];
43
+ const dominated = [];
44
+ for (const a of points) {
45
+ if (points.some((b) => b !== a && dominates(b, a)))
46
+ dominated.push(a);
47
+ else
48
+ frontier.push(a);
49
+ }
50
+ // Frontier sorted cheapest → most expensive (the natural tradeoff curve).
51
+ frontier.sort((x, y) => x.costPerSample - y.costPerSample || y.quality - x.quality);
52
+ return { frontier, dominated };
53
+ }
54
+ /** Convenience: filter scorecard to a category before computing the frontier. */
55
+ export function paretoForCategory(rows, category, minSamples = 3) {
56
+ const scoped = category ? rows.filter((r) => r.taskCategory === category) : rows;
57
+ return computePareto(scoped, minSamples);
58
+ }
59
+ //# sourceMappingURL=pareto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pareto.js","sourceRoot":"","sources":["../../src/apme/pareto.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAqBH,SAAS,OAAO,CAAC,CAAyB;IACxC,OAAO;QACL,SAAS,EAAE,CAAC,CAAC,SAAS;QACtB,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,YAAY,EAAE,CAAC,CAAC,YAAY;QAC5B,OAAO,EAAE,CAAC,CAAC,UAAU,IAAI,CAAC;QAC1B,aAAa,EAAE,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACjE,YAAY,EAAE,CAAC,CAAC,YAAY;QAC5B,OAAO,EAAE,CAAC,CAAC,OAAO;KACnB,CAAC;AACJ,CAAC;AAED;2DAC2D;AAC3D,SAAS,SAAS,CAAC,CAAc,EAAE,CAAc;IAC/C,MAAM,aAAa,GAAG,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,aAAa,IAAI,CAAC,CAAC,aAAa,CAAC;IACnF,MAAM,cAAc,GAAG,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC,aAAa,CAAC;IAClF,OAAO,aAAa,IAAI,cAAc,CAAC;AACzC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC3B,IAA8B,EAC9B,UAAU,GAAG,CAAC;IAEd,MAAM,MAAM,GAAG,IAAI;SAChB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,UAAU,IAAI,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;SACjE,GAAG,CAAC,OAAO,CAAC,CAAC;IAEhB,MAAM,QAAQ,GAAkB,EAAE,CAAC;IACnC,MAAM,SAAS,GAAkB,EAAE,CAAC;IACpC,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAAE,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;;YACjE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACxB,CAAC;IACD,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC,aAAa,IAAI,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC;IACpF,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;AACjC,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,iBAAiB,CAC/B,IAA8B,EAC9B,QAAmC,EACnC,UAAU,GAAG,CAAC;IAEd,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACjF,OAAO,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAC3C,CAAC"}
@@ -28,5 +28,8 @@ export declare class ApmeRecommender {
28
28
  private readonly store;
29
29
  constructor(store: ApmeStore);
30
30
  recommend(input: RecommendInput): RecommendCandidate[];
31
+ /** Legacy run-level recommendation (v_model_scorecard). Used when no
32
+ * sample-granularity composite scores exist yet. */
33
+ private recommendFromRuns;
31
34
  }
32
35
  //# sourceMappingURL=recommend.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"recommend.d.ts","sourceRoot":"","sources":["../../src/apme/recommend.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,mFAAmF;IACnF,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,SAAS,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,SAAS;IAE7C,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,kBAAkB,EAAE;CA2BvD"}
1
+ {"version":3,"file":"recommend.d.ts","sourceRoot":"","sources":["../../src/apme/recommend.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG5C,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,mFAAmF;IACnF,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,SAAS,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,SAAS;IAE7C,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,kBAAkB,EAAE;IAgDtD;yDACqD;IACrD,OAAO,CAAC,iBAAiB;CAyB1B"}
@@ -6,6 +6,7 @@
6
6
  * confidence. v1 uses the v_model_scorecard view; v2 (stretch) layers in
7
7
  * task-similarity via local embeddings.
8
8
  */
9
+ import { paretoForCategory } from './pareto.js';
9
10
  export class ApmeRecommender {
10
11
  store;
11
12
  constructor(store) {
@@ -14,6 +15,48 @@ export class ApmeRecommender {
14
15
  recommend(input) {
15
16
  if (!this.store.enabled)
16
17
  return [];
18
+ // Work at sample granularity (the canonical eval unit) and restrict to the
19
+ // Pareto frontier — dominated models (strictly worse on quality AND cost)
20
+ // are never worth recommending. This is the model-orchestration payoff:
21
+ // the menu is the quality/cost tradeoff curve, not a flat ranking.
22
+ const scorecard = this.store.sampleScorecard();
23
+ let { frontier } = paretoForCategory(scorecard, input.taskKind);
24
+ // Fall back to the whole frontier if the category has too little data.
25
+ if (frontier.length === 0)
26
+ frontier = paretoForCategory(scorecard, undefined).frontier;
27
+ // Fall back to the run-level scorecard when no sample-granularity data has
28
+ // accumulated yet (legacy runs, or before the first task judge resolves).
29
+ if (frontier.length === 0)
30
+ return this.recommendFromRuns(input);
31
+ let candidates = frontier;
32
+ if (input.availableModels) {
33
+ candidates = candidates.filter((p) => input.availableModels.includes(p.modelId));
34
+ }
35
+ if (input.budgetUsd !== undefined) {
36
+ candidates = candidates.filter((p) => p.costPerSample <= input.budgetUsd);
37
+ }
38
+ if (input.latencyBudgetMs !== undefined) {
39
+ candidates = candidates.filter((p) => p.avgLatencyMs == null || p.avgLatencyMs <= input.latencyBudgetMs);
40
+ }
41
+ candidates = [...candidates].sort((a, b) => {
42
+ // Budget-conscious or local-preferring → cheapest first; else best quality.
43
+ if (input.preferLocal || (input.budgetUsd !== undefined && input.budgetUsd < 5)) {
44
+ return a.costPerSample - b.costPerSample || b.quality - a.quality;
45
+ }
46
+ return b.quality - a.quality || a.costPerSample - b.costPerSample;
47
+ });
48
+ return candidates.slice(0, 3).map((p) => ({
49
+ modelId: p.modelId,
50
+ agentType: p.agentType,
51
+ expectedScore: p.quality,
52
+ expectedCostUsd: p.costPerSample,
53
+ confidence: Math.min(1, p.samples / 20),
54
+ rationale: `${p.samples} samples, avg ${(p.quality * 100).toFixed(0)}%, $${p.costPerSample.toFixed(4)}/sample${p.avgLatencyMs != null ? `, ${Math.round(p.avgLatencyMs)}ms` : ''} — on the cost/quality frontier`,
55
+ }));
56
+ }
57
+ /** Legacy run-level recommendation (v_model_scorecard). Used when no
58
+ * sample-granularity composite scores exist yet. */
59
+ recommendFromRuns(input) {
17
60
  const rows = this.store.scorecard();
18
61
  const filtered = input.availableModels
19
62
  ? rows.filter((r) => input.availableModels.includes(r.modelId))
@@ -21,7 +64,6 @@ export class ApmeRecommender {
21
64
  return filtered
22
65
  .filter((r) => r.runs >= 3 && (r.avgOverall ?? 0) > 0)
23
66
  .sort((a, b) => {
24
- // Prefer cost-per-quality if budget is tight, otherwise raw quality.
25
67
  if (input.budgetUsd !== undefined && input.budgetUsd < 5) {
26
68
  return (a.costPerQuality ?? Infinity) - (b.costPerQuality ?? Infinity);
27
69
  }
@@ -1 +1 @@
1
- {"version":3,"file":"recommend.js","sourceRoot":"","sources":["../../src/apme/recommend.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAuBH,MAAM,OAAO,eAAe;IACG;IAA7B,YAA6B,KAAgB;QAAhB,UAAK,GAAL,KAAK,CAAW;IAAG,CAAC;IAEjD,SAAS,CAAC,KAAqB;QAC7B,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO;YAAE,OAAO,EAAE,CAAC;QACnC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;QACpC,MAAM,QAAQ,GAAG,KAAK,CAAC,eAAe;YACpC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,eAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YAChE,CAAC,CAAC,IAAI,CAAC;QACT,OAAO,QAAQ;aACZ,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;aACrD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACb,qEAAqE;YACrE,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,KAAK,CAAC,SAAS,GAAG,CAAC,EAAE,CAAC;gBACzD,OAAO,CAAC,CAAC,CAAC,cAAc,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,cAAc,IAAI,QAAQ,CAAC,CAAC;YACzE,CAAC;YACD,OAAO,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC;QACnD,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;aACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACX,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,SAAS,EAAE,CAAC,CAAC,SAAsB;YACnC,aAAa,EAAE,CAAC,CAAC,UAAU,IAAI,CAAC;YAChC,eAAe,EAAE,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YACzD,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,GAAG,EAAE,CAAC;YACpC,SAAS,EAAE,GAAG,CAAC,CAAC,IAAI,cAAc,CAAC,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IACtE,CAAC,CAAC,YAAY,IAAI,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAC/E,EAAE;SACH,CAAC,CAAC,CAAC;IACR,CAAC;CACF"}
1
+ {"version":3,"file":"recommend.js","sourceRoot":"","sources":["../../src/apme/recommend.ts"],"names":[],"mappings":"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"}