@agentdeck/bridge 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/assets/fm-helper/agentdeck-fm-helper +0 -0
  2. package/dist/apme/collector.d.ts.map +1 -1
  3. package/dist/apme/collector.js +5 -2
  4. package/dist/apme/collector.js.map +1 -1
  5. package/dist/apme/runner.d.ts +11 -0
  6. package/dist/apme/runner.d.ts.map +1 -1
  7. package/dist/apme/runner.js +60 -4
  8. package/dist/apme/runner.js.map +1 -1
  9. package/dist/apme/settings.d.ts +10 -0
  10. package/dist/apme/settings.d.ts.map +1 -1
  11. package/dist/apme/settings.js +14 -0
  12. package/dist/apme/settings.js.map +1 -1
  13. package/dist/awaiting-overlay.d.ts +44 -10
  14. package/dist/awaiting-overlay.d.ts.map +1 -1
  15. package/dist/awaiting-overlay.js +96 -28
  16. package/dist/awaiting-overlay.js.map +1 -1
  17. package/dist/bridge-core.d.ts +10 -0
  18. package/dist/bridge-core.d.ts.map +1 -1
  19. package/dist/bridge-core.js +47 -12
  20. package/dist/bridge-core.js.map +1 -1
  21. package/dist/card-feed.d.ts +107 -0
  22. package/dist/card-feed.d.ts.map +1 -0
  23. package/dist/card-feed.js +277 -0
  24. package/dist/card-feed.js.map +1 -0
  25. package/dist/card-modules.d.ts +87 -0
  26. package/dist/card-modules.d.ts.map +1 -0
  27. package/dist/card-modules.js +179 -0
  28. package/dist/card-modules.js.map +1 -0
  29. package/dist/cli.d.ts.map +1 -1
  30. package/dist/cli.js +93 -0
  31. package/dist/cli.js.map +1 -1
  32. package/dist/daemon-server.d.ts.map +1 -1
  33. package/dist/daemon-server.js +1025 -50
  34. package/dist/daemon-server.js.map +1 -1
  35. package/dist/daemon-ws-client.d.ts +2 -1
  36. package/dist/daemon-ws-client.d.ts.map +1 -1
  37. package/dist/daemon-ws-client.js +2 -1
  38. package/dist/daemon-ws-client.js.map +1 -1
  39. package/dist/daemon.js +1 -1
  40. package/dist/device-photo.d.ts +86 -0
  41. package/dist/device-photo.d.ts.map +1 -0
  42. package/dist/device-photo.js +200 -0
  43. package/dist/device-photo.js.map +1 -0
  44. package/dist/device-voice-reply.d.ts +124 -0
  45. package/dist/device-voice-reply.d.ts.map +1 -0
  46. package/dist/device-voice-reply.js +236 -0
  47. package/dist/device-voice-reply.js.map +1 -0
  48. package/dist/device-voice.d.ts +56 -0
  49. package/dist/device-voice.d.ts.map +1 -0
  50. package/dist/device-voice.js +134 -0
  51. package/dist/device-voice.js.map +1 -0
  52. package/dist/esp32-serial.d.ts +40 -0
  53. package/dist/esp32-serial.d.ts.map +1 -1
  54. package/dist/esp32-serial.js +109 -13
  55. package/dist/esp32-serial.js.map +1 -1
  56. package/dist/foundation-models-helper.d.ts +30 -0
  57. package/dist/foundation-models-helper.d.ts.map +1 -1
  58. package/dist/foundation-models-helper.js +45 -0
  59. package/dist/foundation-models-helper.js.map +1 -1
  60. package/dist/index.js +2 -2
  61. package/dist/index.js.map +1 -1
  62. package/dist/mdns.d.ts +11 -0
  63. package/dist/mdns.d.ts.map +1 -1
  64. package/dist/mdns.js +13 -0
  65. package/dist/mdns.js.map +1 -1
  66. package/dist/observed-inject.d.ts +119 -0
  67. package/dist/observed-inject.d.ts.map +1 -0
  68. package/dist/observed-inject.js +405 -0
  69. package/dist/observed-inject.js.map +1 -0
  70. package/dist/passive-observer.d.ts +14 -0
  71. package/dist/passive-observer.d.ts.map +1 -1
  72. package/dist/passive-observer.js +35 -5
  73. package/dist/passive-observer.js.map +1 -1
  74. package/dist/peripheral-mapping.d.ts +65 -0
  75. package/dist/peripheral-mapping.d.ts.map +1 -0
  76. package/dist/peripheral-mapping.js +115 -0
  77. package/dist/peripheral-mapping.js.map +1 -0
  78. package/dist/session-aggregator.d.ts +4 -1
  79. package/dist/session-aggregator.d.ts.map +1 -1
  80. package/dist/session-aggregator.js +5 -5
  81. package/dist/session-aggregator.js.map +1 -1
  82. package/dist/session-id-resolve.d.ts +17 -0
  83. package/dist/session-id-resolve.d.ts.map +1 -0
  84. package/dist/session-id-resolve.js +35 -0
  85. package/dist/session-id-resolve.js.map +1 -0
  86. package/dist/session-registry.d.ts +12 -0
  87. package/dist/session-registry.d.ts.map +1 -1
  88. package/dist/session-registry.js +31 -0
  89. package/dist/session-registry.js.map +1 -1
  90. package/dist/session-transcript-timeline.d.ts +7 -0
  91. package/dist/session-transcript-timeline.d.ts.map +1 -1
  92. package/dist/session-transcript-timeline.js +16 -6
  93. package/dist/session-transcript-timeline.js.map +1 -1
  94. package/dist/timeline-store.js +2 -2
  95. package/dist/timeline-store.js.map +1 -1
  96. package/dist/usage-event.d.ts.map +1 -1
  97. package/dist/usage-event.js +14 -7
  98. package/dist/usage-event.js.map +1 -1
  99. package/dist/voice.d.ts +13 -10
  100. package/dist/voice.d.ts.map +1 -1
  101. package/dist/voice.js +26 -272
  102. package/dist/voice.js.map +1 -1
  103. package/dist/ws-server.d.ts +14 -0
  104. package/dist/ws-server.d.ts.map +1 -1
  105. package/dist/ws-server.js +66 -1
  106. package/dist/ws-server.js.map +1 -1
  107. package/fm-helper/AgentDeckFMHelper.swift +303 -0
  108. package/package.json +3 -3
  109. package/dist/d200h/hid-protocol.d.ts +0 -62
  110. package/dist/d200h/hid-protocol.d.ts.map +0 -1
  111. package/dist/d200h/hid-protocol.js +0 -124
  112. package/dist/d200h/hid-protocol.js.map +0 -1
  113. package/dist/d200h/image-renderer.d.ts +0 -24
  114. package/dist/d200h/image-renderer.d.ts.map +0 -1
  115. package/dist/d200h/image-renderer.js +0 -321
  116. package/dist/d200h/image-renderer.js.map +0 -1
  117. package/dist/hook-migration.d.ts +0 -2
  118. package/dist/hook-migration.d.ts.map +0 -1
  119. package/dist/hook-migration.js +0 -104
  120. package/dist/hook-migration.js.map +0 -1
  121. package/dist/modules/d200h-module.d.ts +0 -65
  122. package/dist/modules/d200h-module.d.ts.map +0 -1
  123. package/dist/modules/d200h-module.js +0 -495
  124. package/dist/modules/d200h-module.js.map +0 -1
  125. package/dist/modules/d200h-renderer.d.ts +0 -7
  126. package/dist/modules/d200h-renderer.d.ts.map +0 -1
  127. package/dist/modules/d200h-renderer.js +0 -321
  128. package/dist/modules/d200h-renderer.js.map +0 -1
  129. package/dist/modules/trmnl-module.d.ts +0 -38
  130. package/dist/modules/trmnl-module.d.ts.map +0 -1
  131. package/dist/modules/trmnl-module.js +0 -111
  132. package/dist/modules/trmnl-module.js.map +0 -1
  133. package/dist/trmnl/byos-server.d.ts +0 -39
  134. package/dist/trmnl/byos-server.d.ts.map +0 -1
  135. package/dist/trmnl/byos-server.js +0 -301
  136. package/dist/trmnl/byos-server.js.map +0 -1
  137. package/dist/trmnl/frame-cache.d.ts +0 -37
  138. package/dist/trmnl/frame-cache.d.ts.map +0 -1
  139. package/dist/trmnl/frame-cache.js +0 -157
  140. package/dist/trmnl/frame-cache.js.map +0 -1
  141. package/dist/trmnl/image-renderer.d.ts +0 -27
  142. package/dist/trmnl/image-renderer.d.ts.map +0 -1
  143. package/dist/trmnl/image-renderer.js +0 -235
  144. package/dist/trmnl/image-renderer.js.map +0 -1
  145. package/dist/trmnl/trmnl-settings.d.ts +0 -96
  146. package/dist/trmnl/trmnl-settings.d.ts.map +0 -1
  147. package/dist/trmnl/trmnl-settings.js +0 -177
  148. package/dist/trmnl/trmnl-settings.js.map +0 -1
  149. package/dist/trmnl/trmnl-telemetry.d.ts +0 -47
  150. package/dist/trmnl/trmnl-telemetry.d.ts.map +0 -1
  151. package/dist/trmnl/trmnl-telemetry.js +0 -56
  152. package/dist/trmnl/trmnl-telemetry.js.map +0 -1
  153. package/dist/whisper-server-manager.d.ts +0 -19
  154. package/dist/whisper-server-manager.d.ts.map +0 -1
  155. package/dist/whisper-server-manager.js +0 -171
  156. package/dist/whisper-server-manager.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"daemon-ws-client.d.ts","sourceRoot":"","sources":["../src/daemon-ws-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AASH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,oBAAoB,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,uBAAuB,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,cAAc;IASvB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;IAC3B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;IAC7B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;IAxBhC,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,UAAU,CAAS;gBAGR,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,YAAA,EAClB,WAAW,CAAC,EAAE,MAAM,YAAA;IACrC;;;;;;;;;;;OAWG;IACc,YAAY,CAAC,GAAE,MAAM,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,aAAA;IAG9E;;;;OAIG;IACH,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAUxC,kCAAkC;IAClC,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;IAcxE,qBAAqB;IACrB,KAAK,IAAI,IAAI;IAcb,IAAI,WAAW,IAAI,OAAO,CAEzB;YAIa,SAAS;IA4DvB,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,iBAAiB;CAS1B"}
1
+ {"version":3,"file":"daemon-ws-client.d.ts","sourceRoot":"","sources":["../src/daemon-ws-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AASH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,oBAAoB,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,uBAAuB,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,cAAc;IASvB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;IAC3B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;IAC7B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;IAxBhC,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,UAAU,CAAS;gBAGR,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,YAAA,EAClB,WAAW,CAAC,EAAE,MAAM,YAAA;IACrC;;;;;;;;;;;OAWG;IACc,YAAY,CAAC,GAAE,MAAM,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,aAAA;IAG9E;;;;OAIG;IACH,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAUxC,kCAAkC;IAClC,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI;IAejG,qBAAqB;IACrB,KAAK,IAAI,IAAI;IAcb,IAAI,WAAW,IAAI,OAAO,CAEzB;YAIa,SAAS;IA4DvB,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,iBAAiB;CAS1B"}
@@ -64,7 +64,7 @@ export class DaemonWsClient {
64
64
  }
65
65
  }
66
66
  /** Push state update to daemon */
67
- pushState(state, modelName, effortLevel) {
67
+ pushState(state, modelName, effortLevel, permissionMode) {
68
68
  if (!this.ws || this.ws.readyState !== WebSocket.OPEN)
69
69
  return;
70
70
  const msg = {
@@ -73,6 +73,7 @@ export class DaemonWsClient {
73
73
  state,
74
74
  modelName,
75
75
  effortLevel,
76
+ permissionMode,
76
77
  projectName: this.projectName,
77
78
  agentType: this.agentType,
78
79
  };
@@ -1 +1 @@
1
- {"version":3,"file":"daemon-ws-client.js","sourceRoot":"","sources":["../src/daemon-ws-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,SAAS,MAAM,IAAI,CAAC;AAC3B,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEpC,MAAM,GAAG,GAAG,gBAAgB,CAAC;AAC7B,MAAM,cAAc,GAAG,IAAI,CAAC;AAC5B,MAAM,aAAa,GAAG,KAAK,CAAC;AAoB5B,MAAM,OAAO,cAAc;IASN;IACA;IACA;IACA;IAaA;IAxBX,EAAE,GAAqB,IAAI,CAAC;IAC5B,UAAU,GAAkB,IAAI,CAAC;IACjC,cAAc,GAAyC,IAAI,CAAC;IAC5D,cAAc,GAAG,cAAc,CAAC;IAChC,MAAM,GAAG,KAAK,CAAC;IACf,UAAU,GAAG,KAAK,CAAC;IAE3B,YACmB,SAAiB,EACjB,WAAmB,EACnB,SAAkB,EAClB,WAAoB;IACrC;;;;;;;;;;;OAWG;IACc,YAA2D;QAhB3D,cAAS,GAAT,SAAS,CAAQ;QACjB,gBAAW,GAAX,WAAW,CAAQ;QACnB,cAAS,GAAT,SAAS,CAAS;QAClB,gBAAW,GAAX,WAAW,CAAS;QAapB,iBAAY,GAAZ,YAAY,CAA+C;IAC3E,CAAC;IAEJ;;;;OAIG;IACH,OAAO,CAAC,UAAyB;QAC/B,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO;QACxB,IAAI,UAAU,IAAI,IAAI,EAAE,CAAC;YACvB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;YAC7B,KAAK,IAAI,CAAC,SAAS,EAAE,CAAC;QACxB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,kCAAkC;IAClC,SAAS,CAAC,KAAa,EAAE,SAAkB,EAAE,WAAoB;QAC/D,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI;YAAE,OAAO;QAC9D,MAAM,GAAG,GAAqB;YAC5B,IAAI,EAAE,oBAAoB;YAC1B,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,KAAK;YACL,SAAS;YACT,WAAW;YACX,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC;QACF,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;IACpC,CAAC;IAED,qBAAqB;IACrB,KAAK;QACH,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAClC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC7B,CAAC;QACD,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,CAAC,UAAU,GAAG,KAAK,CAAC;IAC1B,CAAC;IAED,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,EAAE,EAAE,UAAU,KAAK,SAAS,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC;IACnE,CAAC;IAED,sBAAsB;IAEd,KAAK,CAAC,SAAS;QACrB,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO;QACxB,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,IAAI,QAAuB,CAAC;YAC5B,IAAI,CAAC;gBACH,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;YACvC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,KAAK,CAAC,GAAG,EAAE,uBAAuB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACtF,QAAQ,GAAG,IAAI,CAAC;YAClB,CAAC;YACD,IAAI,IAAI,CAAC,MAAM;gBAAE,OAAO;YACxB,IAAI,QAAQ,IAAI,IAAI,IAAI,QAAQ,KAAK,IAAI,CAAC,UAAU,EAAE,CAAC;gBACrD,KAAK,CAAC,GAAG,EAAE,wBAAwB,IAAI,CAAC,UAAU,IAAI,MAAM,MAAM,QAAQ,EAAE,CAAC,CAAC;gBAC9E,IAAI,CAAC,UAAU,GAAG,QAAQ,CAAC;YAC7B,CAAC;QACH,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACrB,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACzB,OAAO;QACT,CAAC;QACD,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;YACZ,IAAI,CAAC,EAAE,CAAC,kBAAkB,EAAE,CAAC;YAC7B,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;QAClB,CAAC;QAED,MAAM,GAAG,GAAG,kBAAkB,IAAI,CAAC,UAAU,EAAE,CAAC;QAChD,KAAK,CAAC,GAAG,EAAE,2BAA2B,GAAG,EAAE,CAAC,CAAC;QAE7C,IAAI,CAAC,EAAE,GAAG,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC;QAE7B,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;YACtB,KAAK,CAAC,GAAG,EAAE,uBAAuB,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;YACrD,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;YACrC,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACvB,KAAK,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC;YAC/B,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;YACxB,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC3B,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YAC1B,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YACvC,oCAAoC;QACtC,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE;YAC7B,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;gBACxC,IAAI,GAAG,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;oBACpC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;oBACvB,KAAK,CAAC,GAAG,EAAE,2BAA2B,CAAC,CAAC;gBAC1C,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,oCAAoC;YACtC,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,YAAY;QAClB,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI;YAAE,OAAO;QAC9D,MAAM,GAAG,GAAwB;YAC/B,IAAI,EAAE,uBAAuB;YAC7B,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,IAAI,EAAE,IAAI,CAAC,WAAW;YACtB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,WAAW,EAAE,IAAI,CAAC,WAAW;SAC9B,CAAC;QACF,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;IACpC,CAAC;IAEO,iBAAiB;QACvB,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,cAAc;YAAE,OAAO;QAC/C,KAAK,CAAC,GAAG,EAAE,mBAAmB,IAAI,CAAC,cAAc,IAAI,CAAC,CAAC;QACvD,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC,GAAG,EAAE;YACpC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;YAC3B,KAAK,IAAI,CAAC,SAAS,EAAE,CAAC;QACxB,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;QACxB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,GAAG,GAAG,EAAE,aAAa,CAAC,CAAC;IAC3E,CAAC;CACF"}
1
+ {"version":3,"file":"daemon-ws-client.js","sourceRoot":"","sources":["../src/daemon-ws-client.ts"],"names":[],"mappings":"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"}
package/dist/daemon.js CHANGED
@@ -17,7 +17,7 @@ const program = new Command();
17
17
  program
18
18
  .name('agentdeck')
19
19
  .description('AgentDeck daemon (legacy entry point — use `agentdeck daemon` instead)')
20
- .version('1.0.1');
20
+ .version('1.0.3');
21
21
  program
22
22
  .command('start', { isDefault: true })
23
23
  .description('Start monitoring daemon')
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Device-sourced photos: a board captures a JPEG (T-Display-S3-Pro rear
3
+ * camera) and the daemon turns it into a prompt for the session the board was
4
+ * pointing at — "show-and-tell" for coding agents: snap a whiteboard, an app
5
+ * screen, an error dialog, and the agent gets a file path it can read.
6
+ *
7
+ * Wire shape (per WS connection), mirroring device-voice:
8
+ * {"type":"photo_begin","format":"jpeg","width":…,"height":…,"sessionId":…}
9
+ * <binary frames: raw JPEG bytes>
10
+ * {"type":"photo_end","bytes":…,"cancel":false}
11
+ * Serial transport wraps the same bytes base64 in `photo_chunk` lines.
12
+ *
13
+ * Binary frames carry no envelope, so they are attributed to whichever socket
14
+ * has an open capture — hence the per-connection state here. A connection may
15
+ * hold an open voice utterance OR an open photo, never both; the daemon's
16
+ * onBinary router offers the frame to each collector in turn.
17
+ *
18
+ * Unlike a voice WAV (deleted after transcription), the JPEG must outlive this
19
+ * module: the prompt references the path and the agent reads it seconds or
20
+ * minutes later. Photos land under <dataDir>/photos with a small retention
21
+ * sweep instead of a cleanup callback.
22
+ */
23
+ export interface PhotoCapture {
24
+ sessionId: string;
25
+ board: string;
26
+ format: string;
27
+ width: number;
28
+ height: number;
29
+ chunks: Buffer[];
30
+ bytes: number;
31
+ startedAt: number;
32
+ truncated: boolean;
33
+ }
34
+ export interface PhotoCaptureResult {
35
+ sessionId: string;
36
+ board: string;
37
+ path: string;
38
+ bytes: number;
39
+ width: number;
40
+ height: number;
41
+ truncated: boolean;
42
+ }
43
+ export declare function defaultPhotoDir(): string;
44
+ /** Drop the oldest files beyond the retention count. Best-effort. */
45
+ export declare function prunePhotoDir(dir: string, retain?: number): void;
46
+ /**
47
+ * Per-connection photo assembly. One instance per daemon; connections are
48
+ * keyed by whatever opaque handle the server uses for a socket (WS object or
49
+ * serial port string), exactly like DeviceVoiceCollector.
50
+ */
51
+ export declare class DevicePhotoCollector {
52
+ private photoDir;
53
+ private open;
54
+ constructor(photoDir?: string);
55
+ begin(conn: unknown, msg: Record<string, unknown>): void;
56
+ /** True while this connection has an open capture. */
57
+ isOpen(conn: unknown): boolean;
58
+ /** Returns false when no capture is open — the caller should offer the frame
59
+ * to the next collector. */
60
+ append(conn: unknown, data: Buffer): boolean;
61
+ /**
62
+ * Finish the capture: write the JPEG under the photo dir and return its
63
+ * path. Returns null when cancelled, empty, truncated, or nothing was open.
64
+ */
65
+ end(conn: unknown, msg: Record<string, unknown>): PhotoCaptureResult | null;
66
+ /**
67
+ * Save a photo that arrived whole (HTTP POST body) rather than assembled
68
+ * from chunks. Same directory, retention and result shape as end().
69
+ */
70
+ saveDirect(jpeg: Buffer, meta: {
71
+ board: string;
72
+ sessionId: string;
73
+ width: number;
74
+ height: number;
75
+ }): PhotoCaptureResult;
76
+ /** Drop a capture whose socket died mid-stream. */
77
+ abandon(conn: unknown): void;
78
+ /**
79
+ * Reap captures whose photo_end never arrived. Returns the reaped
80
+ * connections so the caller can tell each board its shutter press died —
81
+ * a silently expired capture left the strip showing "sending" forever.
82
+ */
83
+ sweep(now?: number): unknown[];
84
+ get openCount(): number;
85
+ }
86
+ //# sourceMappingURL=device-photo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-photo.d.ts","sourceRoot":"","sources":["../src/device-photo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAeH,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED,qEAAqE;AACrE,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,SAAe,GAAG,IAAI,CActE;AAED;;;;GAIG;AACH,qBAAa,oBAAoB;IAGnB,OAAO,CAAC,QAAQ;IAF5B,OAAO,CAAC,IAAI,CAAoC;gBAE5B,QAAQ,GAAE,MAA0B;IAExD,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAgBxD,sDAAsD;IACtD,MAAM,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO;IAI9B;iCAC6B;IAC7B,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO;IAe5C;;;OAGG;IACH,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,kBAAkB,GAAG,IAAI;IAyC3E;;;OAGG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;QAC7B,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;KACjE,GAAG,kBAAkB;IAkBtB,mDAAmD;IACnD,OAAO,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAI5B;;;;OAIG;IACH,KAAK,CAAC,GAAG,SAAa,GAAG,OAAO,EAAE;IAYlC,IAAI,SAAS,IAAI,MAAM,CAEtB;CACF"}
@@ -0,0 +1,200 @@
1
+ /**
2
+ * Device-sourced photos: a board captures a JPEG (T-Display-S3-Pro rear
3
+ * camera) and the daemon turns it into a prompt for the session the board was
4
+ * pointing at — "show-and-tell" for coding agents: snap a whiteboard, an app
5
+ * screen, an error dialog, and the agent gets a file path it can read.
6
+ *
7
+ * Wire shape (per WS connection), mirroring device-voice:
8
+ * {"type":"photo_begin","format":"jpeg","width":…,"height":…,"sessionId":…}
9
+ * <binary frames: raw JPEG bytes>
10
+ * {"type":"photo_end","bytes":…,"cancel":false}
11
+ * Serial transport wraps the same bytes base64 in `photo_chunk` lines.
12
+ *
13
+ * Binary frames carry no envelope, so they are attributed to whichever socket
14
+ * has an open capture — hence the per-connection state here. A connection may
15
+ * hold an open voice utterance OR an open photo, never both; the daemon's
16
+ * onBinary router offers the frame to each collector in turn.
17
+ *
18
+ * Unlike a voice WAV (deleted after transcription), the JPEG must outlive this
19
+ * module: the prompt references the path and the agent reads it seconds or
20
+ * minutes later. Photos land under <dataDir>/photos with a small retention
21
+ * sweep instead of a cleanup callback.
22
+ */
23
+ import { mkdirSync, writeFileSync, readdirSync, statSync, rmSync } from 'fs';
24
+ import { homedir } from 'os';
25
+ import { join } from 'path';
26
+ import { debug } from './logger.js';
27
+ /** Refuse to buffer more than one plausible photo. VGA-class JPEGs are tens of
28
+ * KB; a 5 MP OV5640 shield tops out around 1–2 MB. */
29
+ const MAX_PHOTO_BYTES = 4 * 1024 * 1024;
30
+ /** A capture whose photo_end never arrives (board reboot, WiFi drop). */
31
+ const CAPTURE_TTL_MS = 60_000;
32
+ /** Keep this many photos; older ones are pruned on each save. */
33
+ const RETAIN_COUNT = 40;
34
+ export function defaultPhotoDir() {
35
+ return join(process.env.AGENTDECK_DATA_DIR || join(homedir(), '.agentdeck'), 'photos');
36
+ }
37
+ /** Drop the oldest files beyond the retention count. Best-effort. */
38
+ export function prunePhotoDir(dir, retain = RETAIN_COUNT) {
39
+ try {
40
+ const files = readdirSync(dir)
41
+ .filter((f) => f.endsWith('.jpg'))
42
+ .map((f) => {
43
+ const p = join(dir, f);
44
+ try {
45
+ return { p, mtime: statSync(p).mtimeMs };
46
+ }
47
+ catch {
48
+ return null;
49
+ }
50
+ })
51
+ .filter((x) => x !== null)
52
+ .sort((a, b) => b.mtime - a.mtime);
53
+ for (const f of files.slice(retain)) {
54
+ try {
55
+ rmSync(f.p, { force: true });
56
+ }
57
+ catch { /* best effort */ }
58
+ }
59
+ }
60
+ catch { /* dir missing — nothing to prune */ }
61
+ }
62
+ /**
63
+ * Per-connection photo assembly. One instance per daemon; connections are
64
+ * keyed by whatever opaque handle the server uses for a socket (WS object or
65
+ * serial port string), exactly like DeviceVoiceCollector.
66
+ */
67
+ export class DevicePhotoCollector {
68
+ photoDir;
69
+ open = new Map();
70
+ constructor(photoDir = defaultPhotoDir()) {
71
+ this.photoDir = photoDir;
72
+ }
73
+ begin(conn, msg) {
74
+ this.open.set(conn, {
75
+ sessionId: typeof msg.sessionId === 'string' ? msg.sessionId : '',
76
+ board: typeof msg.board === 'string' ? msg.board : 'esp32',
77
+ format: typeof msg.format === 'string' && msg.format ? msg.format : 'jpeg',
78
+ width: typeof msg.width === 'number' ? msg.width : 0,
79
+ height: typeof msg.height === 'number' ? msg.height : 0,
80
+ chunks: [],
81
+ bytes: 0,
82
+ startedAt: Date.now(),
83
+ truncated: false,
84
+ });
85
+ debug('photo', `capture begin (${String(msg.width ?? '?')}x${String(msg.height ?? '?')}, `
86
+ + `session ${String(msg.sessionId ?? '').slice(0, 20)})`);
87
+ }
88
+ /** True while this connection has an open capture. */
89
+ isOpen(conn) {
90
+ return this.open.has(conn);
91
+ }
92
+ /** Returns false when no capture is open — the caller should offer the frame
93
+ * to the next collector. */
94
+ append(conn, data) {
95
+ const c = this.open.get(conn);
96
+ if (!c)
97
+ return false;
98
+ if (c.bytes + data.length > MAX_PHOTO_BYTES) {
99
+ // A truncated JPEG is undecodable (unlike truncated PCM), so mark it and
100
+ // let end() refuse — but keep consuming frames so they don't leak into
101
+ // another collector.
102
+ c.truncated = true;
103
+ return true;
104
+ }
105
+ c.chunks.push(Buffer.from(data));
106
+ c.bytes += data.length;
107
+ return true;
108
+ }
109
+ /**
110
+ * Finish the capture: write the JPEG under the photo dir and return its
111
+ * path. Returns null when cancelled, empty, truncated, or nothing was open.
112
+ */
113
+ end(conn, msg) {
114
+ const c = this.open.get(conn);
115
+ this.open.delete(conn);
116
+ if (!c)
117
+ return null;
118
+ if (msg.cancel === true) {
119
+ debug('photo', 'capture cancelled by device');
120
+ return null;
121
+ }
122
+ if (c.bytes === 0) {
123
+ debug('photo', 'capture empty — nothing received');
124
+ return null;
125
+ }
126
+ if (c.truncated) {
127
+ debug('photo', `capture exceeded ${MAX_PHOTO_BYTES} bytes — dropped`);
128
+ return null;
129
+ }
130
+ const claimed = typeof msg.bytes === 'number' ? msg.bytes : undefined;
131
+ if (claimed !== undefined && claimed !== c.bytes) {
132
+ // Frame loss over a flaky link produces a corrupt JPEG; better an
133
+ // explicit failure the board can show than a garbage image prompt.
134
+ debug('photo', `byte mismatch: board sent ${claimed}, received ${c.bytes} — dropped`);
135
+ return null;
136
+ }
137
+ const jpeg = Buffer.concat(c.chunks);
138
+ mkdirSync(this.photoDir, { recursive: true });
139
+ const stamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
140
+ const path = join(this.photoDir, `${stamp}-${c.board}.jpg`);
141
+ writeFileSync(path, jpeg);
142
+ prunePhotoDir(this.photoDir);
143
+ debug('photo', `capture end: ${c.bytes} bytes → ${path}`);
144
+ return {
145
+ sessionId: c.sessionId,
146
+ board: c.board,
147
+ path,
148
+ bytes: c.bytes,
149
+ width: c.width,
150
+ height: c.height,
151
+ truncated: c.truncated,
152
+ };
153
+ }
154
+ /**
155
+ * Save a photo that arrived whole (HTTP POST body) rather than assembled
156
+ * from chunks. Same directory, retention and result shape as end().
157
+ */
158
+ saveDirect(jpeg, meta) {
159
+ mkdirSync(this.photoDir, { recursive: true });
160
+ const stamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
161
+ const path = join(this.photoDir, `${stamp}-${meta.board}.jpg`);
162
+ writeFileSync(path, jpeg);
163
+ prunePhotoDir(this.photoDir);
164
+ debug('photo', `direct upload: ${jpeg.length} bytes → ${path}`);
165
+ return {
166
+ sessionId: meta.sessionId,
167
+ board: meta.board,
168
+ path,
169
+ bytes: jpeg.length,
170
+ width: meta.width,
171
+ height: meta.height,
172
+ truncated: false,
173
+ };
174
+ }
175
+ /** Drop a capture whose socket died mid-stream. */
176
+ abandon(conn) {
177
+ if (this.open.delete(conn))
178
+ debug('photo', 'capture abandoned (socket closed)');
179
+ }
180
+ /**
181
+ * Reap captures whose photo_end never arrived. Returns the reaped
182
+ * connections so the caller can tell each board its shutter press died —
183
+ * a silently expired capture left the strip showing "sending" forever.
184
+ */
185
+ sweep(now = Date.now()) {
186
+ const expired = [];
187
+ for (const [conn, c] of this.open) {
188
+ if (now - c.startedAt > CAPTURE_TTL_MS) {
189
+ this.open.delete(conn);
190
+ expired.push(conn);
191
+ debug('photo', `capture expired without photo_end (${c.bytes} bytes buffered)`);
192
+ }
193
+ }
194
+ return expired;
195
+ }
196
+ get openCount() {
197
+ return this.open.size;
198
+ }
199
+ }
200
+ //# sourceMappingURL=device-photo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-photo.js","sourceRoot":"","sources":["../src/device-photo.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Spoken replies back to the board that asked the question.
3
+ *
4
+ * The mic half of the voice round trip (device → daemon → session) ends with
5
+ * text arriving in a terminal. This is the other half: when the session that
6
+ * was dictated to finishes its turn, the reply is synthesized on the host and
7
+ * streamed to that board's own amplifier. The host's speakers are the wrong
8
+ * output here by construction — the reason to hold a battery-powered board is
9
+ * that you walked away from the desk.
10
+ *
11
+ * Shape of the exchange (WS only; the serial transport has no binary framing):
12
+ * daemon → board {"type":"audio_play_begin","sampleRate":16000,"text":"…"}
13
+ * daemon → board binary frames of PCM16LE
14
+ * daemon → board {"type":"audio_play_end"}
15
+ *
16
+ * The board cannot buffer a whole reply, so frames are paced at roughly
17
+ * playback speed. Sending as fast as the socket allows would overrun a ring
18
+ * buffer measured in seconds and cost the tail of every long answer.
19
+ */
20
+ export interface ReplySink {
21
+ /** Send a JSON control frame. */
22
+ send(data: string): void;
23
+ /** Send one binary PCM frame. */
24
+ sendBinary(data: Buffer): void;
25
+ /** False once the socket is gone — streaming stops rather than piling up. */
26
+ isOpen(): boolean;
27
+ /** Capability strings the board advertised in device_info. */
28
+ capabilities(): string[];
29
+ /** Short transport label for logs, e.g. `serial:/dev/cu.usbmodem…` or `ws`. */
30
+ describe(): string;
31
+ /**
32
+ * Stable identity of the physical board behind this transport — NOT of the
33
+ * socket. A board is routinely reachable over both USB serial and WiFi, and
34
+ * it drops the WebSocket when serial becomes primary, so the transport a
35
+ * dictation arrived on may be gone by the time the reply exists. The reply
36
+ * follows the board.
37
+ */
38
+ deviceKey(): string;
39
+ }
40
+ export interface ArmedReply {
41
+ sessionId: string;
42
+ armedAt: number;
43
+ }
44
+ /** PCM16 mono frame size. 1 KB = 32 ms at 16 kHz — small enough that a dropped
45
+ * frame is inaudible, large enough that framing overhead stays negligible. */
46
+ export declare const PCM_FRAME_BYTES = 1024;
47
+ /** A spoken reply past this is a monologue, not an answer. Truncated at a
48
+ * sentence boundary when one is near the cap. */
49
+ export declare const MAX_SPOKEN_CHARS = 700;
50
+ /**
51
+ * How long an arming survives *without the session making progress*. Measured
52
+ * from the last sign of work, not from the dictation: a question that kicks off
53
+ * half an hour of tool calls still deserves its answer read out, while a session
54
+ * that went quiet has moved on and speaking then is worse than silence.
55
+ */
56
+ export declare const REPLY_ARM_TTL_MS: number;
57
+ /**
58
+ * Strip the parts of an assistant reply that make no sense read aloud (code
59
+ * fences, markdown scaffolding, bare URLs) and cap the length. Returns an empty
60
+ * string when nothing speakable is left — a reply that was only a diff should
61
+ * play nothing rather than spell out punctuation.
62
+ */
63
+ export declare function speakableReply(raw: string, maxChars?: number): string;
64
+ /**
65
+ * Extract PCM samples from a canonical RIFF/WAVE file by walking the chunk
66
+ * list. Fixed-offset slicing at byte 44 is wrong for any file carrying a LIST
67
+ * or fact chunk, and would emit metadata as audio.
68
+ */
69
+ export declare function pcmFromWav(wav: Buffer): {
70
+ pcm: Buffer;
71
+ sampleRate: number;
72
+ } | null;
73
+ /** Split PCM into fixed-size frames; the last one may be short. */
74
+ export declare function pcmFrames(pcm: Buffer, frameBytes?: number): Buffer[];
75
+ /**
76
+ * Tracks which board is waiting to hear the answer to which session, and
77
+ * streams the audio when it arrives.
78
+ */
79
+ export declare class DeviceVoiceReplyRouter {
80
+ private readonly now;
81
+ private readonly sleep;
82
+ /** Current live transport for a board, when its original one has gone. */
83
+ private readonly resolveLive;
84
+ private armed;
85
+ private streaming;
86
+ constructor(now?: () => number, sleep?: (ms: number) => Promise<void>,
87
+ /** Current live transport for a board, when its original one has gone. */
88
+ resolveLive?: (deviceKey: string) => ReplySink | null);
89
+ /**
90
+ * Remember that this board dictated into this session and should hear the
91
+ * reply. Only boards advertising an amplifier are armed — streaming audio at
92
+ * a board that cannot play it wastes the link and, worse, makes the feature
93
+ * look broken on the boards that can.
94
+ */
95
+ arm(sink: ReplySink, sessionId: string): boolean;
96
+ disarm(sink: ReplySink): void;
97
+ /**
98
+ * Mark these sessions as still working, so a long turn does not age out
99
+ * mid-flight. Called with whatever the daemon currently considers active.
100
+ */
101
+ refresh(activeSessionIds: readonly string[]): void;
102
+ /**
103
+ * Drop armings that have gone stale. Deliberately does NOT evict on a closed
104
+ * transport: a board's link can blink between the dictation and the end of the
105
+ * turn — a serial connection gets recycled, a WebSocket reconnects — and
106
+ * dropping the arming then loses the reply permanently for a device that is
107
+ * about to be reachable again. Liveness is checked where it matters, at the
108
+ * moment of streaming.
109
+ */
110
+ sweep(): void;
111
+ /** How many armings are outstanding — for diagnostics only. */
112
+ armedCount(): number;
113
+ /** Transport labels of everything currently armed, for diagnostics. */
114
+ describeArmed(): string;
115
+ /** Boards currently waiting on this session's reply. */
116
+ targetsFor(sessionId: string): ReplySink[];
117
+ /**
118
+ * Stream one already-synthesized WAV to a board. Consumes the arming, so a
119
+ * single dictation yields a single spoken reply rather than narrating every
120
+ * subsequent turn of that session.
121
+ */
122
+ stream(armedSink: ReplySink, wav: Buffer, spokenText: string): Promise<boolean>;
123
+ }
124
+ //# sourceMappingURL=device-voice-reply.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-voice-reply.d.ts","sourceRoot":"","sources":["../src/device-voice-reply.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,MAAM,WAAW,SAAS;IACxB,iCAAiC;IACjC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,iCAAiC;IACjC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,6EAA6E;IAC7E,MAAM,IAAI,OAAO,CAAC;IAClB,8DAA8D;IAC9D,YAAY,IAAI,MAAM,EAAE,CAAC;IACzB,+EAA+E;IAC/E,QAAQ,IAAI,MAAM,CAAC;IACnB;;;;;;OAMG;IACH,SAAS,IAAI,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;+EAC+E;AAC/E,eAAO,MAAM,eAAe,OAAO,CAAC;AAEpC;kDACkD;AAClD,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAEpC;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,QAAiB,CAAC;AAE/C;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,SAAmB,GAAG,MAAM,CAwB/E;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAqBlF;AAED,mEAAmE;AACnE,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,SAAkB,GAAG,MAAM,EAAE,CAM7E;AAED;;;GAGG;AACH,qBAAa,sBAAsB;IAK/B,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,KAAK;IAEtB,0EAA0E;IAC1E,OAAO,CAAC,QAAQ,CAAC,WAAW;IAR9B,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,SAAS,CAAwB;gBAGtB,GAAG,GAAE,MAAM,MAAyB,EACpC,KAAK,GAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CACL;IAC/C,0EAA0E;IACzD,WAAW,GAAE,CAAC,SAAS,EAAE,MAAM,KAAK,SAAS,GAAG,IAAiB;IAGpF;;;;;OAKG;IACH,GAAG,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO;IAUhD,MAAM,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IAI7B;;;OAGG;IACH,OAAO,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI;IASlD;;;;;;;OAOG;IACH,KAAK,IAAI,IAAI;IAOb,+DAA+D;IAC/D,UAAU,IAAI,MAAM;IAIpB,uEAAuE;IACvE,aAAa,IAAI,MAAM;IAKvB,wDAAwD;IACxD,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE;IAU1C;;;;OAIG;IACG,MAAM,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAqCtF"}