@agentdeck/bridge 1.0.6 → 1.0.8

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 (80) hide show
  1. package/assets/fm-helper/agentdeck-fm-helper +0 -0
  2. package/dist/apme/collector.d.ts +10 -0
  3. package/dist/apme/collector.d.ts.map +1 -1
  4. package/dist/apme/collector.js +39 -10
  5. package/dist/apme/collector.js.map +1 -1
  6. package/dist/apme/dashboard-html.d.ts.map +1 -1
  7. package/dist/apme/dashboard-html.js +289 -0
  8. package/dist/apme/dashboard-html.js.map +1 -1
  9. package/dist/apme/graph.d.ts +48 -0
  10. package/dist/apme/graph.d.ts.map +1 -0
  11. package/dist/apme/graph.js +226 -0
  12. package/dist/apme/graph.js.map +1 -0
  13. package/dist/apme/http.d.ts.map +1 -1
  14. package/dist/apme/http.js +52 -0
  15. package/dist/apme/http.js.map +1 -1
  16. package/dist/apme/judge-detect.d.ts.map +1 -1
  17. package/dist/apme/judge-detect.js +26 -2
  18. package/dist/apme/judge-detect.js.map +1 -1
  19. package/dist/apme/store.d.ts +69 -1
  20. package/dist/apme/store.d.ts.map +1 -1
  21. package/dist/apme/store.js +238 -4
  22. package/dist/apme/store.js.map +1 -1
  23. package/dist/apme/types.d.ts +1 -1
  24. package/dist/apme/types.d.ts.map +1 -1
  25. package/dist/apme/types.js.map +1 -1
  26. package/dist/ble-sync-spawn.d.ts +25 -2
  27. package/dist/ble-sync-spawn.d.ts.map +1 -1
  28. package/dist/ble-sync-spawn.js +38 -2
  29. package/dist/ble-sync-spawn.js.map +1 -1
  30. package/dist/ble-sync-status.d.ts +77 -0
  31. package/dist/ble-sync-status.d.ts.map +1 -0
  32. package/dist/ble-sync-status.js +157 -0
  33. package/dist/ble-sync-status.js.map +1 -0
  34. package/dist/bridge-core.d.ts.map +1 -1
  35. package/dist/bridge-core.js +7 -1
  36. package/dist/bridge-core.js.map +1 -1
  37. package/dist/check-deps.d.ts.map +1 -1
  38. package/dist/check-deps.js +4 -12
  39. package/dist/check-deps.js.map +1 -1
  40. package/dist/cli.js +0 -0
  41. package/dist/codex-rate-limits-live.d.ts +60 -0
  42. package/dist/codex-rate-limits-live.d.ts.map +1 -0
  43. package/dist/codex-rate-limits-live.js +282 -0
  44. package/dist/codex-rate-limits-live.js.map +1 -0
  45. package/dist/daemon-server.d.ts.map +1 -1
  46. package/dist/daemon-server.js +81 -3
  47. package/dist/daemon-server.js.map +1 -1
  48. package/dist/daemon.js +1 -1
  49. package/dist/idotmatrix/idotmatrix-daemon-sync.d.ts +8 -0
  50. package/dist/idotmatrix/idotmatrix-daemon-sync.d.ts.map +1 -1
  51. package/dist/idotmatrix/idotmatrix-daemon-sync.js +19 -3
  52. package/dist/idotmatrix/idotmatrix-daemon-sync.js.map +1 -1
  53. package/dist/index.d.ts.map +1 -1
  54. package/dist/index.js +3 -4
  55. package/dist/index.js.map +1 -1
  56. package/dist/modules/idotmatrix-module.d.ts.map +1 -1
  57. package/dist/modules/idotmatrix-module.js +12 -1
  58. package/dist/modules/idotmatrix-module.js.map +1 -1
  59. package/dist/modules/timebox-module.d.ts.map +1 -1
  60. package/dist/modules/timebox-module.js +12 -1
  61. package/dist/modules/timebox-module.js.map +1 -1
  62. package/dist/timebox/timebox-daemon-sync.d.ts +8 -0
  63. package/dist/timebox/timebox-daemon-sync.d.ts.map +1 -1
  64. package/dist/timebox/timebox-daemon-sync.js +29 -1
  65. package/dist/timebox/timebox-daemon-sync.js.map +1 -1
  66. package/dist/timeline-summarizer.d.ts +12 -2
  67. package/dist/timeline-summarizer.d.ts.map +1 -1
  68. package/dist/timeline-summarizer.js +66 -4
  69. package/dist/timeline-summarizer.js.map +1 -1
  70. package/dist/voice-assistant.d.ts +2 -2
  71. package/dist/voice-assistant.d.ts.map +1 -1
  72. package/dist/voice-assistant.js +1 -1
  73. package/dist/voice.d.ts +5 -5
  74. package/dist/voice.d.ts.map +1 -1
  75. package/dist/voice.js +8 -10
  76. package/dist/voice.js.map +1 -1
  77. package/package.json +13 -14
  78. package/src/idotmatrix/sync.py +16 -1
  79. package/src/pysync/matrix_sync_common.py +83 -0
  80. package/src/timebox/sync_ble.py +16 -0
@@ -7,8 +7,11 @@
7
7
  */
8
8
  import { deviceId, loadTimeboxDevices } from './timebox-settings.js';
9
9
  import { createSyncCycleSquelch, spawnPythonSync, terminateSyncChild } from '../ble-sync-spawn.js';
10
+ import { createBleLinkTracker, mergeBleLinkSnapshots, } from '../ble-sync-status.js';
10
11
  import { getBleRuntimeStatus } from '../python-ble-runtime.js';
11
12
  const entries = new Map();
13
+ /** Set when no child could be spawned at all (missing BLE runtime). */
14
+ let unavailableReason = null;
12
15
  const BASE_BACKOFF_MS = 5_000;
13
16
  const MAX_BACKOFF_MS = 60_000;
14
17
  const HEALTHY_UPTIME_MS = 30_000;
@@ -22,8 +25,12 @@ export function startTimeboxSync(httpPort) {
22
25
  const runtime = getBleRuntimeStatus();
23
26
  if (!runtime.ready || !runtime.python) {
24
27
  log(`sync unavailable (${runtime.reason}); run \`agentdeck ble setup\``);
28
+ // Register the reason so /health can say *why* the panel is dark instead of
29
+ // reporting a bare `connected:false` with no explanation.
30
+ unavailableReason = `BLE sync unavailable: ${runtime.reason}`;
25
31
  return;
26
32
  }
33
+ unavailableReason = null;
27
34
  for (const device of devices) {
28
35
  const id = deviceId(device);
29
36
  if (!id || entries.has(id))
@@ -36,6 +43,7 @@ export function startTimeboxSync(httpPort) {
36
43
  consecutiveFailures: 0,
37
44
  startedAt: 0,
38
45
  squelch: createSyncCycleSquelch(log),
46
+ link: createBleLinkTracker(),
39
47
  };
40
48
  entries.set(id, entry);
41
49
  spawnSync(entry, runtime.python, runtime.paths.scripts.timeboxSync, httpPort);
@@ -51,9 +59,12 @@ function spawnSync(entry, venvPython, syncScript, httpPort) {
51
59
  const args = [syncScript, '--address', device.address, '--url', url, '--brightness', String(brightness)];
52
60
  entry.squelch.logStart(`Starting BLE sync for ${device.name ?? 'Timebox Mini'} (${id}, bridge ${url}, brightness ${brightness}%)`);
53
61
  entry.startedAt = Date.now();
62
+ entry.link.noteSpawn();
54
63
  // stdout/stderr are captured into small rings so clean exits and crashes both
55
64
  // leave enough context without flooding the daemon log while running.
56
- const { proc, stderrTail, outputTail } = spawnPythonSync(venvPython, args);
65
+ const { proc, stderrTail, outputTail } = spawnPythonSync(venvPython, args, {
66
+ onStatus: (payload) => entry.link.applyStatusLine(payload),
67
+ });
57
68
  entry.child = proc;
58
69
  proc.on('error', (err) => {
59
70
  log(`sync failed to spawn for ${id}: ${err.message}`);
@@ -74,6 +85,7 @@ function spawnSync(entry, venvPython, syncScript, httpPort) {
74
85
  const delay = Math.min(MAX_BACKOFF_MS, BASE_BACKOFF_MS * entry.consecutiveFailures);
75
86
  const tail = stderrTail() || outputTail();
76
87
  const why = tail ? `; output: ${tail}` : '';
88
+ entry.link.noteExit(tail || `sync exited (code=${code} signal=${signal})`, Date.now() + delay);
77
89
  entry.squelch.logExit(code, signal, uptimeMs, tail, `sync for ${id} exited (code=${code} signal=${signal})${why}; respawning in ${Math.round(delay / 1000)}s`);
78
90
  entry.respawnTimer = setTimeout(() => spawnSync(entry, venvPython, syncScript, httpPort), delay);
79
91
  if (entry.respawnTimer.unref)
@@ -114,7 +126,23 @@ export async function stopTimeboxSync(awaitFarewell = false) {
114
126
  }
115
127
  }
116
128
  entries.clear();
129
+ unavailableReason = null;
117
130
  if (procs.length)
118
131
  await Promise.all(procs.map((p) => terminateSyncChild(p)));
119
132
  }
133
+ /**
134
+ * Live link state for the configured Timebox panels, in the `BLEMatrixHealth`
135
+ * wire shape. Called by `TimeboxModule.statusSnapshot()` so `/health` reports
136
+ * whether the panel is actually being driven — the configured-device list alone
137
+ * left every dashboard drawing a streaming panel as disconnected.
138
+ */
139
+ export function timeboxLinkSnapshot(configuredDeviceCount) {
140
+ const merged = mergeBleLinkSnapshots([...entries.values()].map((e) => e.link.snapshot(configuredDeviceCount)), configuredDeviceCount);
141
+ // A configured device with no entry at all means the supervisor never got to
142
+ // spawn anything — surface that instead of an unexplained `connected:false`.
143
+ if (unavailableReason && configuredDeviceCount > 0 && !merged.connected) {
144
+ return { ...merged, statusReason: unavailableReason };
145
+ }
146
+ return merged;
147
+ }
120
148
  //# sourceMappingURL=timebox-daemon-sync.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"timebox-daemon-sync.js","sourceRoot":"","sources":["../../src/timebox/timebox-daemon-sync.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"timebox-daemon-sync.js","sourceRoot":"","sources":["../../src/timebox/timebox-daemon-sync.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAsB,MAAM,uBAAuB,CAAC;AACzF,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,kBAAkB,EAAyB,MAAM,sBAAsB,CAAC;AAC1H,OAAO,EACL,oBAAoB,EACpB,qBAAqB,GAGtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAe/D,MAAM,OAAO,GAAG,IAAI,GAAG,EAAqB,CAAC;AAE7C,uEAAuE;AACvE,IAAI,iBAAiB,GAAkB,IAAI,CAAC;AAE5C,MAAM,eAAe,GAAG,KAAK,CAAC;AAC9B,MAAM,cAAc,GAAG,MAAM,CAAC;AAC9B,MAAM,iBAAiB,GAAG,MAAM,CAAC;AAEjC,SAAS,GAAG,CAAC,GAAW;IACtB,OAAO,CAAC,KAAK,CAAC,yBAAyB,GAAG,EAAE,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,MAAM,OAAO,GAAG,kBAAkB,EAAE,CAAC;IACrC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAEjC,MAAM,OAAO,GAAG,mBAAmB,EAAE,CAAC;IACtC,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACtC,GAAG,CAAC,qBAAqB,OAAO,CAAC,MAAM,gCAAgC,CAAC,CAAC;QACzE,4EAA4E;QAC5E,0DAA0D;QAC1D,iBAAiB,GAAG,yBAAyB,OAAO,CAAC,MAAM,EAAE,CAAC;QAC9D,OAAO;IACT,CAAC;IACD,iBAAiB,GAAG,IAAI,CAAC;IAEzB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC5B,IAAI,CAAC,EAAE,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,SAAS;QACrC,MAAM,KAAK,GAAc;YACvB,MAAM;YACN,KAAK,EAAE,IAAI;YACX,QAAQ,EAAE,KAAK;YACf,YAAY,EAAE,IAAI;YAClB,mBAAmB,EAAE,CAAC;YACtB,SAAS,EAAE,CAAC;YACZ,OAAO,EAAE,sBAAsB,CAAC,GAAG,CAAC;YACpC,IAAI,EAAE,oBAAoB,EAAE;SAC7B,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QACvB,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAChF,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,KAAgB,EAAE,UAAkB,EAAE,UAAkB,EAAE,QAAgB;IAC3F,IAAI,KAAK,CAAC,QAAQ;QAAE,OAAO;IAC3B,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC5B,MAAM,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC5B,MAAM,GAAG,GAAG,oBAAoB,QAAQ,EAAE,CAAC;IAC3C,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;IACpF,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,WAAW,EAAE,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;IAEzG,KAAK,CAAC,OAAO,CAAC,QAAQ,CACpB,yBAAyB,MAAM,CAAC,IAAI,IAAI,cAAc,KAAK,EAAE,YAAY,GAAG,gBAAgB,UAAU,IAAI,CAC3G,CAAC;IACF,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;IAEvB,8EAA8E;IAC9E,sEAAsE;IACtE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,eAAe,CAAC,UAAU,EAAE,IAAI,EAAE;QACzE,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC;KAC3D,CAAC,CAAC;IACH,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;IAEnB,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAU,EAAE,EAAE;QAC9B,GAAG,CAAC,4BAA4B,EAAE,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAmB,EAAE,MAA6B,EAAE,EAAE;QACrE,IAAI,KAAK,CAAC,KAAK,KAAK,IAAI;YAAE,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;QAC7C,IAAI,KAAK,CAAC,QAAQ;YAAE,OAAO;QAC3B,wEAAwE;QACxE,qEAAqE;QACrE,0EAA0E;QAC1E,gDAAgD;QAChD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,CAAC;QAC9C,IAAI,IAAI,KAAK,CAAC,IAAI,QAAQ,GAAG,iBAAiB;YAAE,KAAK,CAAC,mBAAmB,GAAG,CAAC,CAAC;QAC9E,KAAK,CAAC,mBAAmB,IAAI,CAAC,CAAC;QAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,eAAe,GAAG,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACpF,MAAM,IAAI,GAAG,UAAU,EAAE,IAAI,UAAU,EAAE,CAAC;QAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5C,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,qBAAqB,IAAI,WAAW,MAAM,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC;QAC/F,KAAK,CAAC,OAAO,CAAC,OAAO,CACnB,IAAI,EACJ,MAAM,EACN,QAAQ,EACR,IAAI,EACJ,YAAY,EAAE,iBAAiB,IAAI,WAAW,MAAM,IAAI,GAAG,mBAAmB,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,CAC1G,CAAC;QACF,KAAK,CAAC,YAAY,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAC;QACjG,IAAI,KAAK,CAAC,YAAY,CAAC,KAAK;YAAE,KAAK,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;IAC3D,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,aAAa,GAAG,KAAK;IACzD,MAAM,KAAK,GAAmB,EAAE,CAAC;IACjC,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QACrC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC;QACtB,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;YACvB,YAAY,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YACjC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC;QAC5B,CAAC;QACD,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAChB,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC;YACzB,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;YACnB,IAAI,aAAa,EAAE,CAAC;gBAClB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnB,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC;oBACH,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBACvB,CAAC;gBAAC,MAAM,CAAC;oBACP,kBAAkB;gBACpB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,CAAC,KAAK,EAAE,CAAC;IAChB,iBAAiB,GAAG,IAAI,CAAC;IACzB,IAAI,KAAK,CAAC,MAAM;QAAE,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/E,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,qBAA6B;IAC/D,MAAM,MAAM,GAAG,qBAAqB,CAClC,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAC,EACxE,qBAAqB,CACtB,CAAC;IACF,6EAA6E;IAC7E,6EAA6E;IAC7E,IAAI,iBAAiB,IAAI,qBAAqB,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QACxE,OAAO,EAAE,GAAG,MAAM,EAAE,YAAY,EAAE,iBAAiB,EAAE,CAAC;IACxD,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -2,10 +2,20 @@
2
2
  * Timeline summarizer — uses local LLM to create concise 1-line summaries
3
3
  * of OpenClaw chat responses for timeline display.
4
4
  *
5
- * Tries: local mlx-serve qwen (port 8800) → Ollama → heuristic fallback.
6
- * Non-blocking — caller should fire-and-forget, update entry when ready.
5
+ * Tries: on-device Foundation Models → local mlx-serve qwen (port 8800) →
6
+ * Ollama → heuristic fallback. Non-blocking — caller should fire-and-forget,
7
+ * update entry when ready.
8
+ *
9
+ * The provider order is the Node mirror of Swift's `TimelineSummarizer`
10
+ * `.auto` chain (FoundationModels → MLX → Ollama → heuristic). It was
11
+ * MLX-first for a long time, which meant a CLI-only user on macOS 26 with
12
+ * Apple Intelligence available still got heuristic rows unless they also ran
13
+ * an MLX server — the same machine summarized differently depending on which
14
+ * daemon happened to be up. Keep the two chains in the same order.
7
15
  */
8
16
  export { extractTopicHint } from '@agentdeck/shared';
17
+ /** Reset the cached provider availability (tests only). */
18
+ export declare function clearSummarizerProviderCacheForTests(): void;
9
19
  /**
10
20
  * Summarize a chat response into a concise 1-line Korean summary.
11
21
  * Returns null if summarization fails (caller should use fallback).
@@ -1 +1 @@
1
- {"version":3,"file":"timeline-summarizer.d.ts","sourceRoot":"","sources":["../src/timeline-summarizer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAiCrD;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAoE5E"}
1
+ {"version":3,"file":"timeline-summarizer.d.ts","sourceRoot":"","sources":["../src/timeline-summarizer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAmCrD,2DAA2D;AAC3D,wBAAgB,oCAAoC,IAAI,IAAI,CAS3D;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAyF5E"}
@@ -2,12 +2,21 @@
2
2
  * Timeline summarizer — uses local LLM to create concise 1-line summaries
3
3
  * of OpenClaw chat responses for timeline display.
4
4
  *
5
- * Tries: local mlx-serve qwen (port 8800) → Ollama → heuristic fallback.
6
- * Non-blocking — caller should fire-and-forget, update entry when ready.
5
+ * Tries: on-device Foundation Models → local mlx-serve qwen (port 8800) →
6
+ * Ollama → heuristic fallback. Non-blocking — caller should fire-and-forget,
7
+ * update entry when ready.
8
+ *
9
+ * The provider order is the Node mirror of Swift's `TimelineSummarizer`
10
+ * `.auto` chain (FoundationModels → MLX → Ollama → heuristic). It was
11
+ * MLX-first for a long time, which meant a CLI-only user on macOS 26 with
12
+ * Apple Intelligence available still got heuristic rows unless they also ran
13
+ * an MLX server — the same machine summarized differently depending on which
14
+ * daemon happened to be up. Keep the two chains in the same order.
7
15
  */
8
16
  import { debug, log } from './logger.js';
9
17
  import { SUMMARY_SYSTEM_PROMPT, cleanLLMOutput, mlxChatUrl, resolveMlxModel } from '@agentdeck/shared';
10
18
  import { fetchMlxModels } from './mlx-probe.js';
19
+ import { callFoundationModelsHelper, probeFoundationModelsHelper } from './foundation-models-helper.js';
11
20
  export { extractTopicHint } from '@agentdeck/shared';
12
21
  const MLX_URL = mlxChatUrl();
13
22
  // In-memory cache of the probe's first result, so summarizers don't hit
@@ -32,11 +41,24 @@ async function resolveModelForCall() {
32
41
  const OLLAMA_URL = 'http://localhost:11434/api/chat';
33
42
  const TIMEOUT_MS = 30_000; // 30s — first inference needs model load time
34
43
  const MAX_INPUT_CHARS = 2000;
44
+ let fmAvailable = null;
35
45
  let mlxAvailable = null;
36
46
  let ollamaAvailable = null;
47
+ let fmFailedAt = 0;
37
48
  let mlxFailedAt = 0;
38
49
  let ollamaFailedAt = 0;
39
50
  const RETRY_INTERVAL_MS = 60_000; // retry failed providers after 60s
51
+ /** Reset the cached provider availability (tests only). */
52
+ export function clearSummarizerProviderCacheForTests() {
53
+ fmAvailable = null;
54
+ mlxAvailable = null;
55
+ ollamaAvailable = null;
56
+ fmFailedAt = 0;
57
+ mlxFailedAt = 0;
58
+ ollamaFailedAt = 0;
59
+ probedFirstModel = null;
60
+ probedAt = 0;
61
+ }
40
62
  /**
41
63
  * Summarize a chat response into a concise 1-line Korean summary.
42
64
  * Returns null if summarization fails (caller should use fallback).
@@ -49,7 +71,29 @@ export async function summarizeResponse(text) {
49
71
  : text;
50
72
  let mlxJustFailed = false;
51
73
  let ollamaJustFailed = false;
52
- // Try MLX qwen first (retry after RETRY_INTERVAL_MS)
74
+ // Try on-device Foundation Models first no server for the user to run,
75
+ // and it is the same helper process the APME judge already keeps warm.
76
+ // A miss here is not an error state: off-macOS, on macOS < 26, or with
77
+ // Apple Intelligence disabled the probe simply reports unavailable and the
78
+ // chain moves on. Only MLX+Ollama failing together is worth telling the
79
+ // user about (that pair is what the user opts into by installing them).
80
+ if (fmAvailable !== false || (Date.now() - fmFailedAt > RETRY_INTERVAL_MS)) {
81
+ try {
82
+ const result = await callFoundationModels(input);
83
+ if (result) {
84
+ if (fmAvailable === false)
85
+ debug('summarizer', 'Foundation Models recovered');
86
+ fmAvailable = true;
87
+ return result;
88
+ }
89
+ }
90
+ catch (err) {
91
+ fmAvailable = false;
92
+ fmFailedAt = Date.now();
93
+ debug('summarizer', `Foundation Models not available: ${String(err)}`);
94
+ }
95
+ }
96
+ // Try MLX qwen next (retry after RETRY_INTERVAL_MS)
53
97
  if (mlxAvailable !== false || (Date.now() - mlxFailedAt > RETRY_INTERVAL_MS)) {
54
98
  try {
55
99
  const result = await callMLX(input);
@@ -99,11 +143,29 @@ export async function summarizeResponse(text) {
99
143
  if ((mlxJustFailed && ollamaJustFailed)
100
144
  || (mlxJustFailed && ollamaAvailable === false)
101
145
  || (ollamaJustFailed && mlxAvailable === false)) {
102
- log('[timeline] LLM summary backend offline (MLX:8800 / Ollama:11434).', 'Timeline rows will use heuristic summaries.', 'Install MLX (`mlx_vlm.server`) or Ollama to get LLM-summarized chat_end rows.');
146
+ log(`[timeline] LLM summary backend offline (on-device Foundation Models: ${fmAvailable === false ? 'unavailable' : 'not reached'}, MLX:8800, Ollama:11434).`, 'Timeline rows will use heuristic summaries.', 'Install MLX (`mlx_vlm.server`) or Ollama to get LLM-summarized chat_end rows.');
103
147
  }
104
148
  return null;
105
149
  }
106
150
  // extractTopicHint and cleanLLMOutput moved to @agentdeck/shared/timeline-summarizer
151
+ /** On-device summary via the bundled Swift helper (Apple Intelligence).
152
+ * Throws when the helper is unavailable so the caller falls to MLX; the
153
+ * helper owns its own request timeout, so there is no unbounded await here. */
154
+ async function callFoundationModels(input) {
155
+ // Probe only on the first attempt: the probe is a full health round-trip to
156
+ // the helper, and after that the generate call is its own liveness check.
157
+ // (`fmAvailable` is null exactly once — the caller flips it either way.)
158
+ if (fmAvailable === null) {
159
+ const status = await probeFoundationModelsHelper();
160
+ if (!status.available)
161
+ throw new Error(status.reason ?? 'helper unavailable');
162
+ }
163
+ const text = await callFoundationModelsHelper(input, SUMMARY_SYSTEM_PROMPT);
164
+ const result = cleanLLMOutput(text);
165
+ if (result)
166
+ debug('summarizer', `Foundation Models summary: ${result}`);
167
+ return result;
168
+ }
107
169
  async function callMLX(input) {
108
170
  const controller = new AbortController();
109
171
  const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
@@ -1 +1 @@
1
- {"version":3,"file":"timeline-summarizer.js","sourceRoot":"","sources":["../src/timeline-summarizer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"timeline-summarizer.js","sourceRoot":"","sources":["../src/timeline-summarizer.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,7 @@
5
5
  * 1. WakeWordListener detects "오픈클로"
6
6
  * 2. Record user speech via sox/rec (reusing VoiceManager's approach)
7
7
  * 3. VAD: stop recording on silence
8
- * 4. Transcribe via whisper-server
8
+ * 4. Transcribe via the bundled helper (Apple on-device Speech)
9
9
  * 5. Route to OpenClaw Gateway (or Claude Code) via adapter
10
10
  * 6. Receive response text
11
11
  * 7. Synthesize + play via macOS say
@@ -17,7 +17,7 @@ import type { VoiceAssistantState } from '@agentdeck/shared';
17
17
  export interface VoiceAssistantOptions {
18
18
  /** Callback to send a prompt to the active agent */
19
19
  sendPrompt: (text: string) => void;
20
- /** Callback to transcribe a WAV file via whisper-server */
20
+ /** Callback to transcribe a WAV file (Apple on-device Speech via the helper) */
21
21
  transcribeFile: (filePath: string) => Promise<string>;
22
22
  /** Function that returns true if push-to-talk is recording (mutex) */
23
23
  isPttRecording?: () => boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"voice-assistant.d.ts","sourceRoot":"","sources":["../src/voice-assistant.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAStC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AA4D7D,MAAM,WAAW,qBAAqB;IACpC,oDAAoD;IACpD,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,2DAA2D;IAC3D,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACtD,sEAAsE;IACtE,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC;CAChC;AAED,qBAAa,qBAAsB,SAAQ,YAAY;IACrD,OAAO,CAAC,KAAK,CAAmC;IAChD,OAAO,CAAC,QAAQ,CAAmB;IACnC,OAAO,CAAC,GAAG,CAAY;IACvB,OAAO,CAAC,IAAI,CAAwB;IACpC,OAAO,CAAC,MAAM,CAAS;IAGvB,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,QAAQ,CAA+C;IAC/D,OAAO,CAAC,iBAAiB,CAA8C;IACvE,OAAO,CAAC,cAAc,CAAK;IAG3B,OAAO,CAAC,eAAe,CAA8C;IAGrE,OAAO,CAAC,eAAe,CAAM;gBAEjB,IAAI,EAAE,qBAAqB;IAcvC,6DAA6D;IACvD,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC;IA2B/B,0CAA0C;IAC1C,IAAI,IAAI,IAAI;IAQZ,QAAQ,IAAI,mBAAmB;IAI/B;;;;OAIG;IACH,oBAAoB,IAAI,IAAI;IAa5B,8CAA8C;IACxC,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqCjD,OAAO,CAAC,QAAQ;IAShB,OAAO,CAAC,kBAAkB;IAyB1B,OAAO,CAAC,cAAc;IA+CtB,OAAO,CAAC,QAAQ;YAoBF,eAAe;IA+F7B,8EAA8E;YAChE,cAAc;IAkB5B,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,WAAW;IAWnB,OAAO,CAAC,YAAY;CAMrB"}
1
+ {"version":3,"file":"voice-assistant.d.ts","sourceRoot":"","sources":["../src/voice-assistant.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAStC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AA4D7D,MAAM,WAAW,qBAAqB;IACpC,oDAAoD;IACpD,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,gFAAgF;IAChF,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACtD,sEAAsE;IACtE,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC;CAChC;AAED,qBAAa,qBAAsB,SAAQ,YAAY;IACrD,OAAO,CAAC,KAAK,CAAmC;IAChD,OAAO,CAAC,QAAQ,CAAmB;IACnC,OAAO,CAAC,GAAG,CAAY;IACvB,OAAO,CAAC,IAAI,CAAwB;IACpC,OAAO,CAAC,MAAM,CAAS;IAGvB,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,QAAQ,CAA+C;IAC/D,OAAO,CAAC,iBAAiB,CAA8C;IACvE,OAAO,CAAC,cAAc,CAAK;IAG3B,OAAO,CAAC,eAAe,CAA8C;IAGrE,OAAO,CAAC,eAAe,CAAM;gBAEjB,IAAI,EAAE,qBAAqB;IAcvC,6DAA6D;IACvD,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC;IA2B/B,0CAA0C;IAC1C,IAAI,IAAI,IAAI;IAQZ,QAAQ,IAAI,mBAAmB;IAI/B;;;;OAIG;IACH,oBAAoB,IAAI,IAAI;IAa5B,8CAA8C;IACxC,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqCjD,OAAO,CAAC,QAAQ;IAShB,OAAO,CAAC,kBAAkB;IAyB1B,OAAO,CAAC,cAAc;IA+CtB,OAAO,CAAC,QAAQ;YAoBF,eAAe;IA+F7B,8EAA8E;YAChE,cAAc;IAkB5B,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,WAAW;IAWnB,OAAO,CAAC,YAAY;CAMrB"}
@@ -5,7 +5,7 @@
5
5
  * 1. WakeWordListener detects "오픈클로"
6
6
  * 2. Record user speech via sox/rec (reusing VoiceManager's approach)
7
7
  * 3. VAD: stop recording on silence
8
- * 4. Transcribe via whisper-server
8
+ * 4. Transcribe via the bundled helper (Apple on-device Speech)
9
9
  * 5. Route to OpenClaw Gateway (or Claude Code) via adapter
10
10
  * 6. Receive response text
11
11
  * 7. Synthesize + play via macOS say
package/dist/voice.d.ts CHANGED
@@ -6,11 +6,11 @@ export declare class VoiceManager extends EventEmitter {
6
6
  private recBin;
7
7
  private soxBin;
8
8
  constructor();
9
- /** No-op kept so callers written for the whisper-server era keep compiling.
10
- * Transcription now goes through the bundled Swift helper, which the
11
- * Foundation Models client already manages as a long-lived process. */
12
- connectToServer(): Promise<void>;
13
- disconnectFromServer(): void;
9
+ /** Probe the bundled Swift helper so an unavailable recognizer shows up in
10
+ * the log at startup rather than on the user's first utterance. There is
11
+ * nothing to connect to or tear down — the helper is a long-lived process
12
+ * owned by foundation-models-helper.ts. */
13
+ probeSpeechHelper(): Promise<void>;
14
14
  startRecording(): void;
15
15
  stopRecording(): Promise<string>;
16
16
  cancel(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"voice.d.ts","sourceRoot":"","sources":["../src/voice.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AA+BtC,qBAAa,YAAa,SAAQ,YAAY;IAC5C,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAS;;IASvB;;4EAEwE;IAClE,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAOtC,oBAAoB,IAAI,IAAI;IAI5B,cAAc,IAAI,IAAI;IA2ChB,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAyDtC,MAAM,IAAI,IAAI;IAUd,WAAW,IAAI,OAAO;IAItB,iEAAiE;IAC3D,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAWvD;;;;;;;;OAQG;YACW,mBAAmB;IAOjC,OAAO,CAAC,OAAO;CAMhB"}
1
+ {"version":3,"file":"voice.d.ts","sourceRoot":"","sources":["../src/voice.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AA8BtC,qBAAa,YAAa,SAAQ,YAAY;IAC5C,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAS;;IASvB;;;gDAG4C;IACtC,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAOxC,cAAc,IAAI,IAAI;IA2ChB,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IA0DtC,MAAM,IAAI,IAAI;IAUd,WAAW,IAAI,OAAO;IAItB,iEAAiE;IAC3D,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAWvD;;;;;;;;OAQG;YACW,mBAAmB;IAOjC,OAAO,CAAC,OAAO;CAMhB"}
package/dist/voice.js CHANGED
@@ -13,7 +13,6 @@ function findBinary(candidates, fallback) {
13
13
  }
14
14
  return fallback;
15
15
  }
16
- /** Check if a whisper-cli binary has Metal GPU support (native arm64 + libggml-metal). */
17
16
  /** Compute RMS energy of a 16-bit PCM WAV file (skip 44-byte header). */
18
17
  function computeRms(wavFile) {
19
18
  const buf = readFileSync(wavFile);
@@ -40,18 +39,16 @@ export class VoiceManager extends EventEmitter {
40
39
  this.soxBin = findBinary(SOX_CANDIDATES, 'sox');
41
40
  debug('Voice', `Binaries: rec=${this.recBin}, sox=${this.soxBin} (transcription: Apple Speech via bundled helper)`);
42
41
  }
43
- /** No-op kept so callers written for the whisper-server era keep compiling.
44
- * Transcription now goes through the bundled Swift helper, which the
45
- * Foundation Models client already manages as a long-lived process. */
46
- async connectToServer() {
42
+ /** Probe the bundled Swift helper so an unavailable recognizer shows up in
43
+ * the log at startup rather than on the user's first utterance. There is
44
+ * nothing to connect to or tear down — the helper is a long-lived process
45
+ * owned by foundation-models-helper.ts. */
46
+ async probeSpeechHelper() {
47
47
  const status = await probeFoundationModelsHelper();
48
48
  if (!status.available) {
49
49
  debug('Voice', `Speech helper unavailable: ${status.reason ?? 'unknown'}`);
50
50
  }
51
51
  }
52
- disconnectFromServer() {
53
- // Helper lifetime is owned by foundation-models-helper.ts.
54
- }
55
52
  startRecording() {
56
53
  if (this.recording)
57
54
  return;
@@ -120,14 +117,15 @@ export class VoiceManager extends EventEmitter {
120
117
  this.cleanup();
121
118
  throw new Error('Recording too short or empty');
122
119
  }
123
- // Check audio RMS to detect silence (whisper hallucinates on silent audio)
120
+ // Check audio RMS to detect silence a recognizer handed silence returns
121
+ // invented text rather than an error, so catch it before transcribing.
124
122
  const rms = computeRms(this.audioFile);
125
123
  debug('Voice', `Audio RMS: ${rms.toFixed(4)}`);
126
124
  if (rms < 0.001) {
127
125
  this.cleanup();
128
126
  throw new Error('No audio detected — check microphone permission');
129
127
  }
130
- // --- Transcription: prefer whisper-server, fallback to whisper-cli ---
128
+ // --- Transcription: Apple on-device Speech via the bundled helper ---
131
129
  try {
132
130
  const text = await this.transcribeViaHelper(this.audioFile);
133
131
  debug('Voice', `Transcription result: "${text.slice(0, 80)}"`);
package/dist/voice.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"voice.js","sourceRoot":"","sources":["../src/voice.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"voice.js","sourceRoot":"","sources":["../src/voice.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentdeck/bridge",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -24,18 +24,7 @@
24
24
  "bin": {
25
25
  "agentdeck": "./dist/cli.js"
26
26
  },
27
- "scripts": {
28
- "build": "tsc",
29
- "build:fm-helper": "node scripts/build-fm-helper.mjs",
30
- "prepack": "node scripts/build-fm-helper.mjs",
31
- "dev": "tsc --watch",
32
- "clean": "rm -rf dist",
33
- "typecheck": "tsc --noEmit",
34
- "start": "node dist/cli.js claude"
35
- },
36
27
  "dependencies": {
37
- "@agentdeck/hooks": "workspace:*",
38
- "@agentdeck/shared": "workspace:*",
39
28
  "@anthropic-ai/sdk": "^0.111.0",
40
29
  "bonjour-service": "^1.3.0",
41
30
  "commander": "^14.0.3",
@@ -43,7 +32,9 @@
43
32
  "qrcode": "^1.5.4",
44
33
  "sharp": "^0.34.5",
45
34
  "strip-ansi": "^7.2.0",
46
- "ws": "^8.20.0"
35
+ "ws": "^8.20.0",
36
+ "@agentdeck/shared": "1.0.8",
37
+ "@agentdeck/hooks": "1.0.8"
47
38
  },
48
39
  "optionalDependencies": {
49
40
  "@picovoice/porcupine-node": "^4.0.2",
@@ -59,5 +50,13 @@
59
50
  "@types/qrcode": "^1.5.6",
60
51
  "@types/ws": "^8.18.1",
61
52
  "typescript": "^6.0.3"
53
+ },
54
+ "scripts": {
55
+ "build": "tsc",
56
+ "build:fm-helper": "node scripts/build-fm-helper.mjs",
57
+ "dev": "tsc --watch",
58
+ "clean": "rm -rf dist",
59
+ "typecheck": "tsc --noEmit",
60
+ "start": "node dist/cli.js claude"
62
61
  }
63
- }
62
+ }
@@ -21,6 +21,7 @@ from matrix_sync_common import ( # noqa: E402
21
21
  DEFAULT_URL,
22
22
  POLL_INTERVAL,
23
23
  BRIDGE_GONE_EXIT_SEC,
24
+ StatusReporter,
24
25
  fetch_display_state as _fetch_display_state_sync,
25
26
  bridge_reachable as _bridge_reachable_sync,
26
27
  resolve_display_brightness as _resolve_display_brightness_common,
@@ -124,7 +125,13 @@ async def run_sync(address: str, url: str, brightness: int = 100, boost: float =
124
125
  print(f"AgentDeck Bridge API URL: {url}")
125
126
  print(f"Initial Hardware Brightness: {brightness}%")
126
127
  print(f"Software Brightness Boost: {boost}x")
127
-
128
+
129
+ # Machine-readable link state for the daemon supervisor — it spawns us but
130
+ # cannot see the BLE link, and we reconnect inside this loop rather than
131
+ # exiting, so process liveness tells it nothing about whether the panel is
132
+ # actually being driven.
133
+ status = StatusReporter()
134
+
128
135
  manager = ConnectionManager()
129
136
 
130
137
  idm_image = IdmImage()
@@ -187,8 +194,10 @@ async def run_sync(address: str, url: str, brightness: int = 100, boost: float =
187
194
  # 1. Ensure bluetooth connection
188
195
  if not connected:
189
196
  print(f"Connecting to iDotMatrix ({address})...")
197
+ status.connecting()
190
198
  await manager.connectByAddress(address)
191
199
  print("Connected to Bluetooth device!")
200
+ status.connected()
192
201
 
193
202
  # Settle: the panel drops commands sent too soon after the GATT
194
203
  # link comes up. Without this the first setBrightness is lost on a
@@ -227,6 +236,7 @@ async def run_sync(address: str, url: str, brightness: int = 100, boost: float =
227
236
  # bleak's is_connected reflects the real OS-level link state.
228
237
  if manager.client is None or not manager.client.is_connected:
229
238
  print("BLE link lost — reconnecting...")
239
+ status.disconnected("BLE link lost")
230
240
  connected = False
231
241
  last_hash = ""
232
242
  await _interruptible_sleep(stop_event, 1.0)
@@ -274,6 +284,7 @@ async def run_sync(address: str, url: str, brightness: int = 100, boost: float =
274
284
  last_brightness_assert = time.monotonic()
275
285
 
276
286
  if display_dimmed:
287
+ status.streaming(dimmed=True)
277
288
  await _interruptible_sleep(stop_event, POLL_INTERVAL)
278
289
  continue
279
290
 
@@ -302,6 +313,7 @@ async def run_sync(address: str, url: str, brightness: int = 100, boost: float =
302
313
  current_hash = hashlib.sha256(frame_data).hexdigest()
303
314
  if current_hash == last_hash:
304
315
  # Frame didn't change, skip BLE transmission to save battery and bandwidth
316
+ status.streaming()
305
317
  await _interruptible_sleep(stop_event, POLL_INTERVAL)
306
318
  continue
307
319
 
@@ -332,8 +344,10 @@ async def run_sync(address: str, url: str, brightness: int = 100, boost: float =
332
344
  if res:
333
345
  last_hash = current_hash
334
346
  print("Frame uploaded successfully.")
347
+ status.frame_sent()
335
348
  else:
336
349
  print("Failed to upload frame (uploadUnprocessed returned False).")
350
+ status.disconnected("frame upload failed")
337
351
 
338
352
  await _interruptible_sleep(stop_event, POLL_INTERVAL)
339
353
 
@@ -343,6 +357,7 @@ async def run_sync(address: str, url: str, brightness: int = 100, boost: float =
343
357
  except Exception as e:
344
358
  print(f"Error during loop: {e}")
345
359
  print("Resetting bluetooth connection...")
360
+ status.failed(e)
346
361
  connected = False
347
362
  try:
348
363
  await manager.disconnect()
@@ -10,6 +10,7 @@ so this module must stay dependency-free beyond the stdlib.
10
10
  """
11
11
 
12
12
  import json
13
+ import sys
13
14
  import urllib.request
14
15
 
15
16
  DEFAULT_URL = "http://127.0.0.1:9120"
@@ -87,3 +88,85 @@ def resolve_display_brightness(display_state, normal_brightness, *, off_floor, l
87
88
  if display_on or not dim_enabled:
88
89
  return normal_brightness, False, signature, dim_mode
89
90
  return (dim_level if dim_mode == "min" else off_floor), True, signature, dim_mode
91
+
92
+
93
+ # ---------------------------------------------------------------------------
94
+ # Link status reporting
95
+ # ---------------------------------------------------------------------------
96
+
97
+ # Prefix of the machine-readable status lines the daemon supervisor parses.
98
+ # Mirrored in bridge/src/ble-sync-spawn.ts (`BLE_STATUS_LINE_PREFIX`).
99
+ STATUS_LINE_PREFIX = "AGENTDECK_STATUS "
100
+
101
+
102
+ class StatusReporter:
103
+ """Report BLE link state to the daemon that spawned us, one line per change.
104
+
105
+ The Node daemon has no BLE of its own: it spawns this client and can only
106
+ watch the process. But both clients reconnect *inside* their own loop, so a
107
+ powered-off panel leaves the child running indefinitely and "process alive"
108
+ says nothing about whether the panel is being driven. Without this signal
109
+ the daemon's /health could only report the configured device list, and every
110
+ consumer that renders `connected` — macOS menubar, Dashboard rail, TUI —
111
+ drew both BLE panels as disconnected while they were streaming.
112
+
113
+ Emitting only on *change* keeps the frame loop from flooding the daemon log,
114
+ and the supervisor keeps these lines out of its diagnostic output ring so a
115
+ reconnect never looks like a new crash cycle.
116
+ """
117
+
118
+ def __init__(self, emit=None):
119
+ self._emit = emit if emit is not None else _write_status_line
120
+ self._last = None
121
+ # Sticky: once we have painted the panel, our frame is on it even while
122
+ # the link is down. Matches `hasFrame` in the daemon's health shape.
123
+ self._has_frame = False
124
+
125
+ def _update(self, connected, phase, dimmed=False, error=None):
126
+ payload = {
127
+ "connected": bool(connected),
128
+ "phase": phase,
129
+ "hasFrame": self._has_frame,
130
+ "dimmed": bool(dimmed),
131
+ "error": error,
132
+ }
133
+ if payload == self._last:
134
+ return
135
+ self._last = payload
136
+ self._emit(payload)
137
+
138
+ def connecting(self):
139
+ self._update(False, "connecting")
140
+
141
+ def connected(self):
142
+ self._update(True, "connected")
143
+
144
+ def streaming(self, dimmed=False):
145
+ """Link up and the frame loop is running — does not claim a painted frame.
146
+
147
+ Used on the dim/pause path, where a reconnect while the host display is
148
+ already asleep runs the loop without pushing anything.
149
+ """
150
+ self._update(True, "streaming", dimmed=dimmed)
151
+
152
+ def frame_sent(self, dimmed=False):
153
+ self._has_frame = True
154
+ self.streaming(dimmed=dimmed)
155
+
156
+ def disconnected(self, error=None):
157
+ self._update(False, "disconnected", error=error)
158
+
159
+ def failed(self, error):
160
+ self._update(False, "error", error=str(error) if error is not None else None)
161
+
162
+
163
+ def _write_status_line(payload):
164
+ """Write one status line to stdout. Never raises — a closed pipe during
165
+ shutdown must not take the farewell frame down with it."""
166
+ try:
167
+ sys.stdout.write(
168
+ STATUS_LINE_PREFIX + json.dumps(payload, separators=(",", ":")) + "\n"
169
+ )
170
+ sys.stdout.flush()
171
+ except Exception:
172
+ pass