@agentdeck/bridge 1.1.0 → 1.2.1

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 (199) 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/classifier.d.ts.map +1 -1
  15. package/dist/apme/classifier.js +18 -10
  16. package/dist/apme/classifier.js.map +1 -1
  17. package/dist/apme/claude-transcript-reader.d.ts +36 -0
  18. package/dist/apme/claude-transcript-reader.d.ts.map +1 -1
  19. package/dist/apme/claude-transcript-reader.js +78 -2
  20. package/dist/apme/claude-transcript-reader.js.map +1 -1
  21. package/dist/apme/collector.d.ts +126 -3
  22. package/dist/apme/collector.d.ts.map +1 -1
  23. package/dist/apme/collector.js +450 -41
  24. package/dist/apme/collector.js.map +1 -1
  25. package/dist/apme/dashboard-html.d.ts.map +1 -1
  26. package/dist/apme/dashboard-html.js +278 -36
  27. package/dist/apme/dashboard-html.js.map +1 -1
  28. package/dist/apme/graph.d.ts +1 -1
  29. package/dist/apme/graph.d.ts.map +1 -1
  30. package/dist/apme/graph.js +51 -1
  31. package/dist/apme/graph.js.map +1 -1
  32. package/dist/apme/http.d.ts.map +1 -1
  33. package/dist/apme/http.js +37 -5
  34. package/dist/apme/http.js.map +1 -1
  35. package/dist/apme/index.d.ts +4 -0
  36. package/dist/apme/index.d.ts.map +1 -1
  37. package/dist/apme/index.js +19 -3
  38. package/dist/apme/index.js.map +1 -1
  39. package/dist/apme/runner.d.ts +90 -0
  40. package/dist/apme/runner.d.ts.map +1 -1
  41. package/dist/apme/runner.js +524 -48
  42. package/dist/apme/runner.js.map +1 -1
  43. package/dist/apme/sample-to-timeline.d.ts.map +1 -1
  44. package/dist/apme/sample-to-timeline.js +5 -0
  45. package/dist/apme/sample-to-timeline.js.map +1 -1
  46. package/dist/apme/settings.d.ts +8 -0
  47. package/dist/apme/settings.d.ts.map +1 -1
  48. package/dist/apme/settings.js +4 -0
  49. package/dist/apme/settings.js.map +1 -1
  50. package/dist/apme/store.d.ts +118 -9
  51. package/dist/apme/store.d.ts.map +1 -1
  52. package/dist/apme/store.js +342 -44
  53. package/dist/apme/store.js.map +1 -1
  54. package/dist/apme/task-gradeability.d.ts +82 -0
  55. package/dist/apme/task-gradeability.d.ts.map +1 -0
  56. package/dist/apme/task-gradeability.js +126 -0
  57. package/dist/apme/task-gradeability.js.map +1 -0
  58. package/dist/awaiting-overlay.d.ts +13 -26
  59. package/dist/awaiting-overlay.d.ts.map +1 -1
  60. package/dist/awaiting-overlay.js +7 -40
  61. package/dist/awaiting-overlay.js.map +1 -1
  62. package/dist/bridge-core.d.ts +15 -0
  63. package/dist/bridge-core.d.ts.map +1 -1
  64. package/dist/bridge-core.js +30 -4
  65. package/dist/bridge-core.js.map +1 -1
  66. package/dist/claude-permission-rules.d.ts +20 -32
  67. package/dist/claude-permission-rules.d.ts.map +1 -1
  68. package/dist/claude-permission-rules.js +19 -102
  69. package/dist/claude-permission-rules.js.map +1 -1
  70. package/dist/claude-usage-recovery.d.ts +54 -0
  71. package/dist/claude-usage-recovery.d.ts.map +1 -0
  72. package/dist/claude-usage-recovery.js +200 -0
  73. package/dist/claude-usage-recovery.js.map +1 -0
  74. package/dist/cli.d.ts +11 -0
  75. package/dist/cli.d.ts.map +1 -1
  76. package/dist/cli.js +81 -14
  77. package/dist/cli.js.map +1 -1
  78. package/dist/codex-rate-limits-live.d.ts +180 -10
  79. package/dist/codex-rate-limits-live.d.ts.map +1 -1
  80. package/dist/codex-rate-limits-live.js +475 -22
  81. package/dist/codex-rate-limits-live.js.map +1 -1
  82. package/dist/codex-rollout-response.d.ts +43 -0
  83. package/dist/codex-rollout-response.d.ts.map +1 -1
  84. package/dist/codex-rollout-response.js +67 -0
  85. package/dist/codex-rollout-response.js.map +1 -1
  86. package/dist/coordination-evidence.d.ts +150 -0
  87. package/dist/coordination-evidence.d.ts.map +1 -0
  88. package/dist/coordination-evidence.js +455 -0
  89. package/dist/coordination-evidence.js.map +1 -0
  90. package/dist/daemon-server.d.ts.map +1 -1
  91. package/dist/daemon-server.js +592 -35
  92. package/dist/daemon-server.js.map +1 -1
  93. package/dist/daemon-ws-client.d.ts +1 -0
  94. package/dist/daemon-ws-client.d.ts.map +1 -1
  95. package/dist/daemon-ws-client.js +25 -16
  96. package/dist/daemon-ws-client.js.map +1 -1
  97. package/dist/daemon.js +1 -1
  98. package/dist/deferred-reply-read.d.ts +24 -0
  99. package/dist/deferred-reply-read.d.ts.map +1 -0
  100. package/dist/deferred-reply-read.js +42 -0
  101. package/dist/deferred-reply-read.js.map +1 -0
  102. package/dist/esp32-serial.d.ts +15 -0
  103. package/dist/esp32-serial.d.ts.map +1 -1
  104. package/dist/esp32-serial.js +61 -2
  105. package/dist/esp32-serial.js.map +1 -1
  106. package/dist/font-pack.d.ts +15 -0
  107. package/dist/font-pack.d.ts.map +1 -0
  108. package/dist/font-pack.js +75 -0
  109. package/dist/font-pack.js.map +1 -0
  110. package/dist/glance-frame.d.ts.map +1 -1
  111. package/dist/glance-frame.js +2 -0
  112. package/dist/glance-frame.js.map +1 -1
  113. package/dist/hook-codex-sessions.d.ts +9 -0
  114. package/dist/hook-codex-sessions.d.ts.map +1 -1
  115. package/dist/hook-codex-sessions.js +35 -2
  116. package/dist/hook-codex-sessions.js.map +1 -1
  117. package/dist/hook-opencode-sessions.d.ts +62 -0
  118. package/dist/hook-opencode-sessions.d.ts.map +1 -0
  119. package/dist/hook-opencode-sessions.js +180 -0
  120. package/dist/hook-opencode-sessions.js.map +1 -0
  121. package/dist/hook-response-source.d.ts +40 -0
  122. package/dist/hook-response-source.d.ts.map +1 -0
  123. package/dist/hook-response-source.js +31 -0
  124. package/dist/hook-response-source.js.map +1 -0
  125. package/dist/http-auth-gate.d.ts.map +1 -1
  126. package/dist/http-auth-gate.js +9 -1
  127. package/dist/http-auth-gate.js.map +1 -1
  128. package/dist/index.d.ts.map +1 -1
  129. package/dist/index.js +6 -3
  130. package/dist/index.js.map +1 -1
  131. package/dist/learning-pack.d.ts +24 -0
  132. package/dist/learning-pack.d.ts.map +1 -0
  133. package/dist/learning-pack.js +125 -0
  134. package/dist/learning-pack.js.map +1 -0
  135. package/dist/mdns.js +1 -1
  136. package/dist/mdns.js.map +1 -1
  137. package/dist/native-dependency-diagnostics.d.ts +29 -0
  138. package/dist/native-dependency-diagnostics.d.ts.map +1 -0
  139. package/dist/native-dependency-diagnostics.js +95 -0
  140. package/dist/native-dependency-diagnostics.js.map +1 -0
  141. package/dist/observed-steering.d.ts +4 -4
  142. package/dist/observed-steering.d.ts.map +1 -1
  143. package/dist/observed-steering.js +28 -32
  144. package/dist/observed-steering.js.map +1 -1
  145. package/dist/openclaw-gateway-stability.d.ts +94 -0
  146. package/dist/openclaw-gateway-stability.d.ts.map +1 -0
  147. package/dist/openclaw-gateway-stability.js +176 -0
  148. package/dist/openclaw-gateway-stability.js.map +1 -0
  149. package/dist/pairing-knocks.d.ts +80 -0
  150. package/dist/pairing-knocks.d.ts.map +1 -0
  151. package/dist/pairing-knocks.js +312 -0
  152. package/dist/pairing-knocks.js.map +1 -0
  153. package/dist/passive-observer.d.ts +5 -0
  154. package/dist/passive-observer.d.ts.map +1 -1
  155. package/dist/passive-observer.js +6 -0
  156. package/dist/passive-observer.js.map +1 -1
  157. package/dist/pixoo/micro-glyphs.d.ts +4 -0
  158. package/dist/pixoo/micro-glyphs.d.ts.map +1 -1
  159. package/dist/pixoo/micro-glyphs.js +29 -0
  160. package/dist/pixoo/micro-glyphs.js.map +1 -1
  161. package/dist/pixoo/pixoo-font.d.ts.map +1 -1
  162. package/dist/pixoo/pixoo-font.js +3 -1
  163. package/dist/pixoo/pixoo-font.js.map +1 -1
  164. package/dist/pixoo/pixoo-renderer.d.ts +1 -1
  165. package/dist/pixoo/pixoo-renderer.d.ts.map +1 -1
  166. package/dist/pixoo/pixoo-renderer.js +17 -2
  167. package/dist/pixoo/pixoo-renderer.js.map +1 -1
  168. package/dist/pty-manager.d.ts +9 -0
  169. package/dist/pty-manager.d.ts.map +1 -1
  170. package/dist/pty-manager.js +63 -4
  171. package/dist/pty-manager.js.map +1 -1
  172. package/dist/relayed-usage.d.ts +30 -0
  173. package/dist/relayed-usage.d.ts.map +1 -1
  174. package/dist/relayed-usage.js +25 -2
  175. package/dist/relayed-usage.js.map +1 -1
  176. package/dist/review-runner.js +1 -1
  177. package/dist/subagent-timeline.d.ts +27 -0
  178. package/dist/subagent-timeline.d.ts.map +1 -1
  179. package/dist/subagent-timeline.js +52 -5
  180. package/dist/subagent-timeline.js.map +1 -1
  181. package/dist/surface-protocol.d.ts.map +1 -1
  182. package/dist/surface-protocol.js +2 -0
  183. package/dist/surface-protocol.js.map +1 -1
  184. package/dist/tui/dashboard.d.ts.map +1 -1
  185. package/dist/tui/dashboard.js +8 -1
  186. package/dist/tui/dashboard.js.map +1 -1
  187. package/dist/usage-api.d.ts +3 -0
  188. package/dist/usage-api.d.ts.map +1 -1
  189. package/dist/usage-api.js +101 -36
  190. package/dist/usage-api.js.map +1 -1
  191. package/dist/usage-event.d.ts.map +1 -1
  192. package/dist/usage-event.js +2 -1
  193. package/dist/usage-event.js.map +1 -1
  194. package/dist/ws-server.d.ts +18 -0
  195. package/dist/ws-server.d.ts.map +1 -1
  196. package/dist/ws-server.js +40 -2
  197. package/dist/ws-server.js.map +1 -1
  198. package/package.json +6 -5
  199. package/src/timebox/sync_ble.py +35 -16
@@ -0,0 +1,200 @@
1
+ import { execFile } from 'child_process';
2
+ import { createHash } from 'crypto';
3
+ import { mkdirSync, readFileSync, renameSync, statSync, writeFileSync } from 'fs';
4
+ import { homedir, tmpdir } from 'os';
5
+ import { delimiter, join, resolve } from 'path';
6
+ import { logTagged } from './logger.js';
7
+ const RECOVERY_TIMEOUT_MS = 25_000;
8
+ const RETRY_MS = 30 * 60_000;
9
+ const LONG_RETRY_MS = 6 * 60 * 60_000;
10
+ /** The daemon's data directory — `AGENTDECK_DATA_DIR` when set, else
11
+ * `~/.agentdeck`. Every other file in that directory resolves it this way; the
12
+ * cooldown record did not, so two daemons pointed at different data dirs
13
+ * silently shared one retry budget and each spent the other's quota. Kept
14
+ * identical to `usage-api.ts`'s AGENTDECK_DIR — they are the same directory,
15
+ * and item 5 of #286 is explicit that both move together or neither does. */
16
+ const AGENTDECK_DIR = process.env.AGENTDECK_DATA_DIR || join(homedir(), '.agentdeck');
17
+ export const CLAUDE_USAGE_RECOVERY_FILE = join(AGENTDECK_DIR, 'claude-usage-recovery.json');
18
+ /** Claude owns the rotating refresh token and its interprocess lock. Never copy,
19
+ * rotate, or write those credentials ourselves. This bounded turn may consume a
20
+ * small amount of subscription quota; it carries no workspace or user content.
21
+ * --bare is NOT appropriate: that mode explicitly disables OAuth/keychain reads.
22
+ * An older CLI rejecting --safe-mode fails closed rather than loading hooks.
23
+ */
24
+ export const CLAUDE_USAGE_RECOVERY_ARGS = [
25
+ '--safe-mode', '--print', '--tools', '', '--strict-mcp-config',
26
+ '--mcp-config', '{"mcpServers":{}}', '--settings', '{"disableAllHooks":true}',
27
+ '--no-session-persistence', '--disable-slash-commands', '--no-chrome',
28
+ '--model', 'haiku', '--max-turns', '1', '--max-budget-usd', '0.01',
29
+ '--system-prompt', 'Reply with OK.', '--output-format', 'json', 'Reply with OK.',
30
+ ];
31
+ /** Keep the recovery CLI on the same credential store as usage-api.ts.
32
+ * On macOS that reader targets the default Keychain service; a custom config
33
+ * directory can select a DIFFERENT Keychain namespace in Claude. Fail closed
34
+ * rather than spend quota or renew an unrelated account. On other platforms,
35
+ * resolve relative paths before the child changes cwd to the temporary folder.
36
+ */
37
+ export function buildClaudeUsageRecoveryEnv(source = process.env, platform = process.platform, home = homedir()) {
38
+ const env = { ...source, CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: '1' };
39
+ if (env.CLAUDE_CONFIG_DIR) {
40
+ const configDir = resolve(env.CLAUDE_CONFIG_DIR);
41
+ if (platform === 'darwin' && configDir !== join(home, '.claude'))
42
+ return null;
43
+ env.CLAUDE_CONFIG_DIR = configDir;
44
+ }
45
+ // A daemon started from an agent must not be mistaken for its nested session.
46
+ // API-key / provider overrides must not redirect an OAuth recovery request.
47
+ for (const key of Object.keys(env)) {
48
+ if (key === 'CLAUDECODE' || key === 'ANTHROPIC_API_KEY' || key === 'ANTHROPIC_AUTH_TOKEN'
49
+ || key === 'ANTHROPIC_BASE_URL' || key === 'CLAUDE_CODE_OAUTH_TOKEN'
50
+ || key.startsWith('CLAUDE_CODE_USE_') || key.startsWith('AGENTDECK_'))
51
+ delete env[key];
52
+ }
53
+ return env;
54
+ }
55
+ /** `execFile` runs one executable — it does not search PATHEXT and (since the
56
+ * Node 20.12/18.20 spawn hardening) will not run a `.cmd`/`.bat` shim without a
57
+ * shell. A bare `'claude'` was therefore ENOENT on every Windows install, and a
58
+ * LaunchAgent carries the installing shell's PATH, which may not contain the
59
+ * CLI at all — both surfaced only as a recurring generic failure line. Resolve
60
+ * the real file once so the unavailable case can SAY it is unavailable.
61
+ * Returns `{ shim: true }` for a Windows shell shim: shell-quoting a JSON
62
+ * argument through cmd.exe is a worse failure than declining, so recovery is
63
+ * skipped there and says so. */
64
+ export function resolveClaudeCli(env = process.env, platform = process.platform) {
65
+ const isFile = (candidate) => {
66
+ try {
67
+ return statSync(candidate).isFile();
68
+ }
69
+ catch {
70
+ return false;
71
+ }
72
+ };
73
+ const override = env.AGENTDECK_CLAUDE_CLI;
74
+ if (override)
75
+ return isFile(override) ? { path: override, shim: false } : null;
76
+ const exts = platform === 'win32'
77
+ ? (env.PATHEXT || '.COM;.EXE;.BAT;.CMD').split(';').filter(Boolean)
78
+ : [''];
79
+ for (const dir of (env.PATH || '').split(delimiter).filter(Boolean)) {
80
+ for (const ext of exts) {
81
+ const candidate = join(dir, `claude${ext}`);
82
+ if (isFile(candidate))
83
+ return { path: candidate, shim: /\.(cmd|bat)$/i.test(ext) };
84
+ }
85
+ }
86
+ return null;
87
+ }
88
+ let reportedUnavailable = false;
89
+ function reportUnavailableOnce(reason) {
90
+ if (reportedUnavailable)
91
+ return;
92
+ reportedUnavailable = true;
93
+ logTagged('usage', `Claude authorization recovery unavailable: ${reason}`);
94
+ }
95
+ export function runClaudeUsageRecovery() {
96
+ const env = buildClaudeUsageRecoveryEnv();
97
+ if (!env) {
98
+ logTagged('usage', 'Claude authorization recovery skipped: custom macOS credential namespace cannot be matched');
99
+ return Promise.resolve();
100
+ }
101
+ const cli = resolveClaudeCli(env);
102
+ if (!cli) {
103
+ reportUnavailableOnce('the claude CLI was not found on this daemon\'s PATH (set AGENTDECK_CLAUDE_CLI to its full path)');
104
+ return Promise.resolve();
105
+ }
106
+ if (cli.shim) {
107
+ reportUnavailableOnce(`only a shell shim is installed (${cli.path}); point AGENTDECK_CLAUDE_CLI at an executable`);
108
+ return Promise.resolve();
109
+ }
110
+ return new Promise((resolve) => {
111
+ const child = execFile(cli.path, CLAUDE_USAGE_RECOVERY_ARGS, {
112
+ cwd: tmpdir(), env, timeout: RECOVERY_TIMEOUT_MS, killSignal: 'SIGKILL',
113
+ maxBuffer: 64 * 1024, windowsHide: true,
114
+ }, (error) => {
115
+ if (error)
116
+ logTagged('usage', `Claude authorization recovery CLI ended (${error.killed ? 'timeout' : error.code ?? 'failed'})`);
117
+ resolve(); // Outcome is verified by re-reading credentials, never stdout.
118
+ });
119
+ child.stdin?.end();
120
+ // The child holds no port and gates no shutdown, but a clean stop that
121
+ // SIGKILLs the daemon takes `execFile`'s timeout with it — the orphan then
122
+ // runs unbounded. Track it so shutdown can end it, and unref it so it can
123
+ // never be the reason this process stays alive.
124
+ child.unref();
125
+ liveRecoveryChildren.add(child);
126
+ // `close`, not `exit`: a spawn that fails outright (the resolved binary
127
+ // vanished between the probe and the spawn) emits `error` + `close` and
128
+ // never `exit`, so an `exit` listener retains a dead ChildProcess for the
129
+ // life of the daemon — one per attempt, against a comment that says "at
130
+ // most one". `close` fires on both paths.
131
+ child.once('close', () => liveRecoveryChildren.delete(child));
132
+ });
133
+ }
134
+ /** Recovery children currently running. At most one — the class serializes on
135
+ * `pending` — but a Set costs nothing and cannot go negative. */
136
+ const liveRecoveryChildren = new Set();
137
+ /** Kill any in-flight recovery child. Called from the daemon's shutdown path;
138
+ * safe to call with none running. */
139
+ export function stopClaudeUsageRecoveryChildren() {
140
+ for (const child of liveRecoveryChildren) {
141
+ try {
142
+ child.kill('SIGKILL');
143
+ }
144
+ catch { /* already gone */ }
145
+ }
146
+ liveRecoveryChildren.clear();
147
+ }
148
+ /** Single daemon owner; persisted cooldown also survives daemon restart. */
149
+ export class ClaudeUsageRecovery {
150
+ deps;
151
+ pending = null;
152
+ record = null;
153
+ constructor(deps) {
154
+ this.deps = deps;
155
+ }
156
+ async recover(accessToken) {
157
+ if (this.pending)
158
+ return this.pending;
159
+ const credentialHash = createHash('sha256').update(accessToken).digest('hex');
160
+ const previous = this.record ?? this.deps.read();
161
+ if (previous && this.deps.now() < previous.nextAttemptAt)
162
+ return;
163
+ const attempts = previous?.credentialHash === credentialHash ? previous.attempts + 1 : 1;
164
+ this.record = { credentialHash, attempts,
165
+ nextAttemptAt: this.deps.now() + (attempts >= 3 ? LONG_RETRY_MS : RETRY_MS) };
166
+ // Record BEFORE spawning: a crash/restart must not cause a recovery loop.
167
+ try {
168
+ this.deps.write(this.record);
169
+ }
170
+ catch {
171
+ return;
172
+ }
173
+ logTagged('usage', `Claude usage authorization expired — requesting bounded CLI recovery (attempt ${attempts})`);
174
+ this.pending = this.deps.run().catch(() => { }).finally(() => { this.pending = null; });
175
+ return this.pending;
176
+ }
177
+ }
178
+ export const claudeUsageRecovery = new ClaudeUsageRecovery({
179
+ now: Date.now,
180
+ read: () => {
181
+ try {
182
+ const r = JSON.parse(readFileSync(CLAUDE_USAGE_RECOVERY_FILE, 'utf8'));
183
+ return typeof r.credentialHash === 'string' && Number.isFinite(r.attempts)
184
+ && Number.isFinite(r.nextAttemptAt) ? r : null;
185
+ }
186
+ catch {
187
+ return null;
188
+ }
189
+ },
190
+ write: (record) => {
191
+ mkdirSync(AGENTDECK_DIR, { recursive: true });
192
+ // tmp+rename like every other file in this directory: a torn write reads
193
+ // back as "no cooldown", which is the one failure that spends quota.
194
+ const tmp = `${CLAUDE_USAGE_RECOVERY_FILE}.${process.pid}.tmp`;
195
+ writeFileSync(tmp, JSON.stringify(record), { mode: 0o600 });
196
+ renameSync(tmp, CLAUDE_USAGE_RECOVERY_FILE);
197
+ },
198
+ run: runClaudeUsageRecovery,
199
+ });
200
+ //# sourceMappingURL=claude-usage-recovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-usage-recovery.js","sourceRoot":"","sources":["../src/claude-usage-recovery.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts CHANGED
@@ -1,5 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from 'commander';
3
+ export type LegacySessionCommand = 'claude' | 'codex' | 'opencode' | 'monitor';
4
+ /**
5
+ * User-visible compatibility notice for the legacy per-session bridge. Keep
6
+ * this pure so CLI tests can pin the public migration contract without starting
7
+ * a PTY or importing its native dependencies.
8
+ */
9
+ export declare function managedPtyCompatibilityNotice(command: LegacySessionCommand): string[];
3
10
  export declare function daemonPostureArgs(opts: {
4
11
  local?: boolean;
5
12
  loopback?: boolean;
@@ -22,6 +29,10 @@ export interface CliOtaIdentity {
22
29
  board: string;
23
30
  updateChannel: string;
24
31
  }
32
+ export declare function inlineOtaPayload(target: string, firmwareB64: string, opts?: {
33
+ stage?: boolean;
34
+ identity?: CliOtaIdentity;
35
+ }): Record<string, unknown>;
25
36
  /** Resolve one exact OTA namespace from an integration manifest. Ambiguity is
26
37
  * an error: a release command must never guess which product or channel owns
27
38
  * an image. */
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAwB,MAAM,WAAW,CAAC;AA6M1D,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,EAAE,CAQ/G;AAED,wBAAgB,UAAU,CAAC,SAAS,GAAE,MAAM,EAAO,GAAG,MAAM,CAmC3D;AAgGD,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAM,CAAC;AAOtF;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAElE;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;eAEe;AACf,wBAAgB,8BAA8B,CAC5C,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,MAAM,EAClB,aAAa,CAAC,EAAE,MAAM,GACrB,cAAc,CAmBhB;AA+BD,gFAAgF;AAChF,QAAA,MAAM,cAAc,EAAE,MAAM,CAAC,aAAa,GAAG,WAAW,GAAG,UAAU,EAAE,MAAM,CAI5E,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAsBjE;AAKD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,EAAE,CAyBV;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,OAAO,cAAc,EACtC,OAAO,EAAE,MAAM,EACf,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CAIR;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,OAAO,cAAc,EACtC,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,OAAO,EACvB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CAER;AAID,QAAA,MAAM,OAAO,SAAgB,CAAC;AAyuB9B;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,EACX,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,EAC/D,cAAc,EAAE,MAAM;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,EACjE,cAAc,EAAE,MAAM,MAAM,GAAG,IAAI,EACnC,SAAS,SAAS;AAClB;;;;;;;;;;;;;;;GAeG;AACH,YAAY,CAAC,EAAE,MAAM,OAAO,EAC5B,SAAS,SAAU,EACnB,cAAc,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GACrC,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CA4B/C;AA44ED,wBAAsB,MAAM,CAAC,IAAI,GAAE,MAAM,EAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAMzE;AAED,OAAO,EAAE,OAAO,EAAE,CAAC"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
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);
@@ -1246,8 +1277,13 @@ daemon
1246
1277
  const targetPort = registryPort ?? port;
1247
1278
  try {
1248
1279
  const res = await fetch(`http://127.0.0.1:${targetPort}/health`);
1249
- const data = await res.json();
1280
+ const data = (await res.json());
1250
1281
  log(`Daemon status (port ${targetPort}): ${JSON.stringify(data, null, 2)}`);
1282
+ const apmeHealth = data.apme;
1283
+ if (apmeHealth?.enabled === false) {
1284
+ log(`WARNING: APME evaluation is disabled${typeof apmeHealth.error === 'string' ? ` — ${apmeHealth.error}` : '.'}`);
1285
+ log('Run `agentdeck diag native` for the exact Node executable, ABI, and recovery command.');
1286
+ }
1251
1287
  // A daemon on a fallback port keeps working — clients resolve it from
1252
1288
  // daemon.json — so nothing else ever says it happened. Without this line
1253
1289
  // the only symptom is that the canonical port is owned by nobody.
@@ -1343,6 +1379,12 @@ daemon
1343
1379
  .option('--loopback', 'Alias for --enterprise')
1344
1380
  .action(async (opts) => {
1345
1381
  const postureArgs = daemonPostureArgs(opts);
1382
+ const { collectNativeDependencyDiagnostic, formatNativeDependencyDiagnosticReport, } = await import('./native-dependency-diagnostics.js');
1383
+ const nativeReport = collectNativeDependencyDiagnostic();
1384
+ if (!nativeReport.ok) {
1385
+ log('WARNING: daemon autostart will be registered, but APME evaluation cannot start under this runtime.');
1386
+ log(formatNativeDependencyDiagnosticReport(nativeReport));
1387
+ }
1346
1388
  if (postureArgs.length > 0) {
1347
1389
  log(`Autostart posture: ${postureArgs.join(' ')} (baked into the autostart unit's arguments).`);
1348
1390
  }
@@ -1889,7 +1931,17 @@ program
1889
1931
  // Pull-OTA staging: for wake-sync-sleep boards (XTeink X3/X4) that never
1890
1932
  // hold a live WS. The daemon adverts the build on the board's feed pulls;
1891
1933
  // 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);
1934
+ let { statusCode, body } = await postJsonWithTimeout(`http://127.0.0.1:${port}/esp32/ota`, { target: daemonTarget, firmwarePath, stage: true, ...(otaIdentity ?? {}) }, 30_000);
1935
+ if (body.ok === false && String(body.error ?? '').startsWith('firmware_unreadable')) {
1936
+ // The App Store daemon cannot reopen an arbitrary CLI path. Preserve
1937
+ // the stage bit and exact product namespace when retrying inline — the
1938
+ // live-OTA retry below is a different operation and must not consume a
1939
+ // pull-stage request by accident.
1940
+ log('Daemon cannot read the firmware path (sandbox) — resending stage inline...');
1941
+ const { readFileSync } = await import('fs');
1942
+ const firmwareB64 = readFileSync(firmwarePath).toString('base64');
1943
+ ({ statusCode, body } = await postJsonWithTimeout(`http://127.0.0.1:${port}/esp32/ota`, inlineOtaPayload(daemonTarget, firmwareB64, { stage: true, identity: otaIdentity }), 30_000));
1944
+ }
1893
1945
  if (statusCode < 200 || statusCode >= 300 || body.ok === false) {
1894
1946
  throw new Error(String(body.error ?? `HTTP ${statusCode}`));
1895
1947
  }
@@ -1919,7 +1971,7 @@ program
1919
1971
  log('Daemon cannot read the firmware path (sandbox) — resending inline...');
1920
1972
  const { readFileSync } = await import('fs');
1921
1973
  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));
1974
+ ({ statusCode, body } = await postJsonWithTimeout(`http://127.0.0.1:${port}/esp32/ota`, inlineOtaPayload(daemonTarget, firmwareB64), 15 * 60_000));
1923
1975
  }
1924
1976
  if (statusCode < 200 || statusCode >= 300 || body.ok === false) {
1925
1977
  throw new Error(String(body.error ?? `HTTP ${statusCode}`));
@@ -2337,15 +2389,15 @@ program
2337
2389
  });
2338
2390
  program
2339
2391
  .command('diag [target]')
2340
- .description('Generate a diagnostic dump, or a privacy-safe agent diagnostic')
2392
+ .description('Generate a diagnostic dump, or a focused agent/native-runtime diagnostic')
2341
2393
  .option('-p, --port <port>', 'Bridge server port', String(BRIDGE_WS_PORT))
2342
2394
  .option('-a, --analyze', 'Run AI analysis on the dump')
2343
2395
  .option('-t, --tail <lines>', 'Number of journal entries', '200')
2344
2396
  .option('--json', 'Print target diagnostics as machine-readable JSON')
2345
2397
  .action(async (target, opts) => {
2346
2398
  if (target) {
2347
- if (target !== 'kiro') {
2348
- log(`Unknown diagnostic target: ${target}. Supported target: kiro`);
2399
+ if (target !== 'kiro' && target !== 'agents' && target !== 'native') {
2400
+ log(`Unknown diagnostic target: ${target}. Supported targets: agents, kiro, native`);
2349
2401
  process.exitCode = 1;
2350
2402
  return;
2351
2403
  }
@@ -2354,6 +2406,20 @@ program
2354
2406
  process.exitCode = 1;
2355
2407
  return;
2356
2408
  }
2409
+ if (target === 'agents') {
2410
+ const { collectAgentCliDiagnosticReport, formatAgentCliDiagnosticReport } = await import('./agent-cli-diagnostics.js');
2411
+ const report = collectAgentCliDiagnosticReport();
2412
+ process.stdout.write(`${opts.json ? JSON.stringify(report, null, 2) : formatAgentCliDiagnosticReport(report)}\n`);
2413
+ return;
2414
+ }
2415
+ if (target === 'native') {
2416
+ const { collectNativeDependencyDiagnostic, formatNativeDependencyDiagnosticReport, } = await import('./native-dependency-diagnostics.js');
2417
+ const report = collectNativeDependencyDiagnostic();
2418
+ process.stdout.write(`${opts.json ? JSON.stringify(report, null, 2) : formatNativeDependencyDiagnosticReport(report)}\n`);
2419
+ if (!report.ok)
2420
+ process.exitCode = 1;
2421
+ return;
2422
+ }
2357
2423
  const { collectKiroDiagnosticReport, formatKiroDiagnosticReport } = await import('./kiro-diagnostics.js');
2358
2424
  const report = await collectKiroDiagnosticReport();
2359
2425
  process.stdout.write(`${opts.json ? JSON.stringify(report, null, 2) : formatKiroDiagnosticReport(report)}\n`);
@@ -3346,22 +3412,23 @@ apme
3346
3412
  return;
3347
3413
  }
3348
3414
  log(`\n Turns started in the last ${opts.since} — how each one's end was learned`);
3349
- log(` ${'Agent'.padEnd(14)} ${'Turns'.padEnd(7)} ${'Stop'.padEnd(7)} ${'Synth'.padEnd(7)} ${'NoStop'.padEnd(7)} ${'Esc'.padEnd(6)} ${'Abort'.padEnd(6)} ${'Folded'.padEnd(7)} ${'SessEnd'.padEnd(8)} ${'Open'.padEnd(6)} ${'?'.padEnd(6)} Stop loss`);
3350
- log(` ${'─'.repeat(14)} ${'─'.repeat(7)} ${'─'.repeat(7)} ${'─'.repeat(7)} ${'─'.repeat(7)} ${'─'.repeat(6)} ${'─'.repeat(6)} ${'─'.repeat(7)} ${'─'.repeat(8)} ${'─'.repeat(6)} ${'─'.repeat(6)} ${'─'.repeat(9)}`);
3415
+ log(` ${'Agent'.padEnd(14)} ${'Turns'.padEnd(7)} ${'Stop'.padEnd(7)} ${'Synth'.padEnd(7)} ${'NoStop'.padEnd(7)} ${'Esc'.padEnd(6)} ${'Abort'.padEnd(6)} ${'Folded'.padEnd(7)} ${'SessEnd'.padEnd(8)} ${'Reaped'.padEnd(7)} ${'Open'.padEnd(6)} ${'?'.padEnd(6)} Stop loss`);
3416
+ log(` ${'─'.repeat(14)} ${'─'.repeat(7)} ${'─'.repeat(7)} ${'─'.repeat(7)} ${'─'.repeat(7)} ${'─'.repeat(6)} ${'─'.repeat(6)} ${'─'.repeat(7)} ${'─'.repeat(8)} ${'─'.repeat(7)} ${'─'.repeat(6)} ${'─'.repeat(6)} ${'─'.repeat(9)}`);
3351
3417
  for (const r of rows) {
3352
3418
  // Which buckets the ratio may read is defined once, in shared — see
3353
3419
  // `stopDeliveryLoss`. Restating it here is how the instrument would come
3354
3420
  // to measure something other than what its legend claims.
3355
3421
  const { adjudicated, ratio } = stopDeliveryLoss(r);
3356
3422
  const rate = ratio != null ? `${(ratio * 100).toFixed(0)}% of ${adjudicated}` : '—';
3357
- log(` ${r.agentType.slice(0, 14).padEnd(14)} ${String(r.total).padEnd(7)} ${String(r.stop).padEnd(7)} ${String(r.syntheticStop).padEnd(7)} ${String(r.nextPrompt).padEnd(7)} ${String(r.interrupted).padEnd(6)} ${String(r.aborted).padEnd(6)} ${String(r.superseded).padEnd(7)} ${String(r.sessionEnd).padEnd(8)} ${String(r.open).padEnd(6)} ${String(r.preInstrument).padEnd(6)} ${rate}`);
3423
+ log(` ${r.agentType.slice(0, 14).padEnd(14)} ${String(r.total).padEnd(7)} ${String(r.stop).padEnd(7)} ${String(r.syntheticStop).padEnd(7)} ${String(r.nextPrompt).padEnd(7)} ${String(r.interrupted).padEnd(6)} ${String(r.aborted).padEnd(6)} ${String(r.superseded).padEnd(7)} ${String(r.sessionEnd).padEnd(8)} ${String(r.runClose).padEnd(7)} ${String(r.open).padEnd(6)} ${String(r.preInstrument).padEnd(6)} ${rate}`);
3358
3424
  }
3359
3425
  log('');
3360
- log(' Synth = Stop hook dropped, watchdog recovered it from the transcript');
3426
+ log(" Synth = Stop hook dropped, recovered from the agent's own record (transcript watchdog; rollout at the next prompt for Codex)");
3361
3427
  log(' NoStop = Stop hook dropped and nothing recovered it (closed by the next prompt)');
3362
3428
  log(' Esc = user cancelled the turn — Claude Code owes no Stop, so not a loss');
3363
3429
  log(' Abort = usage limit / auth / API error ended the turn — no Stop is fired for those');
3364
3430
  log(' Folded = a second prompt arrived before this one ran; one turn served both');
3431
+ log(' Reaped = the run was reaped under the open turn — the daemon that would have taken its Stop was gone (a restart)');
3365
3432
  log(' ? = closed before end_source existed — signal unknown, never guessed');
3366
3433
  log('');
3367
3434
  });