@agentdeck/bridge 0.2.3 → 1.0.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 (185) hide show
  1. package/assets/fm-helper/agentdeck-fm-helper +0 -0
  2. package/dist/apme/collector.d.ts +4 -0
  3. package/dist/apme/collector.d.ts.map +1 -1
  4. package/dist/apme/collector.js +1 -0
  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 +30 -0
  8. package/dist/apme/dashboard-html.js.map +1 -1
  9. package/dist/apme/http.d.ts.map +1 -1
  10. package/dist/apme/http.js +9 -0
  11. package/dist/apme/http.js.map +1 -1
  12. package/dist/apme/index.d.ts.map +1 -1
  13. package/dist/apme/index.js +14 -3
  14. package/dist/apme/index.js.map +1 -1
  15. package/dist/apme/judge-detect.d.ts +26 -0
  16. package/dist/apme/judge-detect.d.ts.map +1 -0
  17. package/dist/apme/judge-detect.js +69 -0
  18. package/dist/apme/judge-detect.js.map +1 -0
  19. package/dist/apme/runner.d.ts +7 -0
  20. package/dist/apme/runner.d.ts.map +1 -1
  21. package/dist/apme/runner.js +188 -33
  22. package/dist/apme/runner.js.map +1 -1
  23. package/dist/apme/settings.d.ts +10 -8
  24. package/dist/apme/settings.d.ts.map +1 -1
  25. package/dist/apme/settings.js +11 -16
  26. package/dist/apme/settings.js.map +1 -1
  27. package/dist/awaiting-overlay.d.ts +17 -4
  28. package/dist/awaiting-overlay.d.ts.map +1 -1
  29. package/dist/awaiting-overlay.js +39 -8
  30. package/dist/awaiting-overlay.js.map +1 -1
  31. package/dist/bridge-core.d.ts +10 -0
  32. package/dist/bridge-core.d.ts.map +1 -1
  33. package/dist/bridge-core.js +50 -0
  34. package/dist/bridge-core.js.map +1 -1
  35. package/dist/claude-permission-rules.d.ts +55 -0
  36. package/dist/claude-permission-rules.d.ts.map +1 -0
  37. package/dist/claude-permission-rules.js +197 -0
  38. package/dist/claude-permission-rules.js.map +1 -0
  39. package/dist/cli.d.ts.map +1 -1
  40. package/dist/cli.js +10 -1
  41. package/dist/cli.js.map +1 -1
  42. package/dist/d200h/hid-protocol.d.ts +62 -0
  43. package/dist/d200h/hid-protocol.d.ts.map +1 -0
  44. package/dist/d200h/hid-protocol.js +124 -0
  45. package/dist/d200h/hid-protocol.js.map +1 -0
  46. package/dist/d200h/image-renderer.d.ts +24 -0
  47. package/dist/d200h/image-renderer.d.ts.map +1 -0
  48. package/dist/d200h/image-renderer.js +321 -0
  49. package/dist/d200h/image-renderer.js.map +1 -0
  50. package/dist/daemon-server.d.ts.map +1 -1
  51. package/dist/daemon-server.js +374 -26
  52. package/dist/daemon-server.js.map +1 -1
  53. package/dist/daemon.js +1 -1
  54. package/dist/esp32-serial.d.ts +30 -0
  55. package/dist/esp32-serial.d.ts.map +1 -1
  56. package/dist/esp32-serial.js +148 -11
  57. package/dist/esp32-serial.js.map +1 -1
  58. package/dist/fallback-task-timeline.d.ts.map +1 -1
  59. package/dist/fallback-task-timeline.js +9 -2
  60. package/dist/fallback-task-timeline.js.map +1 -1
  61. package/dist/hook-server.d.ts.map +1 -1
  62. package/dist/hook-server.js +6 -5
  63. package/dist/hook-server.js.map +1 -1
  64. package/dist/idotmatrix/idotmatrix-daemon-sync.js +2 -2
  65. package/dist/idotmatrix/idotmatrix-daemon-sync.js.map +1 -1
  66. package/dist/index.d.ts.map +1 -1
  67. package/dist/index.js +2 -0
  68. package/dist/index.js.map +1 -1
  69. package/dist/logger.d.ts +3 -1
  70. package/dist/logger.d.ts.map +1 -1
  71. package/dist/logger.js +6 -2
  72. package/dist/logger.js.map +1 -1
  73. package/dist/model-catalog.d.ts +1 -1
  74. package/dist/model-catalog.d.ts.map +1 -1
  75. package/dist/model-catalog.js +2 -4
  76. package/dist/model-catalog.js.map +1 -1
  77. package/dist/modules/d200h-module.d.ts +65 -0
  78. package/dist/modules/d200h-module.d.ts.map +1 -0
  79. package/dist/modules/d200h-module.js +495 -0
  80. package/dist/modules/d200h-module.js.map +1 -0
  81. package/dist/modules/d200h-renderer.d.ts +7 -0
  82. package/dist/modules/d200h-renderer.d.ts.map +1 -0
  83. package/dist/modules/d200h-renderer.js +321 -0
  84. package/dist/modules/d200h-renderer.js.map +1 -0
  85. package/dist/modules/trmnl-module.d.ts +38 -0
  86. package/dist/modules/trmnl-module.d.ts.map +1 -0
  87. package/dist/modules/trmnl-module.js +111 -0
  88. package/dist/modules/trmnl-module.js.map +1 -0
  89. package/dist/observed-steering.d.ts +93 -0
  90. package/dist/observed-steering.d.ts.map +1 -0
  91. package/dist/observed-steering.js +247 -0
  92. package/dist/observed-steering.js.map +1 -0
  93. package/dist/opencode-steering.d.ts +36 -0
  94. package/dist/opencode-steering.d.ts.map +1 -0
  95. package/dist/opencode-steering.js +84 -0
  96. package/dist/opencode-steering.js.map +1 -0
  97. package/dist/output-parser.d.ts.map +1 -1
  98. package/dist/output-parser.js +48 -10
  99. package/dist/output-parser.js.map +1 -1
  100. package/dist/passive-observer.d.ts +6 -0
  101. package/dist/passive-observer.d.ts.map +1 -1
  102. package/dist/passive-observer.js +31 -1
  103. package/dist/passive-observer.js.map +1 -1
  104. package/dist/permission-resolver.d.ts +13 -5
  105. package/dist/permission-resolver.d.ts.map +1 -1
  106. package/dist/permission-resolver.js +18 -9
  107. package/dist/permission-resolver.js.map +1 -1
  108. package/dist/pixoo/micro-glyphs.d.ts +10 -41
  109. package/dist/pixoo/micro-glyphs.d.ts.map +1 -1
  110. package/dist/pixoo/micro-glyphs.js +130 -263
  111. package/dist/pixoo/micro-glyphs.js.map +1 -1
  112. package/dist/pixoo/official-dot-glyphs.generated.d.ts +8 -0
  113. package/dist/pixoo/official-dot-glyphs.generated.d.ts.map +1 -0
  114. package/dist/pixoo/official-dot-glyphs.generated.js +247 -0
  115. package/dist/pixoo/official-dot-glyphs.generated.js.map +1 -0
  116. package/dist/pixoo/pixoo-bridge.d.ts +14 -6
  117. package/dist/pixoo/pixoo-bridge.d.ts.map +1 -1
  118. package/dist/pixoo/pixoo-bridge.js +63 -39
  119. package/dist/pixoo/pixoo-bridge.js.map +1 -1
  120. package/dist/pixoo/pixoo-renderer.d.ts +21 -2
  121. package/dist/pixoo/pixoo-renderer.d.ts.map +1 -1
  122. package/dist/pixoo/pixoo-renderer.js +401 -132
  123. package/dist/pixoo/pixoo-renderer.js.map +1 -1
  124. package/dist/pixoo/pixoo-sprites.d.ts +24 -0
  125. package/dist/pixoo/pixoo-sprites.d.ts.map +1 -1
  126. package/dist/pixoo/pixoo-sprites.js +108 -0
  127. package/dist/pixoo/pixoo-sprites.js.map +1 -1
  128. package/dist/review-runner.d.ts +113 -0
  129. package/dist/review-runner.d.ts.map +1 -0
  130. package/dist/review-runner.js +428 -0
  131. package/dist/review-runner.js.map +1 -0
  132. package/dist/session-aggregator.d.ts +8 -0
  133. package/dist/session-aggregator.d.ts.map +1 -1
  134. package/dist/session-aggregator.js.map +1 -1
  135. package/dist/session-focus-relay.d.ts.map +1 -1
  136. package/dist/session-focus-relay.js +7 -1
  137. package/dist/session-focus-relay.js.map +1 -1
  138. package/dist/session-registry.d.ts +3 -0
  139. package/dist/session-registry.d.ts.map +1 -1
  140. package/dist/session-registry.js +3 -0
  141. package/dist/session-registry.js.map +1 -1
  142. package/dist/timeline-store.d.ts +49 -0
  143. package/dist/timeline-store.d.ts.map +1 -1
  144. package/dist/timeline-store.js +175 -7
  145. package/dist/timeline-store.js.map +1 -1
  146. package/dist/trmnl/byos-server.d.ts +39 -0
  147. package/dist/trmnl/byos-server.d.ts.map +1 -0
  148. package/dist/trmnl/byos-server.js +301 -0
  149. package/dist/trmnl/byos-server.js.map +1 -0
  150. package/dist/trmnl/frame-cache.d.ts +37 -0
  151. package/dist/trmnl/frame-cache.d.ts.map +1 -0
  152. package/dist/trmnl/frame-cache.js +157 -0
  153. package/dist/trmnl/frame-cache.js.map +1 -0
  154. package/dist/trmnl/image-renderer.d.ts +27 -0
  155. package/dist/trmnl/image-renderer.d.ts.map +1 -0
  156. package/dist/trmnl/image-renderer.js +235 -0
  157. package/dist/trmnl/image-renderer.js.map +1 -0
  158. package/dist/trmnl/trmnl-settings.d.ts +96 -0
  159. package/dist/trmnl/trmnl-settings.d.ts.map +1 -0
  160. package/dist/trmnl/trmnl-settings.js +177 -0
  161. package/dist/trmnl/trmnl-settings.js.map +1 -0
  162. package/dist/trmnl/trmnl-telemetry.d.ts +47 -0
  163. package/dist/trmnl/trmnl-telemetry.d.ts.map +1 -0
  164. package/dist/trmnl/trmnl-telemetry.js +56 -0
  165. package/dist/trmnl/trmnl-telemetry.js.map +1 -0
  166. package/dist/tui/dashboard.d.ts.map +1 -1
  167. package/dist/tui/dashboard.js +14 -4
  168. package/dist/tui/dashboard.js.map +1 -1
  169. package/dist/tui/renderer.d.ts.map +1 -1
  170. package/dist/tui/renderer.js +63 -13
  171. package/dist/tui/renderer.js.map +1 -1
  172. package/dist/tui/terrarium.d.ts.map +1 -1
  173. package/dist/tui/terrarium.js +7 -2
  174. package/dist/tui/terrarium.js.map +1 -1
  175. package/dist/usage-event.d.ts.map +1 -1
  176. package/dist/usage-event.js +25 -2
  177. package/dist/usage-event.js.map +1 -1
  178. package/dist/version-check.d.ts.map +1 -1
  179. package/dist/version-check.js +1 -17
  180. package/dist/version-check.js.map +1 -1
  181. package/dist/ws-server.d.ts +0 -7
  182. package/dist/ws-server.d.ts.map +1 -1
  183. package/dist/ws-server.js +5 -20
  184. package/dist/ws-server.js.map +1 -1
  185. package/package.json +4 -4
@@ -0,0 +1,197 @@
1
+ /**
2
+ * Conservative predictor for "would Claude Code actually prompt the user for
3
+ * this tool call?" — the precision guard for the observed-session PreToolUse
4
+ * device-approval gate.
5
+ *
6
+ * HISTORY (why precision-first): the first PreToolUse gate held EVERY gated
7
+ * tool call, so tools Claude auto-approves (allowlist rules, acceptEdits,
8
+ * session "always allow") still popped Allow/Deny on devices — the reported
9
+ * false-attention bug that got the gate removed (DEVELOPMENT_LOG 2026-05).
10
+ * This module exists so the reinstated gate only ever holds calls we are
11
+ * CONFIDENT Claude will prompt for. Every uncertainty resolves to "don't
12
+ * hold": a missed hold just means the user answers in the terminal (the
13
+ * pre-gate status quo), while a false hold nags the user with a popup Claude
14
+ * never asked for.
15
+ *
16
+ * Rule semantics mirror Claude Code `permissions.allow/deny/ask` entries:
17
+ * "Bash" → every Bash call
18
+ * "Bash(git status)" → exact command
19
+ * "Bash(git status:*)" → command prefix
20
+ * "Read(...)"/"WebFetch(domain:x)"/"mcp__srv__tool" → tool + spec
21
+ * Matching is deliberately asymmetric:
22
+ * - allow/deny rules match LOOSELY (tool-name match with any spec counts)
23
+ * because a loose match only suppresses a hold (safe direction).
24
+ * - ask rules match STRICTLY (tool-only, or exact/prefix Bash) because an
25
+ * ask match *causes* a hold and must not fire on a spec we can't parse.
26
+ */
27
+ import { readFileSync, statSync } from 'fs';
28
+ import { join } from 'path';
29
+ import { homedir } from 'os';
30
+ import { debug } from './logger.js';
31
+ /** Tools that never trigger a permission prompt — holding them can only ever
32
+ * be a false positive. Kept intentionally tight (unknown tools are excluded
33
+ * by the prompt-prone check below, not this list). */
34
+ const NEVER_PROMPT_TOOLS = new Set([
35
+ 'Read', 'Glob', 'Grep', 'LS',
36
+ 'TodoWrite', 'TodoRead', 'NotebookRead',
37
+ 'Task', 'TaskOutput', 'BashOutput',
38
+ ]);
39
+ /** Tools that DO prompt in default/auto permission mode unless allowlisted.
40
+ * Anything outside this set (including every mcp__* tool, whose per-server
41
+ * trust state we cannot see) is never held. */
42
+ const PROMPT_PRONE_TOOLS = new Set([
43
+ 'Bash', 'Write', 'Edit', 'MultiEdit', 'NotebookEdit', 'WebFetch', 'WebSearch',
44
+ ]);
45
+ export function isNeverPromptTool(tool) {
46
+ return NEVER_PROMPT_TOOLS.has(tool);
47
+ }
48
+ export function isPromptProneTool(tool) {
49
+ return PROMPT_PRONE_TOOLS.has(tool);
50
+ }
51
+ const RULES_CACHE_TTL_MS = 10_000;
52
+ const rulesCache = new Map();
53
+ /** Test seam: isolates rule loading from the developer's real ~/.claude. */
54
+ let homeOverride = null;
55
+ export function _setHomeOverrideForTests(path) {
56
+ homeOverride = path;
57
+ rulesCache.clear();
58
+ }
59
+ function settingsCandidates(cwd) {
60
+ const home = homeOverride ?? homedir();
61
+ const files = [
62
+ // Enterprise managed policy (rare; parse failure here must also disable holds)
63
+ '/Library/Application Support/ClaudeCode/managed-settings.json',
64
+ join(home, '.claude', 'settings.json'),
65
+ join(home, '.claude', 'settings.local.json'),
66
+ ];
67
+ if (cwd) {
68
+ files.push(join(cwd, '.claude', 'settings.json'));
69
+ files.push(join(cwd, '.claude', 'settings.local.json'));
70
+ }
71
+ return files;
72
+ }
73
+ /**
74
+ * Load and merge permission rules from every settings file Claude Code reads
75
+ * for this cwd. Returns null ("unknown") when any EXISTING file fails to
76
+ * parse — we can no longer trust our picture of the allowlist, so the caller
77
+ * must not hold anything.
78
+ */
79
+ export function loadMergedPermissionRules(cwd) {
80
+ const key = cwd ?? '';
81
+ const cached = rulesCache.get(key);
82
+ if (cached && Date.now() - cached.loadedAt < RULES_CACHE_TTL_MS)
83
+ return cached.rules;
84
+ const merged = { allow: [], deny: [], ask: [] };
85
+ let unknown = false;
86
+ for (const file of settingsCandidates(cwd)) {
87
+ let exists = false;
88
+ try {
89
+ exists = statSync(file).isFile();
90
+ }
91
+ catch {
92
+ exists = false;
93
+ }
94
+ if (!exists)
95
+ continue;
96
+ try {
97
+ const parsed = JSON.parse(readFileSync(file, 'utf-8'));
98
+ const perms = parsed?.permissions;
99
+ if (perms && typeof perms === 'object') {
100
+ for (const bucket of ['allow', 'deny', 'ask']) {
101
+ const arr = perms[bucket];
102
+ if (Array.isArray(arr)) {
103
+ for (const r of arr)
104
+ if (typeof r === 'string')
105
+ merged[bucket].push(r);
106
+ }
107
+ }
108
+ }
109
+ }
110
+ catch {
111
+ debug('permission', `settings parse failed: ${file} — disabling holds for cwd=${cwd ?? '?'}`);
112
+ unknown = true;
113
+ break;
114
+ }
115
+ }
116
+ const rules = unknown ? null : merged;
117
+ rulesCache.set(key, { rules, loadedAt: Date.now() });
118
+ return rules;
119
+ }
120
+ /** Test helper. */
121
+ export function _clearRulesCache() {
122
+ rulesCache.clear();
123
+ }
124
+ function parseRule(rule) {
125
+ const m = /^([A-Za-z][A-Za-z0-9_]*)(?:\((.*)\))?$/.exec(rule.trim());
126
+ if (!m)
127
+ return null;
128
+ return { tool: m[1], spec: m[2] };
129
+ }
130
+ function bashSpecMatches(spec, command) {
131
+ if (spec === '*')
132
+ return true;
133
+ if (spec.endsWith(':*'))
134
+ return command.startsWith(spec.slice(0, -2));
135
+ return command === spec;
136
+ }
137
+ /** Loose match (allow/deny direction): a tool-name match with ANY spec counts,
138
+ * except Bash specs which we can compare precisely. */
139
+ function matchesLoose(rule, tool, command) {
140
+ if (rule.tool !== tool)
141
+ return false;
142
+ if (rule.spec === undefined)
143
+ return true;
144
+ if (tool === 'Bash') {
145
+ if (command === undefined)
146
+ return true; // malformed input — assume covered
147
+ return bashSpecMatches(rule.spec, command)
148
+ // Compound commands: Claude prompts unless every segment is allowed; we
149
+ // only need "might be auto-approved", so a prefix match on the first
150
+ // segment is enough to suppress the hold.
151
+ || bashSpecMatches(rule.spec, command.split(/&&|\|\||;|\|/)[0]?.trim() ?? command);
152
+ }
153
+ // Non-Bash specs (paths, domains, globs): we don't replicate the matcher —
154
+ // any spec on the right tool MIGHT match, so treat it as covered.
155
+ return true;
156
+ }
157
+ /** Strict match (ask direction): only patterns we can evaluate exactly. */
158
+ function matchesStrict(rule, tool, command) {
159
+ if (rule.tool !== tool)
160
+ return false;
161
+ if (rule.spec === undefined)
162
+ return true;
163
+ if (tool === 'Bash' && command !== undefined)
164
+ return bashSpecMatches(rule.spec, command);
165
+ return false;
166
+ }
167
+ /**
168
+ * Predict Claude's permission-rule verdict for a tool call.
169
+ * 'deny' → a deny rule may match: Claude auto-denies (or prompts) — don't hold
170
+ * 'allow' → an allow rule may match: Claude may auto-approve — don't hold
171
+ * 'ask' → an ask rule definitely matches: Claude will prompt — hold-eligible
172
+ * 'none' → no rule matches: default behavior for the tool applies
173
+ * 'unknown' → settings unreadable: don't hold
174
+ */
175
+ export function evaluatePermissionRules(tool, toolInput, cwd) {
176
+ const rules = loadMergedPermissionRules(cwd);
177
+ if (rules === null)
178
+ return 'unknown';
179
+ const command = typeof toolInput?.command === 'string' ? toolInput.command : undefined;
180
+ for (const r of rules.deny) {
181
+ const parsed = parseRule(r);
182
+ if (parsed && matchesLoose(parsed, tool, command))
183
+ return 'deny';
184
+ }
185
+ for (const r of rules.allow) {
186
+ const parsed = parseRule(r);
187
+ if (parsed && matchesLoose(parsed, tool, command))
188
+ return 'allow';
189
+ }
190
+ for (const r of rules.ask) {
191
+ const parsed = parseRule(r);
192
+ if (parsed && matchesStrict(parsed, tool, command))
193
+ return 'ask';
194
+ }
195
+ return 'none';
196
+ }
197
+ //# sourceMappingURL=claude-permission-rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-permission-rules.js","sourceRoot":"","sources":["../src/claude-permission-rules.ts"],"names":[],"mappings":"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"}
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,EAAE,MAAM,WAAW,CAAC;AAyLpC,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;AAoBD,QAAA,MAAM,OAAO,SAAgB,CAAC;AAm5D9B,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":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyLpC,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;AAoBD,QAAA,MAAM,OAAO,SAAgB,CAAC;AAg6D9B,wBAAsB,MAAM,CAAC,IAAI,GAAE,MAAM,EAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAMzE;AAED,OAAO,EAAE,OAAO,EAAE,CAAC"}
package/dist/cli.js CHANGED
@@ -908,7 +908,16 @@ program
908
908
  const daemonTarget = resolveEsp32OtaDaemonTarget(target);
909
909
  const firmwarePath = resolveEsp32FirmwarePath(target, opts.env, opts.firmware);
910
910
  log(`Uploading ${firmwarePath} to ${daemonTarget} via daemon :${port}...`);
911
- const { statusCode, body } = await postJsonWithTimeout(`http://127.0.0.1:${port}/esp32/ota`, { target: daemonTarget, firmwarePath }, 15 * 60_000);
911
+ let { statusCode, body } = await postJsonWithTimeout(`http://127.0.0.1:${port}/esp32/ota`, { target: daemonTarget, firmwarePath }, 15 * 60_000);
912
+ if (body.ok === false && String(body.error ?? '').startsWith('firmware_unreadable')) {
913
+ // Sandboxed Swift daemon can't read files outside its container —
914
+ // resend with the image inlined instead of failing over to a manual
915
+ // daemon swap.
916
+ log('Daemon cannot read the firmware path (sandbox) — resending inline...');
917
+ const { readFileSync } = await import('fs');
918
+ const firmwareB64 = readFileSync(firmwarePath).toString('base64');
919
+ ({ statusCode, body } = await postJsonWithTimeout(`http://127.0.0.1:${port}/esp32/ota`, { target: daemonTarget, firmwareB64 }, 15 * 60_000));
920
+ }
912
921
  if (statusCode < 200 || statusCode >= 300 || body.ok === false) {
913
922
  throw new Error(String(body.error ?? `HTTP ${statusCode}`));
914
923
  }