@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
@@ -0,0 +1,196 @@
1
+ /**
2
+ * Shared spawn helper for the daemon-managed Python BLE sync clients
3
+ * (iDotMatrix `sync.py`, Timebox `sync_ble.py`).
4
+ *
5
+ * Both clients were previously spawned with `stdio: 'ignore'`, which keeps the
6
+ * child's verbose stdout from flooding the daemon log — but also discards the
7
+ * crash traceback on stderr. A missing `bleak`/`idotmatrix` dependency, a stale
8
+ * venv, or a bad BLE address then looks identical to a clean exit: the panel
9
+ * goes dark and the daemon logs only "respawning in Ns" with no cause. This
10
+ * helper pipes stdout/stderr into small ring buffers so the manager can log
11
+ * *why* the sync died without flooding the daemon log while it is running.
12
+ */
13
+ import { spawn } from 'child_process';
14
+ /**
15
+ * Spawn a Python sync child with stdout/stderr captured into bounded tail
16
+ * buffers. Output is not streamed live; callers read it only if the child exits.
17
+ */
18
+ export function spawnPythonSync(venvPython, args, maxTailLines = 8) {
19
+ // [stdin ignored, stdout/stderr piped into small rings for diagnostics]
20
+ const proc = spawn(venvPython, args, { stdio: ['ignore', 'pipe', 'pipe'] });
21
+ const stderrTail = [];
22
+ const outputTail = [];
23
+ let stderrPartial = '';
24
+ let stdoutPartial = '';
25
+ const capture = (label, chunk) => {
26
+ let partial = label === 'stderr' ? stderrPartial : stdoutPartial;
27
+ partial += chunk.toString();
28
+ const lines = partial.split('\n');
29
+ partial = lines.pop() ?? '';
30
+ for (const line of lines) {
31
+ const trimmed = line.trimEnd();
32
+ if (!trimmed)
33
+ continue;
34
+ const tagged = `${label}: ${trimmed}`;
35
+ outputTail.push(tagged);
36
+ if (outputTail.length > maxTailLines)
37
+ outputTail.shift();
38
+ if (label === 'stderr') {
39
+ stderrTail.push(trimmed);
40
+ if (stderrTail.length > maxTailLines)
41
+ stderrTail.shift();
42
+ }
43
+ }
44
+ if (label === 'stderr')
45
+ stderrPartial = partial;
46
+ else
47
+ stdoutPartial = partial;
48
+ };
49
+ proc.stdout?.on('data', (chunk) => capture('stdout', chunk));
50
+ proc.stderr?.on('data', (chunk) => capture('stderr', chunk));
51
+ return {
52
+ proc,
53
+ stderrTail: () => {
54
+ const lines = stderrPartial.trim() ? [...stderrTail, stderrPartial.trim()] : stderrTail;
55
+ return lines.slice(-maxTailLines).join(' | ');
56
+ },
57
+ outputTail: () => {
58
+ const lines = [...outputTail];
59
+ if (stdoutPartial.trim())
60
+ lines.push(`stdout: ${stdoutPartial.trim()}`);
61
+ if (stderrPartial.trim())
62
+ lines.push(`stderr: ${stderrPartial.trim()}`);
63
+ return lines.slice(-maxTailLines).join(' | ');
64
+ },
65
+ };
66
+ }
67
+ /** Emit a repeated-cycle summary at most this often while suppressing. */
68
+ const SQUELCH_SUMMARY_INTERVAL_MS = 60 * 60_000;
69
+ /** A run this long means the previous respawn loop ended; the next exit logs fresh. */
70
+ const SQUELCH_RESET_UPTIME_MS = 5 * 60_000;
71
+ /**
72
+ * Collapse variable parts so consecutive exits from the same failure loop
73
+ * compare equal: timestamps/addresses/hashes are masked, and the ` | `-joined
74
+ * output tail is reduced to its set of distinct lines — the ring buffer
75
+ * captures 1 or 2 copies of the same retry error depending on timing, which
76
+ * must not read as a different cycle.
77
+ */
78
+ function cycleSignature(code, signal, tail) {
79
+ const masked = tail.replace(/[0-9A-Fa-f]{4,}/g, '#').replace(/\d+/g, '#');
80
+ const segments = [...new Set(masked.split(' | ').map((s) => s.trim()))].sort();
81
+ return `${code}|${signal}|${segments.join(' | ')}`;
82
+ }
83
+ /**
84
+ * Log gate for the respawn loop of a managed BLE sync child.
85
+ *
86
+ * A powered-off or out-of-range panel makes the sync child exit the same way
87
+ * every backoff period, all night — thousands of identical start/exit pairs in
88
+ * the daemon log. The gate logs the first two occurrences of an exit cycle in
89
+ * full, then suppresses identical repeats (including their respawn start
90
+ * lines), emitting an hourly count summary instead. Any *different* exit —
91
+ * new error text, non-zero code, a crash after a long healthy run — flushes
92
+ * the summary and logs immediately, so novel failures are never hidden.
93
+ */
94
+ export function createSyncCycleSquelch(log) {
95
+ let lastSignature = null;
96
+ let repeats = 0; // suppressed repeats of lastSignature (beyond the logged first occurrence)
97
+ let suppressedSinceSummary = 0;
98
+ let suppressedSince = 0;
99
+ let lastSummaryAt = 0;
100
+ let lastLine = '';
101
+ const flush = () => {
102
+ if (suppressedSinceSummary > 0) {
103
+ log(`suppressed ${suppressedSinceSummary} repeats of the same sync cycle since ` +
104
+ `${new Date(suppressedSince).toISOString()}; latest: ${lastLine}`);
105
+ }
106
+ lastSignature = null;
107
+ repeats = 0;
108
+ suppressedSinceSummary = 0;
109
+ };
110
+ return {
111
+ logStart(line) {
112
+ if (repeats > 0)
113
+ return; // inside a suppressed repeating cycle
114
+ log(line);
115
+ },
116
+ logExit(code, signal, uptimeMs, tail, line) {
117
+ // A long healthy run means the old loop ended; whatever exits next is a
118
+ // fresh incident even if the text matches the old one.
119
+ if (uptimeMs >= SQUELCH_RESET_UPTIME_MS)
120
+ flush();
121
+ const signature = cycleSignature(code, signal, tail);
122
+ if (signature !== lastSignature) {
123
+ flush();
124
+ lastSignature = signature;
125
+ log(line);
126
+ return;
127
+ }
128
+ repeats += 1;
129
+ suppressedSinceSummary += 1;
130
+ lastLine = line;
131
+ const now = Date.now();
132
+ if (repeats === 1) {
133
+ // Second identical cycle: log it once more, then go quiet.
134
+ suppressedSinceSummary = 0;
135
+ suppressedSince = now;
136
+ lastSummaryAt = now;
137
+ log(`${line} — repeating cycle; suppressing identical start/exit logs (hourly summary, a different exit logs immediately)`);
138
+ return;
139
+ }
140
+ if (now - lastSummaryAt >= SQUELCH_SUMMARY_INTERVAL_MS) {
141
+ log(`suppressed ${suppressedSinceSummary} repeats of the same sync cycle in the last ` +
142
+ `${Math.round((now - lastSummaryAt) / 60_000)}m; latest: ${lastLine}`);
143
+ lastSummaryAt = now;
144
+ suppressedSinceSummary = 0;
145
+ }
146
+ },
147
+ };
148
+ }
149
+ /**
150
+ * SIGTERM a managed sync child and wait (bounded) for it to exit, so the child's
151
+ * OFFLINE / blank farewell frame finishes painting before the daemon process
152
+ * exits.
153
+ *
154
+ * The Python sync clients trap SIGTERM, break their loop, push a final OFFLINE
155
+ * (iDotMatrix) or black (Timebox) frame over BLE, then disconnect. That push
156
+ * takes ~1s. If we only fire SIGTERM and return immediately (the old behaviour),
157
+ * the daemon exits right away; when the daemon is a launchd job, launchd then
158
+ * tears the job down and SIGKILLs the orphaned child mid-farewell — leaving the
159
+ * stateful BLE panel frozen on its last dashboard frame instead of OFFLINE.
160
+ * Awaiting the child's exit here keeps the daemon alive just long enough for the
161
+ * farewell to land. Escalates to SIGKILL if the child overruns `timeoutMs`.
162
+ */
163
+ export function terminateSyncChild(proc, timeoutMs = 3_000) {
164
+ return new Promise((resolve) => {
165
+ if (proc.exitCode !== null || proc.signalCode !== null) {
166
+ resolve();
167
+ return;
168
+ }
169
+ let settled = false;
170
+ const finish = () => {
171
+ if (settled)
172
+ return;
173
+ settled = true;
174
+ clearTimeout(timer);
175
+ resolve();
176
+ };
177
+ const timer = setTimeout(() => {
178
+ try {
179
+ proc.kill('SIGKILL');
180
+ }
181
+ catch {
182
+ /* already gone */
183
+ }
184
+ finish();
185
+ }, timeoutMs);
186
+ timer.unref?.();
187
+ proc.once('exit', finish);
188
+ try {
189
+ proc.kill('SIGTERM');
190
+ }
191
+ catch {
192
+ finish();
193
+ }
194
+ });
195
+ }
196
+ //# sourceMappingURL=ble-sync-spawn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ble-sync-spawn.js","sourceRoot":"","sources":["../src/ble-sync-spawn.ts"],"names":[],"mappings":"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"}
@@ -9,12 +9,28 @@ import { BridgeTimelineStore } from './timeline-store.js';
9
9
  import type { BridgeLogStream } from './log-stream.js';
10
10
  import { type ApiUsageData } from './usage-api.js';
11
11
  import type { ApmeModule } from './apme/index.js';
12
- import { type BridgeEvent, type StateSnapshot, type AgentType, type AgentCapabilities, type ModelCatalogEntry, type VoiceAssistantState } from './types.js';
12
+ import { type BridgeEvent, type StateSnapshot, type AgentType, type AgentCapabilities, type ModelCatalogEntry, type VoiceAssistantState, type TimelineEntry } from './types.js';
13
+ export declare const INITIAL_TIMELINE_HISTORY_MAX_BYTES: number;
14
+ /** Attach host-local "HH:MM" to a timeline entry. Devices have no timezone
15
+ * (their NTP runs UTC), so rendering `ts` directly shows a 9-hour-off clock
16
+ * in KST. Stamped at the SOURCE (broadcast + history) so both the serial and
17
+ * WS transports carry it; native apps simply ignore the extra field. */
18
+ export declare function stampLocalHm<T extends {
19
+ ts?: number;
20
+ localHm?: string;
21
+ }>(entry: T): T;
22
+ export declare function buildCappedTimelineHistory(entries: TimelineEntry[], maxBytes?: number, extraFields?: Record<string, unknown>): BridgeEvent | null;
13
23
  export interface BridgeCoreOptions {
14
24
  port: number;
15
25
  sessionId?: string;
16
26
  projectName: string;
17
27
  httpServer: Server;
28
+ /**
29
+ * True for the daemon hub. The hub aggregates many agents and has no single
30
+ * session model, so it must always expose the account-level Claude subscription
31
+ * quota in usage events rather than gating it on the (arbitrary) active model.
32
+ */
33
+ isDaemon?: boolean;
18
34
  }
19
35
  /**
20
36
  * Shared infrastructure extracted from index.ts and daemon-server.ts.
@@ -47,6 +63,7 @@ export declare class BridgeCore {
47
63
  cachedAntigravityStatus: import("./antigravity-local.js").AntigravityStatusInfo | null;
48
64
  cachedGatewayAvailable: boolean;
49
65
  cachedGatewayConnected: boolean;
66
+ cachedGatewayAuthStatus: 'gateway_not_found' | 'gateway_reachable' | 'gateway_token_missing' | 'pairing_required' | 'approval_pending' | 'connected' | 'auth_failed' | 'token_mismatch' | 'device_auth_invalid' | 'unsupported_protocol';
50
67
  cachedGatewayHasError: boolean;
51
68
  cachedModelCatalog: ModelCatalogEntry[] | null;
52
69
  cachedVoiceAssistantState: VoiceAssistantState;
@@ -55,6 +72,7 @@ export declare class BridgeCore {
55
72
  private intervals;
56
73
  private timeouts;
57
74
  private lastSessionsListBroadcast;
75
+ private lastSessionsListEvent;
58
76
  private shutdownInProgress;
59
77
  private shutdownCallbacks;
60
78
  private sseBroadcast?;
@@ -69,6 +87,8 @@ export declare class BridgeCore {
69
87
  private apmeAgentType;
70
88
  private apmeCwd;
71
89
  private static readonly USAGE_STALE_TTL;
90
+ /** True when this core backs the daemon hub (see BridgeCoreOptions.isDaemon). */
91
+ readonly isDaemon: boolean;
72
92
  constructor(opts: BridgeCoreOptions);
73
93
  /** Set optional SSE broadcast callback (for HookServer-based sessions) */
74
94
  setSseBroadcast(cb: (evt: BridgeEvent) => void): void;
@@ -132,6 +152,9 @@ export declare class BridgeCore {
132
152
  private hasClients;
133
153
  /** Broadcast enriched sessions list (debounced 2s from state_changed) */
134
154
  broadcastSessionsList(): Promise<void>;
155
+ /** The most recent sessions_list event, for the ESP32 serial heartbeat
156
+ * re-sync. Null until the first broadcast. */
157
+ getLastSessionsListEvent(): BridgeEvent | null;
135
158
  /** Debounced sessions list broadcast (for state_changed handler) */
136
159
  maybeBroadcastSessionsList(): void;
137
160
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"bridge-core.d.ts","sourceRoot":"","sources":["../src/bridge-core.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bridge-core.d.ts","sourceRoot":"","sources":["../src/bridge-core.ts"],"names":[],"mappings":"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"}
@@ -8,16 +8,65 @@ import { BridgeTimelineStore } from './timeline-store.js';
8
8
  import { readAntigravityLocalStatus } from './antigravity-local.js';
9
9
  import { buildSubscriptions, buildUsageEvent } from './usage-event.js';
10
10
  import { readCodexAuthStatus } from './codex-auth.js';
11
+ import { readCodexRateLimits } from './codex-rate-limits.js';
11
12
  import { fetchMlxModels } from './mlx-probe.js';
13
+ import { buildDisplayStateEvent } from './display-dim.js';
12
14
  import { loadMlxSettings } from '@agentdeck/shared';
13
15
  import { probeGateway, checkGatewayHealth } from './gateway-probe.js';
14
16
  import { fetchUsageFromApi, hasOAuthToken, getTokenStatus } from './usage-api.js';
15
17
  import { buildEnrichedSessionsList } from './session-aggregator.js';
18
+ import { activityFor } from './session-activity.js';
16
19
  import { register as registerSession, deregister as deregisterSession, } from './session-registry.js';
17
20
  import { getOrCreateToken, getWsUrl } from './auth.js';
18
21
  import { log, logError, debug } from './logger.js';
19
- import { invalidateMdnsInstance } from './mdns.js';
22
+ import { invalidateMdnsInstance, isNonFatalMdnsError } from './mdns.js';
20
23
  import { State, } from './types.js';
24
+ // log(), logError(), debug() imported from logger.ts
25
+ // - log(): suppressed in PTY mode (after setPtyMode(true))
26
+ // - logError(): always shown (critical errors requiring user action)
27
+ // - debug(): file-only (when --debug enabled)
28
+ // links2004/WebSockets, used by the ESP32-C3 e-ink firmware, closes inbound
29
+ // frames above 15KB with 1009 before the firmware parser can see them. Keep the
30
+ // initial replay comfortably below that library cap; Detail views can request a
31
+ // scoped session replay later via query_session_timeline.
32
+ export const INITIAL_TIMELINE_HISTORY_MAX_BYTES = 12 * 1024;
33
+ /** Attach host-local "HH:MM" to a timeline entry. Devices have no timezone
34
+ * (their NTP runs UTC), so rendering `ts` directly shows a 9-hour-off clock
35
+ * in KST. Stamped at the SOURCE (broadcast + history) so both the serial and
36
+ * WS transports carry it; native apps simply ignore the extra field. */
37
+ export function stampLocalHm(entry) {
38
+ if (!entry || !Number.isFinite(entry.ts) || entry.localHm)
39
+ return entry;
40
+ const d = new Date(entry.ts);
41
+ return {
42
+ ...entry,
43
+ localHm: `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`,
44
+ };
45
+ }
46
+ export function buildCappedTimelineHistory(entries, maxBytes = INITIAL_TIMELINE_HISTORY_MAX_BYTES, extraFields = {}) {
47
+ const stamped = entries.map((e) => stampLocalHm(e));
48
+ const kept = [];
49
+ for (let i = stamped.length - 1; i >= 0; i--) {
50
+ const candidate = [stamped[i], ...kept];
51
+ const event = { type: 'timeline_history', ...extraFields, entries: candidate };
52
+ if (Buffer.byteLength(JSON.stringify(event), 'utf8') <= maxBytes) {
53
+ kept.unshift(stamped[i]);
54
+ }
55
+ }
56
+ return kept.length > 0 ? { type: 'timeline_history', ...extraFields, entries: kept } : null;
57
+ }
58
+ function exitProcessNow(code = 0) {
59
+ if (code === 0) {
60
+ try {
61
+ process.kill(process.pid, 'SIGKILL');
62
+ return;
63
+ }
64
+ catch {
65
+ // fall through
66
+ }
67
+ }
68
+ process.exit(code);
69
+ }
21
70
  // ===== BridgeCore =====
22
71
  /**
23
72
  * Shared infrastructure extracted from index.ts and daemon-server.ts.
@@ -53,6 +102,7 @@ export class BridgeCore {
53
102
  cachedAntigravityStatus = readAntigravityLocalStatus() ?? null;
54
103
  cachedGatewayAvailable = false;
55
104
  cachedGatewayConnected = false;
105
+ cachedGatewayAuthStatus = 'gateway_not_found';
56
106
  cachedGatewayHasError = false;
57
107
  cachedModelCatalog = null;
58
108
  // Voice assistant state (for piggybacking on state_update)
@@ -63,6 +113,7 @@ export class BridgeCore {
63
113
  intervals = [];
64
114
  timeouts = [];
65
115
  lastSessionsListBroadcast = 0;
116
+ lastSessionsListEvent = null;
66
117
  shutdownInProgress = false;
67
118
  shutdownCallbacks = [];
68
119
  sseBroadcast;
@@ -77,10 +128,13 @@ export class BridgeCore {
77
128
  apmeAgentType = null;
78
129
  apmeCwd;
79
130
  static USAGE_STALE_TTL = 10 * 60 * 1000; // 10 minutes
131
+ /** True when this core backs the daemon hub (see BridgeCoreOptions.isDaemon). */
132
+ isDaemon;
80
133
  constructor(opts) {
81
134
  this.port = opts.port;
82
135
  this.sessionId = opts.sessionId ?? randomUUID();
83
136
  this.projectName = opts.projectName;
137
+ this.isDaemon = opts.isDaemon ?? false;
84
138
  // Core components
85
139
  this.usageTracker = new UsageTracker();
86
140
  this.stateMachine = new StateMachine(this.usageTracker);
@@ -105,13 +159,50 @@ export class BridgeCore {
105
159
  }
106
160
  // ===== Timeline wiring =====
107
161
  wireTimeline(logStream) {
162
+ // Attribute every entry to this session at *storage time* so history
163
+ // replay (`timeline_history`) carries the same task/run/session metadata
164
+ // as live `timeline_event` broadcasts. taskId/runId pull from live APME
165
+ // state — turn rows inherit the active task header without each emitter
166
+ // having to thread the task id through.
167
+ //
168
+ // Idempotent: caller-set fields take precedence. This means relayed
169
+ // entries (e.g. timeline_event from session bridges into the daemon)
170
+ // keep their original sessionId/taskId; only entries emitted on this
171
+ // BridgeCore's own session get filled in.
172
+ this.bridgeTimeline.setAttributor((entry) => {
173
+ const apme = this.apme;
174
+ const sessionId = entry.sessionId ?? this.sessionId;
175
+ const taskId = entry.taskId ?? (apme ? apme.collector.getActiveTaskId(this.sessionId) ?? undefined : undefined);
176
+ const runId = entry.runId ?? (apme ? apme.collector.getRunId(this.sessionId) ?? undefined : undefined);
177
+ // agentType backfill — the single place every timeline row acquires its
178
+ // brand. Priority: caller-set → per-session collector run (authoritative
179
+ // for observed hook sessions, where this BridgeCore's own agentType is
180
+ // 'daemon') → this bridge's own session agent (managed session bridges
181
+ // whose collector run may not exist yet). 'daemon' is never stamped: it
182
+ // would mislabel every observed session's rows with the hub's identity.
183
+ const ownAgent = this.apmeAgentType && this.apmeAgentType !== 'daemon'
184
+ ? this.apmeAgentType : undefined;
185
+ const runAgent = apme ? apme.collector.getRunAgentType(sessionId) : null;
186
+ const agentType = entry.agentType ?? runAgent ?? ownAgent ?? undefined;
187
+ return {
188
+ ...entry,
189
+ projectName: entry.projectName ?? this.projectName,
190
+ sessionId,
191
+ ...(agentType ? { agentType } : {}),
192
+ ...(taskId ? { taskId } : {}),
193
+ ...(runId ? { runId } : {}),
194
+ };
195
+ });
108
196
  if (logStream) {
109
197
  logStream.on('entry', (entry) => {
110
198
  this.bridgeTimeline.addEntry(entry);
111
199
  });
112
200
  }
113
201
  this.bridgeTimeline.onEntry((entry, upsert) => {
114
- const evt = { type: 'timeline_event', entry, ...(upsert ? { upsert: true } : {}) };
202
+ // Entry is already attributed by the storage-time attributor above;
203
+ // forward as-is (plus the device-local HH:MM stamp). Doing the
204
+ // attribution here too would be redundant and risks divergence.
205
+ const evt = { type: 'timeline_event', entry: stampLocalHm(entry), ...(upsert ? { upsert: true } : {}) };
115
206
  this.broadcast(evt);
116
207
  });
117
208
  }
@@ -119,16 +210,16 @@ export class BridgeCore {
119
210
  _previousDisplayOn = true;
120
211
  _wakeHandler = null;
121
212
  wireDisplayMonitor() {
122
- this.displayMonitor.start();
123
213
  this.displayMonitor.on('display_state_changed', (displayOn) => {
124
214
  // Detect wake transition (asleep → awake)
125
215
  if (displayOn && !this._previousDisplayOn) {
126
216
  this._wakeHandler?.();
127
217
  }
128
218
  this._previousDisplayOn = displayOn;
129
- const evt = { type: 'display_state', displayOn };
219
+ const evt = buildDisplayStateEvent(displayOn);
130
220
  this.broadcast(evt);
131
221
  });
222
+ this.displayMonitor.start();
132
223
  // Time-discontinuity safety net (python3 process may die during deep sleep)
133
224
  let lastTick = Date.now();
134
225
  setInterval(() => {
@@ -195,6 +286,7 @@ export class BridgeCore {
195
286
  antigravityStatus: this.cachedAntigravityStatus ?? undefined,
196
287
  gatewayAvailable: this.cachedGatewayAvailable,
197
288
  gatewayConnected: this.cachedGatewayConnected,
289
+ gatewayAuthStatus: this.cachedGatewayAuthStatus,
198
290
  gatewayHasError: this.cachedGatewayHasError,
199
291
  moduleHealth: this.moduleHealthProvider?.(),
200
292
  voiceAssistantState: this.cachedVoiceAssistantState !== 'disabled' ? this.cachedVoiceAssistantState : undefined,
@@ -213,7 +305,7 @@ export class BridgeCore {
213
305
  /** Build and return a usage event */
214
306
  buildUsage() {
215
307
  const snapshot = this.stateMachine.getSnapshot();
216
- return buildUsageEvent(snapshot, this.cachedApiUsage, this.oauthConnected, this.cachedOllamaStatus, this.cachedMlxModels, this.apiUsageStale, readCodexAuthStatus(), snapshot.billingType, this.cachedModelCatalog, this.cachedAntigravityStatus, this.apiUsagePreAdjusted);
308
+ return buildUsageEvent(snapshot, this.cachedApiUsage, this.oauthConnected, this.cachedOllamaStatus, this.cachedMlxModels, this.apiUsageStale, readCodexAuthStatus(), snapshot.billingType, this.cachedModelCatalog, this.cachedAntigravityStatus, this.apiUsagePreAdjusted, this.isDaemon, readCodexRateLimits());
217
309
  }
218
310
  /** Broadcast current usage to all clients */
219
311
  broadcastUsage() {
@@ -331,6 +423,8 @@ export class BridgeCore {
331
423
  }
332
424
  else if (!status.available && wasAvailable) {
333
425
  this.cachedGatewayConnected = false;
426
+ this.cachedGatewayAuthStatus = 'gateway_not_found';
427
+ this.cachedGatewayHasError = false;
334
428
  onDisappeared?.();
335
429
  }
336
430
  if (status.available !== wasAvailable) {
@@ -424,7 +518,25 @@ export class BridgeCore {
424
518
  let sessions = await buildEnrichedSessionsList(this.sessionId, snapshot.state, snapshot.modelName ?? undefined, snapshot.effortLevel ?? undefined);
425
519
  if (this.sessionsEnricher)
426
520
  sessions = this.sessionsEnricher(sessions);
427
- this.wsServer.broadcast({ type: 'sessions_list', sessions });
521
+ // Attach the shared per-session activity one-liner to the FINAL list (covers
522
+ // managed + observed sessions). Heuristic is immediate; a Foundation Models
523
+ // summary, when available, lands on a later periodic broadcast via the cache.
524
+ for (const s of sessions) {
525
+ const a = activityFor(s);
526
+ if (a)
527
+ s.activity = a;
528
+ }
529
+ const event = { type: 'sessions_list', sessions };
530
+ // Cache for the serial heartbeat re-sync (like display_state): a board that
531
+ // reconnects across a daemon handoff during a quiet window otherwise sits
532
+ // on an empty roster until the next unrelated session change broadcasts.
533
+ this.lastSessionsListEvent = event;
534
+ this.wsServer.broadcast(event);
535
+ }
536
+ /** The most recent sessions_list event, for the ESP32 serial heartbeat
537
+ * re-sync. Null until the first broadcast. */
538
+ getLastSessionsListEvent() {
539
+ return this.lastSessionsListEvent;
428
540
  }
429
541
  /** Debounced sessions list broadcast (for state_changed handler) */
430
542
  maybeBroadcastSessionsList() {
@@ -457,15 +569,25 @@ export class BridgeCore {
457
569
  sessionId: this.sessionId,
458
570
  });
459
571
  // Display state
460
- this.wsServer.sendTo(ws, {
461
- type: 'display_state',
462
- displayOn: this.displayMonitor.isDisplayOn(),
463
- });
464
- // Timeline history
465
- const history = this.bridgeTimeline.getHistory();
466
- if (history.length > 0) {
467
- this.wsServer.sendTo(ws, { type: 'timeline_history', entries: history });
468
- }
572
+ this.wsServer.sendTo(ws, buildDisplayStateEvent(this.displayMonitor.isDisplayOn()));
573
+ // Timeline history — entries were already attributed at storage time by
574
+ // the attributor installed in `wireTimeline`, so they ship with taskId /
575
+ // runId / sessionId / projectName intact. The `??` fallbacks below
576
+ // protect entries that landed before `wireTimeline` ran (e.g. very early
577
+ // boot logStream events) so we never broadcast bare entries.
578
+ const history = this.bridgeTimeline.getHistory().map((entry) => ({
579
+ ...entry,
580
+ projectName: entry.projectName ?? this.projectName,
581
+ sessionId: entry.sessionId ?? this.sessionId,
582
+ }));
583
+ // Always send a timeline_history on connect — an EMPTY one when the store
584
+ // is empty. Clients replace (not merge) their timeline on this event, so a
585
+ // freshly-restarted daemon must send `entries: []` to wipe the client's
586
+ // stale rows; suppressing it (the old `if (historyEvent)`) left old logs
587
+ // frozen on Android/ESP32 across a daemon restart.
588
+ const historyEvent = buildCappedTimelineHistory(history)
589
+ ?? { type: 'timeline_history', entries: [] };
590
+ this.wsServer.sendTo(ws, historyEvent);
469
591
  // Sessions list
470
592
  buildEnrichedSessionsList(this.sessionId, snapshot.state, snapshot.modelName ?? undefined, snapshot.effortLevel ?? undefined).then((sessions) => {
471
593
  const enriched = this.sessionsEnricher ? this.sessionsEnricher(sessions) : sessions;
@@ -551,11 +673,12 @@ export class BridgeCore {
551
673
  const msg = err?.message ?? '';
552
674
  const code = err?.code ?? '';
553
675
  // mDNS errors are non-critical — network interface changes (sleep/wake,
554
- // WiFi reconnect, VPN toggle) cause transient multicast failures.
555
- // Null out the mDNS instance so the recovery timer can re-publish.
556
- if (msg.includes('already in use on the network') ||
557
- (msg.includes('EADDRNOTAVAIL') && msg.includes('5353'))) {
558
- debug('mDNS', `error (ignored): ${msg}`);
676
+ // WiFi reconnect, VPN toggle) and unroutable virtual interfaces (Windows
677
+ // WSL/Hyper-V EHOSTUNREACH to 224.0.0.251:5353) cause transient
678
+ // multicast failures. Null out the mDNS instance so the recovery timer
679
+ // can re-publish.
680
+ if (isNonFatalMdnsError(msg, code)) {
681
+ debug('mDNS', `error (ignored): ${code || msg}`);
559
682
  invalidateMdnsInstance();
560
683
  return;
561
684
  }
@@ -602,10 +725,16 @@ export class BridgeCore {
602
725
  }
603
726
  /** Graceful shutdown */
604
727
  async shutdown() {
605
- if (this.shutdownInProgress)
728
+ if (this.shutdownInProgress) {
729
+ exitProcessNow(0);
606
730
  return;
731
+ }
607
732
  this.shutdownInProgress = true;
608
733
  log('Shutting down...');
734
+ const hardExitTimer = setTimeout(() => {
735
+ logError('Shutdown timeout — forcing exit.');
736
+ exitProcessNow(0);
737
+ }, 7000);
609
738
  // Clear all timers
610
739
  for (const iv of this.intervals)
611
740
  clearInterval(iv);
@@ -615,13 +744,17 @@ export class BridgeCore {
615
744
  this.deregisterSession();
616
745
  // Stop display monitor
617
746
  this.displayMonitor.stop();
618
- // Run shutdown callbacks (best-effort, 2s total budget)
747
+ // Run shutdown callbacks (best-effort, 5s total budget). Budget covers the
748
+ // BLE stateful-panel farewell: device modules (iDotMatrix/Timebox) await
749
+ // their Python sync child painting a final OFFLINE/blank frame over BLE
750
+ // (~1-3s) so the panel doesn't freeze on its last dashboard frame.
619
751
  const callbacksDone = Promise.all(this.shutdownCallbacks.map(cb => Promise.resolve().then(cb).catch(() => { })));
620
- await Promise.race([callbacksDone, new Promise(r => { const t = setTimeout(r, 2000); t.unref(); })]);
752
+ await Promise.race([callbacksDone, new Promise(r => { const t = setTimeout(r, 5000); t.unref(); })]);
621
753
  // Close WS
622
754
  this.wsServer.close();
623
755
  // Exit immediately — all cleanup is done or timed out
624
- process.exit(0);
756
+ clearTimeout(hardExitTimer);
757
+ exitProcessNow(0);
625
758
  }
626
759
  }
627
760
  //# sourceMappingURL=bridge-core.js.map