@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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-activity.js","sourceRoot":"","sources":["../src/session-activity.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { type SessionEntry } from './session-registry.js';
2
2
  import type { AgentType } from './types.js';
3
+ import { type PromptOption } from '@agentdeck/shared';
3
4
  export interface EnrichedSession {
4
5
  id: string;
5
6
  port: number;
@@ -14,8 +15,28 @@ export interface EnrichedSession {
14
15
  controlMode?: 'managed' | 'observed';
15
16
  cwd?: string;
16
17
  currentTask?: string;
18
+ /** One-line gist of the session's purpose (first user prompt). */
19
+ goal?: string;
20
+ currentTool?: string;
17
21
  contextPercent?: number;
18
22
  totalTokens?: number;
23
+ question?: string;
24
+ requestId?: string;
25
+ promptType?: 'yes_no' | 'yes_no_always' | 'multi_select' | 'diff_review';
26
+ options?: PromptOption[];
27
+ /** Seconds since startedAt — derived at broadcast time so NTP-less devices (ESP32) render elapsed per session. */
28
+ elapsedSec?: number;
29
+ /** Daemon-synthesized "what is this agent doing right now" one-liner (heuristic,
30
+ * upgraded to a Foundation Models summary when available). Shared by X3 + TRMNL. */
31
+ activity?: string;
32
+ /** Daemon-computed latest MILESTONE timeline row for this session (TIMELINE
33
+ * parity for glance devices — IPS10 cards render "HH:MM task • text" from
34
+ * these instead of their tiny reboot-empty on-device timeline ring). */
35
+ lastEventText?: string;
36
+ /** Resolved enclosing-task label for that row ("" / absent when none). */
37
+ lastEventTask?: string;
38
+ /** Host-local "HH:MM" of that row (boards are NTP-UTC or clockless). */
39
+ lastEventHm?: string;
19
40
  }
20
41
  /** Update push-channel cache (called from daemon-server when session_push_state arrives) */
21
42
  export declare function updatePushState(sessionId: string, state: string, modelName?: string, effortLevel?: string): void;
@@ -36,6 +57,10 @@ export declare function clearSiblingStateCache(sessionId: string): void;
36
57
  export declare function enrichSessionsWithState(sessions: SessionEntry[], ownSessionId: string, ownState: string, ownModelName?: string, ownEffortLevel?: string): Promise<EnrichedSession[]>;
37
58
  /**
38
59
  * Build an enriched sessions list for multi-session display.
60
+ *
61
+ * Includes the own session so single-session mode (`agentdeck claude` without a daemon)
62
+ * still surfaces the active session. The daemon-server enricher overrides this list in
63
+ * multi-session setups, so per-session bridges keeping their own entry is safe.
39
64
  */
40
65
  export declare function buildEnrichedSessionsList(ownSessionId: string, ownState: string, ownModelName?: string, ownEffortLevel?: string): Promise<EnrichedSession[]>;
41
66
  //# sourceMappingURL=session-aggregator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"session-aggregator.d.ts","sourceRoot":"","sources":["../src/session-aggregator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC5F,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG5C,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;IACrC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAQD,4FAA4F;AAC5F,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAIhH;AAED,wDAAwD;AACxD,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAKvH;AAED,uFAAuF;AACvF,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAG9D;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,YAAY,EAAE,EACxB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,YAAY,CAAC,EAAE,MAAM,EACrB,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,eAAe,EAAE,CAAC,CA8B5B;AAED;;GAEG;AACH,wBAAsB,yBAAyB,CAC7C,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,YAAY,CAAC,EAAE,MAAM,EACrB,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,eAAe,EAAE,CAAC,CAI5B"}
1
+ {"version":3,"file":"session-aggregator.d.ts","sourceRoot":"","sources":["../src/session-aggregator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC5F,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEpE,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;IACrC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,QAAQ,GAAG,eAAe,GAAG,cAAc,GAAG,aAAa,CAAC;IACzE,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;IACzB,kHAAkH;IAClH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;yFACqF;IACrF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;6EAEyE;IACzE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0EAA0E;IAC1E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,wEAAwE;IACxE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAaD,4FAA4F;AAC5F,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAIhH;AAED,wDAAwD;AACxD,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAUvH;AAED,uFAAuF;AACvF,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAG9D;AAoBD;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,YAAY,EAAE,EACxB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,YAAY,CAAC,EAAE,MAAM,EACrB,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,eAAe,EAAE,CAAC,CAsC5B;AAED;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAC7C,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,YAAY,CAAC,EAAE,MAAM,EACrB,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,eAAe,EAAE,CAAC,CAI5B"}
@@ -1,22 +1,31 @@
1
1
  import { listActive as listActiveSessions } from './session-registry.js';
2
2
  import { sortSessions } from '@agentdeck/shared';
3
- /** Cache last-known sibling state to avoid propagating undefined on transient fetch failures */
3
+ /** Cache last-known sibling state to avoid propagating undefined on transient fetch failures.
4
+ * `updatedAt` bounds how long a vanished session may ride its last-known state: once the
5
+ * cache ages past LIVENESS_GRACE_MS without a successful probe/push, we stop treating it as
6
+ * alive so devices (TRMNL e-ink, ESP32, Pixoo) prune ended sessions instead of showing them
7
+ * forever (the registry only prunes on PID death, which lingers when the parent shell lives). */
4
8
  const siblingStateCache = new Map();
9
+ const LIVENESS_GRACE_MS = 20_000;
5
10
  /** Push-channel state cache — populated by DaemonWsClient session_push_state messages */
6
11
  const pushStateCache = new Map();
7
12
  /** Update push-channel cache (called from daemon-server when session_push_state arrives) */
8
13
  export function updatePushState(sessionId, state, modelName, effortLevel) {
9
14
  pushStateCache.set(sessionId, { state, modelName, effortLevel, updatedAt: Date.now() });
10
15
  // Also update sibling cache so it stays consistent
11
- siblingStateCache.set(sessionId, { state, modelName, effortLevel });
16
+ siblingStateCache.set(sessionId, { state, modelName, effortLevel, updatedAt: Date.now() });
12
17
  }
13
18
  /** Check if push-channel has fresh state (< 30s old) */
14
19
  export function getPushState(sessionId) {
15
20
  const entry = pushStateCache.get(sessionId);
16
21
  if (!entry)
17
22
  return undefined;
18
- if (Date.now() - entry.updatedAt > 30_000)
19
- return undefined; // stale
23
+ if (Date.now() - entry.updatedAt > 30_000) {
24
+ // Drop the stale entry instead of merely skipping it, so the map doesn't
25
+ // accumulate dead sessions over a long-running daemon's lifetime.
26
+ pushStateCache.delete(sessionId);
27
+ return undefined;
28
+ }
20
29
  return { state: entry.state, modelName: entry.modelName, effortLevel: entry.effortLevel };
21
30
  }
22
31
  /** Clear cache entry when a session is removed (call from session-registry cleanup) */
@@ -24,6 +33,25 @@ export function clearSiblingStateCache(sessionId) {
24
33
  siblingStateCache.delete(sessionId);
25
34
  pushStateCache.delete(sessionId);
26
35
  }
36
+ /**
37
+ * Drop cache entries for sessions that are no longer active. `siblingStateCache`
38
+ * has no TTL (it's the last-known fallback for a still-live session whose
39
+ * /health probe transiently failed), so without this sweep a session that dies
40
+ * without a clean `deregister()` (SIGKILL, daemon crash) would leave its state
41
+ * cached forever. Called from the enricher with the current active id set.
42
+ * Observed sessions never populate these caches, so pruning to the managed set
43
+ * is safe.
44
+ */
45
+ function sweepStaleCacheEntries(activeIds) {
46
+ for (const id of siblingStateCache.keys()) {
47
+ if (!activeIds.has(id))
48
+ siblingStateCache.delete(id);
49
+ }
50
+ for (const id of pushStateCache.keys()) {
51
+ if (!activeIds.has(id))
52
+ pushStateCache.delete(id);
53
+ }
54
+ }
27
55
  /**
28
56
  * Enrich sibling sessions with state from their /health endpoint.
29
57
  * For the own session (matched by ownSessionId), uses ownState directly.
@@ -31,6 +59,9 @@ export function clearSiblingStateCache(sessionId) {
31
59
  * transient undefined propagation to all clients.
32
60
  */
33
61
  export async function enrichSessionsWithState(sessions, ownSessionId, ownState, ownModelName, ownEffortLevel) {
62
+ // Prune cache entries for sessions that have dropped out of the active set
63
+ // (the registry already pruned dead PIDs before handing us this list).
64
+ sweepStaleCacheEntries(new Set(sessions.map((s) => s.id)));
34
65
  return Promise.all(sessions.map(async (s) => {
35
66
  const base = {
36
67
  id: s.id,
@@ -53,24 +84,32 @@ export async function enrichSessionsWithState(sessions, ownSessionId, ownState,
53
84
  const res = await fetch(`http://127.0.0.1:${s.port}/health`, { signal: AbortSignal.timeout(2000) });
54
85
  const data = await res.json();
55
86
  if (data.state) {
56
- siblingStateCache.set(s.id, { state: data.state, modelName: data.modelName, effortLevel: data.effortLevel });
87
+ siblingStateCache.set(s.id, { state: data.state, modelName: data.modelName, effortLevel: data.effortLevel, updatedAt: Date.now() });
57
88
  }
58
89
  return { ...base, state: data.state, modelName: data.modelName, effortLevel: data.effortLevel };
59
90
  }
60
91
  catch {
92
+ // Probe failed. Within the grace window keep the last-known state alive so a
93
+ // transient blip doesn't flicker a healthy session off the deck; past it,
94
+ // mark the session dead so devices prune the ended session.
61
95
  const cached = siblingStateCache.get(s.id);
62
- if (cached)
96
+ if (cached && Date.now() - cached.updatedAt < LIVENESS_GRACE_MS) {
63
97
  return { ...base, state: cached.state, modelName: cached.modelName, effortLevel: cached.effortLevel };
64
- return base;
98
+ }
99
+ return { ...base, alive: false, state: cached?.state ?? 'disconnected' };
65
100
  }
66
101
  }));
67
102
  }
68
103
  /**
69
104
  * Build an enriched sessions list for multi-session display.
105
+ *
106
+ * Includes the own session so single-session mode (`agentdeck claude` without a daemon)
107
+ * still surfaces the active session. The daemon-server enricher overrides this list in
108
+ * multi-session setups, so per-session bridges keeping their own entry is safe.
70
109
  */
71
110
  export async function buildEnrichedSessionsList(ownSessionId, ownState, ownModelName, ownEffortLevel) {
72
- const siblings = listActiveSessions().filter(s => s.agentType !== 'daemon' && s.id !== ownSessionId);
73
- const enriched = await enrichSessionsWithState(siblings, ownSessionId, ownState, ownModelName, ownEffortLevel);
111
+ const all = listActiveSessions().filter(s => s.agentType !== 'daemon');
112
+ const enriched = await enrichSessionsWithState(all, ownSessionId, ownState, ownModelName, ownEffortLevel);
74
113
  return sortSessions(enriched);
75
114
  }
76
115
  //# sourceMappingURL=session-aggregator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"session-aggregator.js","sourceRoot":"","sources":["../src/session-aggregator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session-aggregator.js","sourceRoot":"","sources":["../src/session-aggregator.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"session-focus-relay.d.ts","sourceRoot":"","sources":["../src/session-focus-relay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAuB7D,MAAM,MAAM,iBAAiB,GAAG,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;AAE7D,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,OAAO,CAAkC;IACjD,OAAO,CAAC,MAAM,CAAS;IAEvB,yEAAyE;IACzE,eAAe,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI;IAIjD,uCAAuC;IACvC,mBAAmB,IAAI,MAAM,GAAG,IAAI;IAIpC,gEAAgE;IAChE,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAqB9B,+BAA+B;IAC/B,OAAO,IAAI,IAAI;IAaf,uEAAuE;IACvE,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO;IAYzC,2BAA2B;IAC3B,IAAI,IAAI,IAAI;IAKZ,OAAO,CAAC,OAAO;CAkChB"}
1
+ {"version":3,"file":"session-focus-relay.d.ts","sourceRoot":"","sources":["../src/session-focus-relay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAuB7D,MAAM,MAAM,iBAAiB,GAAG,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;AAE7D,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,OAAO,CAAkC;IACjD,OAAO,CAAC,MAAM,CAAS;IAEvB,yEAAyE;IACzE,eAAe,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI;IAIjD,uCAAuC;IACvC,mBAAmB,IAAI,MAAM,GAAG,IAAI;IAIpC,gEAAgE;IAChE,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAqB9B,+BAA+B;IAC/B,OAAO,IAAI,IAAI;IAaf,uEAAuE;IACvE,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO;IAYzC,2BAA2B;IAC3B,IAAI,IAAI,IAAI;IAKZ,OAAO,CAAC,OAAO;CAwChB"}
@@ -108,7 +108,13 @@ export class SessionFocusRelay {
108
108
  const evt = JSON.parse(raw.toString());
109
109
  if (RELAYED_EVENTS.has(evt.type)) {
110
110
  debug(TAG, `Relay ${evt.type} from session ${sessionId}`);
111
- this.onEvent?.(evt);
111
+ // prompt_options used to be source-less, allowing a late event from
112
+ // the previous focus to become buttons for the newly selected session.
113
+ // Stamp the captured relay identity before it leaves this boundary.
114
+ const tagged = evt.type === 'prompt_options' && sessionId
115
+ ? { ...evt, sessionId, focusedSessionId: sessionId }
116
+ : evt;
117
+ this.onEvent?.(tagged);
112
118
  }
113
119
  }
114
120
  catch {
@@ -1 +1 @@
1
- {"version":3,"file":"session-focus-relay.js","sourceRoot":"","sources":["../src/session-focus-relay.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session-focus-relay.js","sourceRoot":"","sources":["../src/session-focus-relay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,SAAS,MAAM,IAAI,CAAC;AAC3B,OAAO,EAAE,UAAU,IAAI,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEzE,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEpC,MAAM,GAAG,GAAG,aAAa,CAAC;AAE1B,4DAA4D;AAC5D,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC;IAC7B,cAAc;IACd,gBAAgB;IAChB,cAAc;CACf,CAAC,CAAC;AAEH,6DAA6D;AAC7D,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IAC9B,SAAS;IACT,WAAW;IACX,QAAQ;IACR,eAAe;IACf,aAAa;IACb,iBAAiB;IACjB,aAAa;CACd,CAAC,CAAC;AAIH,MAAM,OAAO,iBAAiB;IACpB,EAAE,GAAqB,IAAI,CAAC;IAC5B,gBAAgB,GAAkB,IAAI,CAAC;IACvC,WAAW,GAAkB,IAAI,CAAC;IAClC,OAAO,GAA6B,IAAI,CAAC;IACzC,MAAM,GAAG,KAAK,CAAC;IAEvB,yEAAyE;IACzE,eAAe,CAAC,OAA0B;QACxC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,uCAAuC;IACvC,mBAAmB;QACjB,OAAO,IAAI,CAAC,gBAAgB,CAAC;IAC/B,CAAC;IAED,gEAAgE;IAChE,KAAK,CAAC,SAAiB;QACrB,IAAI,IAAI,CAAC,gBAAgB,KAAK,SAAS,IAAI,IAAI,CAAC,EAAE,EAAE,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;YAClF,KAAK,CAAC,GAAG,EAAE,sBAAsB,SAAS,EAAE,CAAC,CAAC;YAC9C,OAAO;QACT,CAAC;QAED,IAAI,CAAC,OAAO,EAAE,CAAC;QAEf,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAC;QACtC,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,IAAI,CAAC,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC;QACnF,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,KAAK,CAAC,GAAG,EAAE,WAAW,SAAS,yBAAyB,CAAC,CAAC;YAC1D,OAAO;QACT,CAAC;QAED,IAAI,CAAC,gBAAgB,GAAG,SAAS,CAAC;QAClC,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;QAChC,KAAK,CAAC,GAAG,EAAE,oBAAoB,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;QACtE,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,+BAA+B;IAC/B,OAAO;QACL,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;YACZ,IAAI,CAAC,EAAE,CAAC,kBAAkB,EAAE,CAAC;YAC7B,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;YAChB,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC;QACjB,CAAC;QACD,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC1B,KAAK,CAAC,GAAG,EAAE,qBAAqB,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;QAC3D,CAAC;QACD,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC7B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;IAC1B,CAAC;IAED,uEAAuE;IACvE,YAAY,CAAC,GAAkB;QAC7B,IAAI,CAAC,IAAI,CAAC,gBAAgB,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;YAChF,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACnC,OAAO,KAAK,CAAC;QACf,CAAC;QACD,KAAK,CAAC,GAAG,EAAE,WAAW,GAAG,CAAC,IAAI,cAAc,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;QACrE,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,2BAA2B;IAC3B,IAAI;QACF,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAEO,OAAO;QACb,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW;YAAE,OAAO;QAE7C,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,kBAAkB,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QAC/D,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,MAAM,SAAS,GAAG,IAAI,CAAC,gBAAgB,CAAC;QAExC,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;YACjB,KAAK,CAAC,GAAG,EAAE,wBAAwB,SAAS,YAAY,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QAC9E,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,GAAoB,EAAE,EAAE;YACxC,IAAI,IAAI,CAAC,gBAAgB,KAAK,SAAS;gBAAE,OAAO;YAEhD,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAgB,CAAC;gBACtD,IAAI,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;oBACjC,KAAK,CAAC,GAAG,EAAE,SAAS,GAAG,CAAC,IAAI,iBAAiB,SAAS,EAAE,CAAC,CAAC;oBAC1D,oEAAoE;oBACpE,uEAAuE;oBACvE,oEAAoE;oBACpE,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,KAAK,gBAAgB,IAAI,SAAS;wBACvD,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,SAAS,EAAE,gBAAgB,EAAE,SAAS,EAAE;wBACpD,CAAC,CAAC,GAAG,CAAC;oBACR,IAAI,CAAC,OAAO,EAAE,CAAC,MAAqB,CAAC,CAAC;gBACxC,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,2BAA2B;YAC7B,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YAClB,IAAI,IAAI,CAAC,gBAAgB,KAAK,SAAS,EAAE,CAAC;gBACxC,KAAK,CAAC,GAAG,EAAE,WAAW,SAAS,YAAY,CAAC,CAAC;gBAC7C,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC;YACjB,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAC3B,CAAC;CACF"}
@@ -2,8 +2,9 @@
2
2
  * Ordered list of data directories this process should READ from.
3
3
  *
4
4
  * The App Store macOS build writes its `daemon.json` / `sessions.json`
5
- * into `~/Library/Group Containers/group.bound.serendipity.agentdeck.dashboard`
6
- * (sandbox forces it), whereas the Node CLI writes to `~/.agentdeck`.
5
+ * inside its sandbox container, whereas the Node CLI writes to
6
+ * `~/.agentdeck`. Older App Store candidates used an App Group container,
7
+ * so reads keep that path as a legacy fallback.
7
8
  * Without cross-reads, `agentdeck claude` launched from Terminal can't
8
9
  * see the Swift daemon that's already listening on 9120, and session
9
10
  * bridges end up orphaned.
@@ -11,7 +12,8 @@
11
12
  * Order:
12
13
  * 1. `AGENTDECK_DATA_DIR` env override (tests, explicit pinning)
13
14
  * 2. `~/.agentdeck` (CLI / Homebrew / Node default)
14
- * 3. App Store group container (macOS App Store build)
15
+ * 3. App Store sandbox container (macOS App Store build)
16
+ * 4. Legacy App Store group container (pre-1.0 App Store candidates)
15
17
  *
16
18
  * Writes stay in the process's own dir via `getDataDir()`. Only reads
17
19
  * iterate this list.
@@ -23,7 +25,12 @@ export declare function getCandidateDataDirs(): string[];
23
25
  * generate a shell snippet with the same discovery order.
24
26
  */
25
27
  export declare function getCandidateDaemonJsonPaths(): string[];
28
+ /** Where THIS process persists the device timeline. Reads may come from any
29
+ * candidate dir (see `latestTimelinePath`), but the daemon writes only here. */
30
+ export declare function getOwnTimelineFile(): string;
26
31
  export declare const DAEMON_DEFAULT_PORT = 9120;
32
+ /** Documented daemon port window (docs/daemon.md) — scanned for cross-implementation discovery. */
33
+ export declare const DAEMON_PORT_WINDOW: readonly [number, number];
27
34
  export interface DaemonInfo {
28
35
  port: number;
29
36
  pid: number;
@@ -41,8 +48,31 @@ export interface SessionEntry {
41
48
  parentTty?: string;
42
49
  startedAt: string;
43
50
  }
51
+ /** Check if a PID is alive */
52
+ export declare function isProcessAlive(pid: number): boolean;
53
+ /**
54
+ * Decide whether a daemon that just lost the bind race for its requested port
55
+ * should concede (exit) to the process currently answering `/health` there.
56
+ *
57
+ * Concede ONLY when the occupant is a verified, distinct, live daemon:
58
+ * - `mode !== 'daemon'` → a non-daemon (e.g. a session bridge) holds it; do
59
+ * not concede (caller falls back to a fresh port, preserving prior behavior).
60
+ * - `mode === 'daemon'` with a numeric `pid` → concede only if that PID is a
61
+ * live process other than ourselves. A forged or stale `mode:'daemon'`
62
+ * response with a dead/own/missing-but-claimed PID must NOT evict us.
63
+ * - `mode === 'daemon'` with no `pid` → trust the mode (e.g. the Swift App
64
+ * Store daemon omits `pid`), so cross-implementation coexistence still
65
+ * hands the port over.
66
+ *
67
+ * `aliveCheck` is injectable for tests; defaults to the real PID liveness probe.
68
+ */
69
+ export declare function shouldConcedePortToOccupant(occupant: {
70
+ mode?: string;
71
+ pid?: number;
72
+ } | null, selfPid: number, aliveCheck?: (pid: number) => boolean): boolean;
44
73
  export declare function register(entry: SessionEntry): void;
45
74
  export declare function deregister(id: string): void;
75
+ export declare function removeDaemonSession(entry: Pick<SessionEntry, 'pid' | 'port'>): void;
46
76
  export declare function listActive(): SessionEntry[];
47
77
  /** Find an existing live daemon session, if any */
48
78
  export declare function findExistingDaemon(): SessionEntry | null;
@@ -77,7 +107,48 @@ export declare function readDaemonInfo(): DaemonInfo | null;
77
107
  export declare function probeDaemonHealth(port: number): Promise<{
78
108
  mode?: string;
79
109
  pid?: number;
110
+ isSwift?: boolean;
80
111
  } | null>;
112
+ /**
113
+ * Sweep the daemon port window for live daemons that file-based discovery
114
+ * cannot see. Two blind spots make this necessary:
115
+ * - The App Store Swift daemon writes `daemon.json` into its private sandbox
116
+ * container, which `getCandidateDataDirs()` cannot read.
117
+ * - Transient 9120 contention can bump a daemon to a fallback port (9121+),
118
+ * where the default-port probe never looks.
119
+ * Probes all window ports concurrently (localhost refusals resolve instantly)
120
+ * and returns every occupant whose `/health` reports `mode: 'daemon'`.
121
+ */
122
+ export declare function scanDaemonPortWindow(skip?: ReadonlySet<number>, window?: readonly [number, number]): Promise<Array<{
123
+ port: number;
124
+ health: {
125
+ mode?: string;
126
+ pid?: number;
127
+ isSwift?: boolean;
128
+ };
129
+ }>>;
130
+ /**
131
+ * Poll a port's `/health` until the daemon there stops answering, or the
132
+ * timeout expires. Used after `requestDaemonShutdown()` instead of a fixed
133
+ * sleep: the Swift daemon tears down device modules (serial, ADB reverse,
134
+ * BLE) during shutdown, and taking over before it finishes leaves two owners
135
+ * briefly contending for the same tty / adb reverse mapping.
136
+ * Returns true once the daemon is gone.
137
+ */
138
+ export declare function waitForDaemonExit(port: number, timeoutMs?: number): Promise<boolean>;
139
+ /**
140
+ * Request another daemon to shutdown (used to clear Swift daemon when CLI starts)
141
+ */
142
+ export declare function requestDaemonShutdown(port: number): Promise<void>;
143
+ /**
144
+ * Ask an app-owned Swift in-process daemon to YIELD the canonical port (POST
145
+ * /stand-down) so this CLI daemon can take over with the full feature set.
146
+ * Unlike `/shutdown`, this keeps the macOS app running — it just demotes its
147
+ * daemon to a client of the incoming CLI daemon. Returns true if the daemon
148
+ * acknowledged (HTTP 2xx). The caller should then `waitForDaemonExit()` for the
149
+ * port to clear before binding.
150
+ */
151
+ export declare function requestDaemonStandDown(port: number): Promise<boolean>;
81
152
  /**
82
153
  * Find the daemon port for client connections.
83
154
  * Priority: daemon.json (fast) → sessions.json fallback.
@@ -1 +1 @@
1
- {"version":3,"file":"session-registry.d.ts","sourceRoot":"","sources":["../src/session-registry.ts"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,EAAE,CAW/C;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,IAAI,MAAM,EAAE,CAEtD;AAID,eAAO,MAAM,mBAAmB,OAAO,CAAC;AAIxC,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAwDD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAOlD;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAO3C;AAED,wBAAgB,UAAU,IAAI,YAAY,EAAE,CAQ3C;AAED,mDAAmD;AACnD,wBAAgB,kBAAkB,IAAI,YAAY,GAAG,IAAI,CAGxD;AAcD,wBAAsB,iBAAiB,CAAC,IAAI,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAY3F;AAED,sDAAsD;AACtD,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,SAAS,CAWtD;AAID,gEAAgE;AAChE,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAOtD;AAED;wEACwE;AACxE,wBAAgB,gBAAgB,IAAI,IAAI,CAWvC;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,IAAI,UAAU,GAAG,IAAI,CAmBlD;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAiB/F;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,MAAM,GAAG,IAAI,CAU9C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAwB/F"}
1
+ {"version":3,"file":"session-registry.d.ts","sourceRoot":"","sources":["../src/session-registry.ts"],"names":[],"mappings":"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"}
@@ -14,8 +14,9 @@ function getDataDir() {
14
14
  * Ordered list of data directories this process should READ from.
15
15
  *
16
16
  * The App Store macOS build writes its `daemon.json` / `sessions.json`
17
- * into `~/Library/Group Containers/group.bound.serendipity.agentdeck.dashboard`
18
- * (sandbox forces it), whereas the Node CLI writes to `~/.agentdeck`.
17
+ * inside its sandbox container, whereas the Node CLI writes to
18
+ * `~/.agentdeck`. Older App Store candidates used an App Group container,
19
+ * so reads keep that path as a legacy fallback.
19
20
  * Without cross-reads, `agentdeck claude` launched from Terminal can't
20
21
  * see the Swift daemon that's already listening on 9120, and session
21
22
  * bridges end up orphaned.
@@ -23,7 +24,8 @@ function getDataDir() {
23
24
  * Order:
24
25
  * 1. `AGENTDECK_DATA_DIR` env override (tests, explicit pinning)
25
26
  * 2. `~/.agentdeck` (CLI / Homebrew / Node default)
26
- * 3. App Store group container (macOS App Store build)
27
+ * 3. App Store sandbox container (macOS App Store build)
28
+ * 4. Legacy App Store group container (pre-1.0 App Store candidates)
27
29
  *
28
30
  * Writes stay in the process's own dir via `getDataDir()`. Only reads
29
31
  * iterate this list.
@@ -33,7 +35,11 @@ export function getCandidateDataDirs() {
33
35
  return [process.env.AGENTDECK_DATA_DIR];
34
36
  const dirs = [join(homedir(), '.agentdeck')];
35
37
  if (process.platform === 'darwin') {
36
- const groupContainer = join(homedir(), 'Library/Group Containers/group.bound.serendipity.agentdeck.dashboard');
38
+ // Avoid reading the App Store sandbox container directly from non-sandboxed
39
+ // Node CLI/daemon, as macOS TCC will block the process and cause it to hang
40
+ // waiting for a permissions dialog that never shows.
41
+ // Instead, rely on port scan/health checks for cross-talk.
42
+ const groupContainer = join(homedir(), 'Library/Group Containers/group.bound.serendipity.agent.deck');
37
43
  if (!dirs.includes(groupContainer))
38
44
  dirs.push(groupContainer);
39
45
  }
@@ -48,10 +54,15 @@ export function getCandidateDaemonJsonPaths() {
48
54
  return getCandidateDataDirs().map((d) => join(d, 'daemon.json'));
49
55
  }
50
56
  function getSessionsFile() { return join(getDataDir(), 'sessions.json'); }
57
+ /** Where THIS process persists the device timeline. Reads may come from any
58
+ * candidate dir (see `latestTimelinePath`), but the daemon writes only here. */
59
+ export function getOwnTimelineFile() { return join(getDataDir(), 'timeline.json'); }
51
60
  function getDaemonFile() { return join(getDataDir(), 'daemon.json'); }
52
61
  export const DAEMON_DEFAULT_PORT = 9120;
53
62
  const BASE_PORT = 9120;
54
63
  const MAX_PORT = 9139;
64
+ /** Documented daemon port window (docs/daemon.md) — scanned for cross-implementation discovery. */
65
+ export const DAEMON_PORT_WINDOW = [BASE_PORT, MAX_PORT];
55
66
  function ensureDir() {
56
67
  const dir = getDataDir();
57
68
  if (!existsSync(dir)) {
@@ -91,7 +102,7 @@ function writeSessions(sessions) {
91
102
  renameSync(tmpFile, getSessionsFile());
92
103
  }
93
104
  /** Check if a PID is alive */
94
- function isProcessAlive(pid) {
105
+ export function isProcessAlive(pid) {
95
106
  try {
96
107
  process.kill(pid, 0);
97
108
  return true;
@@ -100,6 +111,30 @@ function isProcessAlive(pid) {
100
111
  return false;
101
112
  }
102
113
  }
114
+ /**
115
+ * Decide whether a daemon that just lost the bind race for its requested port
116
+ * should concede (exit) to the process currently answering `/health` there.
117
+ *
118
+ * Concede ONLY when the occupant is a verified, distinct, live daemon:
119
+ * - `mode !== 'daemon'` → a non-daemon (e.g. a session bridge) holds it; do
120
+ * not concede (caller falls back to a fresh port, preserving prior behavior).
121
+ * - `mode === 'daemon'` with a numeric `pid` → concede only if that PID is a
122
+ * live process other than ourselves. A forged or stale `mode:'daemon'`
123
+ * response with a dead/own/missing-but-claimed PID must NOT evict us.
124
+ * - `mode === 'daemon'` with no `pid` → trust the mode (e.g. the Swift App
125
+ * Store daemon omits `pid`), so cross-implementation coexistence still
126
+ * hands the port over.
127
+ *
128
+ * `aliveCheck` is injectable for tests; defaults to the real PID liveness probe.
129
+ */
130
+ export function shouldConcedePortToOccupant(occupant, selfPid, aliveCheck = isProcessAlive) {
131
+ if (occupant?.mode !== 'daemon')
132
+ return false;
133
+ const pid = typeof occupant.pid === 'number' ? occupant.pid : null;
134
+ if (pid === null)
135
+ return true;
136
+ return pid !== selfPid && aliveCheck(pid);
137
+ }
103
138
  /** Remove dead sessions (PID no longer alive) */
104
139
  function pruneDeadSessions(sessions) {
105
140
  return sessions.filter((s) => isProcessAlive(s.pid));
@@ -120,6 +155,14 @@ export function deregister(id) {
120
155
  import('./session-aggregator.js').then(m => m.clearSiblingStateCache(id)).catch(() => { });
121
156
  debug('SessionRegistry', `Deregistered session ${id}`);
122
157
  }
158
+ export function removeDaemonSession(entry) {
159
+ const sessions = readSessions();
160
+ const filtered = sessions.filter((s) => !(s.agentType === 'daemon' && s.pid === entry.pid && s.port === entry.port));
161
+ if (filtered.length !== sessions.length) {
162
+ writeSessions(filtered);
163
+ debug('SessionRegistry', `Removed stale daemon session on port ${entry.port} pid=${entry.pid}`);
164
+ }
165
+ }
123
166
  export function listActive() {
124
167
  const sessions = readSessions();
125
168
  const alive = pruneDeadSessions(sessions);
@@ -134,7 +177,14 @@ export function findExistingDaemon() {
134
177
  const sessions = listActive(); // prunes dead PIDs
135
178
  return sessions.find((s) => s.agentType === 'daemon') ?? null;
136
179
  }
137
- /** Try to bind a TCP server to a port to verify it's actually free */
180
+ /**
181
+ * Try to bind a TCP server to a port to verify it's actually free.
182
+ * Binds on 0.0.0.0 (all interfaces) — the same address the WebSocket server uses —
183
+ * so a port held by another process on any interface is correctly detected as busy.
184
+ * The original 127.0.0.1 bind missed ports already occupied on 0.0.0.0 (e.g. zombie
185
+ * session bridges), causing findAvailablePort to hand out ports that immediately
186
+ * caused EADDRINUSE on the real server start.
187
+ */
138
188
  function isPortFree(port) {
139
189
  return new Promise((resolve) => {
140
190
  const server = createServer();
@@ -142,7 +192,7 @@ function isPortFree(port) {
142
192
  server.once('listening', () => {
143
193
  server.close(() => resolve(true));
144
194
  });
145
- server.listen(port, '127.0.0.1');
195
+ server.listen(port, '0.0.0.0');
146
196
  });
147
197
  }
148
198
  export async function findAvailablePort(opts) {
@@ -259,6 +309,88 @@ export function probeDaemonHealth(port) {
259
309
  req.on('timeout', () => { req.destroy(); resolve(null); });
260
310
  });
261
311
  }
312
+ /**
313
+ * Sweep the daemon port window for live daemons that file-based discovery
314
+ * cannot see. Two blind spots make this necessary:
315
+ * - The App Store Swift daemon writes `daemon.json` into its private sandbox
316
+ * container, which `getCandidateDataDirs()` cannot read.
317
+ * - Transient 9120 contention can bump a daemon to a fallback port (9121+),
318
+ * where the default-port probe never looks.
319
+ * Probes all window ports concurrently (localhost refusals resolve instantly)
320
+ * and returns every occupant whose `/health` reports `mode: 'daemon'`.
321
+ */
322
+ export async function scanDaemonPortWindow(skip = new Set(), window = DAEMON_PORT_WINDOW) {
323
+ const ports = [];
324
+ for (let p = window[0]; p <= window[1]; p++) {
325
+ if (!skip.has(p))
326
+ ports.push(p);
327
+ }
328
+ const probes = await Promise.all(ports.map(async (port) => ({ port, health: await probeDaemonHealth(port) })));
329
+ return probes.filter((r) => r.health?.mode === 'daemon');
330
+ }
331
+ /**
332
+ * Poll a port's `/health` until the daemon there stops answering, or the
333
+ * timeout expires. Used after `requestDaemonShutdown()` instead of a fixed
334
+ * sleep: the Swift daemon tears down device modules (serial, ADB reverse,
335
+ * BLE) during shutdown, and taking over before it finishes leaves two owners
336
+ * briefly contending for the same tty / adb reverse mapping.
337
+ * Returns true once the daemon is gone.
338
+ */
339
+ export async function waitForDaemonExit(port, timeoutMs = 5000) {
340
+ const deadline = Date.now() + timeoutMs;
341
+ for (;;) {
342
+ if (!(await probeDaemonHealth(port)))
343
+ return true;
344
+ if (Date.now() >= deadline)
345
+ return false;
346
+ await new Promise((resolve) => setTimeout(resolve, 250));
347
+ }
348
+ }
349
+ /**
350
+ * Request another daemon to shutdown (used to clear Swift daemon when CLI starts)
351
+ */
352
+ export function requestDaemonShutdown(port) {
353
+ return new Promise((resolve) => {
354
+ const req = http.request({
355
+ hostname: '127.0.0.1',
356
+ port,
357
+ path: '/shutdown',
358
+ method: 'POST',
359
+ timeout: 2000
360
+ }, (res) => {
361
+ res.on('data', () => { });
362
+ res.on('end', () => { resolve(); });
363
+ });
364
+ req.on('error', () => resolve());
365
+ req.on('timeout', () => { req.destroy(); resolve(); });
366
+ req.end();
367
+ });
368
+ }
369
+ /**
370
+ * Ask an app-owned Swift in-process daemon to YIELD the canonical port (POST
371
+ * /stand-down) so this CLI daemon can take over with the full feature set.
372
+ * Unlike `/shutdown`, this keeps the macOS app running — it just demotes its
373
+ * daemon to a client of the incoming CLI daemon. Returns true if the daemon
374
+ * acknowledged (HTTP 2xx). The caller should then `waitForDaemonExit()` for the
375
+ * port to clear before binding.
376
+ */
377
+ export function requestDaemonStandDown(port) {
378
+ return new Promise((resolve) => {
379
+ const req = http.request({
380
+ hostname: '127.0.0.1',
381
+ port,
382
+ path: '/stand-down',
383
+ method: 'POST',
384
+ timeout: 2000,
385
+ }, (res) => {
386
+ res.on('data', () => { });
387
+ res.on('end', () => { resolve((res.statusCode ?? 500) < 300); });
388
+ });
389
+ req.on('error', () => resolve(false));
390
+ req.on('timeout', () => { req.destroy(); resolve(false); });
391
+ req.end();
392
+ });
393
+ }
262
394
  /**
263
395
  * Find the daemon port for client connections.
264
396
  * Priority: daemon.json (fast) → sessions.json fallback.
@@ -303,7 +435,7 @@ export async function findDaemonPortAsync() {
303
435
  // 2. Port scan fallback — covers the "App Store daemon is up but its
304
436
  // daemon.json sits in a dir this process can't read" case. Narrow
305
437
  // range (9120-9139) matches the documented daemon port window.
306
- for (let p = 9120; p <= 9139; p++) {
438
+ for (let p = DAEMON_PORT_WINDOW[0]; p <= DAEMON_PORT_WINDOW[1]; p++) {
307
439
  const health = await probeDaemonHealth(p);
308
440
  if (health?.mode === 'daemon') {
309
441
  return { port: p };