@reticlehq/server 3.5.0 → 3.7.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 (721) hide show
  1. package/README.md +1 -1
  2. package/SKILL.md +123 -116
  3. package/dist/chromium-launch-options.d.ts +3 -1
  4. package/dist/chromium-launch-options.js +2 -1
  5. package/dist/command/cli/adhoc-suite.d.ts +14 -0
  6. package/dist/command/cli/adhoc-suite.js +42 -7
  7. package/dist/command/cli/adhoc-verdict.d.ts +19 -2
  8. package/dist/command/cli/adhoc-verdict.js +76 -9
  9. package/dist/command/cli/answers/gate-exit.d.ts +23 -0
  10. package/dist/command/cli/answers/gate-exit.js +45 -0
  11. package/dist/command/cli/answers/gate-hook-message.d.ts +2 -0
  12. package/dist/command/cli/answers/gate-hook-message.js +3 -1
  13. package/dist/command/cli/answers/open-note.d.ts +2 -0
  14. package/dist/command/cli/answers/open-note.js +22 -0
  15. package/dist/command/cli/auth/device-flow.d.ts +13 -2
  16. package/dist/command/cli/auth/device-flow.js +17 -0
  17. package/dist/command/cli/cli-doctor.js +14 -0
  18. package/dist/command/cli/cli-flow-commands.d.ts +0 -11
  19. package/dist/command/cli/cli-flow-commands.js +31 -112
  20. package/dist/command/cli/cli-kill.js +3 -2
  21. package/dist/command/cli/cli-parse-grammar.d.ts +24 -0
  22. package/dist/command/cli/cli-parse-grammar.js +75 -0
  23. package/dist/command/cli/cli-parse-verify.d.ts +2 -0
  24. package/dist/command/cli/cli-parse-verify.js +18 -0
  25. package/dist/command/cli/cli-parse.d.ts +19 -28
  26. package/dist/command/cli/cli-parse.js +82 -182
  27. package/dist/command/cli/cli-update-commands.d.ts +1 -1
  28. package/dist/command/cli/cli-update-commands.js +61 -9
  29. package/dist/command/cli/cli-usage.d.ts +33 -0
  30. package/dist/command/cli/cli-usage.js +287 -0
  31. package/dist/command/cli/cli-verify.d.ts +35 -5
  32. package/dist/command/cli/cli-verify.js +114 -35
  33. package/dist/command/cli/cloud-cli.d.ts +13 -0
  34. package/dist/command/cli/cloud-cli.js +192 -341
  35. package/dist/command/cli/cloud-kit.d.ts +12 -0
  36. package/dist/command/cli/cloud-kit.js +41 -2
  37. package/dist/command/cli/cloud-link.d.ts +57 -0
  38. package/dist/command/cli/cloud-link.js +308 -0
  39. package/dist/command/cli/cloud-login.d.ts +22 -0
  40. package/dist/command/cli/cloud-login.js +96 -8
  41. package/dist/command/cli/context-command.d.ts +1 -0
  42. package/dist/command/cli/context-command.js +33 -0
  43. package/dist/command/cli/daemon-start-options.d.ts +3 -0
  44. package/dist/command/cli/daemon-start-options.js +24 -3
  45. package/dist/command/cli/doctor/browser/chromium-hint.d.ts +46 -0
  46. package/dist/command/cli/doctor/browser/chromium-hint.js +99 -1
  47. package/dist/command/cli/doctor/doctor-coverage-line.d.ts +2 -0
  48. package/dist/command/cli/doctor/doctor-coverage-line.js +47 -0
  49. package/dist/command/cli/doctor/doctor-project-line.d.ts +0 -12
  50. package/dist/command/cli/doctor/doctor-project-line.js +5 -4
  51. package/dist/command/cli/doctor/doctor-rows.d.ts +6 -0
  52. package/dist/command/cli/doctor/doctor-rows.js +6 -0
  53. package/dist/command/cli/doctor/doctor-signing-line.d.ts +38 -0
  54. package/dist/command/cli/doctor/doctor-signing-line.js +114 -0
  55. package/dist/command/cli/drive/drive-attach.d.ts +27 -2
  56. package/dist/command/cli/drive/drive-attach.js +71 -4
  57. package/dist/command/cli/drive/drive-command.d.ts +2 -1
  58. package/dist/command/cli/drive/drive-command.js +13 -7
  59. package/dist/command/cli/known-regression.d.ts +13 -0
  60. package/dist/command/cli/known-regression.js +34 -0
  61. package/dist/command/cli/launch/sdk-version-match.d.ts +12 -0
  62. package/dist/command/cli/launch/sdk-version-match.js +25 -0
  63. package/dist/command/cli/lifecycle/daemon-lifecycle.js +15 -3
  64. package/dist/command/cli/mcp-command.d.ts +6 -0
  65. package/dist/command/cli/mcp-command.js +13 -5
  66. package/dist/command/cli/ports/port-holder.d.ts +10 -0
  67. package/dist/command/cli/ports/port-holder.js +25 -1
  68. package/dist/command/cli/project-name.d.ts +29 -1
  69. package/dist/command/cli/project-name.js +107 -2
  70. package/dist/command/cli/setup-mcp-cli.d.ts +17 -1
  71. package/dist/command/cli/setup-mcp-cli.js +35 -12
  72. package/dist/command/cli/status/status-lines.d.ts +1 -0
  73. package/dist/command/cli/status/status-lines.js +47 -2
  74. package/dist/command/cli/status/workspace-links.d.ts +10 -0
  75. package/dist/command/cli/status/workspace-links.js +29 -0
  76. package/dist/command/cli/try-command.d.ts +96 -0
  77. package/dist/command/cli/try-command.js +362 -0
  78. package/dist/command/cli/tutorial.d.ts +0 -100
  79. package/dist/command/cli/tutorial.js +0 -181
  80. package/dist/command/cli/verify-results.d.ts +19 -0
  81. package/dist/command/cli/verify-results.js +29 -0
  82. package/dist/command/cli-onboarding.d.ts +0 -11
  83. package/dist/command/cli-onboarding.js +0 -15
  84. package/dist/command/cli.d.ts +20 -0
  85. package/dist/command/cli.js +130 -104
  86. package/dist/command/daemon/binding/daemon-status-probe.d.ts +2 -0
  87. package/dist/command/daemon/binding/daemon-status-probe.js +1 -0
  88. package/dist/command/daemon/daemon-resilience.js +4 -4
  89. package/dist/command/daemon/daemon-resolve.d.ts +23 -1
  90. package/dist/command/daemon/daemon-resolve.js +79 -9
  91. package/dist/command/setup/agent-writer.d.ts +1 -1
  92. package/dist/command/setup/agent-writer.js +3 -2
  93. package/dist/command/setup/bringup/bridge-port.d.ts +3 -1
  94. package/dist/command/setup/bringup/bridge-port.js +13 -3
  95. package/dist/command/setup/bringup/connect-lease.d.ts +1 -0
  96. package/dist/command/setup/bringup/connect-lease.js +1 -0
  97. package/dist/command/setup/bringup/dev-server-log-cap.js +2 -0
  98. package/dist/command/setup/bringup/dev-server-wait.d.ts +8 -0
  99. package/dist/command/setup/bringup/dev-server-wait.js +19 -0
  100. package/dist/command/setup/bringup/ensure-daemon.js +9 -2
  101. package/dist/command/setup/init/agent-restart.d.ts +23 -0
  102. package/dist/command/setup/init/agent-restart.js +28 -0
  103. package/dist/command/setup/init/init-port.d.ts +14 -1
  104. package/dist/command/setup/init/init-port.js +32 -2
  105. package/dist/command/setup/init/init-runtime.d.ts +22 -2
  106. package/dist/command/setup/init/init-runtime.js +114 -38
  107. package/dist/command/setup/node-effects.d.ts +2 -0
  108. package/dist/command/setup/node-effects.js +38 -9
  109. package/dist/command/setup/probe/existing-app.d.ts +12 -0
  110. package/dist/command/setup/probe/existing-app.js +14 -0
  111. package/dist/command/setup/remaining-steps.js +2 -1
  112. package/dist/command/setup/run-setup.d.ts +34 -9
  113. package/dist/command/setup/run-setup.js +65 -51
  114. package/dist/command/setup/setup-command.d.ts +25 -1
  115. package/dist/command/setup/setup-command.js +59 -4
  116. package/dist/command/setup/setup-mcp.js +25 -2
  117. package/dist/command/setup/tauri-signing.d.ts +19 -0
  118. package/dist/command/setup/tauri-signing.js +79 -0
  119. package/dist/command/setup/terminal/listeners.d.ts +10 -1
  120. package/dist/command/setup/terminal/listeners.js +37 -6
  121. package/dist/command/update/update-nudge.d.ts +9 -0
  122. package/dist/command/update/update-nudge.js +1 -1
  123. package/dist/command/update/updater.js +11 -15
  124. package/dist/command/version/version-nudge.js +3 -0
  125. package/dist/command/version/version-skew.d.ts +20 -1
  126. package/dist/command/version/version-skew.js +49 -4
  127. package/dist/features/crawl/crawl-tools.js +4 -0
  128. package/dist/features/crawl/crawl.d.ts +6 -0
  129. package/dist/features/crawl/crawl.js +23 -2
  130. package/dist/features/exhaust/ledger.d.ts +21 -14
  131. package/dist/features/exhaust/ledger.js +35 -9
  132. package/dist/features/harness/app-findings.d.ts +2 -0
  133. package/dist/features/harness/app-findings.js +52 -0
  134. package/dist/features/harness/drive-report.d.ts +61 -1
  135. package/dist/features/harness/drive-report.js +394 -26
  136. package/dist/features/harness/drive-runs.d.ts +120 -0
  137. package/dist/features/harness/drive-runs.js +289 -0
  138. package/dist/features/harness/drivers.d.ts +10 -14
  139. package/dist/features/harness/drivers.js +10 -14
  140. package/dist/features/harness/explore/console-pages.d.ts +15 -0
  141. package/dist/features/harness/explore/console-pages.js +146 -0
  142. package/dist/features/harness/explore/disparity.d.ts +19 -0
  143. package/dist/features/harness/explore/disparity.js +71 -0
  144. package/dist/features/harness/explore/fake-app.d.ts +16 -0
  145. package/dist/features/harness/explore/fake-app.js +49 -0
  146. package/dist/features/harness/explore/goal-search.d.ts +26 -0
  147. package/dist/features/harness/explore/goal-search.js +144 -0
  148. package/dist/features/harness/explore/page-tree.d.ts +49 -0
  149. package/dist/features/harness/explore/page-tree.js +148 -0
  150. package/dist/features/harness/explore/site-map.d.ts +34 -0
  151. package/dist/features/harness/explore/site-map.js +150 -0
  152. package/dist/features/harness/fill-values.d.ts +3 -73
  153. package/dist/features/harness/fill-values.js +3 -169
  154. package/dist/features/harness/goals.d.ts +82 -0
  155. package/dist/features/harness/goals.js +330 -0
  156. package/dist/features/harness/harness.d.ts +51 -1
  157. package/dist/features/harness/harness.js +207 -6
  158. package/dist/features/harness/platform/drive-target.d.ts +30 -0
  159. package/dist/features/harness/platform/drive-target.js +81 -0
  160. package/dist/features/harness/platform/local-apps.d.ts +127 -0
  161. package/dist/features/harness/platform/local-apps.js +280 -0
  162. package/dist/features/harness/platform/persona-credentials.d.ts +20 -0
  163. package/dist/features/harness/platform/persona-credentials.js +69 -0
  164. package/dist/features/harness/platform/platform-drives.d.ts +61 -0
  165. package/dist/features/harness/platform/platform-drives.js +114 -0
  166. package/dist/features/harness/platform/refusal.d.ts +52 -0
  167. package/dist/features/harness/platform/refusal.js +71 -0
  168. package/dist/features/harness/platform/remote-drive.d.ts +186 -0
  169. package/dist/features/harness/platform/remote-drive.js +378 -0
  170. package/dist/features/harness/platform/script.d.ts +94 -0
  171. package/dist/features/harness/platform/script.js +260 -0
  172. package/dist/features/harness/platform/server-driver.d.ts +54 -0
  173. package/dist/features/harness/platform/server-driver.js +182 -0
  174. package/dist/features/harness/platform-config.d.ts +41 -1
  175. package/dist/features/harness/platform-config.js +106 -9
  176. package/dist/features/harness/route-guess.d.ts +13 -0
  177. package/dist/features/harness/route-guess.js +49 -0
  178. package/dist/features/harness/script/app-controls.d.ts +5 -0
  179. package/dist/features/harness/script/app-controls.js +40 -0
  180. package/dist/features/harness/script/lane-ids.d.ts +14 -0
  181. package/dist/features/harness/script/lane-ids.js +16 -0
  182. package/dist/features/harness/script/script-run.d.ts +70 -0
  183. package/dist/features/harness/script/script-run.js +606 -0
  184. package/dist/features/license/license.d.ts +2 -2
  185. package/dist/features/visual/step-shots.d.ts +31 -0
  186. package/dist/features/visual/step-shots.js +231 -0
  187. package/dist/features/visual/visual-tools.d.ts +10 -1
  188. package/dist/features/visual/visual-tools.js +62 -17
  189. package/dist/hooks/client-directory.d.ts +18 -0
  190. package/dist/hooks/client-directory.js +57 -0
  191. package/dist/hooks/coding-agents.d.ts +34 -0
  192. package/dist/hooks/coding-agents.js +117 -0
  193. package/dist/hooks/driven-by.d.ts +23 -0
  194. package/dist/hooks/driven-by.js +56 -0
  195. package/dist/hooks/hook-bus.d.ts +4 -0
  196. package/dist/hooks/hook-bus.js +18 -0
  197. package/dist/hooks/hook-commands.js +15 -4
  198. package/dist/hooks/tool-log.d.ts +9 -0
  199. package/dist/hooks/tool-log.js +29 -0
  200. package/dist/index.d.ts +2 -0
  201. package/dist/index.js +80 -243
  202. package/dist/judgement/capsule/capsule-store.d.ts +2 -2
  203. package/dist/judgement/capsule/causal-summary.d.ts +15 -1
  204. package/dist/judgement/capsule/causal-summary.js +33 -0
  205. package/dist/judgement/runs/artifact/build-verification-run.d.ts +1 -1
  206. package/dist/judgement/runs/artifact/build-verification-run.js +25 -3
  207. package/dist/judgement/runs/artifact/gap-summary.d.ts +0 -18
  208. package/dist/judgement/runs/artifact/gap-summary.js +12 -3
  209. package/dist/judgement/runs/artifact/replay-mapping.d.ts +1 -1
  210. package/dist/judgement/runs/artifact/replay-mapping.js +37 -11
  211. package/dist/judgement/runs/artifact/run-store.d.ts +14 -2
  212. package/dist/judgement/runs/artifact/run-store.js +195 -3
  213. package/dist/judgement/runs/context-tools.js +59 -1
  214. package/dist/judgement/runs/default-run-id.d.ts +3 -0
  215. package/dist/judgement/runs/default-run-id.js +16 -0
  216. package/dist/judgement/runs/drive-run.d.ts +71 -1
  217. package/dist/judgement/runs/drive-run.js +317 -5
  218. package/dist/judgement/runs/repair-prompt.js +1 -1
  219. package/dist/judgement/runs/resume.d.ts +44 -0
  220. package/dist/judgement/runs/resume.js +137 -0
  221. package/dist/judgement/runs/reticle-runner.js +13 -3
  222. package/dist/judgement/runs/runner-port.d.ts +5 -1
  223. package/dist/judgement/runs/runner-port.js +8 -2
  224. package/dist/judgement/runs/verification-sync.d.ts +5 -2
  225. package/dist/judgement/runs/verification-sync.js +40 -18
  226. package/dist/language/flows/change/gate.d.ts +10 -0
  227. package/dist/language/flows/change/gate.js +22 -0
  228. package/dist/language/flows/decision.js +36 -1
  229. package/dist/language/flows/fields/flow-secret-field.d.ts +12 -0
  230. package/dist/language/flows/fields/flow-secret-field.js +25 -2
  231. package/dist/language/flows/flow-anchor.d.ts +61 -10
  232. package/dist/language/flows/flow-anchor.js +98 -6
  233. package/dist/language/flows/flow-cross-step.d.ts +15 -0
  234. package/dist/language/flows/flow-cross-step.js +21 -0
  235. package/dist/language/flows/flow-intent.d.ts +1 -0
  236. package/dist/language/flows/flow-journey.d.ts +6 -0
  237. package/dist/language/flows/flow-journey.js +20 -0
  238. package/dist/language/flows/flow-learning.d.ts +4 -0
  239. package/dist/language/flows/flow-learning.js +45 -14
  240. package/dist/language/flows/flow-mutate-tools.js +5 -3
  241. package/dist/language/flows/flow-replay-run.d.ts +23 -9
  242. package/dist/language/flows/flow-replay-run.js +115 -110
  243. package/dist/language/flows/flow-replay-types.d.ts +1 -1
  244. package/dist/language/flows/flow-replay.d.ts +40 -1
  245. package/dist/language/flows/flow-replay.js +110 -22
  246. package/dist/language/flows/flow-result.d.ts +22 -1
  247. package/dist/language/flows/flow-result.js +47 -2
  248. package/dist/language/flows/flow-scope.js +5 -1
  249. package/dist/language/flows/flow-step-runners.d.ts +22 -2
  250. package/dist/language/flows/flow-step-runners.js +247 -47
  251. package/dist/language/flows/flow-store-for-session.d.ts +2 -2
  252. package/dist/language/flows/flow-store-for-session.js +7 -3
  253. package/dist/language/flows/flow-tools.d.ts +10 -0
  254. package/dist/language/flows/flow-tools.js +112 -89
  255. package/dist/language/flows/flows.d.ts +16 -1
  256. package/dist/language/flows/flows.js +74 -12
  257. package/dist/language/flows/heal-run.js +6 -4
  258. package/dist/language/flows/narrow-write.d.ts +7 -0
  259. package/dist/language/flows/narrow-write.js +36 -1
  260. package/dist/language/flows/recording/flake.d.ts +2 -2
  261. package/dist/language/flows/recording/recording-backtrack.js +14 -1
  262. package/dist/language/flows/recording/tape/recordings.d.ts +58 -4
  263. package/dist/language/flows/recording/tape/recordings.js +95 -13
  264. package/dist/language/flows/replay-from-hud.d.ts +20 -0
  265. package/dist/language/flows/replay-from-hud.js +51 -0
  266. package/dist/language/flows/replay.d.ts +9 -5
  267. package/dist/language/flows/replay.js +56 -15
  268. package/dist/language/flows/single-replay.d.ts +7 -0
  269. package/dist/language/flows/single-replay.js +26 -0
  270. package/dist/language/flows/suite/suite-flakes.js +2 -0
  271. package/dist/language/flows/suite-selection.d.ts +2 -15
  272. package/dist/language/flows/suite-selection.js +4 -3
  273. package/dist/language/flows/verify-change-tools.d.ts +1 -0
  274. package/dist/language/flows/verify-change-tools.js +202 -191
  275. package/dist/launch-chromium.d.ts +27 -5
  276. package/dist/launch-chromium.js +38 -8
  277. package/dist/memory/cloud/cloud-config.d.ts +22 -1
  278. package/dist/memory/cloud/cloud-config.js +34 -5
  279. package/dist/memory/cloud/cloud-sync.d.ts +17 -14
  280. package/dist/memory/cloud/cloud-sync.js +15 -4
  281. package/dist/memory/cloud/harness-config.d.ts +75 -1
  282. package/dist/memory/cloud/harness-config.js +115 -24
  283. package/dist/memory/cloud/hud-notices-source.d.ts +21 -0
  284. package/dist/memory/cloud/hud-notices-source.js +128 -0
  285. package/dist/memory/cloud/memory-scope.d.ts +161 -0
  286. package/dist/memory/cloud/memory-scope.js +227 -0
  287. package/dist/memory/cloud/sync-cycle.d.ts +44 -7
  288. package/dist/memory/cloud/sync-cycle.js +129 -15
  289. package/dist/memory/cloud/sync-daemon.d.ts +11 -0
  290. package/dist/memory/cloud/sync-daemon.js +121 -9
  291. package/dist/memory/cloud/sync-disk.d.ts +1 -1
  292. package/dist/memory/cloud/sync-disk.js +31 -10
  293. package/dist/memory/cloud/sync-screenshots.d.ts +32 -0
  294. package/dist/memory/cloud/sync-screenshots.js +105 -0
  295. package/dist/memory/cloud/unsynced-roots.d.ts +47 -0
  296. package/dist/memory/cloud/unsynced-roots.js +166 -0
  297. package/dist/memory/impact/account-watch.d.ts +34 -0
  298. package/dist/memory/impact/account-watch.js +59 -0
  299. package/dist/memory/impact/impact-recorder.d.ts +8 -0
  300. package/dist/memory/impact/impact-recorder.js +12 -2
  301. package/dist/memory/impact/impact-store.d.ts +17 -4
  302. package/dist/memory/impact/impact-store.js +169 -63
  303. package/dist/memory/intent/inline-intent.d.ts +1 -0
  304. package/dist/memory/intent/intent-shard-store.js +16 -4
  305. package/dist/memory/intent/intent-shard.d.ts +14 -2
  306. package/dist/memory/intent/intent-store.d.ts +1 -0
  307. package/dist/memory/intent/intent-tools.js +122 -4
  308. package/dist/memory/intent/open-intents.d.ts +6 -0
  309. package/dist/memory/intent/open-intents.js +10 -1
  310. package/dist/memory/intent/settled-words.d.ts +24 -0
  311. package/dist/memory/intent/settled-words.js +130 -0
  312. package/dist/memory/journal/drive-flow.d.ts +16 -0
  313. package/dist/memory/journal/drive-flow.js +34 -2
  314. package/dist/memory/journal/drive-run-flush.d.ts +2 -0
  315. package/dist/memory/journal/drive-run-flush.js +20 -5
  316. package/dist/memory/journal/envelope.d.ts +8 -8
  317. package/dist/memory/journal/journal-recorder.js +52 -3
  318. package/dist/memory/journal/on-disk/retention.d.ts +8 -0
  319. package/dist/memory/journal/on-disk/retention.js +32 -2
  320. package/dist/memory/journal/on-disk/startup-maintenance.js +3 -1
  321. package/dist/memory/journal/on-disk/workspace-tiers.js +9 -4
  322. package/dist/memory/journal/session-end.d.ts +15 -1
  323. package/dist/memory/journal/session-end.js +42 -9
  324. package/dist/memory/project/artifact-root-resolver.d.ts +26 -1
  325. package/dist/memory/project/artifact-root-resolver.js +125 -16
  326. package/dist/memory/project/artifact-root.d.ts +46 -8
  327. package/dist/memory/project/artifact-root.js +89 -10
  328. package/dist/memory/project/dir/reticle-dir.d.ts +18 -2
  329. package/dist/memory/project/dir/reticle-dir.js +26 -3
  330. package/dist/memory/project/link-directory.d.ts +15 -0
  331. package/dist/memory/project/link-directory.js +44 -0
  332. package/dist/memory/project/project-tools.js +22 -3
  333. package/dist/memory/project/root-claims.d.ts +6 -0
  334. package/dist/memory/project/root-claims.js +39 -0
  335. package/dist/memory/project/session-root.d.ts +26 -1
  336. package/dist/memory/project/session-root.js +49 -5
  337. package/dist/memory/project/sync-status.d.ts +85 -0
  338. package/dist/memory/project/sync-status.js +224 -0
  339. package/dist/memory/recall/memory-tools.js +47 -2
  340. package/dist/memory/recall/platform-memory.d.ts +34 -0
  341. package/dist/memory/recall/platform-memory.js +139 -0
  342. package/dist/memory/recall/project-memory.d.ts +19 -0
  343. package/dist/memory/recall/project-memory.js +80 -13
  344. package/dist/portal/bridge/bridge.d.ts +9 -3
  345. package/dist/portal/bridge/bridge.js +82 -22
  346. package/dist/portal/bridge/harness-request.d.ts +23 -0
  347. package/dist/portal/bridge/harness-request.js +27 -0
  348. package/dist/portal/bridge/pairing-token.d.ts +9 -0
  349. package/dist/portal/bridge/pairing-token.js +17 -0
  350. package/dist/portal/bridge/wrong-path.d.ts +17 -0
  351. package/dist/portal/bridge/wrong-path.js +35 -0
  352. package/dist/portal/input/network-mock-tools.js +11 -2
  353. package/dist/portal/input/real-input.d.ts +83 -10
  354. package/dist/portal/input/real-input.js +218 -30
  355. package/dist/portal/input/viewport-tools.js +3 -3
  356. package/dist/portal/pool/browser-pool.d.ts +70 -9
  357. package/dist/portal/pool/browser-pool.js +190 -37
  358. package/dist/portal/pool/context-permissions.d.ts +33 -0
  359. package/dist/portal/pool/context-permissions.js +33 -0
  360. package/dist/portal/pool/lease-marker-stamp.d.ts +23 -0
  361. package/dist/portal/pool/lease-marker-stamp.js +49 -0
  362. package/dist/portal/pool/playwright-launcher.d.ts +35 -0
  363. package/dist/portal/pool/playwright-launcher.js +64 -3
  364. package/dist/portal/pool/pool-contract.d.ts +28 -5
  365. package/dist/portal/session/agent-link.d.ts +8 -0
  366. package/dist/portal/session/agent-link.js +17 -0
  367. package/dist/portal/session/command-payload.d.ts +8 -0
  368. package/dist/portal/session/command-payload.js +24 -0
  369. package/dist/portal/session/daemon-answers.d.ts +3 -3
  370. package/dist/portal/session/daemon-answers.js +4 -2
  371. package/dist/portal/session/dev-server/dev-command.d.ts +21 -0
  372. package/dist/portal/session/dev-server/dev-command.js +87 -12
  373. package/dist/portal/session/facts/departure-note.d.ts +22 -0
  374. package/dist/portal/session/facts/departure-note.js +47 -0
  375. package/dist/portal/session/facts/observed-state.d.ts +16 -18
  376. package/dist/portal/session/facts/observed-state.js +46 -3
  377. package/dist/portal/session/facts/session-replaced.d.ts +5 -0
  378. package/dist/portal/session/facts/session-replaced.js +5 -0
  379. package/dist/portal/session/first-run-wiring.d.ts +42 -0
  380. package/dist/portal/session/first-run-wiring.js +132 -0
  381. package/dist/portal/session/human/live-control.d.ts +9 -2
  382. package/dist/portal/session/human/live-control.js +12 -3
  383. package/dist/portal/session/human/notes-ledger.d.ts +20 -0
  384. package/dist/portal/session/human/notes-ledger.js +55 -0
  385. package/dist/portal/session/human/review-store.d.ts +12 -0
  386. package/dist/portal/session/human/review-store.js +18 -10
  387. package/dist/portal/session/live-control-tools.d.ts +0 -13
  388. package/dist/portal/session/live-control-tools.js +107 -13
  389. package/dist/portal/session/narration-args.d.ts +5 -0
  390. package/dist/portal/session/narration-args.js +17 -0
  391. package/dist/portal/session/no-session-diagnosis.d.ts +8 -1
  392. package/dist/portal/session/no-session-diagnosis.js +46 -9
  393. package/dist/portal/session/no-session-next-action.d.ts +31 -0
  394. package/dist/portal/session/no-session-next-action.js +159 -60
  395. package/dist/portal/session/no-session-watch.d.ts +14 -1
  396. package/dist/portal/session/no-session-watch.js +227 -17
  397. package/dist/portal/session/presence/session-lease.js +1 -1
  398. package/dist/portal/session/presence/session-mirror.js +3 -0
  399. package/dist/portal/session/recorded-gaps.d.ts +97 -0
  400. package/dist/portal/session/recorded-gaps.js +251 -0
  401. package/dist/portal/session/serving-directory.d.ts +27 -0
  402. package/dist/portal/session/serving-directory.js +45 -0
  403. package/dist/portal/session/session-health.d.ts +18 -0
  404. package/dist/portal/session/session-health.js +9 -1
  405. package/dist/portal/session/session-info.d.ts +8 -1
  406. package/dist/portal/session/session-info.js +8 -1
  407. package/dist/portal/session/session-manager.d.ts +39 -0
  408. package/dist/portal/session/session-manager.js +98 -11
  409. package/dist/portal/session/session-reaper.js +4 -1
  410. package/dist/portal/session/session-successor.d.ts +13 -0
  411. package/dist/portal/session/session-successor.js +1 -1
  412. package/dist/portal/session/session-tools.js +26 -3
  413. package/dist/portal/session/session.d.ts +22 -30
  414. package/dist/portal/session/session.js +81 -79
  415. package/dist/portal/session/timing/command-timeout.js +25 -1
  416. package/dist/portal/session/timing/wall-clock.d.ts +1 -1
  417. package/dist/portal/session/timing/wall-clock.js +1 -1
  418. package/dist/portal/session/zero-install-first-call.d.ts +31 -0
  419. package/dist/portal/session/zero-install-first-call.js +88 -0
  420. package/dist/start-options.d.ts +12 -0
  421. package/dist/start-wiring.d.ts +63 -0
  422. package/dist/start-wiring.js +169 -0
  423. package/dist/status-payload.d.ts +23 -1
  424. package/dist/status-payload.js +36 -1
  425. package/dist/surface/http-server.js +18 -2
  426. package/dist/surface/mcp/attach-memory.d.ts +1 -0
  427. package/dist/surface/mcp/attach-memory.js +12 -1
  428. package/dist/surface/mcp/mcp-proxy.d.ts +9 -0
  429. package/dist/surface/mcp/mcp-proxy.js +65 -13
  430. package/dist/surface/mcp/mcp.d.ts +34 -6
  431. package/dist/surface/mcp/mcp.js +61 -17
  432. package/dist/surface/mcp/proxy/drive-calls.d.ts +10 -0
  433. package/dist/surface/mcp/proxy/drive-calls.js +27 -0
  434. package/dist/surface/mcp/proxy/mcp-post-transport.js +5 -0
  435. package/dist/surface/mcp/server-instructions.d.ts +4 -2
  436. package/dist/surface/mcp/server-instructions.js +32 -14
  437. package/dist/surface/mcp/shared-params.js +2 -2
  438. package/dist/surface/mcp/surface-vocabulary.d.ts +2 -0
  439. package/dist/surface/mcp/surface-vocabulary.js +1 -0
  440. package/dist/surface/tools/account-tool.d.ts +22 -0
  441. package/dist/surface/tools/account-tool.js +157 -0
  442. package/dist/surface/tools/act/act-danger.d.ts +11 -0
  443. package/dist/surface/tools/act/act-danger.js +38 -1
  444. package/dist/surface/tools/act/act-observation.d.ts +33 -0
  445. package/dist/surface/tools/act/act-observation.js +57 -0
  446. package/dist/surface/tools/act/act-preflight.js +25 -2
  447. package/dist/surface/tools/act/act-target.js +8 -3
  448. package/dist/surface/tools/act/navigation/navigate-arrival.d.ts +8 -0
  449. package/dist/surface/tools/act/navigation/navigate-arrival.js +56 -2
  450. package/dist/surface/tools/act/resolve-target.d.ts +1 -1
  451. package/dist/surface/tools/act/resolve-target.js +18 -3
  452. package/dist/surface/tools/act/screen-request.d.ts +34 -0
  453. package/dist/surface/tools/act/screen-request.js +113 -0
  454. package/dist/surface/tools/act/sequence-grade.d.ts +8 -0
  455. package/dist/surface/tools/act/sequence-grade.js +13 -2
  456. package/dist/surface/tools/act/settle-in-flight.js +25 -3
  457. package/dist/surface/tools/act-sequence-tool.js +138 -29
  458. package/dist/surface/tools/act-tools.d.ts +0 -9
  459. package/dist/surface/tools/act-tools.js +71 -41
  460. package/dist/surface/tools/agent/app-notes-learning.d.ts +7 -0
  461. package/dist/surface/tools/agent/app-notes-learning.js +80 -0
  462. package/dist/surface/tools/agent/app-notes.d.ts +4 -0
  463. package/dist/surface/tools/agent/app-notes.js +48 -0
  464. package/dist/surface/tools/agent/build-staleness.d.ts +7 -0
  465. package/dist/surface/tools/agent/build-staleness.js +62 -0
  466. package/dist/surface/tools/agent/compact-envelope.d.ts +80 -0
  467. package/dist/surface/tools/agent/compact-envelope.js +374 -0
  468. package/dist/surface/tools/agent/for-the-agent.d.ts +12 -0
  469. package/dist/surface/tools/agent/for-the-agent.js +44 -0
  470. package/dist/surface/tools/agent/notices.d.ts +50 -0
  471. package/dist/surface/tools/agent/notices.js +152 -0
  472. package/dist/surface/tools/agent/reteach.d.ts +11 -0
  473. package/dist/surface/tools/agent/reteach.js +50 -0
  474. package/dist/surface/tools/args/alias-args.d.ts +5 -0
  475. package/dist/surface/tools/args/alias-args.js +10 -0
  476. package/dist/surface/tools/args/confirm-dangerous-arg.d.ts +6 -0
  477. package/dist/surface/tools/args/confirm-dangerous-arg.js +6 -0
  478. package/dist/surface/tools/assert/assert-source.d.ts +15 -0
  479. package/dist/surface/tools/assert/assert-source.js +40 -0
  480. package/dist/surface/tools/assert/assert-verdict.d.ts +1 -1
  481. package/dist/surface/tools/assert/assert-verdict.js +42 -17
  482. package/dist/surface/tools/browser-tools.js +51 -2
  483. package/dist/surface/tools/chat-drives.d.ts +101 -0
  484. package/dist/surface/tools/chat-drives.js +409 -0
  485. package/dist/surface/tools/coverage-tools.d.ts +2 -10
  486. package/dist/surface/tools/coverage-tools.js +2 -53
  487. package/dist/surface/tools/dynamic-tools.js +29 -1
  488. package/dist/surface/tools/empty-session-list.d.ts +51 -0
  489. package/dist/surface/tools/empty-session-list.js +120 -0
  490. package/dist/surface/tools/error-recovery.d.ts +14 -0
  491. package/dist/surface/tools/error-recovery.js +105 -8
  492. package/dist/surface/tools/explore-tools.d.ts +31 -1
  493. package/dist/surface/tools/explore-tools.js +438 -66
  494. package/dist/surface/tools/feedback-tools.d.ts +2 -3
  495. package/dist/surface/tools/feedback-tools.js +18 -3
  496. package/dist/surface/tools/gap-novelty.d.ts +3 -1
  497. package/dist/surface/tools/gap-novelty.js +8 -1
  498. package/dist/surface/tools/harness-explore.d.ts +118 -57
  499. package/dist/surface/tools/harness-explore.js +344 -292
  500. package/dist/surface/tools/harness-gate.d.ts +88 -0
  501. package/dist/surface/tools/harness-gate.js +235 -0
  502. package/dist/surface/tools/harness-hunt.d.ts +43 -0
  503. package/dist/surface/tools/harness-hunt.js +215 -0
  504. package/dist/surface/tools/harness-plan.d.ts +17 -0
  505. package/dist/surface/tools/harness-plan.js +38 -0
  506. package/dist/surface/tools/harness-script.d.ts +30 -0
  507. package/dist/surface/tools/harness-script.js +560 -0
  508. package/dist/surface/tools/harness-tab-guard.d.ts +5 -0
  509. package/dist/surface/tools/harness-tab-guard.js +27 -0
  510. package/dist/surface/tools/harness-toolset.d.ts +22 -1
  511. package/dist/surface/tools/harness-toolset.js +101 -7
  512. package/dist/surface/tools/human-notes.d.ts +16 -0
  513. package/dist/surface/tools/human-notes.js +27 -0
  514. package/dist/surface/tools/invoke-tool.d.ts +5 -2
  515. package/dist/surface/tools/invoke-tool.js +263 -85
  516. package/dist/surface/tools/lease-hint.js +26 -5
  517. package/dist/surface/tools/lease-permissions.d.ts +33 -0
  518. package/dist/surface/tools/lease-permissions.js +73 -0
  519. package/dist/surface/tools/lease-readiness.d.ts +38 -0
  520. package/dist/surface/tools/lease-readiness.js +57 -0
  521. package/dist/surface/tools/lease-seed.d.ts +49 -0
  522. package/dist/surface/tools/lease-seed.js +167 -0
  523. package/dist/surface/tools/lease-tools.d.ts +13 -24
  524. package/dist/surface/tools/lease-tools.js +146 -197
  525. package/dist/surface/tools/live-call-text.js +4 -4
  526. package/dist/surface/tools/merge-tools.js +42 -2
  527. package/dist/surface/tools/merged-name-redirect.js +4 -0
  528. package/dist/surface/tools/next-step.d.ts +29 -0
  529. package/dist/surface/tools/next-step.js +214 -0
  530. package/dist/surface/tools/observe-tools.js +45 -9
  531. package/dist/surface/tools/platform-moment.d.ts +72 -0
  532. package/dist/surface/tools/platform-moment.js +296 -0
  533. package/dist/surface/tools/query-hint-schema.d.ts +7 -0
  534. package/dist/surface/tools/query-hint-schema.js +10 -0
  535. package/dist/surface/tools/read-tools.js +71 -14
  536. package/dist/surface/tools/real-input-attempt.js +96 -13
  537. package/dist/surface/tools/reticle-result.d.ts +120 -0
  538. package/dist/surface/tools/reticle-result.js +364 -0
  539. package/dist/surface/tools/tool-kit.d.ts +83 -3
  540. package/dist/surface/tools/tool-kit.js +77 -7
  541. package/dist/surface/tools/tools.js +43 -59
  542. package/dist/telemetry/account-envelope.d.ts +7 -0
  543. package/dist/telemetry/account-envelope.js +61 -0
  544. package/dist/telemetry/agent-client.d.ts +15 -0
  545. package/dist/telemetry/agent-client.js +57 -0
  546. package/dist/telemetry/app-instrumented.js +9 -2
  547. package/dist/telemetry/argument-shape.d.ts +7 -0
  548. package/dist/telemetry/argument-shape.js +86 -1
  549. package/dist/telemetry/automation-hint.d.ts +2 -3
  550. package/dist/telemetry/automation-hint.js +33 -8
  551. package/dist/telemetry/cli-telemetry.js +7 -2
  552. package/dist/telemetry/daemon-telemetry.js +3 -0
  553. package/dist/telemetry/error-fingerprint.d.ts +10 -1
  554. package/dist/telemetry/error-fingerprint.js +61 -5
  555. package/dist/telemetry/feedback-cli.d.ts +0 -13
  556. package/dist/telemetry/feedback-cli.js +0 -77
  557. package/dist/telemetry/feedback.d.ts +13 -0
  558. package/dist/telemetry/feedback.js +183 -17
  559. package/dist/telemetry/harness-run.d.ts +18 -0
  560. package/dist/telemetry/harness-run.js +80 -0
  561. package/dist/telemetry/hud-events.d.ts +16 -0
  562. package/dist/telemetry/hud-events.js +27 -0
  563. package/dist/telemetry/hud-metrics.d.ts +29 -6
  564. package/dist/telemetry/hud-metrics.js +116 -25
  565. package/dist/telemetry/init-telemetry.js +2 -2
  566. package/dist/telemetry/install-source.d.ts +13 -25
  567. package/dist/telemetry/install-source.js +44 -3
  568. package/dist/telemetry/mcp-connection.d.ts +0 -14
  569. package/dist/telemetry/mcp-connection.js +5 -1
  570. package/dist/telemetry/onboarding-firsts.d.ts +32 -0
  571. package/dist/telemetry/onboarding-firsts.js +81 -6
  572. package/dist/telemetry/platform-linked.d.ts +5 -0
  573. package/dist/telemetry/platform-linked.js +32 -0
  574. package/dist/telemetry/project-profile.js +5 -3
  575. package/dist/telemetry/proxy-telemetry.js +4 -1
  576. package/dist/telemetry/session-metrics.d.ts +15 -4
  577. package/dist/telemetry/session-metrics.js +88 -52
  578. package/dist/telemetry/telemetry.d.ts +38 -2
  579. package/dist/telemetry/telemetry.js +144 -34
  580. package/dist/telemetry/verification-of.d.ts +3 -1
  581. package/dist/telemetry/verification-of.js +13 -4
  582. package/dist/wire-journal.d.ts +2 -2
  583. package/dist/wire-journal.js +20 -6
  584. package/docs/README.md +3 -3
  585. package/docs/actions.mdx +6 -3
  586. package/docs/adapters.md +1 -1
  587. package/docs/agent-cheatsheet.md +25 -28
  588. package/docs/architecture.md +5 -5
  589. package/docs/autodrive.md +33 -28
  590. package/docs/benchmarks.md +5 -5
  591. package/docs/best-practices.mdx +27 -9
  592. package/docs/capabilities.mdx +14 -16
  593. package/docs/cli/affected.mdx +1 -1
  594. package/docs/cli/cloud.mdx +54 -75
  595. package/docs/cli/doctor.mdx +14 -3
  596. package/docs/cli/drive.mdx +20 -14
  597. package/docs/cli/feedback.mdx +3 -3
  598. package/docs/cli/gate.mdx +7 -2
  599. package/docs/cli/help.mdx +50 -55
  600. package/docs/cli/init.mdx +43 -28
  601. package/docs/cli/license.mdx +12 -8
  602. package/docs/cli/mcp.mdx +4 -4
  603. package/docs/cli/open.mdx +3 -3
  604. package/docs/cli/report.mdx +4 -2
  605. package/docs/cli/restart.mdx +2 -2
  606. package/docs/cli/rollback.mdx +14 -8
  607. package/docs/cli/serve.mdx +4 -4
  608. package/docs/cli/setup.mdx +23 -0
  609. package/docs/cli/status.mdx +18 -5
  610. package/docs/cli/stop.mdx +67 -8
  611. package/docs/cli/try.mdx +62 -0
  612. package/docs/cli/update.mdx +4 -3
  613. package/docs/cli/verify.mdx +17 -6
  614. package/docs/cli/version.mdx +5 -4
  615. package/docs/cli.mdx +111 -42
  616. package/docs/debugging.md +3 -3
  617. package/docs/deploy-checks.md +1 -1
  618. package/docs/desktop.mdx +9 -3
  619. package/docs/enterprise.md +11 -10
  620. package/docs/environment.mdx +7 -8
  621. package/docs/faq.mdx +3 -3
  622. package/docs/first-drive.md +5 -4
  623. package/docs/flows.md +35 -27
  624. package/docs/for-agents.md +4 -5
  625. package/docs/frameworks.mdx +32 -21
  626. package/docs/getting-started.md +65 -61
  627. package/docs/human-control.md +16 -16
  628. package/docs/index.mdx +15 -42
  629. package/docs/install-agentic.mdx +22 -37
  630. package/docs/install-manual.mdx +23 -13
  631. package/docs/instrumentation.mdx +5 -3
  632. package/docs/integration-patterns.md +7 -7
  633. package/docs/license-activation.mdx +1 -1
  634. package/docs/multi-agent-testing.md +24 -6
  635. package/docs/packages/babel-plugin.mdx +4 -2
  636. package/docs/packages/browser.mdx +16 -10
  637. package/docs/packages/core.mdx +12 -5
  638. package/docs/packages/electron.mdx +3 -2
  639. package/docs/packages/engine.mdx +1 -1
  640. package/docs/packages/eslint-plugin.mdx +18 -12
  641. package/docs/packages/next.mdx +8 -7
  642. package/docs/packages/open-verification.mdx +1 -1
  643. package/docs/packages/server.mdx +5 -5
  644. package/docs/packages/tauri.mdx +9 -9
  645. package/docs/packages/test.mdx +4 -10
  646. package/docs/packages/vite-plugin.mdx +32 -4
  647. package/docs/packages.mdx +11 -15
  648. package/docs/platform-integration.md +6 -5
  649. package/docs/predicates.mdx +40 -24
  650. package/docs/quickstart.mdx +69 -30
  651. package/docs/required-checks.md +8 -7
  652. package/docs/reticle-manual.md +15 -5
  653. package/docs/skill-file.mdx +17 -79
  654. package/docs/skill-setup.md +9 -9
  655. package/docs/skill.md +200 -0
  656. package/docs/system-map.md +7 -7
  657. package/docs/telemetry.md +23 -25
  658. package/docs/testing.md +4 -4
  659. package/docs/token-efficiency.md +12 -12
  660. package/docs/tools/act-and-wait.mdx +9 -2
  661. package/docs/tools/act-sequence.mdx +6 -7
  662. package/docs/tools/act.mdx +2 -2
  663. package/docs/tools/assert.mdx +18 -17
  664. package/docs/tools/console.mdx +9 -9
  665. package/docs/tools/inspect.mdx +16 -7
  666. package/docs/tools/look.mdx +24 -0
  667. package/docs/tools/navigate.mdx +5 -3
  668. package/docs/tools/network.mdx +2 -2
  669. package/docs/tools/observe.mdx +6 -6
  670. package/docs/tools/overview.mdx +34 -33
  671. package/docs/tools/query.mdx +5 -5
  672. package/docs/tools/session-and-feedback.mdx +22 -13
  673. package/docs/tools/sessions.mdx +8 -8
  674. package/docs/tools/snapshot.mdx +6 -5
  675. package/docs/tools/state.mdx +9 -9
  676. package/docs/tools/tools-and-run.mdx +26 -24
  677. package/docs/tools/verify.mdx +28 -0
  678. package/docs/tools/wait-for.mdx +8 -4
  679. package/docs/troubleshooting.mdx +21 -6
  680. package/docs/usage.md +55 -46
  681. package/docs/use-cases.mdx +3 -3
  682. package/docs/vs-chrome-devtools-mcp.mdx +9 -6
  683. package/docs/vs-playwright-mcp.mdx +3 -1
  684. package/docs/what-is-recorded.md +17 -5
  685. package/docs/what-is-reticle.mdx +5 -3
  686. package/docs/why-reticle.mdx +1 -1
  687. package/package.json +9 -12
  688. package/dist/command/cli/demo/demo-page.d.ts +0 -78
  689. package/dist/command/cli/demo/demo-page.js +0 -241
  690. package/dist/command/cli/demo/demo-run.d.ts +0 -38
  691. package/dist/command/cli/demo/demo-run.js +0 -138
  692. package/dist/features/harness/driver.d.ts +0 -50
  693. package/dist/features/harness/driver.js +0 -236
  694. package/dist/features/harness/jev-driver.d.ts +0 -188
  695. package/dist/features/harness/jev-driver.js +0 -678
  696. package/dist/features/harness/openai-driver.d.ts +0 -58
  697. package/dist/features/harness/openai-driver.js +0 -206
  698. package/dist/judgement/hunt/hunt-report.d.ts +0 -49
  699. package/dist/judgement/hunt/hunt-report.js +0 -84
  700. package/dist/language/flows/buddy-status.d.ts +0 -25
  701. package/dist/language/flows/buddy-status.js +0 -32
  702. package/dist/language/flows/change/watch-batcher.d.ts +0 -18
  703. package/dist/language/flows/change/watch-batcher.js +0 -19
  704. package/dist/memory/cloud/harness-offer.d.ts +0 -44
  705. package/dist/memory/cloud/harness-offer.js +0 -145
  706. package/dist/memory/project/dir/fill-value-store.d.ts +0 -32
  707. package/dist/memory/project/dir/fill-value-store.js +0 -88
  708. package/dist/surface/tools/feature-capture.d.ts +0 -151
  709. package/dist/surface/tools/feature-capture.js +0 -235
  710. package/dist/surface/tools/tool-hit-rate.d.ts +0 -87
  711. package/dist/surface/tools/tool-hit-rate.js +0 -90
  712. package/dist/telemetry/harness-drive.d.ts +0 -4
  713. package/dist/telemetry/harness-drive.js +0 -35
  714. package/dist/telemetry/identify.d.ts +0 -22
  715. package/dist/telemetry/identify.js +0 -73
  716. package/docs/cli/capsules.mdx +0 -70
  717. package/docs/cli/hunt.mdx +0 -73
  718. package/docs/cli/identify.mdx +0 -76
  719. package/docs/cli/kill.mdx +0 -91
  720. package/docs/cli/watch.mdx +0 -62
  721. package/docs/local-registry.md +0 -143
@@ -31,5 +31,17 @@ export declare const baseUrl: (session: {
31
31
  export declare const bearer: (session: {
32
32
  token: string;
33
33
  } | null) => string | null;
34
+ /**
35
+ * The platform refused the credential this command sent. Its generic answer ("sign in or API key
36
+ * required") read as if none had been set; a revoked key, or one whose owner was removed from the
37
+ * workspace, needs replacing, not adding.
38
+ */
39
+ export declare class CredentialRefusedError extends Error {
40
+ readonly status: number;
41
+ readonly apiKey: boolean;
42
+ constructor(status: number, apiKey: boolean,
43
+ /** The platform's own reason, when it named one (`refusalSaid`). */
44
+ reason?: string);
45
+ }
34
46
  /** One `/v1` call. Throws a friendly Error on a non-2xx so the command surfaces it and exits 1. */
35
47
  export declare const api: (method: string, url: string, token: string | null, body?: unknown) => Promise<unknown>;
@@ -8,6 +8,7 @@
8
8
  * `cloud-login` is the first to move — and it is a real seam rather than a file-size dodge: nothing
9
9
  * here knows what a project, a credential or a link is.
10
10
  */
11
+ import { KEY_REFUSED, refusalSaid } from '../../memory/project/sync-status.js';
11
12
  import { DEFAULT_PLATFORM_URL, apiKeyFrom, cloudUrlFrom } from '@reticlehq/core';
12
13
  import { readFile } from 'node:fs/promises';
13
14
  import { homedir } from 'node:os';
@@ -83,6 +84,32 @@ export const baseUrl = (session, explicit) => {
83
84
  };
84
85
  /** Bearer for a command: an explicit api key (agent) wins, else the human login token. */
85
86
  export const bearer = (session) => apiKeyFrom(process.env) ?? session?.token ?? null;
87
+ /** The platform's code for a missing or refused credential, as opposed to a permission. */
88
+ const GENERIC_REFUSAL = 'unauthorized';
89
+ /** A credential the platform answered with: not accepted, rather than not given. */
90
+ const REFUSED_STATUSES = new Set([401, 403]);
91
+ /**
92
+ * The platform refused the credential this command sent. Its generic answer ("sign in or API key
93
+ * required") read as if none had been set; a revoked key, or one whose owner was removed from the
94
+ * workspace, needs replacing, not adding.
95
+ */
96
+ export class CredentialRefusedError extends Error {
97
+ status;
98
+ apiKey;
99
+ constructor(status, apiKey,
100
+ /** The platform's own reason, when it named one (`refusalSaid`). */
101
+ reason) {
102
+ super(apiKey
103
+ ? `the platform refused this API key (${String(status)}): ${reason === undefined || KEY_REFUSED === reason
104
+ ? 'it was revoked, or its owner no longer has access to the workspace'
105
+ : reason.replace(/\.$/, '')}. Mint a new key in Settings → API keys and set RETICLE_API_KEY to it.`
106
+ : `the platform refused your sign-in (${String(status)}): ${reason === undefined || KEY_REFUSED === reason
107
+ ? 'it expired, was revoked, or you no longer have access to the workspace'
108
+ : reason.replace(/\.$/, '')}. Run \`reticle login\`.`);
109
+ this.status = status;
110
+ this.apiKey = apiKey;
111
+ }
112
+ }
86
113
  /** One `/v1` call. Throws a friendly Error on a non-2xx so the command surfaces it and exits 1. */
87
114
  export const api = async (method, url, token, body) => {
88
115
  const headers = {};
@@ -108,8 +135,20 @@ export const api = async (method, url, token, body) => {
108
135
  }
109
136
  }
110
137
  if (!res.ok) {
111
- const parsed = z.object({ error: z.object({ message: z.string() }) }).safeParse(json);
112
- throw new Error(parsed.success ? parsed.data.error.message : `${res.status} ${res.statusText}`);
138
+ const parsed = z
139
+ .object({ error: z.object({ message: z.string(), code: z.string().optional() }) })
140
+ .safeParse(json);
141
+ const said = parsed.success ? parsed.data.error.message : `${res.status} ${res.statusText}`;
142
+ // A 403 the platform explains as something else (a contributor creating a project) is a
143
+ // permission, not a refused credential: printed as it is worded, never as "sign in again".
144
+ const permission = 403 === res.status &&
145
+ parsed.success &&
146
+ KEY_REFUSED === refusalSaid(text) &&
147
+ GENERIC_REFUSAL !== parsed.data.error.code;
148
+ if (token !== null && REFUSED_STATUSES.has(res.status) && !permission) {
149
+ throw new CredentialRefusedError(res.status, token === apiKeyFrom(process.env), refusalSaid(text));
150
+ }
151
+ throw new Error(said);
113
152
  }
114
153
  return json;
115
154
  };
@@ -0,0 +1,57 @@
1
+ import { PlatformLinkVia } from '@reticlehq/core/telemetry';
2
+ import { z } from 'zod';
3
+ /**
4
+ * What a key is good for, or undefined when the cloud will not accept it.
5
+ *
6
+ * Never throws: a revoked key, a rotated one and an unreachable cloud are all "cannot reuse this",
7
+ * and the caller's answer to every one of them is the same — mint a fresh one.
8
+ */
9
+ export declare const validateKey: (url: string, key: string) => Promise<z.infer<typeof WhoamiSchema> | undefined>;
10
+ declare const WhoamiSchema: z.ZodObject<{
11
+ projectId: z.ZodString;
12
+ projectName: z.ZodString;
13
+ /**
14
+ * Which tenant the key belongs to. Optional for the same reason `dashboardUrl` is — an older
15
+ * cloud does not send it — and when it is missing a stored key cannot be proved to be ours, which
16
+ * is why the reuse path below mints instead of guessing.
17
+ */
18
+ orgId: z.ZodOptional<z.ZodString>;
19
+ /**
20
+ * Where this project's dashboard lives. Optional because an older cloud does not send it, and a
21
+ * CLI that refused to link against one would break the thing it is supposed to connect.
22
+ */
23
+ dashboardUrl: z.ZodOptional<z.ZodString>;
24
+ }, "strip", z.ZodTypeAny, {
25
+ projectId: string;
26
+ projectName: string;
27
+ orgId?: string | undefined;
28
+ dashboardUrl?: string | undefined;
29
+ }, {
30
+ projectId: string;
31
+ projectName: string;
32
+ orgId?: string | undefined;
33
+ dashboardUrl?: string | undefined;
34
+ }>;
35
+ export interface PlatformLinked {
36
+ via: PlatformLinkVia;
37
+ /** The project this folder was bound to before, if any: a re-run against it is not a new link. */
38
+ priorProjectId: unknown;
39
+ projectId: string;
40
+ /** The workspace's platform id, when the cloud said. */
41
+ workspaceId: string | undefined;
42
+ }
43
+ /** Hear every link this process makes. One listener: a second replaces the first. */
44
+ export declare function onPlatformLinked(next: (link: PlatformLinked) => void): void;
45
+ export declare function notePlatformLinked(link: PlatformLinked): void;
46
+ /**
47
+ * `reticle link [--project <id>]` — bind THIS repo to a cloud project. With a login token it MINTS a
48
+ * project-scoped key (no pasting); with a pre-set RETICLE_API_KEY it resolves the key's project via
49
+ * whoami. Writes the non-secret binding to <repo>/.reticle/cloud.json and the secret key to
50
+ * ~/.reticle/credentials.json (keyed by projectId).
51
+ */
52
+ export declare const cmdLink: (argv: readonly string[],
53
+ /** The folder to link. The CLI's own; the daemon passes the folder of the tab that asked. */
54
+ cwd?: string,
55
+ /** What started this link, for `platform_linked`. */
56
+ via?: PlatformLinkVia) => Promise<number>;
57
+ export {};
@@ -0,0 +1,308 @@
1
+ /**
2
+ * `reticle link` — binding this repo to a cloud project, and the key that binding sends with.
3
+ *
4
+ * Split from `cloud-cli` because it is one story with its own rules: which project a bare `link`
5
+ * targets, when a key already on this machine may be reused and when it provably belongs to another
6
+ * tenant, and what is written where (`<repo>/.reticle/cloud.json` and `~/.reticle/credentials.json`).
7
+ * Every other cloud verb only reads what this writes.
8
+ */
9
+ import { inWorkspace, repoIdentity, resolveProjectId, defaultProjectFor } from './project-name.js';
10
+ import { apiKeyFrom } from '@reticlehq/core';
11
+ import { PlatformLinkVia } from '@reticlehq/core/telemetry';
12
+ import { mkdir, writeFile } from 'node:fs/promises';
13
+ import { basename, join, relative, resolve } from 'node:path';
14
+ import { z } from 'zod';
15
+ import { createNodeFileSystem } from '../../memory/project/fs/fs-port.js';
16
+ import { CLOUD_LINK_FILE } from '../../memory/cloud/cloud-config.js';
17
+ import { applyCredential, findCredential } from './auth/cloud-keystore.js';
18
+ import { linkDirectoryFrom } from '../../memory/project/link-directory.js';
19
+ import { RETICLE_CONFIG_BASENAME, readProjectId } from './ports/resolve/cli-port.js';
20
+ import { api, baseUrl, CREDENTIALS_FILE, emit, err, flags, hint, home, readJson, readSession, readSessionFor, RETICLE_DIR, } from './cloud-kit.js';
21
+ /**
22
+ * How a key is named out loud: enough to match it against the dashboard, never enough to use.
23
+ *
24
+ * The same shape the web console shows, so the two name one key identically and somebody can tell
25
+ * at a glance which row this repo is using.
26
+ */
27
+ const KEY_HINT_CHARS = 16;
28
+ const keyHint = (key) => key.length <= KEY_HINT_CHARS ? key : `${key.slice(0, KEY_HINT_CHARS)}…`;
29
+ /**
30
+ * The api key this machine already holds for a project ON THIS CLOUD, if any.
31
+ *
32
+ * Two shapes, matching the resolver: `{ key, url }` is what `link` writes now and is only returned
33
+ * when the URL matches, and a bare string is the legacy shape with no URL to check. Without the URL
34
+ * check this would happily reuse a production key for a self-hosted link, because `link` names
35
+ * every project "default" and the two collide in one slot.
36
+ */
37
+ const storedCredential = async (projectId, url, orgId) => findCredential(await readJson(join(home(), CREDENTIALS_FILE)), projectId, url, orgId);
38
+ /**
39
+ * What a key is good for, or undefined when the cloud will not accept it.
40
+ *
41
+ * Never throws: a revoked key, a rotated one and an unreachable cloud are all "cannot reuse this",
42
+ * and the caller's answer to every one of them is the same — mint a fresh one.
43
+ */
44
+ export const validateKey = async (url, key) => {
45
+ try {
46
+ return WhoamiSchema.parse(await api('GET', `${url}/v1/cloud/whoami`, key));
47
+ }
48
+ catch {
49
+ return undefined;
50
+ }
51
+ };
52
+ const KeySchema = z.object({ projectId: z.string(), projectName: z.string(), key: z.string() });
53
+ const WhoamiSchema = z.object({
54
+ projectId: z.string(),
55
+ projectName: z.string(),
56
+ /**
57
+ * Which tenant the key belongs to. Optional for the same reason `dashboardUrl` is — an older
58
+ * cloud does not send it — and when it is missing a stored key cannot be proved to be ours, which
59
+ * is why the reuse path below mints instead of guessing.
60
+ */
61
+ orgId: z.string().optional(),
62
+ /**
63
+ * Where this project's dashboard lives. Optional because an older cloud does not send it, and a
64
+ * CLI that refused to link against one would break the thing it is supposed to connect.
65
+ */
66
+ dashboardUrl: z.string().optional(),
67
+ });
68
+ let listener;
69
+ /** Hear every link this process makes. One listener: a second replaces the first. */
70
+ export function onPlatformLinked(next) {
71
+ listener = next;
72
+ }
73
+ export function notePlatformLinked(link) {
74
+ try {
75
+ listener?.(link);
76
+ }
77
+ catch {
78
+ /* a listener never fails a link */
79
+ }
80
+ }
81
+ /**
82
+ * `reticle link [--project <id>]` — bind THIS repo to a cloud project. With a login token it MINTS a
83
+ * project-scoped key (no pasting); with a pre-set RETICLE_API_KEY it resolves the key's project via
84
+ * whoami. Writes the non-secret binding to <repo>/.reticle/cloud.json and the secret key to
85
+ * ~/.reticle/credentials.json (keyed by projectId).
86
+ */
87
+ export const cmdLink = async (argv,
88
+ /** The folder to link. The CLI's own; the daemon passes the folder of the tab that asked. */
89
+ cwd = process.cwd(),
90
+ /** What started this link, for `platform_linked`. */
91
+ via = PlatformLinkVia.LINK) => {
92
+ const f = flags(argv);
93
+ const url = baseUrl(await readSession(), f['url']);
94
+ // Same rule as every other authed verb: the token is looked up by the host it will be sent to.
95
+ const session = await readSessionFor(url);
96
+ const envKey = apiKeyFrom(process.env);
97
+ /*
98
+ * Read the existing binding FIRST, because it decides which project a bare `link` targets.
99
+ * Re-running `link` is ordinary — rotating a key, repointing an environment — and it must land in
100
+ * the project this repo already reports to, or its history splits in two without saying so.
101
+ */
102
+ // The project's own folder, which is where a session from here writes its runs. A link made before
103
+ // this, in the folder `link` was run from, is still read as the prior binding.
104
+ const projectDir = linkDirectoryFrom(cwd);
105
+ const priorLink = (await readJson(join(projectDir, RETICLE_DIR, CLOUD_LINK_FILE))) ??
106
+ (await readJson(join(cwd, RETICLE_DIR, CLOUD_LINK_FILE)));
107
+ const priorProjectId = 'object' === typeof priorLink && priorLink !== null
108
+ ? priorLink['projectId']
109
+ : undefined;
110
+ let projectId;
111
+ let projectName;
112
+ let key;
113
+ /**
114
+ * The tenant this binding belongs to, recorded so the credential can be filed and found per-org.
115
+ * Undefined against an older cloud, where the slot stays cloud+project as it always was.
116
+ */
117
+ let orgId;
118
+ let workspace; // the binding's, said when the sign-in names it
119
+ let repo; // which repository and folder, so a same-named app is not shared
120
+ /** The key this machine already had for the slot, and whether it provably belongs to another tenant. */
121
+ let priorKey;
122
+ let priorIsForeign = false;
123
+ /*
124
+ * Where this project's dashboard lives. Asked of the cloud rather than derived from `url`: the API
125
+ * origin and the console origin are different hosts in every deployment that is not a laptop, so a
126
+ * link the CLI guessed would be wrong exactly where it matters.
127
+ */
128
+ let dashboardUrl;
129
+ /** Whether the key was already on this machine — so the report can say so instead of "minted". */
130
+ let reusedKey = false;
131
+ // Tracked separately from the value: an OLDER cloud answers whoami without a dashboardUrl, and
132
+ // keying the fallback off the value would ask the same question twice every time.
133
+ let askedWhoami = false;
134
+ if (envKey !== undefined && envKey.length > 0) {
135
+ const who = WhoamiSchema.parse(await api('GET', `${url}/v1/cloud/whoami`, envKey));
136
+ projectId = who.projectId;
137
+ projectName = who.projectName;
138
+ dashboardUrl = who.dashboardUrl;
139
+ orgId = who.orgId;
140
+ askedWhoami = true;
141
+ key = envKey;
142
+ }
143
+ else if (session !== null) {
144
+ // --project accepts a slug id OR a display name; default when omitted. Resolve to the canonical id.
145
+ const wanted = f['project'];
146
+ /*
147
+ * A repo is named after itself, not "Default".
148
+ *
149
+ * When every repo binds to one project called "Default", two unrelated checkouts on one account
150
+ * merge their runs, issues and impact into a single bucket and the per-project view describes
151
+ * nothing. It is also what lets two TENANTS collide, since a credential slot built from a
152
+ * project id is only as distinct as the ids are.
153
+ */
154
+ const fallback = defaultProjectFor(basename(projectDir), 'string' === typeof priorProjectId ? priorProjectId : undefined, readProjectId(projectDir));
155
+ workspace = session.orgName;
156
+ repo = repoIdentity(projectDir);
157
+ // Only a default create asks for the folder's own id; a named or already-linked one is kept.
158
+ const localId = wanted === undefined && 'string' !== typeof priorProjectId
159
+ ? readProjectId(projectDir)
160
+ : undefined;
161
+ const targetId = await resolveProjectId(url, session.token, wanted ?? fallback, workspace, repo, localId);
162
+ /*
163
+ * Reuse the key this machine already holds for the project, rather than minting another.
164
+ *
165
+ * `link` was idempotent about the BINDING and not about the KEY: two runs against one project
166
+ * left two live `reticle-cli` keys on the account, each valid, neither identifiable to a repo.
167
+ * Agents retry — that is what agents do — so it accumulates silently until somebody has a key
168
+ * list they cannot reason about and revokes the wrong one.
169
+ *
170
+ * Validated before trusting, because a stored key can have been revoked or rotated from the
171
+ * dashboard and a stale credential must not strand the repo. The check is the whoami call the
172
+ * mint path already makes for `dashboardUrl`, so the common path costs no extra round trip —
173
+ * and a key that fails it is replaced rather than reported.
174
+ */
175
+ const existing = await storedCredential(targetId, url, session.orgId);
176
+ const validated = existing === undefined ? undefined : await validateKey(url, existing);
177
+ /*
178
+ * A valid key is not the same as OUR key.
179
+ *
180
+ * `validateKey` only asks whether the cloud still accepts it, and a key belonging to another
181
+ * organisation on the same cloud passes that question perfectly. With every project named
182
+ * "default", the slot `<url>::default` was shared across tenants — so a brand-new workspace
183
+ * signing in on a machine that had linked a different account reused that account's key and
184
+ * would have pushed its runs into a stranger's dashboard. Measured, not hypothesised.
185
+ *
186
+ * So reuse now requires PROOF of a tenant match, and treats anything less as no match: an older
187
+ * cloud that omits `orgId`, or a session file written before we recorded one, both fall through
188
+ * to minting. Minting a second key is a tidiness problem; pushing to the wrong tenant is a
189
+ * disclosure, and only one of those is worth defaulting to.
190
+ */
191
+ const sameTenant = validated !== undefined &&
192
+ session.orgId !== undefined &&
193
+ validated.orgId !== undefined &&
194
+ validated.orgId === session.orgId;
195
+ const reusable = sameTenant ? validated : undefined;
196
+ priorKey = existing;
197
+ // Provably somebody else's: it still works on this cloud AND whoami names a different org. A key
198
+ // that merely FAILED validation is our own revoked one, and overwriting that is the point.
199
+ priorIsForeign =
200
+ validated !== undefined &&
201
+ validated.orgId !== undefined &&
202
+ session.orgId !== undefined &&
203
+ validated.orgId !== session.orgId;
204
+ if (existing !== undefined && reusable !== undefined) {
205
+ projectId = reusable.projectId;
206
+ projectName = reusable.projectName;
207
+ dashboardUrl = reusable.dashboardUrl;
208
+ orgId = reusable.orgId;
209
+ askedWhoami = true;
210
+ key = existing;
211
+ reusedKey = true;
212
+ }
213
+ else {
214
+ const minted = KeySchema.parse(await api('POST', `${url}/v1/keys`, session.token, {
215
+ name: 'reticle-cli',
216
+ projectId: targetId,
217
+ }));
218
+ projectId = minted.projectId;
219
+ projectName = minted.projectName;
220
+ key = minted.key;
221
+ // The key was minted WITH this session, so its tenant is this session's by construction.
222
+ orgId = session.orgId;
223
+ }
224
+ }
225
+ else {
226
+ err('run `reticle connect` first, or set RETICLE_API_KEY to link with an existing key');
227
+ return 2;
228
+ }
229
+ const reticleDir = join(projectDir, RETICLE_DIR);
230
+ await mkdir(reticleDir, { recursive: true });
231
+ const linkPath = join(reticleDir, CLOUD_LINK_FILE);
232
+ const prev = await readJson(linkPath);
233
+ const prevObj = 'object' === typeof prev && prev !== null ? prev : {};
234
+ // The minted-key path has not asked yet. Best-effort: a link that works is worth more than a link
235
+ // that also has a link in it, and an older cloud simply does not send one.
236
+ if (!askedWhoami) {
237
+ try {
238
+ const who = WhoamiSchema.parse(await api('GET', `${url}/v1/cloud/whoami`, key));
239
+ dashboardUrl = who.dashboardUrl;
240
+ // Only FILL IN a tenant we do not have. The session we minted with is the authority on which
241
+ // org this key belongs to; letting a later lookup overwrite it is how the answer drifts.
242
+ orgId = orgId ?? who.orgId;
243
+ }
244
+ catch {
245
+ // Older cloud, or a transient failure. The HUD shows its list without a link.
246
+ }
247
+ }
248
+ const cloudJson = {
249
+ projectId,
250
+ projectName,
251
+ // Recorded so the daemon resolves the credential in the ORG slot rather than the ambiguous
252
+ // cloud+project one, which two tenants on one cloud both answer to.
253
+ ...(orgId === undefined ? {} : { orgId }),
254
+ url,
255
+ ...(dashboardUrl === undefined ? {} : { dashboardUrl }),
256
+ ...(repo === undefined ? {} : { repo }),
257
+ // The workspace's name, so `reticle status` can say where this repo sends.
258
+ ...(workspace === undefined ? {} : { workspace }),
259
+ sync: prevObj['sync'] ?? { runs: true, memory: true, flows: true },
260
+ verify: prevObj['verify'] ?? 'local',
261
+ };
262
+ await writeFile(linkPath, `${JSON.stringify(cloudJson, null, 2)}\n`);
263
+ await mkdir(home(), { recursive: true });
264
+ const credPath = join(home(), CREDENTIALS_FILE);
265
+ const creds = (await readJson(credPath)) ?? {};
266
+ const credObj = applyCredential('object' === typeof creds && creds !== null ? creds : {}, { projectId, url, key, orgId, priorKey, priorIsForeign });
267
+ await writeFile(credPath, `${JSON.stringify(credObj, null, 2)}\n`);
268
+ emit({ linked: projectName, projectId, cloudJson: linkPath, credentials: credPath });
269
+ notePlatformLinked({ via, priorProjectId, projectId, workspaceId: orgId });
270
+ /*
271
+ * Say what just happened, in the vocabulary of somebody who has used other tools.
272
+ *
273
+ * `link` mints the key and stores it for you, which is the product's whole edge — and it is
274
+ * invisible, which is its whole cost. A real report: somebody pasted a masked placeholder key
275
+ * into a `.env` because their mental model said "I must make a key and put it somewhere". One had
276
+ * already been minted and filed outside the repo. They did not need another step; they needed to
277
+ * be told the step had happened.
278
+ *
279
+ * The key is identified the way the dashboard identifies it — a prefix, never the secret — so
280
+ * this can be read aloud, pasted into an issue, or left in a terminal without leaking anything.
281
+ */
282
+ hint(`bound this repo to project "${projectName}"${inWorkspace(workspace)}`);
283
+ if (projectDir !== resolve(cwd))
284
+ hint(`linked ${relative(cwd, projectDir)}: that is where this app's runs are written`);
285
+ hint(reusedKey
286
+ ? `reusing key ${keyHint(key)} — already stored in ${credPath}, not in your repo`
287
+ : `minted key ${keyHint(key)} — stored in ${credPath}, not in your repo`);
288
+ hint('to change it: `reticle connect --project <other>`; to inspect: `reticle status`');
289
+ hint('linked ✓ runs auto-push on `reticle verify`; `reticle sync` sends existing local runs; `reticle status` shows state');
290
+ /*
291
+ * A binding is not a connection.
292
+ *
293
+ * Without `.reticle.json` the app's bundle carries no projectId, so the daemon cannot attribute a
294
+ * session to this repo: its runs pool into whichever root the daemon itself was started in, and
295
+ * `sync` here reports "nothing to send" however much was actually recorded. Measured on this
296
+ * repo's bench app — two verdicts driven, then a sync that claimed there was nothing.
297
+ *
298
+ * Said AFTER the success line rather than refusing: the binding really was written and really is
299
+ * correct, and the missing half is one command away. Refusing would strand somebody who links
300
+ * before they install, which is a legitimate order to work in.
301
+ */
302
+ if (!(await createNodeFileSystem().exists(join(projectDir, RETICLE_CONFIG_BASENAME)))) {
303
+ hint(`no ${RETICLE_CONFIG_BASENAME} here: this app's runs reach this binding only while its dev ` +
304
+ 'server runs with the Reticle build plugin, which announces it. Run `reticle init` in the app ' +
305
+ 'to make the binding hold without it.');
306
+ }
307
+ return 0;
308
+ };
@@ -15,4 +15,26 @@ export declare const cmdLogin: (argv: readonly string[], link: Linker, autoLink?
15
15
  * one you did not mean.
16
16
  */
17
17
  export declare const cmdLogout: (argv?: readonly string[]) => Promise<number>;
18
+ /**
19
+ * The panel's Sign in: the same browser approval `reticle login` opens, started by the daemon, which
20
+ * owns `~/.reticle`. One flow at a time, and a second press while it is pending reopens its approval
21
+ * page rather than doing nothing: somebody who closed that tab must be able to get it back.
22
+ * `onSignedIn` runs when the approval lands so every open panel can repaint. A failure stays in the
23
+ * daemon log: the panel copied `reticle login` as it was clicked, which is the way through.
24
+ */
25
+ export declare function hudSignIn(onSignedIn: () => void, start?: (open: (url: string) => void) => Promise<number>, opener?: (url: string) => void,
26
+ /**
27
+ * Link the asking tab's project once signed in: "Save for your team" signed in and linked
28
+ * nothing, so the panel asked for the click just made. The daemon passes `projectLinkOnly`.
29
+ */
30
+ link?: (root: string) => Promise<number>): (from?: {
31
+ artifactRoot?: string | undefined;
32
+ }) => void;
33
+ /**
34
+ * The workspace `connect` links in. A person in several was linked in whichever the saved sign-in
35
+ * was for, told "Connected", and nothing moved on the dashboard they were looking at. `--workspace
36
+ * <name|id>` switches the sign-in (and saves it); without it, a person in more than one is told which
37
+ * one this is and how to choose. Returns non-zero when the named workspace is not theirs.
38
+ */
39
+ export declare const chooseWorkspace: (url: string, wanted: string | undefined) => Promise<number>;
18
40
  export {};
@@ -16,7 +16,7 @@ import { setTimeout as sleep } from 'node:timers/promises';
16
16
  import { createNodeFileSystem } from '../../memory/project/fs/fs-port.js';
17
17
  import { CLOUD_LINK_FILE } from '../../memory/cloud/cloud-config.js';
18
18
  import { RETICLE_CONFIG_BASENAME } from './ports/resolve/cli-port.js';
19
- import { DevicePollSchema, DeviceStartSchema, openBrowser } from './auth/device-flow.js';
19
+ import { DevicePollSchema, DeviceStartSchema, LoginOrigin, openBrowser, withLoginOrigin, } from './auth/device-flow.js';
20
20
  import { normalizeUrl, sessionPath, SESSIONS_DIR } from './auth/cloud-session.js';
21
21
  import { api, baseUrl, emit, err, flags, hint, home, readSession, RETICLE_DIR, SESSION_FILE, } from './cloud-kit.js';
22
22
  const LoginSchema = z.object({
@@ -101,7 +101,7 @@ const linkAfterLogin = async (url, project, link) => {
101
101
  * two verdicts had been recorded. Measured, on this very repo's bench app.
102
102
  */
103
103
  if (!(await fs.exists(join(process.cwd(), RETICLE_CONFIG_BASENAME)))) {
104
- hint('next: `reticle init` here first, then `reticle link` — or log in from a project directory');
104
+ hint('next: `reticle init` here first, then `reticle connect`');
105
105
  return;
106
106
  }
107
107
  /*
@@ -111,25 +111,25 @@ const linkAfterLogin = async (url, project, link) => {
111
111
  */
112
112
  if (project === undefined &&
113
113
  (await fs.exists(join(process.cwd(), RETICLE_DIR, CLOUD_LINK_FILE)))) {
114
- hint('this repo is already linked — `reticle push` to send what it has recorded');
114
+ hint('this repo is already linked — `reticle sync` to send what it has recorded');
115
115
  return;
116
116
  }
117
117
  try {
118
118
  await link(project === undefined ? ['--url', url] : ['--url', url, '--project', project]);
119
119
  }
120
120
  catch {
121
- hint('signed in, but linking this repo failed — run `reticle link` to retry');
121
+ hint('signed in, but linking this repo failed — run `reticle connect` to retry');
122
122
  }
123
123
  };
124
124
  /**
125
125
  * Browser device flow — the DEFAULT `reticle login` (like `gh auth login`): fetch a device + user code,
126
126
  * open the browser to approve, then poll until the user confirms. No email to type, no code to copy back.
127
127
  */
128
- const cmdLoginDevice = async (explicitUrl, project, link, autoLink) => {
128
+ const cmdLoginDevice = async (explicitUrl, project, link, autoLink, open = openBrowser, from = LoginOrigin.TERMINAL) => {
129
129
  const url = baseUrl(null, explicitUrl);
130
130
  const started = DeviceStartSchema.parse(await api('POST', `${url}/v1/auth/device/start`, null, {}));
131
131
  hint(`Opening ${started.verificationUri} — confirm this code in the browser: ${started.userCode}`);
132
- openBrowser(started.verificationUriComplete);
132
+ open(withLoginOrigin(started.verificationUriComplete, from));
133
133
  const intervalMs = Math.max(1, started.interval) * 1000;
134
134
  for (;;) {
135
135
  await sleep(intervalMs);
@@ -140,14 +140,14 @@ const cmdLoginDevice = async (explicitUrl, project, link, autoLink) => {
140
140
  }
141
141
  if ('pending' === poll.status) {
142
142
  if (Date.now() > started.expiresAt) {
143
- err('device login expired — run `reticle login` again');
143
+ err('device login expired — run `reticle connect` again');
144
144
  return 1;
145
145
  }
146
146
  continue;
147
147
  }
148
148
  err('denied' === poll.status
149
149
  ? 'device login was denied in the browser'
150
- : 'device login expired — run `reticle login` again');
150
+ : 'device login expired — run `reticle connect` again');
151
151
  return 1;
152
152
  }
153
153
  };
@@ -200,3 +200,91 @@ export const cmdLogout = async (argv = []) => {
200
200
  emit({ loggedOut: true, url });
201
201
  return 0;
202
202
  };
203
+ /** The daemon signs in for the panel and links nothing: its working directory is not the user's app. */
204
+ const NO_LINK = () => Promise.resolve(0);
205
+ /**
206
+ * The panel's Sign in: the same browser approval `reticle login` opens, started by the daemon, which
207
+ * owns `~/.reticle`. One flow at a time, and a second press while it is pending reopens its approval
208
+ * page rather than doing nothing: somebody who closed that tab must be able to get it back.
209
+ * `onSignedIn` runs when the approval lands so every open panel can repaint. A failure stays in the
210
+ * daemon log: the panel copied `reticle login` as it was clicked, which is the way through.
211
+ */
212
+ export function hudSignIn(onSignedIn, start = (open) => cmdLoginDevice(undefined, undefined, NO_LINK, false, open, LoginOrigin.HUD), opener = openBrowser,
213
+ /**
214
+ * Link the asking tab's project once signed in: "Save for your team" signed in and linked
215
+ * nothing, so the panel asked for the click just made. The daemon passes `projectLinkOnly`.
216
+ */
217
+ link) {
218
+ let running = false;
219
+ let pending;
220
+ return (from) => {
221
+ if (running) {
222
+ if (pending !== undefined)
223
+ opener(pending);
224
+ return;
225
+ }
226
+ running = true;
227
+ const root = from?.artifactRoot;
228
+ void start((url) => {
229
+ pending = url;
230
+ opener(url);
231
+ })
232
+ .then(async (code) => {
233
+ if (0 !== code)
234
+ return;
235
+ if (link !== undefined && root !== undefined)
236
+ await link(root).catch(() => 1);
237
+ onSignedIn();
238
+ })
239
+ .catch(() => undefined)
240
+ .finally(() => {
241
+ running = false;
242
+ pending = undefined;
243
+ });
244
+ };
245
+ }
246
+ const WorkspacesSchema = z.object({
247
+ active: z.string().optional(),
248
+ memberships: z.array(z.object({ orgId: z.string(), name: z.string() })).default([]),
249
+ });
250
+ const ActivatedSchema = z.object({
251
+ token: z.string(),
252
+ org: z.object({ id: z.string(), name: z.string() }),
253
+ });
254
+ /**
255
+ * The workspace `connect` links in. A person in several was linked in whichever the saved sign-in
256
+ * was for, told "Connected", and nothing moved on the dashboard they were looking at. `--workspace
257
+ * <name|id>` switches the sign-in (and saves it); without it, a person in more than one is told which
258
+ * one this is and how to choose. Returns non-zero when the named workspace is not theirs.
259
+ */
260
+ export const chooseWorkspace = async (url, wanted) => {
261
+ const session = await readSession();
262
+ if (null === session)
263
+ return 0;
264
+ let listed;
265
+ try {
266
+ listed = WorkspacesSchema.parse(await api('GET', `${url}/v1/me/workspaces`, session.token));
267
+ }
268
+ catch {
269
+ return 0; // an older platform: nothing to choose between
270
+ }
271
+ const names = listed.memberships.map((m) => `"${m.name}"`).join(', ');
272
+ if (wanted === undefined) {
273
+ if (1 < listed.memberships.length)
274
+ hint(`you belong to ${String(listed.memberships.length)} workspaces (${names}); this links in ` +
275
+ `"${session.orgName}". Another: reticle connect --workspace <name>`);
276
+ return 0;
277
+ }
278
+ const lc = wanted.toLowerCase();
279
+ const target = listed.memberships.find((m) => m.orgId === wanted || m.name.toLowerCase() === lc);
280
+ if (target === undefined) {
281
+ err(`you are not a member of a workspace "${wanted}": yours are ${names}`);
282
+ return 2;
283
+ }
284
+ if (target.orgId === listed.active)
285
+ return 0;
286
+ const activated = ActivatedSchema.parse(await api('POST', `${url}/v1/me/workspaces/${encodeURIComponent(target.orgId)}/activate`, session.token, {}));
287
+ await writeSession(url, activated.token, activated.org.name, activated.org.id, undefined, () => Promise.resolve(0), session.email, false);
288
+ hint(`signed in to workspace "${activated.org.name}"`);
289
+ return 0;
290
+ };
@@ -0,0 +1 @@
1
+ export declare function handleContext(session: string | undefined): Promise<void>;