@agentdeck/bridge 0.1.0 → 0.2.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 (380) hide show
  1. package/LICENSE +21 -0
  2. package/dist/adapters/claude-code.d.ts +11 -27
  3. package/dist/adapters/claude-code.d.ts.map +1 -1
  4. package/dist/adapters/claude-code.js +29 -123
  5. package/dist/adapters/claude-code.js.map +1 -1
  6. package/dist/adapters/codex-cli.d.ts +21 -0
  7. package/dist/adapters/codex-cli.d.ts.map +1 -0
  8. package/dist/adapters/codex-cli.js +53 -0
  9. package/dist/adapters/codex-cli.js.map +1 -0
  10. package/dist/adapters/index.d.ts +4 -0
  11. package/dist/adapters/index.d.ts.map +1 -1
  12. package/dist/adapters/index.js +13 -0
  13. package/dist/adapters/index.js.map +1 -1
  14. package/dist/adapters/monitor.d.ts +34 -0
  15. package/dist/adapters/monitor.d.ts.map +1 -0
  16. package/dist/adapters/monitor.js +86 -0
  17. package/dist/adapters/monitor.js.map +1 -0
  18. package/dist/adapters/openclaw.d.ts +36 -2
  19. package/dist/adapters/openclaw.d.ts.map +1 -1
  20. package/dist/adapters/openclaw.js +329 -59
  21. package/dist/adapters/openclaw.js.map +1 -1
  22. package/dist/adapters/opencode-adapter.d.ts +48 -0
  23. package/dist/adapters/opencode-adapter.d.ts.map +1 -0
  24. package/dist/adapters/opencode-adapter.js +345 -0
  25. package/dist/adapters/opencode-adapter.js.map +1 -0
  26. package/dist/adapters/pty-adapter.d.ts +56 -0
  27. package/dist/adapters/pty-adapter.d.ts.map +1 -0
  28. package/dist/adapters/pty-adapter.js +143 -0
  29. package/dist/adapters/pty-adapter.js.map +1 -0
  30. package/dist/adb-reverse.d.ts +25 -0
  31. package/dist/adb-reverse.d.ts.map +1 -0
  32. package/dist/adb-reverse.js +129 -0
  33. package/dist/adb-reverse.js.map +1 -0
  34. package/dist/antigravity-local.d.ts +7 -0
  35. package/dist/antigravity-local.d.ts.map +1 -0
  36. package/dist/antigravity-local.js +153 -0
  37. package/dist/antigravity-local.js.map +1 -0
  38. package/dist/apme/adapters/claude-hook.d.ts +15 -0
  39. package/dist/apme/adapters/claude-hook.d.ts.map +1 -0
  40. package/dist/apme/adapters/claude-hook.js +85 -0
  41. package/dist/apme/adapters/claude-hook.js.map +1 -0
  42. package/dist/apme/adapters/claude-pty.d.ts +28 -0
  43. package/dist/apme/adapters/claude-pty.d.ts.map +1 -0
  44. package/dist/apme/adapters/claude-pty.js +88 -0
  45. package/dist/apme/adapters/claude-pty.js.map +1 -0
  46. package/dist/apme/adapters/timeline.d.ts +16 -0
  47. package/dist/apme/adapters/timeline.d.ts.map +1 -0
  48. package/dist/apme/adapters/timeline.js +66 -0
  49. package/dist/apme/adapters/timeline.js.map +1 -0
  50. package/dist/apme/classifier.d.ts +53 -0
  51. package/dist/apme/classifier.d.ts.map +1 -0
  52. package/dist/apme/classifier.js +266 -0
  53. package/dist/apme/classifier.js.map +1 -0
  54. package/dist/apme/claude-transcript-reader.d.ts +38 -0
  55. package/dist/apme/claude-transcript-reader.d.ts.map +1 -0
  56. package/dist/apme/claude-transcript-reader.js +127 -0
  57. package/dist/apme/claude-transcript-reader.js.map +1 -0
  58. package/dist/apme/collector.d.ts +108 -0
  59. package/dist/apme/collector.d.ts.map +1 -0
  60. package/dist/apme/collector.js +659 -0
  61. package/dist/apme/collector.js.map +1 -0
  62. package/dist/apme/dashboard-html.d.ts +9 -0
  63. package/dist/apme/dashboard-html.d.ts.map +1 -0
  64. package/dist/apme/dashboard-html.js +416 -0
  65. package/dist/apme/dashboard-html.js.map +1 -0
  66. package/dist/apme/http.d.ts +19 -0
  67. package/dist/apme/http.d.ts.map +1 -0
  68. package/dist/apme/http.js +210 -0
  69. package/dist/apme/http.js.map +1 -0
  70. package/dist/apme/hw-sampler.d.ts +30 -0
  71. package/dist/apme/hw-sampler.d.ts.map +1 -0
  72. package/dist/apme/hw-sampler.js +106 -0
  73. package/dist/apme/hw-sampler.js.map +1 -0
  74. package/dist/apme/index.d.ts +43 -0
  75. package/dist/apme/index.d.ts.map +1 -0
  76. package/dist/apme/index.js +75 -0
  77. package/dist/apme/index.js.map +1 -0
  78. package/dist/apme/outcome.d.ts +48 -0
  79. package/dist/apme/outcome.d.ts.map +1 -0
  80. package/dist/apme/outcome.js +232 -0
  81. package/dist/apme/outcome.js.map +1 -0
  82. package/dist/apme/recommend.d.ts +32 -0
  83. package/dist/apme/recommend.d.ts.map +1 -0
  84. package/dist/apme/recommend.js +41 -0
  85. package/dist/apme/recommend.js.map +1 -0
  86. package/dist/apme/runner.d.ts +94 -0
  87. package/dist/apme/runner.d.ts.map +1 -0
  88. package/dist/apme/runner.js +812 -0
  89. package/dist/apme/runner.js.map +1 -0
  90. package/dist/apme/settings.d.ts +65 -0
  91. package/dist/apme/settings.d.ts.map +1 -0
  92. package/dist/apme/settings.js +97 -0
  93. package/dist/apme/settings.js.map +1 -0
  94. package/dist/apme/store.d.ts +99 -0
  95. package/dist/apme/store.d.ts.map +1 -0
  96. package/dist/apme/store.js +911 -0
  97. package/dist/apme/store.js.map +1 -0
  98. package/dist/apme/tuner.d.ts +64 -0
  99. package/dist/apme/tuner.d.ts.map +1 -0
  100. package/dist/apme/tuner.js +297 -0
  101. package/dist/apme/tuner.js.map +1 -0
  102. package/dist/apme/types.d.ts +11 -0
  103. package/dist/apme/types.d.ts.map +1 -0
  104. package/dist/apme/types.js +10 -0
  105. package/dist/apme/types.js.map +1 -0
  106. package/dist/auth.d.ts +1 -1
  107. package/dist/auth.d.ts.map +1 -1
  108. package/dist/auth.js +15 -5
  109. package/dist/auth.js.map +1 -1
  110. package/dist/bridge-core.d.ts +162 -0
  111. package/dist/bridge-core.d.ts.map +1 -0
  112. package/dist/bridge-core.js +627 -0
  113. package/dist/bridge-core.js.map +1 -0
  114. package/dist/check-deps.d.ts +3 -1
  115. package/dist/check-deps.d.ts.map +1 -1
  116. package/dist/check-deps.js +34 -13
  117. package/dist/check-deps.js.map +1 -1
  118. package/dist/cli.d.ts +3 -0
  119. package/dist/cli.d.ts.map +1 -0
  120. package/dist/cli.js +1235 -0
  121. package/dist/cli.js.map +1 -0
  122. package/dist/codex-auth.d.ts +10 -0
  123. package/dist/codex-auth.d.ts.map +1 -0
  124. package/dist/codex-auth.js +63 -0
  125. package/dist/codex-auth.js.map +1 -0
  126. package/dist/codex-output-parser.d.ts +21 -0
  127. package/dist/codex-output-parser.d.ts.map +1 -0
  128. package/dist/codex-output-parser.js +253 -0
  129. package/dist/codex-output-parser.js.map +1 -0
  130. package/dist/d200h/hid-protocol.d.ts +62 -0
  131. package/dist/d200h/hid-protocol.d.ts.map +1 -0
  132. package/dist/d200h/hid-protocol.js +124 -0
  133. package/dist/d200h/hid-protocol.js.map +1 -0
  134. package/dist/d200h/image-renderer.d.ts +36 -0
  135. package/dist/d200h/image-renderer.d.ts.map +1 -0
  136. package/dist/d200h/image-renderer.js +487 -0
  137. package/dist/d200h/image-renderer.js.map +1 -0
  138. package/dist/daemon-server.d.ts +19 -0
  139. package/dist/daemon-server.d.ts.map +1 -0
  140. package/dist/daemon-server.js +1168 -0
  141. package/dist/daemon-server.js.map +1 -0
  142. package/dist/daemon-ws-client.d.ts +82 -0
  143. package/dist/daemon-ws-client.d.ts.map +1 -0
  144. package/dist/daemon-ws-client.js +179 -0
  145. package/dist/daemon-ws-client.js.map +1 -0
  146. package/dist/daemon.d.ts +10 -0
  147. package/dist/daemon.d.ts.map +1 -0
  148. package/dist/daemon.js +56 -0
  149. package/dist/daemon.js.map +1 -0
  150. package/dist/display-monitor.d.ts +25 -0
  151. package/dist/display-monitor.d.ts.map +1 -0
  152. package/dist/display-monitor.js +143 -0
  153. package/dist/display-monitor.js.map +1 -0
  154. package/dist/esp32-serial.d.ts +112 -0
  155. package/dist/esp32-serial.d.ts.map +1 -0
  156. package/dist/esp32-serial.js +502 -0
  157. package/dist/esp32-serial.js.map +1 -0
  158. package/dist/gateway-probe.d.ts +12 -0
  159. package/dist/gateway-probe.d.ts.map +1 -0
  160. package/dist/gateway-probe.js +39 -0
  161. package/dist/gateway-probe.js.map +1 -0
  162. package/dist/hook-server.d.ts +29 -0
  163. package/dist/hook-server.d.ts.map +1 -1
  164. package/dist/hook-server.js +366 -8
  165. package/dist/hook-server.js.map +1 -1
  166. package/dist/index.d.ts +20 -2
  167. package/dist/index.d.ts.map +1 -1
  168. package/dist/index.js +1305 -562
  169. package/dist/index.js.map +1 -1
  170. package/dist/log-stream.d.ts +26 -0
  171. package/dist/log-stream.d.ts.map +1 -0
  172. package/dist/log-stream.js +111 -0
  173. package/dist/log-stream.js.map +1 -0
  174. package/dist/logger.d.ts +9 -2
  175. package/dist/logger.d.ts.map +1 -1
  176. package/dist/logger.js +36 -5
  177. package/dist/logger.js.map +1 -1
  178. package/dist/mdns.d.ts +15 -1
  179. package/dist/mdns.d.ts.map +1 -1
  180. package/dist/mdns.js +143 -28
  181. package/dist/mdns.js.map +1 -1
  182. package/dist/mlx-probe.d.ts +14 -0
  183. package/dist/mlx-probe.d.ts.map +1 -0
  184. package/dist/mlx-probe.js +44 -0
  185. package/dist/mlx-probe.js.map +1 -0
  186. package/dist/model-catalog.d.ts +5 -3
  187. package/dist/model-catalog.d.ts.map +1 -1
  188. package/dist/model-catalog.js +45 -29
  189. package/dist/model-catalog.js.map +1 -1
  190. package/dist/modules/adb-module.d.ts +14 -0
  191. package/dist/modules/adb-module.d.ts.map +1 -0
  192. package/dist/modules/adb-module.js +36 -0
  193. package/dist/modules/adb-module.js.map +1 -0
  194. package/dist/modules/d200h-module.d.ts +43 -0
  195. package/dist/modules/d200h-module.d.ts.map +1 -0
  196. package/dist/modules/d200h-module.js +360 -0
  197. package/dist/modules/d200h-module.js.map +1 -0
  198. package/dist/modules/d200h-renderer.d.ts +7 -0
  199. package/dist/modules/d200h-renderer.d.ts.map +1 -0
  200. package/dist/modules/d200h-renderer.js +321 -0
  201. package/dist/modules/d200h-renderer.js.map +1 -0
  202. package/dist/modules/index.d.ts +23 -0
  203. package/dist/modules/index.d.ts.map +1 -0
  204. package/dist/modules/index.js +65 -0
  205. package/dist/modules/index.js.map +1 -0
  206. package/dist/modules/mdns-module.d.ts +12 -0
  207. package/dist/modules/mdns-module.d.ts.map +1 -0
  208. package/dist/modules/mdns-module.js +21 -0
  209. package/dist/modules/mdns-module.js.map +1 -0
  210. package/dist/modules/pixoo-module.d.ts +8 -0
  211. package/dist/modules/pixoo-module.d.ts.map +1 -0
  212. package/dist/modules/pixoo-module.js +24 -0
  213. package/dist/modules/pixoo-module.js.map +1 -0
  214. package/dist/modules/serial-module.d.ts +18 -0
  215. package/dist/modules/serial-module.d.ts.map +1 -0
  216. package/dist/modules/serial-module.js +47 -0
  217. package/dist/modules/serial-module.js.map +1 -0
  218. package/dist/modules/types.d.ts +39 -0
  219. package/dist/modules/types.d.ts.map +1 -0
  220. package/dist/modules/types.js +2 -0
  221. package/dist/modules/types.js.map +1 -0
  222. package/dist/ollama-probe.d.ts +13 -0
  223. package/dist/ollama-probe.d.ts.map +1 -0
  224. package/dist/ollama-probe.js +46 -0
  225. package/dist/ollama-probe.js.map +1 -0
  226. package/dist/opencode-client.d.ts +126 -0
  227. package/dist/opencode-client.d.ts.map +1 -0
  228. package/dist/opencode-client.js +181 -0
  229. package/dist/opencode-client.js.map +1 -0
  230. package/dist/output-parser.d.ts +3 -0
  231. package/dist/output-parser.d.ts.map +1 -1
  232. package/dist/output-parser.js +29 -3
  233. package/dist/output-parser.js.map +1 -1
  234. package/dist/passive-observer.d.ts +38 -0
  235. package/dist/passive-observer.d.ts.map +1 -0
  236. package/dist/passive-observer.js +632 -0
  237. package/dist/passive-observer.js.map +1 -0
  238. package/dist/pixoo/pixoo-bridge.d.ts +50 -0
  239. package/dist/pixoo/pixoo-bridge.d.ts.map +1 -0
  240. package/dist/pixoo/pixoo-bridge.js +280 -0
  241. package/dist/pixoo/pixoo-bridge.js.map +1 -0
  242. package/dist/pixoo/pixoo-camera.d.ts +80 -0
  243. package/dist/pixoo/pixoo-camera.d.ts.map +1 -0
  244. package/dist/pixoo/pixoo-camera.js +271 -0
  245. package/dist/pixoo/pixoo-camera.js.map +1 -0
  246. package/dist/pixoo/pixoo-client.d.ts +67 -0
  247. package/dist/pixoo/pixoo-client.d.ts.map +1 -0
  248. package/dist/pixoo/pixoo-client.js +335 -0
  249. package/dist/pixoo/pixoo-client.js.map +1 -0
  250. package/dist/pixoo/pixoo-font.d.ts +24 -0
  251. package/dist/pixoo/pixoo-font.d.ts.map +1 -0
  252. package/dist/pixoo/pixoo-font.js +121 -0
  253. package/dist/pixoo/pixoo-font.js.map +1 -0
  254. package/dist/pixoo/pixoo-renderer.d.ts +32 -0
  255. package/dist/pixoo/pixoo-renderer.d.ts.map +1 -0
  256. package/dist/pixoo/pixoo-renderer.js +696 -0
  257. package/dist/pixoo/pixoo-renderer.js.map +1 -0
  258. package/dist/pixoo/pixoo-settings.d.ts +10 -0
  259. package/dist/pixoo/pixoo-settings.d.ts.map +1 -0
  260. package/dist/pixoo/pixoo-settings.js +47 -0
  261. package/dist/pixoo/pixoo-settings.js.map +1 -0
  262. package/dist/pixoo/pixoo-sprites.d.ts +187 -0
  263. package/dist/pixoo/pixoo-sprites.d.ts.map +1 -0
  264. package/dist/pixoo/pixoo-sprites.js +926 -0
  265. package/dist/pixoo/pixoo-sprites.js.map +1 -0
  266. package/dist/pty-manager.d.ts +1 -1
  267. package/dist/pty-manager.d.ts.map +1 -1
  268. package/dist/pty-manager.js +36 -15
  269. package/dist/pty-manager.js.map +1 -1
  270. package/dist/session-aggregator.d.ts +41 -0
  271. package/dist/session-aggregator.d.ts.map +1 -0
  272. package/dist/session-aggregator.js +76 -0
  273. package/dist/session-aggregator.js.map +1 -0
  274. package/dist/session-focus-relay.d.ts +35 -0
  275. package/dist/session-focus-relay.d.ts.map +1 -0
  276. package/dist/session-focus-relay.js +127 -0
  277. package/dist/session-focus-relay.js.map +1 -0
  278. package/dist/session-registry.d.ts +88 -1
  279. package/dist/session-registry.d.ts.map +1 -1
  280. package/dist/session-registry.js +222 -15
  281. package/dist/session-registry.js.map +1 -1
  282. package/dist/session-timeline-relay.d.ts +27 -0
  283. package/dist/session-timeline-relay.d.ts.map +1 -0
  284. package/dist/session-timeline-relay.js +124 -0
  285. package/dist/session-timeline-relay.js.map +1 -0
  286. package/dist/state-machine.d.ts +1 -0
  287. package/dist/state-machine.d.ts.map +1 -1
  288. package/dist/state-machine.js +14 -0
  289. package/dist/state-machine.js.map +1 -1
  290. package/dist/terminal-status.d.ts +28 -0
  291. package/dist/terminal-status.d.ts.map +1 -0
  292. package/dist/terminal-status.js +152 -0
  293. package/dist/terminal-status.js.map +1 -0
  294. package/dist/timeline-store.d.ts +22 -0
  295. package/dist/timeline-store.d.ts.map +1 -0
  296. package/dist/timeline-store.js +79 -0
  297. package/dist/timeline-store.js.map +1 -0
  298. package/dist/timeline-summarizer.d.ts +14 -0
  299. package/dist/timeline-summarizer.d.ts.map +1 -0
  300. package/dist/timeline-summarizer.js +154 -0
  301. package/dist/timeline-summarizer.js.map +1 -0
  302. package/dist/tts.d.ts +25 -0
  303. package/dist/tts.d.ts.map +1 -0
  304. package/dist/tts.js +99 -0
  305. package/dist/tts.js.map +1 -0
  306. package/dist/tui/ansi.d.ts +92 -0
  307. package/dist/tui/ansi.d.ts.map +1 -0
  308. package/dist/tui/ansi.js +181 -0
  309. package/dist/tui/ansi.js.map +1 -0
  310. package/dist/tui/dashboard.d.ts +35 -0
  311. package/dist/tui/dashboard.d.ts.map +1 -0
  312. package/dist/tui/dashboard.js +436 -0
  313. package/dist/tui/dashboard.js.map +1 -0
  314. package/dist/tui/gauge.d.ts +15 -0
  315. package/dist/tui/gauge.d.ts.map +1 -0
  316. package/dist/tui/gauge.js +82 -0
  317. package/dist/tui/gauge.js.map +1 -0
  318. package/dist/tui/renderer.d.ts +15 -0
  319. package/dist/tui/renderer.d.ts.map +1 -0
  320. package/dist/tui/renderer.js +758 -0
  321. package/dist/tui/renderer.js.map +1 -0
  322. package/dist/tui/screen.d.ts +27 -0
  323. package/dist/tui/screen.d.ts.map +1 -0
  324. package/dist/tui/screen.js +109 -0
  325. package/dist/tui/screen.js.map +1 -0
  326. package/dist/tui/terrarium.d.ts +96 -0
  327. package/dist/tui/terrarium.d.ts.map +1 -0
  328. package/dist/tui/terrarium.js +912 -0
  329. package/dist/tui/terrarium.js.map +1 -0
  330. package/dist/types.d.ts +4 -2
  331. package/dist/types.d.ts.map +1 -1
  332. package/dist/types.js +3 -2
  333. package/dist/types.js.map +1 -1
  334. package/dist/usage-api.d.ts +9 -2
  335. package/dist/usage-api.d.ts.map +1 -1
  336. package/dist/usage-api.js +224 -42
  337. package/dist/usage-api.js.map +1 -1
  338. package/dist/usage-event.d.ts +12 -0
  339. package/dist/usage-event.d.ts.map +1 -0
  340. package/dist/usage-event.js +78 -0
  341. package/dist/usage-event.js.map +1 -0
  342. package/dist/usage-tracker.d.ts +4 -0
  343. package/dist/usage-tracker.d.ts.map +1 -1
  344. package/dist/usage-tracker.js +17 -0
  345. package/dist/usage-tracker.js.map +1 -1
  346. package/dist/utility-proxy.d.ts +30 -0
  347. package/dist/utility-proxy.d.ts.map +1 -0
  348. package/dist/utility-proxy.js +217 -0
  349. package/dist/utility-proxy.js.map +1 -0
  350. package/dist/utils/project-name.d.ts +22 -0
  351. package/dist/utils/project-name.d.ts.map +1 -0
  352. package/dist/utils/project-name.js +72 -0
  353. package/dist/utils/project-name.js.map +1 -0
  354. package/dist/version-check.d.ts +26 -0
  355. package/dist/version-check.d.ts.map +1 -0
  356. package/dist/version-check.js +225 -0
  357. package/dist/version-check.js.map +1 -0
  358. package/dist/voice-assistant.d.ts +63 -0
  359. package/dist/voice-assistant.d.ts.map +1 -0
  360. package/dist/voice-assistant.js +406 -0
  361. package/dist/voice-assistant.js.map +1 -0
  362. package/dist/voice.d.ts +2 -0
  363. package/dist/voice.d.ts.map +1 -1
  364. package/dist/voice.js +26 -1
  365. package/dist/voice.js.map +1 -1
  366. package/dist/wake-word.d.ts +35 -0
  367. package/dist/wake-word.d.ts.map +1 -0
  368. package/dist/wake-word.js +225 -0
  369. package/dist/wake-word.js.map +1 -0
  370. package/dist/whisper-server-manager.d.ts +1 -1
  371. package/dist/whisper-server-manager.js +1 -1
  372. package/dist/wifi-config.d.ts +24 -0
  373. package/dist/wifi-config.d.ts.map +1 -0
  374. package/dist/wifi-config.js +84 -0
  375. package/dist/wifi-config.js.map +1 -0
  376. package/dist/ws-server.d.ts +12 -0
  377. package/dist/ws-server.d.ts.map +1 -1
  378. package/dist/ws-server.js +81 -3
  379. package/dist/ws-server.js.map +1 -1
  380. package/package.json +22 -13
@@ -0,0 +1,225 @@
1
+ /**
2
+ * Wake Word Listener — Porcupine (Picovoice) wrapper.
3
+ *
4
+ * Continuously captures audio from the Mac microphone via @picovoice/pvrecorder-node
5
+ * and runs Porcupine wake word detection for "오픈클로".
6
+ *
7
+ * Emits 'detected' when the wake word is heard.
8
+ * Provides start() / stop() / isListening() interface.
9
+ */
10
+ import { EventEmitter } from 'events';
11
+ import { existsSync, readFileSync, readdirSync } from 'fs';
12
+ import { join } from 'path';
13
+ import { homedir } from 'os';
14
+ import { log, debug } from './logger.js';
15
+ import { WAKE_WORD_MODEL_DIR, PICOVOICE_ACCESS_KEY_FILE, } from '@agentdeck/shared';
16
+ const TAG = 'WakeWord';
17
+ /** Find the .ppn keyword model file in the wake word model directory */
18
+ function findPpnModel() {
19
+ if (!existsSync(WAKE_WORD_MODEL_DIR))
20
+ return null;
21
+ const files = readdirSync(WAKE_WORD_MODEL_DIR).filter(f => f.endsWith('.ppn'));
22
+ if (files.length === 0)
23
+ return null;
24
+ const preferred = files.find(f => /openclaw|오픈클로/i.test(f));
25
+ return join(WAKE_WORD_MODEL_DIR, preferred ?? files[0]);
26
+ }
27
+ /** Find the Porcupine language model (.pv) — Korean for "오픈클로" */
28
+ function findLanguageModel() {
29
+ // 1. Check wake-word dir for language model
30
+ if (existsSync(WAKE_WORD_MODEL_DIR)) {
31
+ const pvFiles = readdirSync(WAKE_WORD_MODEL_DIR).filter(f => f.endsWith('.pv'));
32
+ const koModel = pvFiles.find(f => /ko|korean/i.test(f));
33
+ if (koModel)
34
+ return join(WAKE_WORD_MODEL_DIR, koModel);
35
+ if (pvFiles.length > 0)
36
+ return join(WAKE_WORD_MODEL_DIR, pvFiles[0]);
37
+ }
38
+ return null;
39
+ }
40
+ /** Read Picovoice access key from file */
41
+ function readAccessKey() {
42
+ try {
43
+ if (!existsSync(PICOVOICE_ACCESS_KEY_FILE))
44
+ return null;
45
+ return readFileSync(PICOVOICE_ACCESS_KEY_FILE, 'utf-8').trim();
46
+ }
47
+ catch {
48
+ return null;
49
+ }
50
+ }
51
+ const DEFAULT_SENSITIVITY = 0.8;
52
+ /** Read wakeWordMic + wakeWordSensitivity from settings.json */
53
+ function getWakeWordSettings(PvRecorder) {
54
+ let deviceIndex = -1;
55
+ let sensitivity = DEFAULT_SENSITIVITY;
56
+ try {
57
+ const settings = JSON.parse(readFileSync(join(homedir(), '.agentdeck', 'settings.json'), 'utf-8'));
58
+ // Mic
59
+ const micName = settings.wakeWordMic;
60
+ if (micName) {
61
+ const devices = PvRecorder.getAvailableDevices();
62
+ const idx = devices.findIndex((d) => d.toLowerCase().includes(micName.toLowerCase()));
63
+ if (idx >= 0) {
64
+ debug(TAG, `Configured mic "${micName}" → device ${idx}: ${devices[idx]}`);
65
+ deviceIndex = idx;
66
+ }
67
+ else {
68
+ debug(TAG, `Configured mic "${micName}" not found, using system default`);
69
+ }
70
+ }
71
+ // Sensitivity
72
+ const sens = settings.wakeWordSensitivity;
73
+ if (typeof sens === 'number' && sens >= 0 && sens <= 1) {
74
+ sensitivity = sens;
75
+ }
76
+ }
77
+ catch { /* ok */ }
78
+ return { deviceIndex, sensitivity };
79
+ }
80
+ export class WakeWordListener extends EventEmitter {
81
+ listening = false;
82
+ /** Whether the detection loop is actively running (false during pause) */
83
+ active = false;
84
+ porcupine = null;
85
+ recorder = null;
86
+ accessKey;
87
+ keywordPath;
88
+ languageModelPath;
89
+ constructor() {
90
+ super();
91
+ this.accessKey = readAccessKey() ?? '';
92
+ this.keywordPath = findPpnModel() ?? '';
93
+ this.languageModelPath = findLanguageModel();
94
+ }
95
+ /** Check if wake word detection is available (deps + model + key) */
96
+ isAvailable() {
97
+ if (!this.accessKey) {
98
+ debug(TAG, `Access key not found at ${PICOVOICE_ACCESS_KEY_FILE}`);
99
+ return false;
100
+ }
101
+ if (!this.keywordPath || !existsSync(this.keywordPath)) {
102
+ debug(TAG, `No .ppn model found in ${WAKE_WORD_MODEL_DIR}`);
103
+ return false;
104
+ }
105
+ return true;
106
+ }
107
+ async start() {
108
+ if (this.listening)
109
+ return true;
110
+ if (!this.isAvailable()) {
111
+ debug(TAG, 'Cannot start — missing access key or model');
112
+ return false;
113
+ }
114
+ try {
115
+ // Dynamic imports — these are optional deps
116
+ const { Porcupine } = await import('@picovoice/porcupine-node');
117
+ const { PvRecorder } = await import('@picovoice/pvrecorder-node');
118
+ const options = {};
119
+ if (this.languageModelPath) {
120
+ options.modelPath = this.languageModelPath;
121
+ debug(TAG, `Using language model: ${this.languageModelPath}`);
122
+ }
123
+ const wwSettings = getWakeWordSettings(PvRecorder);
124
+ this.porcupine = new Porcupine(this.accessKey, [this.keywordPath], [wwSettings.sensitivity], options);
125
+ const frameLength = this.porcupine.frameLength;
126
+ const deviceIndex = wwSettings.deviceIndex;
127
+ this.recorder = new PvRecorder(frameLength, deviceIndex);
128
+ this.recorder.start();
129
+ this.listening = true;
130
+ this.active = true;
131
+ log(`Listening on "${this.recorder.getSelectedDevice()}"`);
132
+ debug(TAG, `Listening on "${this.recorder.getSelectedDevice()}" (keyword: ${this.keywordPath})`);
133
+ // Detection loop
134
+ this.runDetectionLoop();
135
+ return true;
136
+ }
137
+ catch (err) {
138
+ const msg = err instanceof Error ? err.message : String(err);
139
+ debug(TAG, `Failed to start: ${msg}`);
140
+ this.cleanup();
141
+ return false;
142
+ }
143
+ }
144
+ stop() {
145
+ if (!this.listening)
146
+ return;
147
+ debug(TAG, 'Stopping');
148
+ this.listening = false;
149
+ this.active = false;
150
+ this.cleanup();
151
+ }
152
+ isListening() {
153
+ return this.listening;
154
+ }
155
+ /** Temporarily pause detection (e.g., while recording user speech).
156
+ * Sets active=false so the detection loop exits naturally,
157
+ * then stops the recorder. */
158
+ pause() {
159
+ if (this.recorder && this.listening && this.active) {
160
+ this.active = false;
161
+ try {
162
+ this.recorder.stop();
163
+ }
164
+ catch { /* ok */ }
165
+ debug(TAG, 'Paused');
166
+ }
167
+ }
168
+ /** Resume detection after pause — starts a fresh detection loop */
169
+ resume() {
170
+ if (this.recorder && this.listening && !this.active) {
171
+ try {
172
+ this.recorder.start();
173
+ }
174
+ catch { /* ok */ }
175
+ this.active = true;
176
+ debug(TAG, 'Resumed');
177
+ this.runDetectionLoop();
178
+ }
179
+ }
180
+ async runDetectionLoop() {
181
+ while (this.active && this.listening && this.recorder && this.porcupine) {
182
+ try {
183
+ const pcm = await this.recorder.read();
184
+ if (!this.active)
185
+ break;
186
+ const keywordIndex = this.porcupine.process(pcm);
187
+ if (keywordIndex >= 0) {
188
+ log('Detected!');
189
+ this.emit('detected', {
190
+ deviceId: 'mac-builtin',
191
+ timestamp: Date.now(),
192
+ });
193
+ }
194
+ }
195
+ catch (err) {
196
+ if (!this.active || !this.listening)
197
+ break;
198
+ debug(TAG, `Detection loop error: ${err}`);
199
+ await new Promise(r => setTimeout(r, 100));
200
+ }
201
+ }
202
+ debug(TAG, `Detection loop exited (active=${this.active}, listening=${this.listening})`);
203
+ }
204
+ cleanup() {
205
+ if (this.recorder) {
206
+ try {
207
+ this.recorder.stop();
208
+ }
209
+ catch { /* ok */ }
210
+ try {
211
+ this.recorder.release();
212
+ }
213
+ catch { /* ok */ }
214
+ this.recorder = null;
215
+ }
216
+ if (this.porcupine) {
217
+ try {
218
+ this.porcupine.release();
219
+ }
220
+ catch { /* ok */ }
221
+ this.porcupine = null;
222
+ }
223
+ }
224
+ }
225
+ //# sourceMappingURL=wake-word.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wake-word.js","sourceRoot":"","sources":["../src/wake-word.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Whisper-server singleton manager.
3
3
  *
4
- * Fixed port 9100 — one server shared across all sdc sessions.
4
+ * Fixed port 9100 — one server shared across all agentdeck sessions.
5
5
  * Info file at ~/.agentdeck/whisper-server.json for discovery.
6
6
  * Last session to exit kills the server.
7
7
  */
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Whisper-server singleton manager.
3
3
  *
4
- * Fixed port 9100 — one server shared across all sdc sessions.
4
+ * Fixed port 9100 — one server shared across all agentdeck sessions.
5
5
  * Info file at ~/.agentdeck/whisper-server.json for discovery.
6
6
  * Last session to exit kills the server.
7
7
  */
@@ -0,0 +1,24 @@
1
+ /**
2
+ * WiFi credential management for ESP32 auto-provisioning.
3
+ *
4
+ * Stores SSID/password in ~/.agentdeck/wifi-config.json.
5
+ * Can auto-detect current macOS WiFi SSID and query Keychain for password.
6
+ */
7
+ export interface WifiConfig {
8
+ ssid: string;
9
+ password: string;
10
+ autoProvision: boolean;
11
+ }
12
+ /** Load saved WiFi config, or null if not configured. */
13
+ export declare function loadWifiConfig(): WifiConfig | null;
14
+ /** Save WiFi config to disk. */
15
+ export declare function saveWifiConfig(config: WifiConfig): void;
16
+ /** Detect current macOS WiFi SSID. Returns null on other platforms or if not connected. */
17
+ export declare function detectCurrentSSID(): string | null;
18
+ /**
19
+ * Try to retrieve WiFi password from macOS Keychain.
20
+ * Requires user approval (Touch ID / password dialog) on first access.
21
+ * Returns null if not found or denied.
22
+ */
23
+ export declare function getKeychainPassword(ssid: string): string | null;
24
+ //# sourceMappingURL=wifi-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wifi-config.d.ts","sourceRoot":"","sources":["../src/wifi-config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,yDAAyD;AACzD,wBAAgB,cAAc,IAAI,UAAU,GAAG,IAAI,CAelD;AAED,gCAAgC;AAChC,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CASvD;AAED,2FAA2F;AAC3F,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,IAAI,CAoBjD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAW/D"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * WiFi credential management for ESP32 auto-provisioning.
3
+ *
4
+ * Stores SSID/password in ~/.agentdeck/wifi-config.json.
5
+ * Can auto-detect current macOS WiFi SSID and query Keychain for password.
6
+ */
7
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
8
+ import { join } from 'path';
9
+ import { homedir } from 'os';
10
+ import { execSync } from 'child_process';
11
+ import { debug } from './logger.js';
12
+ const AGENTDECK_DIR = join(homedir(), '.agentdeck');
13
+ const WIFI_CONFIG_FILE = join(AGENTDECK_DIR, 'wifi-config.json');
14
+ /** Load saved WiFi config, or null if not configured. */
15
+ export function loadWifiConfig() {
16
+ try {
17
+ if (!existsSync(WIFI_CONFIG_FILE))
18
+ return null;
19
+ const data = JSON.parse(readFileSync(WIFI_CONFIG_FILE, 'utf-8'));
20
+ if (data.ssid && data.password) {
21
+ return {
22
+ ssid: data.ssid,
23
+ password: data.password,
24
+ autoProvision: data.autoProvision !== false,
25
+ };
26
+ }
27
+ }
28
+ catch {
29
+ debug('wifi-config', 'Failed to load wifi-config.json');
30
+ }
31
+ return null;
32
+ }
33
+ /** Save WiFi config to disk. */
34
+ export function saveWifiConfig(config) {
35
+ try {
36
+ mkdirSync(AGENTDECK_DIR, { recursive: true });
37
+ writeFileSync(WIFI_CONFIG_FILE, JSON.stringify(config, null, 2) + '\n', { mode: 0o600 });
38
+ debug('wifi-config', `Saved WiFi config for SSID: ${config.ssid}`);
39
+ }
40
+ catch (err) {
41
+ debug('wifi-config', `Failed to save wifi-config.json: ${err}`);
42
+ throw err;
43
+ }
44
+ }
45
+ /** Detect current macOS WiFi SSID. Returns null on other platforms or if not connected. */
46
+ export function detectCurrentSSID() {
47
+ if (process.platform !== 'darwin')
48
+ return null;
49
+ try {
50
+ // Find the actual Wi-Fi interface (not always en0 — e.g. en1 on Mac Studio)
51
+ const ports = execSync('networksetup -listallhardwareports', {
52
+ encoding: 'utf-8', timeout: 3000,
53
+ });
54
+ const wifiMatch = ports.match(/Hardware Port: Wi-Fi\nDevice: (en\d+)/);
55
+ const iface = wifiMatch ? wifiMatch[1] : 'en0';
56
+ const output = execSync(`networksetup -getairportnetwork ${iface}`, {
57
+ encoding: 'utf-8',
58
+ timeout: 3000,
59
+ }).trim();
60
+ // Output: "Current Wi-Fi Network: MyNetwork"
61
+ const match = output.match(/Current Wi-Fi Network:\s*(.+)/);
62
+ return match ? match[1].trim() : null;
63
+ }
64
+ catch {
65
+ return null;
66
+ }
67
+ }
68
+ /**
69
+ * Try to retrieve WiFi password from macOS Keychain.
70
+ * Requires user approval (Touch ID / password dialog) on first access.
71
+ * Returns null if not found or denied.
72
+ */
73
+ export function getKeychainPassword(ssid) {
74
+ if (process.platform !== 'darwin')
75
+ return null;
76
+ try {
77
+ const output = execSync(`security find-generic-password -ga "${ssid.replace(/"/g, '\\"')}" -w 2>/dev/null`, { encoding: 'utf-8', timeout: 10000 }).trim();
78
+ return output || null;
79
+ }
80
+ catch {
81
+ return null;
82
+ }
83
+ }
84
+ //# sourceMappingURL=wifi-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wifi-config.js","sourceRoot":"","sources":["../src/wifi-config.ts"],"names":[],"mappings":"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"}
@@ -4,11 +4,23 @@ import type { BridgeEvent, PluginCommand } from './types.js';
4
4
  export declare class WsServer {
5
5
  private wss;
6
6
  private commandCallback;
7
+ private rawMessageCallback;
7
8
  private onConnectCallback;
8
9
  private onDisconnectCallback;
10
+ private clientAlive;
11
+ private pingTimer;
9
12
  constructor(server: Server);
13
+ private broadcastHooks;
14
+ /** Register a hook that gets called on every broadcast (e.g., ESP32 serial relay). */
15
+ onBroadcast(hook: (event: BridgeEvent) => void): void;
10
16
  broadcast(event: BridgeEvent): void;
11
17
  onCommand(callback: (cmd: PluginCommand) => void): void;
18
+ /** Inject a command from a non-WS source (e.g., D200H agent via stdout/stdin pipe). */
19
+ dispatchCommand(cmd: PluginCommand): void;
20
+ /** Register a callback for raw messages before PluginCommand dispatch. Return true to consume. */
21
+ onRawMessage(callback: (msg: Record<string, unknown>, sender: WebSocket) => boolean): void;
22
+ /** Broadcast to all clients except the sender */
23
+ broadcastExcept(event: BridgeEvent, except: WebSocket): void;
12
24
  onClientConnect(callback: (ws: WebSocket) => void): void;
13
25
  onClientDisconnect(callback: () => void): void;
14
26
  sendTo(ws: WebSocket, event: BridgeEvent): void;
@@ -1 +1 @@
1
- {"version":3,"file":"ws-server.d.ts","sourceRoot":"","sources":["../src/ws-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,SAAS,EAAE,MAAM,IAAI,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,EAAmB,MAAM,MAAM,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAI7D,qBAAa,QAAQ;IACnB,OAAO,CAAC,GAAG,CAAkB;IAC7B,OAAO,CAAC,eAAe,CAA+C;IACtE,OAAO,CAAC,iBAAiB,CAA0C;IACnE,OAAO,CAAC,oBAAoB,CAA6B;gBAE7C,MAAM,EAAE,MAAM;IAiD1B,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAWnC,SAAS,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,IAAI,GAAG,IAAI;IAIvD,eAAe,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,SAAS,KAAK,IAAI,GAAG,IAAI;IAIxD,kBAAkB,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAI9C,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI;IAM/C,cAAc,IAAI,MAAM;IAIxB,KAAK,IAAI,IAAI;CAMd"}
1
+ {"version":3,"file":"ws-server.d.ts","sourceRoot":"","sources":["../src/ws-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,SAAS,EAAE,MAAM,IAAI,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,EAAmB,MAAM,MAAM,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAK7D,qBAAa,QAAQ;IACnB,OAAO,CAAC,GAAG,CAAkB;IAC7B,OAAO,CAAC,eAAe,CAA+C;IACtE,OAAO,CAAC,kBAAkB,CAA+E;IACzG,OAAO,CAAC,iBAAiB,CAA0C;IACnE,OAAO,CAAC,oBAAoB,CAA6B;IACzD,OAAO,CAAC,WAAW,CAAiC;IACpD,OAAO,CAAC,SAAS,CAAiC;gBAEtC,MAAM,EAAE,MAAM;IAqF1B,OAAO,CAAC,cAAc,CAA2C;IAEjE,sFAAsF;IACtF,WAAW,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,GAAG,IAAI;IAIrD,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAenC,SAAS,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,IAAI,GAAG,IAAI;IAIvD,uFAAuF;IACvF,eAAe,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI;IAIzC,kGAAkG;IAClG,YAAY,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,SAAS,KAAK,OAAO,GAAG,IAAI;IAI1F,iDAAiD;IACjD,eAAe,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,GAAG,IAAI;IAS5D,eAAe,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,SAAS,KAAK,IAAI,GAAG,IAAI;IAIxD,kBAAkB,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAI9C,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI;IAM/C,cAAc,IAAI,MAAM;IAIxB,KAAK,IAAI,IAAI;CASd"}
package/dist/ws-server.js CHANGED
@@ -1,13 +1,41 @@
1
1
  import { WebSocketServer, WebSocket } from 'ws';
2
2
  import { isLocalConnection, validateToken } from './auth.js';
3
3
  import { debug } from './logger.js';
4
+ import { WS_PING_INTERVAL_MS } from '@agentdeck/shared';
4
5
  export class WsServer {
5
6
  wss;
6
7
  commandCallback = null;
8
+ rawMessageCallback = null;
7
9
  onConnectCallback = null;
8
10
  onDisconnectCallback = null;
11
+ clientAlive = new Map();
12
+ pingTimer;
9
13
  constructor(server) {
10
14
  this.wss = new WebSocketServer({ server });
15
+ // Catch server-level errors (e.g., upgrade failures, internal ws errors)
16
+ // Without this handler, EventEmitter throws synchronously → process dies
17
+ this.wss.on('error', (err) => {
18
+ debug('WS', `WebSocketServer error: ${err}`);
19
+ });
20
+ // Server-side ping/pong to detect zombie connections
21
+ this.pingTimer = setInterval(() => {
22
+ const dead = [];
23
+ for (const ws of this.wss.clients) {
24
+ if (this.clientAlive.get(ws) === false) {
25
+ dead.push(ws);
26
+ continue;
27
+ }
28
+ this.clientAlive.set(ws, false);
29
+ ws.ping();
30
+ }
31
+ // Terminate outside iteration — ws.terminate() synchronously removes
32
+ // the client from wss.clients Set, which would corrupt the iterator.
33
+ for (const ws of dead) {
34
+ debug('WS', 'Terminating unresponsive client');
35
+ this.clientAlive.delete(ws);
36
+ ws.terminate();
37
+ }
38
+ }, WS_PING_INTERVAL_MS);
11
39
  this.wss.on('connection', (ws, req) => {
12
40
  // Token auth for remote connections
13
41
  const remoteIp = req.socket.remoteAddress || '';
@@ -22,14 +50,22 @@ export class WsServer {
22
50
  debug('WS', `Remote client authenticated from ${remoteIp}`);
23
51
  }
24
52
  debug('WS', 'Plugin connected');
53
+ this.clientAlive.set(ws, true);
25
54
  // Send current state to newly connected client
26
55
  if (this.onConnectCallback) {
27
56
  this.onConnectCallback(ws);
28
57
  }
58
+ ws.on('pong', () => {
59
+ this.clientAlive.set(ws, true);
60
+ });
29
61
  ws.on('message', (data) => {
30
62
  try {
31
63
  const msg = JSON.parse(data.toString());
32
64
  debug('WS', `recv cmd: ${msg.type}`);
65
+ // Allow raw message callback to intercept relay events (e.g. deck_slot_map)
66
+ if (this.rawMessageCallback && this.rawMessageCallback(msg, ws)) {
67
+ return; // handled
68
+ }
33
69
  if (this.commandCallback) {
34
70
  this.commandCallback(msg);
35
71
  }
@@ -40,6 +76,7 @@ export class WsServer {
40
76
  });
41
77
  ws.on('close', () => {
42
78
  debug('WS', 'Plugin disconnected');
79
+ this.clientAlive.delete(ws);
43
80
  if (this.onDisconnectCallback) {
44
81
  this.onDisconnectCallback();
45
82
  }
@@ -49,19 +86,54 @@ export class WsServer {
49
86
  });
50
87
  });
51
88
  }
89
+ broadcastHooks = [];
90
+ /** Register a hook that gets called on every broadcast (e.g., ESP32 serial relay). */
91
+ onBroadcast(hook) {
92
+ this.broadcastHooks.push(hook);
93
+ }
52
94
  broadcast(event) {
53
95
  const payload = JSON.stringify(event);
54
96
  const clientCount = this.wss.clients.size;
55
97
  debug('WS', `broadcast(${event.type}) to ${clientCount} clients`);
56
98
  for (const client of this.wss.clients) {
57
99
  if (client.readyState === WebSocket.OPEN) {
58
- client.send(payload);
100
+ try {
101
+ client.send(payload);
102
+ }
103
+ catch { /* client disconnecting */ }
104
+ }
105
+ }
106
+ // Relay to registered hooks (ESP32 serial, etc.)
107
+ for (const hook of this.broadcastHooks) {
108
+ try {
109
+ hook(event);
59
110
  }
111
+ catch { /* best-effort */ }
60
112
  }
61
113
  }
62
114
  onCommand(callback) {
63
115
  this.commandCallback = callback;
64
116
  }
117
+ /** Inject a command from a non-WS source (e.g., D200H agent via stdout/stdin pipe). */
118
+ dispatchCommand(cmd) {
119
+ this.commandCallback?.(cmd);
120
+ }
121
+ /** Register a callback for raw messages before PluginCommand dispatch. Return true to consume. */
122
+ onRawMessage(callback) {
123
+ this.rawMessageCallback = callback;
124
+ }
125
+ /** Broadcast to all clients except the sender */
126
+ broadcastExcept(event, except) {
127
+ const payload = JSON.stringify(event);
128
+ for (const client of this.wss.clients) {
129
+ if (client !== except && client.readyState === WebSocket.OPEN) {
130
+ try {
131
+ client.send(payload);
132
+ }
133
+ catch { /* client disconnecting */ }
134
+ }
135
+ }
136
+ }
65
137
  onClientConnect(callback) {
66
138
  this.onConnectCallback = callback;
67
139
  }
@@ -70,14 +142,20 @@ export class WsServer {
70
142
  }
71
143
  sendTo(ws, event) {
72
144
  if (ws.readyState === WebSocket.OPEN) {
73
- ws.send(JSON.stringify(event));
145
+ try {
146
+ ws.send(JSON.stringify(event));
147
+ }
148
+ catch { /* client disconnecting */ }
74
149
  }
75
150
  }
76
151
  getClientCount() {
77
152
  return this.wss.clients.size;
78
153
  }
79
154
  close() {
80
- for (const client of this.wss.clients) {
155
+ clearInterval(this.pingTimer);
156
+ this.clientAlive.clear();
157
+ // Spread to array — client.close() modifies wss.clients Set
158
+ for (const client of [...this.wss.clients]) {
81
159
  client.close();
82
160
  }
83
161
  this.wss.close();
@@ -1 +1 @@
1
- {"version":3,"file":"ws-server.js","sourceRoot":"","sources":["../src/ws-server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ws-server.js","sourceRoot":"","sources":["../src/ws-server.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentdeck/bridge",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -14,30 +14,39 @@
14
14
  ],
15
15
  "main": "./dist/index.js",
16
16
  "bin": {
17
- "sdc": "./dist/index.js"
17
+ "agentdeck": "./dist/cli.js"
18
18
  },
19
19
  "dependencies": {
20
20
  "bonjour-service": "^1.3.0",
21
- "commander": "^12.0.0",
22
- "express": "^4.21.0",
23
- "node-pty": "^1.0.0",
21
+ "commander": "^14.0.3",
22
+ "express": "^5.2.1",
24
23
  "qrcode": "^1.5.4",
25
- "strip-ansi": "^7.1.0",
26
- "ws": "^8.18.0",
27
- "@agentdeck/shared": "0.1.0"
24
+ "strip-ansi": "^7.2.0",
25
+ "ws": "^8.20.0",
26
+ "@agentdeck/hooks": "0.2.0",
27
+ "@agentdeck/shared": "0.2.0"
28
28
  },
29
+ "optionalDependencies": {
30
+ "@picovoice/porcupine-node": "^4.0.2",
31
+ "@picovoice/pvrecorder-node": "^1.2.8",
32
+ "@resvg/resvg-js": "^2.6.2",
33
+ "better-sqlite3": "^12.9.0",
34
+ "node-hid": "^3.3.0",
35
+ "node-pty": "^1.1.0"
36
+ },
37
+ "compatibleClaudeCode": ">=2.1.50",
29
38
  "devDependencies": {
30
- "@types/express": "^4.17.21",
31
- "@types/node": "^20.14.0",
39
+ "@types/express": "^5.0.6",
40
+ "@types/node": "^25.6.0",
32
41
  "@types/qrcode": "^1.5.6",
33
- "@types/ws": "^8.5.12",
34
- "typescript": "^5.5.0"
42
+ "@types/ws": "^8.18.1",
43
+ "typescript": "^6.0.3"
35
44
  },
36
45
  "scripts": {
37
46
  "build": "tsc",
38
47
  "dev": "tsc --watch",
39
48
  "clean": "rm -rf dist",
40
49
  "typecheck": "tsc --noEmit",
41
- "start": "node dist/index.js"
50
+ "start": "node dist/cli.js claude"
42
51
  }
43
52
  }