@agentdeck/bridge 1.1.0 → 1.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 (107) hide show
  1. package/README.md +14 -6
  2. package/assets/fonts/NOTICE-PocketSansWorld.md +10 -0
  3. package/assets/fonts/OFL-PocketSansWorld.txt +93 -0
  4. package/assets/fonts/PocketSansWorld_12.cpfont +0 -0
  5. package/assets/fonts/pocket-sans-world.manifest.json +49 -0
  6. package/assets/learning/LICENSE-CC-BY-SA-4.0.txt +10 -0
  7. package/assets/learning/NOTICE.md +33 -0
  8. package/assets/learning/jp-n3-ko.manifest.json +27 -0
  9. package/assets/learning/jp-n3-ko.pdl +0 -0
  10. package/dist/agent-cli-diagnostics.d.ts +20 -0
  11. package/dist/agent-cli-diagnostics.d.ts.map +1 -0
  12. package/dist/agent-cli-diagnostics.js +100 -0
  13. package/dist/agent-cli-diagnostics.js.map +1 -0
  14. package/dist/apme/collector.d.ts +18 -1
  15. package/dist/apme/collector.d.ts.map +1 -1
  16. package/dist/apme/collector.js +48 -3
  17. package/dist/apme/collector.js.map +1 -1
  18. package/dist/apme/dashboard-html.d.ts.map +1 -1
  19. package/dist/apme/dashboard-html.js +275 -35
  20. package/dist/apme/dashboard-html.js.map +1 -1
  21. package/dist/apme/http.d.ts.map +1 -1
  22. package/dist/apme/http.js +33 -5
  23. package/dist/apme/http.js.map +1 -1
  24. package/dist/apme/index.d.ts.map +1 -1
  25. package/dist/apme/index.js +6 -2
  26. package/dist/apme/index.js.map +1 -1
  27. package/dist/apme/store.d.ts +41 -1
  28. package/dist/apme/store.d.ts.map +1 -1
  29. package/dist/apme/store.js +153 -27
  30. package/dist/apme/store.js.map +1 -1
  31. package/dist/bridge-core.d.ts +15 -0
  32. package/dist/bridge-core.d.ts.map +1 -1
  33. package/dist/bridge-core.js +30 -4
  34. package/dist/bridge-core.js.map +1 -1
  35. package/dist/cli.d.ts +11 -0
  36. package/dist/cli.d.ts.map +1 -1
  37. package/dist/cli.js +55 -8
  38. package/dist/cli.js.map +1 -1
  39. package/dist/codex-rate-limits-live.d.ts +180 -10
  40. package/dist/codex-rate-limits-live.d.ts.map +1 -1
  41. package/dist/codex-rate-limits-live.js +475 -22
  42. package/dist/codex-rate-limits-live.js.map +1 -1
  43. package/dist/daemon-server.d.ts.map +1 -1
  44. package/dist/daemon-server.js +263 -1
  45. package/dist/daemon-server.js.map +1 -1
  46. package/dist/daemon-ws-client.d.ts +1 -0
  47. package/dist/daemon-ws-client.d.ts.map +1 -1
  48. package/dist/daemon-ws-client.js +25 -16
  49. package/dist/daemon-ws-client.js.map +1 -1
  50. package/dist/daemon.js +1 -1
  51. package/dist/esp32-serial.d.ts +4 -0
  52. package/dist/esp32-serial.d.ts.map +1 -1
  53. package/dist/esp32-serial.js +4 -0
  54. package/dist/esp32-serial.js.map +1 -1
  55. package/dist/font-pack.d.ts +15 -0
  56. package/dist/font-pack.d.ts.map +1 -0
  57. package/dist/font-pack.js +75 -0
  58. package/dist/font-pack.js.map +1 -0
  59. package/dist/glance-frame.d.ts.map +1 -1
  60. package/dist/glance-frame.js +2 -0
  61. package/dist/glance-frame.js.map +1 -1
  62. package/dist/http-auth-gate.d.ts.map +1 -1
  63. package/dist/http-auth-gate.js +9 -1
  64. package/dist/http-auth-gate.js.map +1 -1
  65. package/dist/index.js +2 -2
  66. package/dist/index.js.map +1 -1
  67. package/dist/learning-pack.d.ts +24 -0
  68. package/dist/learning-pack.d.ts.map +1 -0
  69. package/dist/learning-pack.js +125 -0
  70. package/dist/learning-pack.js.map +1 -0
  71. package/dist/mdns.js +1 -1
  72. package/dist/mdns.js.map +1 -1
  73. package/dist/pairing-knocks.d.ts +80 -0
  74. package/dist/pairing-knocks.d.ts.map +1 -0
  75. package/dist/pairing-knocks.js +312 -0
  76. package/dist/pairing-knocks.js.map +1 -0
  77. package/dist/pixoo/micro-glyphs.d.ts +4 -0
  78. package/dist/pixoo/micro-glyphs.d.ts.map +1 -1
  79. package/dist/pixoo/micro-glyphs.js +29 -0
  80. package/dist/pixoo/micro-glyphs.js.map +1 -1
  81. package/dist/pixoo/pixoo-font.d.ts.map +1 -1
  82. package/dist/pixoo/pixoo-font.js +3 -1
  83. package/dist/pixoo/pixoo-font.js.map +1 -1
  84. package/dist/pixoo/pixoo-renderer.d.ts +1 -1
  85. package/dist/pixoo/pixoo-renderer.d.ts.map +1 -1
  86. package/dist/pixoo/pixoo-renderer.js +17 -2
  87. package/dist/pixoo/pixoo-renderer.js.map +1 -1
  88. package/dist/pty-manager.d.ts +9 -0
  89. package/dist/pty-manager.d.ts.map +1 -1
  90. package/dist/pty-manager.js +63 -4
  91. package/dist/pty-manager.js.map +1 -1
  92. package/dist/relayed-usage.d.ts +30 -0
  93. package/dist/relayed-usage.d.ts.map +1 -1
  94. package/dist/relayed-usage.js +25 -2
  95. package/dist/relayed-usage.js.map +1 -1
  96. package/dist/surface-protocol.d.ts.map +1 -1
  97. package/dist/surface-protocol.js +2 -0
  98. package/dist/surface-protocol.js.map +1 -1
  99. package/dist/tui/dashboard.d.ts.map +1 -1
  100. package/dist/tui/dashboard.js +8 -1
  101. package/dist/tui/dashboard.js.map +1 -1
  102. package/dist/ws-server.d.ts +18 -0
  103. package/dist/ws-server.d.ts.map +1 -1
  104. package/dist/ws-server.js +40 -2
  105. package/dist/ws-server.js.map +1 -1
  106. package/package.json +4 -3
  107. package/src/timebox/sync_ble.py +35 -16
package/dist/cli.js CHANGED
@@ -28,6 +28,25 @@ function warnIfDaemonHostIgnored(opts) {
28
28
  console.error('[agentdeck] --daemon-host / AGENTDECK_DAEMON_HOST is set but ignored: remote attach requires --remote-daemon (or AGENTDECK_REMOTE_DAEMON=1). Session stays local-only.');
29
29
  }
30
30
  }
31
+ /**
32
+ * User-visible compatibility notice for the legacy per-session bridge. Keep
33
+ * this pure so CLI tests can pin the public migration contract without starting
34
+ * a PTY or importing its native dependencies.
35
+ */
36
+ export function managedPtyCompatibilityNotice(command) {
37
+ const directLaunch = command === 'monitor'
38
+ ? 'run `claude`, `codex`, or `opencode` normally'
39
+ : `run \`${command}\` directly`;
40
+ return [
41
+ `[agentdeck] LEGACY COMPATIBILITY MODE: \`agentdeck ${command}\` uses the managed per-session bridge; daemon-first launch is the recommended default.`,
42
+ `[agentdeck] For ordinary local sessions, run \`agentdeck daemon install\`, then ${directLaunch}.`,
43
+ '[agentdeck] --remote-daemon, --weight, AGENTDECK_<AGENT>_ARGS, and terminal-only controls do not yet have daemon-first equivalents. No removal date is set. Design: https://github.com/puritysb/AgentDeck/discussions/278 Tracking: https://github.com/puritysb/AgentDeck/issues/273',
44
+ ];
45
+ }
46
+ function warnManagedPtyCompatibility(command) {
47
+ for (const line of managedPtyCompatibilityNotice(command))
48
+ console.error(line);
49
+ }
31
50
  function log(msg) {
32
51
  process.stderr.write(msg + '\n');
33
52
  }
@@ -323,6 +342,14 @@ for (const b of ESP32_OTA_BOARDS) {
323
342
  export function resolveEsp32OtaDaemonTarget(target) {
324
343
  return ESP32_OTA_BY_TARGET[target]?.board ?? target;
325
344
  }
345
+ export function inlineOtaPayload(target, firmwareB64, opts = {}) {
346
+ return {
347
+ target,
348
+ firmwareB64,
349
+ ...(opts.stage ? { stage: true } : {}),
350
+ ...(opts.identity ?? {}),
351
+ };
352
+ }
326
353
  /** Resolve one exact OTA namespace from an integration manifest. Ambiguity is
327
354
  * an error: a release command must never guess which product or channel owns
328
355
  * an image. */
@@ -552,7 +579,7 @@ weatherCommand
552
579
  // ===== Agent session commands =====
553
580
  program
554
581
  .command('claude')
555
- .description('Start Claude Code session (PTY + bridge)')
582
+ .description('[legacy compatibility] Start Claude Code in the managed PTY session bridge')
556
583
  .option('-p, --port <port>', 'Bridge server port', String(BRIDGE_WS_PORT))
557
584
  .option('-c, --command <cmd>', 'Command to spawn', 'claude')
558
585
  .option('-d, --debug', 'Enable debug logging')
@@ -568,6 +595,7 @@ program
568
595
  .option('--no-env-args', 'Ignore AGENTDECK_COMMANDER_ARGS and AGENTDECK_<AGENT>_ARGS for this invocation')
569
596
  .option('--weight <n>', 'Deck/tab sort order override (integer, lower first; default 0)', parseWeight)
570
597
  .action(async (opts) => {
598
+ warnManagedPtyCompatibility('claude');
571
599
  warnIfDaemonHostIgnored(opts);
572
600
  const { startSession } = await import('./index.js');
573
601
  await startSession({
@@ -596,7 +624,7 @@ program
596
624
  });
597
625
  program
598
626
  .command('codex')
599
- .description('Start Codex CLI session (PTY + bridge)')
627
+ .description('[legacy compatibility] Start Codex in the managed PTY session bridge')
600
628
  .option('-p, --port <port>', 'Bridge server port', String(BRIDGE_WS_PORT))
601
629
  .option('-c, --command <cmd>', 'Command to spawn', 'codex')
602
630
  .option('-d, --debug', 'Enable debug logging')
@@ -610,6 +638,7 @@ program
610
638
  .option('--no-env-args', 'Ignore AGENTDECK_COMMANDER_ARGS and AGENTDECK_<AGENT>_ARGS for this invocation')
611
639
  .option('--weight <n>', 'Deck/tab sort order override (integer, lower first; default 0)', parseWeight)
612
640
  .action(async (opts) => {
641
+ warnManagedPtyCompatibility('codex');
613
642
  warnIfDaemonHostIgnored(opts);
614
643
  // Install Codex lifecycle hooks before starting the session so the
615
644
  // first prompt's UserPromptSubmit / Stop events reach the daemon.
@@ -657,7 +686,7 @@ program
657
686
  });
658
687
  program
659
688
  .command('opencode')
660
- .description('Start OpenCode session (PTY + SSE bridge)')
689
+ .description('[legacy compatibility] Start OpenCode in the managed PTY/SSE session bridge')
661
690
  .option('-p, --port <port>', 'Bridge server port', String(BRIDGE_WS_PORT))
662
691
  .option('-c, --command <cmd>', 'Command to spawn', 'opencode')
663
692
  .option('-d, --debug', 'Enable debug logging')
@@ -671,6 +700,7 @@ program
671
700
  .option('--no-env-args', 'Ignore AGENTDECK_COMMANDER_ARGS and AGENTDECK_<AGENT>_ARGS for this invocation')
672
701
  .option('--weight <n>', 'Deck/tab sort order override (integer, lower first; default 0)', parseWeight)
673
702
  .action(async (opts) => {
703
+ warnManagedPtyCompatibility('opencode');
674
704
  warnIfDaemonHostIgnored(opts);
675
705
  // Install the OpenCode observer plugin so standalone `opencode` runs
676
706
  // (outside this managed session) also reach the daemon timeline. The
@@ -715,7 +745,7 @@ program
715
745
  });
716
746
  program
717
747
  .command('monitor')
718
- .description('Start hook-only bridge (no PTY — run claude separately)')
748
+ .description('[legacy compatibility] Start the managed hook-only per-session bridge')
719
749
  .option('-p, --port <port>', 'Bridge server port', String(BRIDGE_WS_PORT))
720
750
  .option('-d, --debug', 'Enable debug logging')
721
751
  .option('--local', 'Disable all device modules')
@@ -726,6 +756,7 @@ program
726
756
  .option('--no-env-args', 'Ignore AGENTDECK_COMMANDER_ARGS for this invocation')
727
757
  .option('--weight <n>', 'Deck/tab sort order override (integer, lower first; default 0)', parseWeight)
728
758
  .action(async (opts) => {
759
+ warnManagedPtyCompatibility('monitor');
729
760
  warnIfDaemonHostIgnored(opts);
730
761
  const { startSession } = await import('./index.js');
731
762
  const port = parseInt(opts.port, 10);
@@ -1889,7 +1920,17 @@ program
1889
1920
  // Pull-OTA staging: for wake-sync-sleep boards (XTeink X3/X4) that never
1890
1921
  // hold a live WS. The daemon adverts the build on the board's feed pulls;
1891
1922
  // the board downloads + flashes itself on its next wake.
1892
- const { statusCode, body } = await postJsonWithTimeout(`http://127.0.0.1:${port}/esp32/ota`, { target: daemonTarget, firmwarePath, stage: true, ...(otaIdentity ?? {}) }, 30_000);
1923
+ let { statusCode, body } = await postJsonWithTimeout(`http://127.0.0.1:${port}/esp32/ota`, { target: daemonTarget, firmwarePath, stage: true, ...(otaIdentity ?? {}) }, 30_000);
1924
+ if (body.ok === false && String(body.error ?? '').startsWith('firmware_unreadable')) {
1925
+ // The App Store daemon cannot reopen an arbitrary CLI path. Preserve
1926
+ // the stage bit and exact product namespace when retrying inline — the
1927
+ // live-OTA retry below is a different operation and must not consume a
1928
+ // pull-stage request by accident.
1929
+ log('Daemon cannot read the firmware path (sandbox) — resending stage inline...');
1930
+ const { readFileSync } = await import('fs');
1931
+ const firmwareB64 = readFileSync(firmwarePath).toString('base64');
1932
+ ({ statusCode, body } = await postJsonWithTimeout(`http://127.0.0.1:${port}/esp32/ota`, inlineOtaPayload(daemonTarget, firmwareB64, { stage: true, identity: otaIdentity }), 30_000));
1933
+ }
1893
1934
  if (statusCode < 200 || statusCode >= 300 || body.ok === false) {
1894
1935
  throw new Error(String(body.error ?? `HTTP ${statusCode}`));
1895
1936
  }
@@ -1919,7 +1960,7 @@ program
1919
1960
  log('Daemon cannot read the firmware path (sandbox) — resending inline...');
1920
1961
  const { readFileSync } = await import('fs');
1921
1962
  const firmwareB64 = readFileSync(firmwarePath).toString('base64');
1922
- ({ statusCode, body } = await postJsonWithTimeout(`http://127.0.0.1:${port}/esp32/ota`, { target: daemonTarget, firmwareB64 }, 15 * 60_000));
1963
+ ({ statusCode, body } = await postJsonWithTimeout(`http://127.0.0.1:${port}/esp32/ota`, inlineOtaPayload(daemonTarget, firmwareB64), 15 * 60_000));
1923
1964
  }
1924
1965
  if (statusCode < 200 || statusCode >= 300 || body.ok === false) {
1925
1966
  throw new Error(String(body.error ?? `HTTP ${statusCode}`));
@@ -2344,8 +2385,8 @@ program
2344
2385
  .option('--json', 'Print target diagnostics as machine-readable JSON')
2345
2386
  .action(async (target, opts) => {
2346
2387
  if (target) {
2347
- if (target !== 'kiro') {
2348
- log(`Unknown diagnostic target: ${target}. Supported target: kiro`);
2388
+ if (target !== 'kiro' && target !== 'agents') {
2389
+ log(`Unknown diagnostic target: ${target}. Supported targets: agents, kiro`);
2349
2390
  process.exitCode = 1;
2350
2391
  return;
2351
2392
  }
@@ -2354,6 +2395,12 @@ program
2354
2395
  process.exitCode = 1;
2355
2396
  return;
2356
2397
  }
2398
+ if (target === 'agents') {
2399
+ const { collectAgentCliDiagnosticReport, formatAgentCliDiagnosticReport } = await import('./agent-cli-diagnostics.js');
2400
+ const report = collectAgentCliDiagnosticReport();
2401
+ process.stdout.write(`${opts.json ? JSON.stringify(report, null, 2) : formatAgentCliDiagnosticReport(report)}\n`);
2402
+ return;
2403
+ }
2357
2404
  const { collectKiroDiagnosticReport, formatKiroDiagnosticReport } = await import('./kiro-diagnostics.js');
2358
2405
  const report = await collectKiroDiagnosticReport();
2359
2406
  process.stdout.write(`${opts.json ? JSON.stringify(report, null, 2) : formatKiroDiagnosticReport(report)}\n`);