@synap-core/cli 1.12.2 → 1.13.1-next.20261102.246dc73

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 (358) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +38 -11
  3. package/dist/build-info.json +2 -3
  4. package/dist/commands/agents.d.ts +0 -1
  5. package/dist/commands/agents.js +13 -3
  6. package/dist/commands/agents.js.map +1 -1
  7. package/dist/commands/app.js +2 -1
  8. package/dist/commands/app.js.map +1 -1
  9. package/dist/commands/automation.js +46 -41
  10. package/dist/commands/automation.js.map +1 -1
  11. package/dist/commands/box.d.ts +42 -0
  12. package/dist/commands/box.js +89 -0
  13. package/dist/commands/box.js.map +1 -0
  14. package/dist/commands/bridge-setup.js +3 -1
  15. package/dist/commands/bridge-setup.js.map +1 -1
  16. package/dist/commands/capability.d.ts +87 -1
  17. package/dist/commands/capability.js +174 -64
  18. package/dist/commands/capability.js.map +1 -1
  19. package/dist/commands/close-questions.d.ts +27 -0
  20. package/dist/commands/close-questions.js +49 -0
  21. package/dist/commands/close-questions.js.map +1 -0
  22. package/dist/commands/close-questions.test.d.ts +1 -0
  23. package/dist/commands/close-questions.test.js +52 -0
  24. package/dist/commands/close-questions.test.js.map +1 -0
  25. package/dist/commands/connect.d.ts +1 -3
  26. package/dist/commands/connect.js +2 -2
  27. package/dist/commands/connect.js.map +1 -1
  28. package/dist/commands/context.js +74 -44
  29. package/dist/commands/context.js.map +1 -1
  30. package/dist/commands/data-extra.d.ts +13 -0
  31. package/dist/commands/data-extra.js +35 -6
  32. package/dist/commands/data-extra.js.map +1 -1
  33. package/dist/commands/data.js +2 -1
  34. package/dist/commands/data.js.map +1 -1
  35. package/dist/commands/doctor.d.ts +39 -0
  36. package/dist/commands/doctor.js +136 -14
  37. package/dist/commands/doctor.js.map +1 -1
  38. package/dist/commands/hooks.d.ts +19 -0
  39. package/dist/commands/hooks.js +70 -0
  40. package/dist/commands/hooks.js.map +1 -0
  41. package/dist/commands/import.d.ts +25 -0
  42. package/dist/commands/import.js +98 -12
  43. package/dist/commands/import.js.map +1 -1
  44. package/dist/commands/init.d.ts +14 -0
  45. package/dist/commands/init.js +63 -21
  46. package/dist/commands/init.js.map +1 -1
  47. package/dist/commands/keys-request.d.ts +48 -0
  48. package/dist/commands/keys-request.js +236 -0
  49. package/dist/commands/keys-request.js.map +1 -0
  50. package/dist/commands/keys-request.test.d.ts +1 -0
  51. package/dist/commands/keys-request.test.js +176 -0
  52. package/dist/commands/keys-request.test.js.map +1 -0
  53. package/dist/commands/knowledge.d.ts +42 -5
  54. package/dist/commands/knowledge.js +94 -29
  55. package/dist/commands/knowledge.js.map +1 -1
  56. package/dist/commands/lens.js +2 -1
  57. package/dist/commands/lens.js.map +1 -1
  58. package/dist/commands/market-authoring.js +1 -1
  59. package/dist/commands/market-authoring.js.map +1 -1
  60. package/dist/commands/market.d.ts +89 -31
  61. package/dist/commands/market.js +215 -222
  62. package/dist/commands/market.js.map +1 -1
  63. package/dist/commands/mcp.d.ts +1 -1
  64. package/dist/commands/mcp.js +14 -9
  65. package/dist/commands/mcp.js.map +1 -1
  66. package/dist/commands/observe.category.test.d.ts +1 -0
  67. package/dist/commands/observe.category.test.js +59 -0
  68. package/dist/commands/observe.category.test.js.map +1 -0
  69. package/dist/commands/observe.d.ts +3 -0
  70. package/dist/commands/observe.js +7 -5
  71. package/dist/commands/observe.js.map +1 -1
  72. package/dist/commands/observe.title.test.d.ts +1 -0
  73. package/dist/commands/observe.title.test.js +37 -0
  74. package/dist/commands/observe.title.test.js.map +1 -0
  75. package/dist/commands/playbook.js +9 -0
  76. package/dist/commands/playbook.js.map +1 -1
  77. package/dist/commands/pods.d.ts +6 -1
  78. package/dist/commands/pods.js +38 -17
  79. package/dist/commands/pods.js.map +1 -1
  80. package/dist/commands/proposals-actions.js +7 -1
  81. package/dist/commands/proposals-actions.js.map +1 -1
  82. package/dist/commands/proton-setup.js +3 -1
  83. package/dist/commands/proton-setup.js.map +1 -1
  84. package/dist/commands/providers.d.ts +22 -6
  85. package/dist/commands/providers.js +39 -32
  86. package/dist/commands/providers.js.map +1 -1
  87. package/dist/commands/raycast.d.ts +15 -0
  88. package/dist/commands/raycast.js +36 -10
  89. package/dist/commands/raycast.js.map +1 -1
  90. package/dist/commands/session-feed-wait.d.ts +48 -0
  91. package/dist/commands/session-feed-wait.js +261 -0
  92. package/dist/commands/session-feed-wait.js.map +1 -0
  93. package/dist/commands/session-post.d.ts +40 -0
  94. package/dist/commands/session-post.js +96 -0
  95. package/dist/commands/session-post.js.map +1 -0
  96. package/dist/commands/session-wait.d.ts +9 -4
  97. package/dist/commands/session-wait.js +20 -5
  98. package/dist/commands/session-wait.js.map +1 -1
  99. package/dist/commands/sessions.d.ts +2 -0
  100. package/dist/commands/sessions.js +23 -0
  101. package/dist/commands/sessions.js.map +1 -1
  102. package/dist/commands/skills-commands.d.ts +2 -0
  103. package/dist/commands/skills-commands.js +9 -1
  104. package/dist/commands/skills-commands.js.map +1 -1
  105. package/dist/commands/skills-commands.test.d.ts +1 -0
  106. package/dist/commands/skills-commands.test.js +57 -0
  107. package/dist/commands/skills-commands.test.js.map +1 -0
  108. package/dist/commands/status.js +13 -7
  109. package/dist/commands/status.js.map +1 -1
  110. package/dist/commands/statusline.backoff.test.js +13 -3
  111. package/dist/commands/statusline.backoff.test.js.map +1 -1
  112. package/dist/commands/statusline.d.ts +104 -9
  113. package/dist/commands/statusline.js +392 -148
  114. package/dist/commands/statusline.js.map +1 -1
  115. package/dist/commands/statusline.line2.test.d.ts +15 -0
  116. package/dist/commands/statusline.line2.test.js +226 -0
  117. package/dist/commands/statusline.line2.test.js.map +1 -0
  118. package/dist/commands/statusline.needs-you.test.d.ts +1 -0
  119. package/dist/commands/statusline.needs-you.test.js +17 -0
  120. package/dist/commands/statusline.needs-you.test.js.map +1 -0
  121. package/dist/commands/statusline.now.test.d.ts +10 -0
  122. package/dist/commands/statusline.now.test.js +250 -0
  123. package/dist/commands/statusline.now.test.js.map +1 -0
  124. package/dist/commands/tracks.d.ts +68 -6
  125. package/dist/commands/tracks.js +272 -16
  126. package/dist/commands/tracks.js.map +1 -1
  127. package/dist/commands/upload.js +12 -0
  128. package/dist/commands/upload.js.map +1 -1
  129. package/dist/commands/wait.d.ts +124 -0
  130. package/dist/commands/wait.js +384 -0
  131. package/dist/commands/wait.js.map +1 -0
  132. package/dist/commands/wait.test.d.ts +8 -0
  133. package/dist/commands/wait.test.js +308 -0
  134. package/dist/commands/wait.test.js.map +1 -0
  135. package/dist/commands/whoami.d.ts +7 -0
  136. package/dist/commands/whoami.js +17 -0
  137. package/dist/commands/whoami.js.map +1 -1
  138. package/dist/commands/worker-accounts.d.ts +149 -0
  139. package/dist/commands/worker-accounts.js +339 -0
  140. package/dist/commands/worker-accounts.js.map +1 -0
  141. package/dist/commands/worker-accounts.test.d.ts +1 -0
  142. package/dist/commands/worker-accounts.test.js +224 -0
  143. package/dist/commands/worker-accounts.test.js.map +1 -0
  144. package/dist/commands/worker-github-app.d.ts +63 -0
  145. package/dist/commands/worker-github-app.js +161 -0
  146. package/dist/commands/worker-github-app.js.map +1 -0
  147. package/dist/commands/worker-github-app.test.d.ts +1 -0
  148. package/dist/commands/worker-github-app.test.js +102 -0
  149. package/dist/commands/worker-github-app.test.js.map +1 -0
  150. package/dist/commands/worker-github-broker.d.ts +39 -0
  151. package/dist/commands/worker-github-broker.js +106 -0
  152. package/dist/commands/worker-github-broker.js.map +1 -0
  153. package/dist/commands/worker-github-broker.test.d.ts +1 -0
  154. package/dist/commands/worker-github-broker.test.js +90 -0
  155. package/dist/commands/worker-github-broker.test.js.map +1 -0
  156. package/dist/commands/worker-runs.test.d.ts +1 -0
  157. package/dist/commands/worker-runs.test.js +150 -0
  158. package/dist/commands/worker-runs.test.js.map +1 -0
  159. package/dist/commands/worker-worktrees.d.ts +34 -0
  160. package/dist/commands/worker-worktrees.js +87 -0
  161. package/dist/commands/worker-worktrees.js.map +1 -0
  162. package/dist/commands/worker.d.ts +406 -10
  163. package/dist/commands/worker.js +1180 -126
  164. package/dist/commands/worker.js.map +1 -1
  165. package/dist/commands/worker.test.js +588 -11
  166. package/dist/commands/worker.test.js.map +1 -1
  167. package/dist/index.js +220 -28
  168. package/dist/index.js.map +1 -1
  169. package/dist/lib/agent-door.d.ts +1 -3
  170. package/dist/lib/agent-door.js +10 -7
  171. package/dist/lib/agent-door.js.map +1 -1
  172. package/dist/lib/agents-config.d.ts +9 -0
  173. package/dist/lib/agents-config.js +20 -0
  174. package/dist/lib/agents-config.js.map +1 -1
  175. package/dist/lib/atomic-file.d.ts +20 -1
  176. package/dist/lib/atomic-file.js +100 -2
  177. package/dist/lib/atomic-file.js.map +1 -1
  178. package/dist/lib/auth.d.ts +28 -2
  179. package/dist/lib/auth.js +52 -12
  180. package/dist/lib/auth.js.map +1 -1
  181. package/dist/lib/box/egress.d.ts +82 -0
  182. package/dist/lib/box/egress.js +264 -0
  183. package/dist/lib/box/egress.js.map +1 -0
  184. package/dist/lib/box/evidence.d.ts +86 -0
  185. package/dist/lib/box/evidence.js +121 -0
  186. package/dist/lib/box/evidence.js.map +1 -0
  187. package/dist/lib/box/job-server.d.ts +72 -0
  188. package/dist/lib/box/job-server.js +250 -0
  189. package/dist/lib/box/job-server.js.map +1 -0
  190. package/dist/lib/box/provisioner.d.ts +83 -0
  191. package/dist/lib/box/provisioner.js +312 -0
  192. package/dist/lib/box/provisioner.js.map +1 -0
  193. package/dist/lib/box/proxmox.d.ts +112 -0
  194. package/dist/lib/box/proxmox.js +211 -0
  195. package/dist/lib/box/proxmox.js.map +1 -0
  196. package/dist/lib/box/wire.d.ts +98 -0
  197. package/dist/lib/box/wire.js +70 -0
  198. package/dist/lib/box/wire.js.map +1 -0
  199. package/dist/lib/bridge-invocation.test.d.ts +1 -0
  200. package/dist/lib/bridge-invocation.test.js +75 -0
  201. package/dist/lib/bridge-invocation.test.js.map +1 -0
  202. package/dist/lib/bridge-status.d.ts +144 -0
  203. package/dist/lib/bridge-status.js +227 -0
  204. package/dist/lib/bridge-status.js.map +1 -0
  205. package/dist/lib/bridge-status.test.d.ts +6 -0
  206. package/dist/lib/bridge-status.test.js +197 -0
  207. package/dist/lib/bridge-status.test.js.map +1 -0
  208. package/dist/lib/client-header.test.d.ts +1 -0
  209. package/dist/lib/client-header.test.js +103 -0
  210. package/dist/lib/client-header.test.js.map +1 -0
  211. package/dist/lib/conversation-headers.d.ts +89 -9
  212. package/dist/lib/conversation-headers.js +156 -3
  213. package/dist/lib/conversation-headers.js.map +1 -1
  214. package/dist/lib/conversation-headers.test.d.ts +1 -0
  215. package/dist/lib/conversation-headers.test.js +78 -0
  216. package/dist/lib/conversation-headers.test.js.map +1 -0
  217. package/dist/lib/credential-class.d.ts +40 -2
  218. package/dist/lib/credential-class.js +48 -6
  219. package/dist/lib/credential-class.js.map +1 -1
  220. package/dist/lib/device-connect.d.ts +45 -0
  221. package/dist/lib/device-connect.js +60 -0
  222. package/dist/lib/device-connect.js.map +1 -1
  223. package/dist/lib/exporter-coverage.d.ts +1 -1
  224. package/dist/lib/exporter-coverage.js +1 -1
  225. package/dist/lib/goal-words.d.ts +38 -0
  226. package/dist/lib/goal-words.js +115 -0
  227. package/dist/lib/goal-words.js.map +1 -0
  228. package/dist/lib/hub-client.d.ts +87 -8
  229. package/dist/lib/hub-client.js +205 -70
  230. package/dist/lib/hub-client.js.map +1 -1
  231. package/dist/lib/init-handoff.d.ts +8 -0
  232. package/dist/lib/init-handoff.js +9 -2
  233. package/dist/lib/init-handoff.js.map +1 -1
  234. package/dist/lib/key-locations.d.ts +3 -3
  235. package/dist/lib/key-locations.js +3 -39
  236. package/dist/lib/key-locations.js.map +1 -1
  237. package/dist/lib/key-source.d.ts +3 -1
  238. package/dist/lib/key-source.js +7 -4
  239. package/dist/lib/key-source.js.map +1 -1
  240. package/dist/lib/knowledge-title.d.ts +3 -2
  241. package/dist/lib/knowledge-title.js +3 -2
  242. package/dist/lib/knowledge-title.js.map +1 -1
  243. package/dist/lib/machine-instance.d.ts +7 -5
  244. package/dist/lib/machine-instance.js +7 -5
  245. package/dist/lib/machine-instance.js.map +1 -1
  246. package/dist/lib/mcp-bridge.d.ts +50 -0
  247. package/dist/lib/mcp-bridge.js +232 -11
  248. package/dist/lib/mcp-bridge.js.map +1 -1
  249. package/dist/lib/mcp-bridge.test.js +224 -4
  250. package/dist/lib/mcp-bridge.test.js.map +1 -1
  251. package/dist/lib/mcp-call.d.ts +5 -1
  252. package/dist/lib/mcp-call.js +7 -6
  253. package/dist/lib/mcp-call.js.map +1 -1
  254. package/dist/lib/mcp-connector-url.test.d.ts +1 -0
  255. package/dist/lib/mcp-connector-url.test.js +13 -0
  256. package/dist/lib/mcp-connector-url.test.js.map +1 -0
  257. package/dist/lib/mcp-snippets.d.ts +16 -0
  258. package/dist/lib/mcp-snippets.js +20 -2
  259. package/dist/lib/mcp-snippets.js.map +1 -1
  260. package/dist/lib/now-line.d.ts +66 -0
  261. package/dist/lib/now-line.js +193 -0
  262. package/dist/lib/now-line.js.map +1 -0
  263. package/dist/lib/now-line.test.d.ts +5 -0
  264. package/dist/lib/now-line.test.js +177 -0
  265. package/dist/lib/now-line.test.js.map +1 -0
  266. package/dist/lib/package-updates.d.ts +66 -0
  267. package/dist/lib/package-updates.js +76 -0
  268. package/dist/lib/package-updates.js.map +1 -0
  269. package/dist/lib/pod-moved.d.ts +70 -0
  270. package/dist/lib/pod-moved.js +146 -0
  271. package/dist/lib/pod-moved.js.map +1 -0
  272. package/dist/lib/pod-reach.d.ts +39 -0
  273. package/dist/lib/pod-reach.js +117 -0
  274. package/dist/lib/pod-reach.js.map +1 -0
  275. package/dist/lib/pod-reach.test.d.ts +1 -0
  276. package/dist/lib/pod-reach.test.js +67 -0
  277. package/dist/lib/pod-reach.test.js.map +1 -0
  278. package/dist/lib/pod.d.ts +8 -4
  279. package/dist/lib/pod.js +12 -10
  280. package/dist/lib/pod.js.map +1 -1
  281. package/dist/lib/register-claude-code-mcp.test.d.ts +1 -0
  282. package/dist/lib/register-claude-code-mcp.test.js +97 -0
  283. package/dist/lib/register-claude-code-mcp.test.js.map +1 -0
  284. package/dist/lib/review-credential.js +3 -1
  285. package/dist/lib/review-credential.js.map +1 -1
  286. package/dist/lib/safe-open.d.ts +5 -3
  287. package/dist/lib/safe-open.js +9 -8
  288. package/dist/lib/safe-open.js.map +1 -1
  289. package/dist/lib/self-host.d.ts +17 -0
  290. package/dist/lib/self-host.js +24 -0
  291. package/dist/lib/self-host.js.map +1 -0
  292. package/dist/lib/session-feed.d.ts +185 -0
  293. package/dist/lib/session-feed.js +257 -0
  294. package/dist/lib/session-feed.js.map +1 -0
  295. package/dist/lib/targets.d.ts +52 -3
  296. package/dist/lib/targets.js +150 -209
  297. package/dist/lib/targets.js.map +1 -1
  298. package/dist/lib/template-lifecycle.d.ts +0 -31
  299. package/dist/lib/template-lifecycle.js +0 -74
  300. package/dist/lib/template-lifecycle.js.map +1 -1
  301. package/dist/lib/term.d.ts +24 -0
  302. package/dist/lib/term.js +52 -0
  303. package/dist/lib/term.js.map +1 -0
  304. package/dist/lib/term.test.d.ts +1 -0
  305. package/dist/lib/term.test.js +29 -0
  306. package/dist/lib/term.test.js.map +1 -0
  307. package/dist/lib/transcript-index.d.ts +94 -0
  308. package/dist/lib/transcript-index.js +321 -0
  309. package/dist/lib/transcript-index.js.map +1 -0
  310. package/dist/lib/transcript-index.test.d.ts +10 -0
  311. package/dist/lib/transcript-index.test.js +200 -0
  312. package/dist/lib/transcript-index.test.js.map +1 -0
  313. package/dist/lib/wait-help.d.ts +11 -0
  314. package/dist/lib/wait-help.js +25 -0
  315. package/dist/lib/wait-help.js.map +1 -0
  316. package/dist/lib/wait-state.d.ts +57 -0
  317. package/dist/lib/wait-state.js +114 -0
  318. package/dist/lib/wait-state.js.map +1 -0
  319. package/dist/lib/wake-hook-settings.d.ts +57 -0
  320. package/dist/lib/wake-hook-settings.js +153 -0
  321. package/dist/lib/wake-hook-settings.js.map +1 -0
  322. package/dist/lib/wake-state.d.ts +65 -0
  323. package/dist/lib/wake-state.js +122 -0
  324. package/dist/lib/wake-state.js.map +1 -0
  325. package/package.json +5 -2
  326. package/skills/README.md +1 -1
  327. package/skills/agent-os/SKILL.md +8 -8
  328. package/skills/synap/SKILL.md +188 -94
  329. package/skills/synap/code-skills.md +84 -0
  330. package/skills/synap/concepts.md +38 -20
  331. package/skills/synap/creative-loop.md +1 -1
  332. package/skills/synap/document-embeds.md +17 -1
  333. package/skills/synap/focus-sessions.md +17 -8
  334. package/skills/synap/from-intent.md +33 -17
  335. package/skills/synap/governance-rules.md +3 -1
  336. package/skills/synap/hand-off.md +10 -6
  337. package/skills/synap/lenses.md +4 -4
  338. package/skills/synap/linking.md +2 -2
  339. package/skills/synap/mental-model.md +1 -1
  340. package/skills/synap/operating-mode-rules.md +1 -1
  341. package/skills/synap/quick-reference.md +2 -1
  342. package/skills/synap/reflexes.md +8 -8
  343. package/skills/synap/viewframe-cells.md +1 -1
  344. package/skills/synap/work-model.md +24 -10
  345. package/skills/synap/workspace-design.md +5 -5
  346. package/skills/synap/writes.md +16 -9
  347. package/skills/synap/writing-titles.md +7 -0
  348. package/skills/synap-app/SKILL.md +148 -66
  349. package/skills/synap-app/creating-the-base-app.md +12 -7
  350. package/skills/synap-app/governance.md +27 -16
  351. package/skills/synap-app/install-commands.md +18 -9
  352. package/skills/synap-app/overview.md +16 -9
  353. package/skills/synap-app/using-the-sdk.md +75 -25
  354. package/skills/synap-market/SKILL.md +1 -1
  355. package/skills/synap-market/governance-and-catalog.md +1 -1
  356. package/skills/synap-schema/SKILL.md +24 -21
  357. package/skills/synap-schema/intent-vocabulary-ssot.md +24 -21
  358. package/templates/box/runner.py +206 -0
@@ -0,0 +1,339 @@
1
+ /**
2
+ * `synap worker --accounts <file>`: which Claude account a run uses.
3
+ *
4
+ * The file (default ~/.config/synap-worker/accounts.json, owner-only) lists
5
+ * Claude Code setup-tokens in priority order:
6
+ *
7
+ * { "version": 1, "reserve": 2,
8
+ * "accounts": [ { "id": "dev", "label": "Dev", "token": "sk-ant-oat…", "design": true }, … ] }
9
+ *
10
+ * Before a launch every account is MEASURED with a 1-token request whose
11
+ * response headers carry the account's 5-hour and weekly use (the probe is
12
+ * ClaudeSwitch's, main.swift `probeOnce`). A probe that fails is UNMEASURED:
13
+ * it is never read as "has room" and never as "full".
14
+ *
15
+ * A token is a credential. It goes into the launched run's environment and
16
+ * into the probe's Authorization header — nowhere else: no state file, no run
17
+ * log, no line the worker prints. Everything else names an account by id.
18
+ */
19
+ import fs from "node:fs";
20
+ import os from "node:os";
21
+ import path from "node:path";
22
+ export function defaultAccountsFile() {
23
+ return path.join(os.homedir(), ".config", "synap-worker", "accounts.json");
24
+ }
25
+ const ID_RE = /^[A-Za-z0-9_-]{1,64}$/;
26
+ /**
27
+ * The accounts file, or `null` when the DEFAULT file does not exist (the
28
+ * worker then runs on the environment's token, as before). A file named with
29
+ * `--accounts` that is missing, or any file that does not parse or has the
30
+ * wrong shape, THROWS: a broken accounts file is never "no accounts".
31
+ * Error messages never quote a token.
32
+ */
33
+ export function loadAccountsFile(file) {
34
+ const explicit = file !== undefined;
35
+ const target = file ?? defaultAccountsFile();
36
+ if (!fs.existsSync(target)) {
37
+ if (explicit)
38
+ throw new Error(`accounts file ${target} does not exist`);
39
+ return null;
40
+ }
41
+ let data;
42
+ try {
43
+ data = JSON.parse(fs.readFileSync(target, "utf8"));
44
+ }
45
+ catch {
46
+ throw new Error(`accounts file ${target} is not valid JSON`);
47
+ }
48
+ const bad = (why) => new Error(`accounts file ${target}: ${why}`);
49
+ if (!data || typeof data !== "object")
50
+ throw bad("not an object");
51
+ const d = data;
52
+ if (d.version !== 1)
53
+ throw bad(`version must be 1`);
54
+ const reserve = d.reserve === undefined ? 0 : d.reserve;
55
+ if (typeof reserve !== "number" || !Number.isInteger(reserve) || reserve < 0)
56
+ throw bad("reserve must be a whole number ≥ 0");
57
+ if (!Array.isArray(d.accounts) || d.accounts.length === 0)
58
+ throw bad("accounts must be a non-empty list");
59
+ const seen = new Set();
60
+ const accounts = d.accounts.map((raw, i) => {
61
+ const a = (raw ?? {});
62
+ if (typeof a.id !== "string" || !ID_RE.test(a.id))
63
+ throw bad(`accounts[${i}].id must match ${ID_RE}`);
64
+ if (seen.has(a.id))
65
+ throw bad(`account id "${a.id}" appears twice`);
66
+ seen.add(a.id);
67
+ if (typeof a.token !== "string" || a.token.trim() === "")
68
+ throw bad(`account "${a.id}" has no token`);
69
+ return {
70
+ id: a.id,
71
+ label: typeof a.label === "string" && a.label.trim() ? a.label : a.id,
72
+ token: a.token.trim(),
73
+ ...(a.design === true ? { design: true } : {}),
74
+ };
75
+ });
76
+ return { version: 1, reserve, accounts };
77
+ }
78
+ /** True when the file can be read by anyone but its owner. */
79
+ export function accountsFileTooOpen(file) {
80
+ try {
81
+ return (fs.statSync(file).mode & 0o077) !== 0;
82
+ }
83
+ catch {
84
+ return false;
85
+ }
86
+ }
87
+ /** Tried in order when a model is retired, so the probe outlives any one model name. */
88
+ export const PROBE_MODELS = ["claude-haiku-4-5", "claude-haiku-5-5", "claude-sonnet-5-5"];
89
+ export function meterFromHeaders(h, now) {
90
+ const get = (name) => h.get(`anthropic-ratelimit-unified-${name}`);
91
+ const num = (name) => {
92
+ const v = get(name);
93
+ if (v === null || v.trim() === "")
94
+ return undefined;
95
+ const n = Number(v);
96
+ return Number.isFinite(n) ? n : undefined;
97
+ };
98
+ // Utilization is a fraction of the window (0.15 = 15%) and can pass 1 when over.
99
+ const pct = (name) => {
100
+ const n = num(name);
101
+ return n === undefined ? undefined : n * 100;
102
+ };
103
+ const at = (name) => {
104
+ const n = num(name);
105
+ return n === undefined ? undefined : n * 1000;
106
+ };
107
+ return {
108
+ fiveHour: pct("5h-utilization"),
109
+ fiveHourReset: at("5h-reset"),
110
+ week: pct("7d-utilization"),
111
+ weekReset: at("7d-reset"),
112
+ rejected: get("status") === "rejected",
113
+ reset: at("reset"),
114
+ claim: get("representative-claim") ?? undefined,
115
+ checkedAt: now,
116
+ };
117
+ }
118
+ async function probeOnce(token, model, fetchImpl, now) {
119
+ let res;
120
+ try {
121
+ res = await fetchImpl("https://api.anthropic.com/v1/messages", {
122
+ method: "POST",
123
+ headers: {
124
+ Authorization: `Bearer ${token}`,
125
+ "anthropic-version": "2023-06-01",
126
+ "anthropic-beta": "oauth-2025-04-20",
127
+ "content-type": "application/json",
128
+ },
129
+ body: JSON.stringify({ model, max_tokens: 1, messages: [{ role: "user", content: "ok" }] }),
130
+ signal: AbortSignal.timeout(15_000),
131
+ });
132
+ }
133
+ catch (err) {
134
+ return { result: { kind: "unmeasured", reason: `probe failed: ${err.name}` }, modelMissing: false };
135
+ }
136
+ let error;
137
+ try {
138
+ error = (await res.json())?.error;
139
+ }
140
+ catch {
141
+ error = undefined;
142
+ }
143
+ const message = error?.message ?? `HTTP ${res.status}`;
144
+ const meter = meterFromHeaders(res.headers, now());
145
+ switch (res.status) {
146
+ case 200:
147
+ return { result: { kind: "measured", meter }, modelMissing: false };
148
+ case 429:
149
+ // Without status=rejected it is a short burst limit, not the account's quota.
150
+ return meter.rejected
151
+ ? { result: { kind: "measured", meter }, modelMissing: false }
152
+ : { result: { kind: "unmeasured", reason: "briefly rate limited" }, modelMissing: false };
153
+ case 401:
154
+ case 403:
155
+ return { result: { kind: "refused", reason: message }, modelMissing: false };
156
+ case 400:
157
+ case 404: {
158
+ const modelMissing = error?.type === "not_found_error" || message.toLowerCase().includes("model");
159
+ return { result: { kind: "unmeasured", reason: modelMissing ? `model ${model} unavailable` : message }, modelMissing };
160
+ }
161
+ default:
162
+ return { result: { kind: "unmeasured", reason: message }, modelMissing: false };
163
+ }
164
+ }
165
+ /** Measure one account: the first probe model that exists answers. */
166
+ export async function probeAccount(token, opts = {}) {
167
+ const fetchImpl = opts.fetchImpl ?? fetch;
168
+ const now = opts.now ?? Date.now;
169
+ let last = { kind: "unmeasured", reason: "no probe model answered" };
170
+ for (const m of opts.models ?? PROBE_MODELS) {
171
+ const { result, modelMissing } = await probeOnce(token, m, fetchImpl, now);
172
+ if (!modelMissing)
173
+ return result;
174
+ last = result;
175
+ }
176
+ return last;
177
+ }
178
+ // ─── standing + selection ─────────────────────────────────────────────────────
179
+ /** An account counts as full once its 5-hour or weekly window reaches this percent. */
180
+ export const FULL_AT_PERCENT = 95;
181
+ /** A measurement is reused this long before the account is measured again. */
182
+ export const MEASURE_TTL_MS = 3 * 60_000;
183
+ export function isFull(m, threshold = FULL_AT_PERCENT) {
184
+ return m.rejected || (m.fiveHour ?? 0) >= threshold || (m.week ?? 0) >= threshold;
185
+ }
186
+ /** When the window that makes it full resets; a quarter of an hour when the server gave no time. */
187
+ export function fullUntil(m, threshold = FULL_AT_PERCENT) {
188
+ const dates = [];
189
+ if ((m.week ?? 0) >= threshold && m.weekReset)
190
+ dates.push(m.weekReset);
191
+ if ((m.fiveHour ?? 0) >= threshold && m.fiveHourReset)
192
+ dates.push(m.fiveHourReset);
193
+ if (!dates.length && m.rejected) {
194
+ const r = m.reset ?? m.fiveHourReset ?? m.weekReset;
195
+ if (r)
196
+ dates.push(r);
197
+ }
198
+ return dates.length ? Math.max(...dates) : m.checkedAt + 15 * 60_000;
199
+ }
200
+ /**
201
+ * What one account can take now, from its last probe and any "full until"
202
+ * mark a run left on it (a run that ended on a usage limit). A full window
203
+ * whose reset has passed is UNMEASURED until it is measured again — never room.
204
+ */
205
+ export function standingOf(probe, markedFullUntil, now, threshold = FULL_AT_PERCENT) {
206
+ if (markedFullUntil !== undefined && markedFullUntil > now) {
207
+ return { kind: "full", until: markedFullUntil, ...(probe?.kind === "measured" ? { meter: probe.meter } : {}) };
208
+ }
209
+ if (!probe)
210
+ return { kind: "unmeasured", reason: "not measured yet" };
211
+ if (probe.kind === "refused")
212
+ return { kind: "refused", reason: probe.reason };
213
+ if (probe.kind === "unmeasured")
214
+ return { kind: "unmeasured", reason: probe.reason };
215
+ const m = probe.meter;
216
+ if (isFull(m, threshold)) {
217
+ const until = fullUntil(m, threshold);
218
+ return until > now ? { kind: "full", until, meter: m } : { kind: "unmeasured", reason: "full window has reset; not measured since" };
219
+ }
220
+ return { kind: "room", meter: m };
221
+ }
222
+ /** Weekly room left in percent, when the account was measured. */
223
+ function weeklyLeft(s) {
224
+ const m = s.kind === "room" || s.kind === "full" ? s.meter : undefined;
225
+ if (!m || m.week === undefined)
226
+ return undefined;
227
+ return 100 - m.week;
228
+ }
229
+ /**
230
+ * The reserve: the `reserve` NON-design accounts with the most weekly room
231
+ * left — kept for the person's own morning. Only MEASURED accounts are ranked
232
+ * (an unmeasured one cannot be launched on anyway); a measured account whose
233
+ * weekly figure is missing ranks last. Ties go to file order.
234
+ */
235
+ export function reserveIds(accounts, standings, reserve) {
236
+ if (reserve <= 0)
237
+ return new Set();
238
+ const ranked = accounts
239
+ .map((a, order) => ({ a, order, s: standings.get(a.id) }))
240
+ .filter((x) => !x.a.design && x.s && (x.s.kind === "room" || x.s.kind === "full"))
241
+ .map((x) => ({ ...x, left: weeklyLeft(x.s) }))
242
+ .sort((x, y) => (y.left ?? -Infinity) - (x.left ?? -Infinity) || x.order - y.order);
243
+ return new Set(ranked.slice(0, reserve).map((x) => x.a.id));
244
+ }
245
+ /**
246
+ * Pick the account a run launches on.
247
+ *
248
+ * - A DESIGN run: only an account flagged `design` (the artifact belongs to
249
+ * the publishing account). None with room ⇒ nothing: wait, never another one.
250
+ * - Any other run: leave out the reserve; among the rest with room, the one
251
+ * whose 5-hour window resets SOONEST (use it or lose it); ties → file order.
252
+ * A design account comes last: it is spent on other runs only when no other
253
+ * account has room, so its quota stays for the designs only it can publish.
254
+ * An unmeasured, refused or full account is never picked.
255
+ */
256
+ export function selectAccount(file, standings, opts) {
257
+ const pool = opts.design
258
+ ? file.accounts.filter((a) => a.design)
259
+ : (() => {
260
+ const reserved = reserveIds(file.accounts, standings, file.reserve);
261
+ return file.accounts.filter((a) => !reserved.has(a.id));
262
+ })();
263
+ if (opts.design && pool.length === 0)
264
+ return { reason: "no account is flagged design:true" };
265
+ const withRoom = pool
266
+ .map((a, order) => ({ a, order, s: standings.get(a.id) }))
267
+ .filter((x) => x.s?.kind === "room");
268
+ if (!withRoom.length) {
269
+ const why = pool.map((a) => `${a.id}: ${describeStanding(standings.get(a.id))}`).join(", ");
270
+ return { reason: `no ${opts.design ? "design " : ""}account with room (${why || "all reserved"})` };
271
+ }
272
+ withRoom.sort((x, y) => (opts.design ? 0 : Number(!!x.a.design) - Number(!!y.a.design)) ||
273
+ (x.s.meter.fiveHourReset ?? Infinity) - (y.s.meter.fiveHourReset ?? Infinity) ||
274
+ x.order - y.order);
275
+ return { account: withRoom[0].a };
276
+ }
277
+ export function describeStanding(s) {
278
+ if (!s)
279
+ return "not measured";
280
+ switch (s.kind) {
281
+ case "room":
282
+ return `room (5h ${Math.round(s.meter.fiveHour ?? 0)}%, 7d ${Math.round(s.meter.week ?? 0)}%)`;
283
+ case "full":
284
+ return `full until ${new Date(s.until).toISOString()}`;
285
+ case "refused":
286
+ return "token refused";
287
+ case "unmeasured":
288
+ return `unmeasured (${s.reason})`;
289
+ }
290
+ }
291
+ // ─── the pool: cache + marks ──────────────────────────────────────────────────
292
+ /**
293
+ * The accounts plus what the worker knows about each: the last probe (reused
294
+ * for MEASURE_TTL_MS) and a "full until" mark left by a run that ended on a
295
+ * usage limit. In memory only: a restart measures again.
296
+ */
297
+ export class AccountPool {
298
+ file;
299
+ probe;
300
+ now;
301
+ probes = new Map();
302
+ marks = new Map();
303
+ constructor(file, probe, now = Date.now) {
304
+ this.file = file;
305
+ this.probe = probe;
306
+ this.now = now;
307
+ }
308
+ byId(id) {
309
+ return id ? this.file.accounts.find((a) => a.id === id) : undefined;
310
+ }
311
+ /** Measure every account whose measurement is stale (in parallel), skipping marked-full ones. */
312
+ async measure() {
313
+ const t = this.now();
314
+ await Promise.all(this.file.accounts.map(async (a) => {
315
+ const mark = this.marks.get(a.id);
316
+ if (mark !== undefined && mark > t)
317
+ return;
318
+ const last = this.probes.get(a.id);
319
+ const fresh = last?.kind === "measured" && t - last.meter.checkedAt < MEASURE_TTL_MS && !(isFull(last.meter) && fullUntil(last.meter) <= t);
320
+ if (fresh)
321
+ return;
322
+ this.probes.set(a.id, await this.probe(a.token));
323
+ }));
324
+ return this.standings();
325
+ }
326
+ standings() {
327
+ const t = this.now();
328
+ return new Map(this.file.accounts.map((a) => [a.id, standingOf(this.probes.get(a.id), this.marks.get(a.id), t)]));
329
+ }
330
+ /** A run on this account ended on a usage limit: full until then, measured afresh after. */
331
+ markFull(id, until) {
332
+ this.marks.set(id, until);
333
+ this.probes.delete(id);
334
+ }
335
+ select(opts) {
336
+ return selectAccount(this.file, this.standings(), opts);
337
+ }
338
+ }
339
+ //# sourceMappingURL=worker-accounts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-accounts.js","sourceRoot":"","sources":["../../src/commands/worker-accounts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,224 @@
1
+ import fs from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { describe, expect, it } from "vitest";
5
+ import { AccountPool, loadAccountsFile, probeAccount, reserveIds, selectAccount, standingOf, } from "./worker-accounts.js";
6
+ const T = Date.parse("2026-10-24T06:00:00Z");
7
+ const H = 3_600_000;
8
+ const meter = (m) => ({ rejected: false, checkedAt: T, ...m });
9
+ const room = (m) => ({ kind: "room", meter: meter(m) });
10
+ const file = (over = {}) => ({
11
+ version: 1,
12
+ reserve: 0,
13
+ accounts: [
14
+ { id: "dev", label: "Dev", token: "tok-dev", design: true },
15
+ { id: "a", label: "A", token: "tok-a" },
16
+ { id: "b", label: "B", token: "tok-b" },
17
+ { id: "c", label: "C", token: "tok-c" },
18
+ ],
19
+ ...over,
20
+ });
21
+ describe("selectAccount", () => {
22
+ it("picks the account whose 5-hour window resets soonest (use it or lose it)", () => {
23
+ const s = new Map([
24
+ ["dev", room({ fiveHour: 10, fiveHourReset: T + 4 * H, week: 10 })],
25
+ ["a", room({ fiveHour: 10, fiveHourReset: T + 3 * H, week: 10 })],
26
+ ["b", room({ fiveHour: 50, fiveHourReset: T + 1 * H, week: 10 })],
27
+ ["c", room({ fiveHour: 10, fiveHourReset: T + 2 * H, week: 10 })],
28
+ ]);
29
+ expect(selectAccount(file(), s, { design: false }).account?.id).toBe("b");
30
+ });
31
+ it("ties on the reset go to file order", () => {
32
+ const s = new Map([
33
+ ["a", room({ fiveHourReset: T + H })],
34
+ ["b", room({ fiveHourReset: T + H })],
35
+ ]);
36
+ expect(selectAccount(file(), s, { design: false }).account?.id).toBe("a");
37
+ });
38
+ it("leaves out the reserve: the non-design accounts with the most WEEKLY room left", () => {
39
+ // b resets soonest, but b and c have the most weekly room: they stay for the person.
40
+ const s = new Map([
41
+ ["dev", room({ fiveHourReset: T + 5 * H, week: 90 })],
42
+ ["a", room({ fiveHourReset: T + 3 * H, week: 80 })],
43
+ ["b", room({ fiveHourReset: T + 1 * H, week: 5 })],
44
+ ["c", room({ fiveHourReset: T + 2 * H, week: 20 })],
45
+ ]);
46
+ expect([...reserveIds(file().accounts, s, 2)].sort()).toEqual(["b", "c"]);
47
+ expect(selectAccount(file({ reserve: 2 }), s, { design: false }).account?.id).toBe("a");
48
+ });
49
+ it("the design account is never counted in the reserve", () => {
50
+ const s = new Map([
51
+ ["dev", room({ week: 0 })],
52
+ ["a", room({ week: 50 })],
53
+ ["b", room({ week: 60 })],
54
+ ]);
55
+ expect([...reserveIds(file().accounts, s, 1)]).toEqual(["a"]);
56
+ });
57
+ it("an UNMEASURED account is never picked — a failed probe is not room", () => {
58
+ const s = new Map([
59
+ ["a", { kind: "unmeasured", reason: "probe failed: TypeError" }],
60
+ ["b", { kind: "refused", reason: "HTTP 401" }],
61
+ ["c", { kind: "full", until: T + H }],
62
+ ]);
63
+ const sel = selectAccount(file(), s, { design: false });
64
+ expect(sel.account).toBeUndefined();
65
+ expect(sel.reason).toMatch(/a: unmeasured/);
66
+ });
67
+ it("an unmeasured account is never READ as full either: it is not reserved in place of a measured one", () => {
68
+ const s = new Map([
69
+ ["a", { kind: "unmeasured", reason: "x" }],
70
+ ["b", room({ week: 10 })],
71
+ ["c", room({ week: 30 })],
72
+ ]);
73
+ // b has the most weekly room among the MEASURED (90% left); a is not ranked at all.
74
+ expect([...reserveIds(file().accounts, s, 1)]).toEqual(["b"]);
75
+ expect(selectAccount(file({ reserve: 1 }), s, { design: false }).account?.id).toBe("c");
76
+ });
77
+ it("a design run takes ONLY the design account, and waits when it has no room", () => {
78
+ const s = new Map([
79
+ ["dev", { kind: "full", until: T + H }],
80
+ ["a", room({ fiveHourReset: T + H })],
81
+ ]);
82
+ const sel = selectAccount(file(), s, { design: true });
83
+ expect(sel.account).toBeUndefined();
84
+ expect(sel.reason).toMatch(/no design account with room/);
85
+ s.set("dev", room({ fiveHourReset: T + 9 * H }));
86
+ expect(selectAccount(file(), s, { design: true }).account?.id).toBe("dev");
87
+ });
88
+ it("another run spends the design account only when no other account has room", () => {
89
+ // dev resets soonest, yet a takes the run: dev's quota stays for the designs.
90
+ const s = new Map([
91
+ ["dev", room({ fiveHourReset: T + 1 * H })],
92
+ ["a", room({ fiveHourReset: T + 4 * H })],
93
+ ["b", { kind: "full", until: T + H }],
94
+ ["c", { kind: "full", until: T + H }],
95
+ ]);
96
+ expect(selectAccount(file(), s, { design: false }).account?.id).toBe("a");
97
+ s.set("a", { kind: "full", until: T + H });
98
+ expect(selectAccount(file(), s, { design: false }).account?.id).toBe("dev");
99
+ });
100
+ it("a design run with no design account flagged is refused in words", () => {
101
+ const f = file({ accounts: [{ id: "a", label: "A", token: "t" }] });
102
+ expect(selectAccount(f, new Map([["a", room({})]]), { design: true }).reason).toMatch(/flagged design/);
103
+ });
104
+ });
105
+ describe("standingOf", () => {
106
+ it("over the threshold is full until the binding window resets", () => {
107
+ const s = standingOf({ kind: "measured", meter: meter({ fiveHour: 96, fiveHourReset: T + H, week: 10 }) }, undefined, T);
108
+ expect(s).toMatchObject({ kind: "full", until: T + H });
109
+ });
110
+ it("a full window whose reset passed is unmeasured until measured again — not room", () => {
111
+ const s = standingOf({ kind: "measured", meter: meter({ fiveHour: 100, fiveHourReset: T - 1 }) }, undefined, T);
112
+ expect(s.kind).toBe("unmeasured");
113
+ });
114
+ it("a run's limit mark wins over an older probe", () => {
115
+ const s = standingOf({ kind: "measured", meter: meter({ fiveHour: 1 }) }, T + H, T);
116
+ expect(s).toMatchObject({ kind: "full", until: T + H });
117
+ });
118
+ });
119
+ const headers = (h) => Object.fromEntries(Object.entries(h).map(([k, v]) => [`anthropic-ratelimit-unified-${k}`, v]));
120
+ const respond = (status, h = {}, body = {}) => new Response(JSON.stringify(body), { status, headers: { "content-type": "application/json", ...headers(h) } });
121
+ describe("probeAccount (ported from ClaudeSwitch probeOnce)", () => {
122
+ it("200 → measured, utilization as percent, resets in ms", async () => {
123
+ let sent;
124
+ const r = await probeAccount("sk-ant-oat-x", {
125
+ now: () => T,
126
+ fetchImpl: (async (_u, init) => {
127
+ sent = init;
128
+ return respond(200, { status: "allowed", "5h-utilization": "0.25", "5h-reset": "1792725000", "7d-utilization": "0.5", "7d-reset": "1793000000" });
129
+ }),
130
+ });
131
+ expect(r).toEqual({
132
+ kind: "measured",
133
+ meter: expect.objectContaining({ fiveHour: 25, fiveHourReset: 1792725000_000, week: 50, weekReset: 1793000000_000, rejected: false }),
134
+ });
135
+ const h = sent?.headers;
136
+ expect(h.Authorization).toBe("Bearer sk-ant-oat-x");
137
+ expect(h["anthropic-beta"]).toBe("oauth-2025-04-20");
138
+ expect(JSON.parse(String(sent?.body)).max_tokens).toBe(1);
139
+ });
140
+ it("429 rejected → measured full; 429 without rejected → a burst, unmeasured", async () => {
141
+ const full = await probeAccount("t", { fetchImpl: (async () => respond(429, { status: "rejected", reset: "1792725000" })) });
142
+ expect(full).toMatchObject({ kind: "measured", meter: { rejected: true } });
143
+ const burst = await probeAccount("t", { fetchImpl: (async () => respond(429, {})) });
144
+ expect(burst).toEqual({ kind: "unmeasured", reason: "briefly rate limited" });
145
+ });
146
+ it("401/403 → refused", async () => {
147
+ const r = await probeAccount("t", { fetchImpl: (async () => respond(401, {}, { error: { message: "invalid token" } })) });
148
+ expect(r).toEqual({ kind: "refused", reason: "invalid token" });
149
+ });
150
+ it("a missing model tries the next one", async () => {
151
+ const models = [];
152
+ const r = await probeAccount("t", {
153
+ models: ["gone-model", "live-model"],
154
+ fetchImpl: (async (_u, init) => {
155
+ const m = JSON.parse(String(init?.body)).model;
156
+ models.push(m);
157
+ return m === "gone-model" ? respond(404, {}, { error: { type: "not_found_error", message: "model: gone" } }) : respond(200, { "5h-utilization": "0" });
158
+ }),
159
+ });
160
+ expect(models).toEqual(["gone-model", "live-model"]);
161
+ expect(r.kind).toBe("measured");
162
+ });
163
+ it("a network failure is UNMEASURED, never room and never full", async () => {
164
+ const r = await probeAccount("t", { fetchImpl: (async () => { throw new TypeError("fetch failed"); }) });
165
+ expect(r.kind).toBe("unmeasured");
166
+ expect(standingOf(r, undefined, T).kind).toBe("unmeasured");
167
+ });
168
+ });
169
+ describe("AccountPool", () => {
170
+ it("reuses a fresh measurement, and a limit mark keeps the account out without probing it", async () => {
171
+ let t = T;
172
+ const probed = [];
173
+ const probe = async (token) => {
174
+ probed.push(token);
175
+ return { kind: "measured", meter: meter({ fiveHour: 10, fiveHourReset: T + H, checkedAt: t }) };
176
+ };
177
+ const pool = new AccountPool(file({ accounts: file().accounts.slice(1, 3) }), probe, () => t);
178
+ await pool.measure();
179
+ await pool.measure();
180
+ expect(probed).toEqual(["tok-a", "tok-b"]);
181
+ pool.markFull("a", T + H);
182
+ t += 4 * 60_000;
183
+ await pool.measure();
184
+ expect(probed).toEqual(["tok-a", "tok-b", "tok-b"]);
185
+ expect(pool.select({ design: false }).account?.id).toBe("b");
186
+ });
187
+ });
188
+ describe("loadAccountsFile", () => {
189
+ const dir = () => fs.mkdtempSync(path.join(os.tmpdir(), "worker-accounts-"));
190
+ it("no default file → null (the environment's login, as before)", () => {
191
+ expect(loadAccountsFile(undefined)).toBeNull();
192
+ });
193
+ it("a named file that is missing throws", () => {
194
+ expect(() => loadAccountsFile(path.join(dir(), "nope.json"))).toThrow(/does not exist/);
195
+ });
196
+ it("a broken file throws — never 'no accounts' — and never quotes a token", () => {
197
+ const f = path.join(dir(), "accounts.json");
198
+ fs.writeFileSync(f, '{"version":1,"accounts":[{"id":"a","token":"sk-ant-oat-SECRET"}');
199
+ expect(() => loadAccountsFile(f)).toThrow(/not valid JSON/);
200
+ fs.writeFileSync(f, JSON.stringify({ version: 1, accounts: [{ id: "a b", token: "sk-ant-oat-SECRET" }] }));
201
+ let msg = "";
202
+ try {
203
+ loadAccountsFile(f);
204
+ }
205
+ catch (err) {
206
+ msg = err.message;
207
+ }
208
+ expect(msg).toMatch(/id must match/);
209
+ expect(msg).not.toContain("SECRET");
210
+ });
211
+ it("reads the documented shape", () => {
212
+ const f = path.join(dir(), "accounts.json");
213
+ fs.writeFileSync(f, JSON.stringify({ version: 1, reserve: 2, accounts: [{ id: "dev", label: "Dev", token: " t1 ", design: true }, { id: "a", token: "t2" }] }));
214
+ expect(loadAccountsFile(f)).toEqual({
215
+ version: 1,
216
+ reserve: 2,
217
+ accounts: [
218
+ { id: "dev", label: "Dev", token: "t1", design: true },
219
+ { id: "a", label: "a", token: "t2" },
220
+ ],
221
+ });
222
+ });
223
+ });
224
+ //# sourceMappingURL=worker-accounts.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-accounts.test.js","sourceRoot":"","sources":["../../src/commands/worker-accounts.test.ts"],"names":[],"mappings":"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"}