@reticlehq/server 3.7.0 → 3.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (578) hide show
  1. package/SKILL.md +59 -68
  2. package/bin/reticle.js +9 -2
  3. package/dist/command/cli/adhoc-suite.js +1 -1
  4. package/dist/command/cli/adhoc-verdict.d.ts +12 -0
  5. package/dist/command/cli/adhoc-verdict.js +62 -4
  6. package/dist/command/cli/answers/gate-hook-message.d.ts +2 -0
  7. package/dist/command/cli/answers/gate-hook-message.js +5 -1
  8. package/dist/command/cli/auth/cloud-session.d.ts +11 -19
  9. package/dist/command/cli/auth/cloud-session.js +23 -0
  10. package/dist/command/cli/auth/device-flow.d.ts +3 -37
  11. package/dist/command/cli/cli-doctor.js +66 -21
  12. package/dist/command/cli/cli-flow-commands.js +53 -11
  13. package/dist/command/cli/cli-kill.d.ts +8 -0
  14. package/dist/command/cli/cli-kill.js +43 -3
  15. package/dist/command/cli/cli-parse-feedback.d.ts +4 -0
  16. package/dist/command/cli/cli-parse-feedback.js +13 -1
  17. package/dist/command/cli/cli-parse-grammar.d.ts +1 -2
  18. package/dist/command/cli/cli-parse-grammar.js +1 -6
  19. package/dist/command/cli/cli-parse-serve.d.ts +24 -0
  20. package/dist/command/cli/cli-parse-serve.js +124 -0
  21. package/dist/command/cli/cli-parse.d.ts +12 -11
  22. package/dist/command/cli/cli-parse.js +100 -123
  23. package/dist/command/cli/cli-usage.d.ts +0 -11
  24. package/dist/command/cli/cli-usage.js +43 -16
  25. package/dist/command/cli/cli-verify.d.ts +1 -1
  26. package/dist/command/cli/cli-verify.js +29 -14
  27. package/dist/command/cli/cloud-cli.js +27 -9
  28. package/dist/command/cli/cloud-kit.js +3 -3
  29. package/dist/command/cli/cloud-link.d.ts +1 -20
  30. package/dist/command/cli/cloud-link.js +2 -0
  31. package/dist/command/cli/cloud-login.d.ts +6 -2
  32. package/dist/command/cli/cloud-login.js +13 -41
  33. package/dist/command/cli/config/checkout.d.ts +10 -0
  34. package/dist/command/cli/config/checkout.js +78 -0
  35. package/dist/command/cli/doctor/doctor-agent-link.d.ts +23 -0
  36. package/dist/command/cli/doctor/doctor-agent-link.js +28 -0
  37. package/dist/command/cli/doctor/doctor-coverage-line.js +1 -7
  38. package/dist/command/cli/doctor/doctor-rows.d.ts +4 -0
  39. package/dist/command/cli/doctor/doctor-rows.js +4 -0
  40. package/dist/command/cli/drive/drive-attach.d.ts +5 -0
  41. package/dist/command/cli/drive/drive-attach.js +21 -1
  42. package/dist/command/cli/hook/codex-transcript.d.ts +20 -0
  43. package/dist/command/cli/hook/codex-transcript.js +224 -0
  44. package/dist/command/cli/hook/episode-structure.d.ts +24 -0
  45. package/dist/command/cli/hook/episode-structure.js +138 -0
  46. package/dist/command/cli/hook/hook-command.d.ts +9 -0
  47. package/dist/command/cli/hook/hook-command.js +211 -0
  48. package/dist/command/cli/hook/hook-fast.d.ts +31 -0
  49. package/dist/command/cli/hook/hook-fast.js +136 -0
  50. package/dist/command/cli/hook/prompt-hook.d.ts +30 -0
  51. package/dist/command/cli/hook/prompt-hook.js +199 -0
  52. package/dist/command/cli/hook/tool-hook.d.ts +21 -0
  53. package/dist/command/cli/hook/tool-hook.js +259 -0
  54. package/dist/command/cli/launch/cli-launch.d.ts +2 -0
  55. package/dist/command/cli/launch/cli-launch.js +22 -2
  56. package/dist/command/cli/lifecycle/daemon-lifecycle.js +28 -2
  57. package/dist/command/cli/mcp-command.d.ts +9 -0
  58. package/dist/command/cli/mcp-command.js +127 -41
  59. package/dist/command/cli/open-navigate.d.ts +43 -0
  60. package/dist/command/cli/open-navigate.js +85 -0
  61. package/dist/command/cli/ports/port-holder.d.ts +16 -4
  62. package/dist/command/cli/ports/port-holder.js +58 -12
  63. package/dist/command/cli/ports/resolve/cli-port.js +18 -2
  64. package/dist/command/cli/project-name.d.ts +1 -7
  65. package/dist/command/cli/project-name.js +1 -0
  66. package/dist/command/cli/report-command.d.ts +8 -2
  67. package/dist/command/cli/report-command.js +95 -18
  68. package/dist/command/cli/status-fields.d.ts +9 -2
  69. package/dist/command/cli/status-fields.js +148 -4
  70. package/dist/command/cli/try-command.d.ts +3 -4
  71. package/dist/command/cli/try-command.js +6 -11
  72. package/dist/command/cli/verify-results.d.ts +4 -1
  73. package/dist/command/cli/verify-results.js +3 -1
  74. package/dist/command/cli.d.ts +1 -7
  75. package/dist/command/cli.js +79 -160
  76. package/dist/command/daemon/daemon-resilience.d.ts +6 -1
  77. package/dist/command/daemon/daemon-resilience.js +31 -18
  78. package/dist/command/daemon/daemon.d.ts +11 -0
  79. package/dist/command/daemon/daemon.js +70 -2
  80. package/dist/command/daemon/lifetime/daemon-usefulness.d.ts +2 -0
  81. package/dist/command/daemon/lifetime/daemon-usefulness.js +13 -2
  82. package/dist/command/daemon/wake-decision.js +4 -2
  83. package/dist/command/daemon/win32-escape.d.ts +32 -0
  84. package/dist/command/daemon/win32-escape.js +119 -0
  85. package/dist/command/setup/agent-configs.d.ts +9 -0
  86. package/dist/command/setup/agent-configs.js +9 -0
  87. package/dist/command/setup/auto-approve.d.ts +10 -3
  88. package/dist/command/setup/auto-approve.js +51 -3
  89. package/dist/command/setup/bringup/dev-server-files.d.ts +1 -9
  90. package/dist/command/setup/bringup/dev-server-wait.js +5 -1
  91. package/dist/command/setup/bringup/ensure-daemon.js +4 -7
  92. package/dist/command/setup/init/init-host.js +6 -0
  93. package/dist/command/setup/init/init-port.js +5 -4
  94. package/dist/command/setup/init/init-runtime.js +7 -1
  95. package/dist/command/setup/node-effects.d.ts +8 -0
  96. package/dist/command/setup/node-effects.js +36 -4
  97. package/dist/command/setup/probe/dev-port.d.ts +26 -0
  98. package/dist/command/setup/probe/dev-port.js +117 -0
  99. package/dist/command/setup/probe/page-probe.d.ts +1 -1
  100. package/dist/command/setup/probe/page-probe.js +11 -3
  101. package/dist/command/setup/remaining-steps.d.ts +0 -7
  102. package/dist/command/setup/remaining-steps.js +3 -2
  103. package/dist/command/setup/run-setup.d.ts +11 -0
  104. package/dist/command/setup/run-setup.js +33 -5
  105. package/dist/command/setup/setup-command.d.ts +2 -0
  106. package/dist/command/setup/setup-command.js +22 -4
  107. package/dist/command/update/updater.d.ts +1 -6
  108. package/dist/command/update/updater.js +4 -5
  109. package/dist/command/update/version-seen.d.ts +24 -0
  110. package/dist/command/update/version-seen.js +65 -0
  111. package/dist/command/version/peer-announce.d.ts +9 -1
  112. package/dist/command/version/peer-announce.js +25 -2
  113. package/dist/command/version/sdk-fix.d.ts +5 -6
  114. package/dist/command/version/sdk-fix.js +17 -32
  115. package/dist/command/version/version-skew.d.ts +16 -1
  116. package/dist/command/version/version-skew.js +84 -10
  117. package/dist/features/crawl/crawl-tools.js +2 -2
  118. package/dist/features/crawl/crawl.js +2 -0
  119. package/dist/features/exhaust/ledger.d.ts +15 -96
  120. package/dist/features/exhaust/ledger.js +3 -3
  121. package/dist/features/harness/drive-runs.d.ts +28 -4
  122. package/dist/features/harness/drive-runs.js +99 -7
  123. package/dist/features/harness/drivers.d.ts +1 -1
  124. package/dist/features/harness/drivers.js +1 -1
  125. package/dist/features/harness/harness.d.ts +5 -0
  126. package/dist/features/harness/harness.js +24 -12
  127. package/dist/features/harness/platform/platform-drives.d.ts +7 -1
  128. package/dist/features/harness/platform/platform-drives.js +12 -7
  129. package/dist/features/harness/platform/refusal.d.ts +1 -1
  130. package/dist/features/harness/platform/refusal.js +4 -4
  131. package/dist/features/harness/platform/remote-drive.js +70 -28
  132. package/dist/features/harness/platform/server-driver.js +22 -1
  133. package/dist/features/harness/platform-config.d.ts +1 -10
  134. package/dist/features/harness/platform-config.js +0 -20
  135. package/dist/features/license/license.d.ts +2 -14
  136. package/dist/features/visual/step-shots.d.ts +33 -1
  137. package/dist/features/visual/step-shots.js +155 -1
  138. package/dist/features/visual/visual-tools.js +12 -4
  139. package/dist/hooks/coding-agents.d.ts +6 -0
  140. package/dist/hooks/coding-agents.js +24 -3
  141. package/dist/hooks/episode-stamp.d.ts +32 -0
  142. package/dist/hooks/episode-stamp.js +61 -0
  143. package/dist/hooks/hook-commands.js +19 -9
  144. package/dist/index.d.ts +5 -1
  145. package/dist/index.js +66 -24
  146. package/dist/judgement/app-graph/journal-steps.d.ts +8 -0
  147. package/dist/judgement/app-graph/journal-steps.js +92 -0
  148. package/dist/judgement/capsule/capsule-store.d.ts +2 -39
  149. package/dist/judgement/domain/domain-model.js +1 -10
  150. package/dist/judgement/domain/domain-tools.js +4 -2
  151. package/dist/judgement/runs/artifact/run-store.d.ts +28 -8
  152. package/dist/judgement/runs/artifact/run-store.js +153 -28
  153. package/dist/judgement/runs/default-run-id.d.ts +3 -1
  154. package/dist/judgement/runs/default-run-id.js +15 -3
  155. package/dist/judgement/runs/drive-run.d.ts +3 -3
  156. package/dist/judgement/runs/drive-run.js +11 -7
  157. package/dist/judgement/runs/run-ledger.d.ts +21 -0
  158. package/dist/judgement/runs/run-ledger.js +143 -0
  159. package/dist/judgement/runs/runner-port.d.ts +1 -1
  160. package/dist/judgement/runs/runner-port.js +8 -2
  161. package/dist/judgement/runs/verification-sync.d.ts +4 -3
  162. package/dist/judgement/runs/verification-sync.js +27 -5
  163. package/dist/language/flows/affected-tools.js +2 -1
  164. package/dist/language/flows/annotate-notes/annotate.js +8 -3
  165. package/dist/language/flows/annotate-tools.js +1 -1
  166. package/dist/language/flows/change/affected.d.ts +8 -0
  167. package/dist/language/flows/change/affected.js +20 -7
  168. package/dist/language/flows/decision.js +19 -4
  169. package/dist/language/flows/fields/flow-secret-field.d.ts +9 -0
  170. package/dist/language/flows/fields/flow-secret-field.js +67 -5
  171. package/dist/language/flows/flow-anchor.d.ts +5 -0
  172. package/dist/language/flows/flow-anchor.js +4 -0
  173. package/dist/language/flows/flow-cross-step.d.ts +7 -1
  174. package/dist/language/flows/flow-cross-step.js +9 -0
  175. package/dist/language/flows/flow-expect-grammar.js +15 -10
  176. package/dist/language/flows/flow-intent.js +6 -1
  177. package/dist/language/flows/flow-journey.d.ts +8 -0
  178. package/dist/language/flows/flow-journey.js +13 -0
  179. package/dist/language/flows/flow-lease.d.ts +27 -0
  180. package/dist/language/flows/flow-lease.js +59 -0
  181. package/dist/language/flows/flow-replay-run.d.ts +1 -87
  182. package/dist/language/flows/flow-replay-run.js +111 -310
  183. package/dist/language/flows/flow-replay.js +21 -19
  184. package/dist/language/flows/flow-replayable.d.ts +38 -0
  185. package/dist/language/flows/flow-replayable.js +179 -0
  186. package/dist/language/flows/flow-start-path.d.ts +108 -0
  187. package/dist/language/flows/flow-start-path.js +313 -0
  188. package/dist/language/flows/flow-step-runners.d.ts +23 -2
  189. package/dist/language/flows/flow-step-runners.js +191 -32
  190. package/dist/language/flows/flow-store-for-session.d.ts +8 -1
  191. package/dist/language/flows/flow-store-for-session.js +6 -0
  192. package/dist/language/flows/flow-tools.d.ts +2 -23
  193. package/dist/language/flows/flow-tools.js +63 -113
  194. package/dist/language/flows/flows.d.ts +4 -6
  195. package/dist/language/flows/flows.js +90 -15
  196. package/dist/language/flows/heal-run.d.ts +10 -4
  197. package/dist/language/flows/heal-run.js +26 -9
  198. package/dist/language/flows/recording/flake.d.ts +3 -27
  199. package/dist/language/flows/recording/flake.js +1 -1
  200. package/dist/language/flows/recording/recording-backtrack.js +1 -4
  201. package/dist/language/flows/recording/tape/recordings.d.ts +11 -1
  202. package/dist/language/flows/recording/tape/recordings.js +9 -3
  203. package/dist/language/flows/replay.d.ts +25 -5
  204. package/dist/language/flows/replay.js +83 -16
  205. package/dist/language/flows/stores/assertion-tiers-store.js +1 -1
  206. package/dist/language/flows/suite/coverage.d.ts +9 -0
  207. package/dist/language/flows/suite/coverage.js +12 -1
  208. package/dist/language/flows/suite-selection.d.ts +25 -0
  209. package/dist/language/flows/suite-selection.js +41 -9
  210. package/dist/machine/git-tracks.d.ts +6 -0
  211. package/dist/machine/git-tracks.js +36 -0
  212. package/dist/memory/cloud/background-sync.d.ts +25 -0
  213. package/dist/memory/cloud/background-sync.js +79 -0
  214. package/dist/memory/cloud/cloud-config.d.ts +12 -1
  215. package/dist/memory/cloud/cloud-config.js +39 -13
  216. package/dist/memory/cloud/cloud-sync.d.ts +3 -24
  217. package/dist/memory/cloud/cloud-sync.js +5 -2
  218. package/dist/memory/cloud/harness-config.d.ts +0 -7
  219. package/dist/memory/cloud/memory-scope.d.ts +19 -0
  220. package/dist/memory/cloud/memory-scope.js +48 -0
  221. package/dist/memory/cloud/sync-answer.d.ts +43 -0
  222. package/dist/memory/cloud/sync-answer.js +42 -0
  223. package/dist/memory/cloud/sync-cycle.d.ts +40 -10
  224. package/dist/memory/cloud/sync-cycle.js +97 -144
  225. package/dist/memory/cloud/sync-daemon.d.ts +50 -3
  226. package/dist/memory/cloud/sync-daemon.js +473 -83
  227. package/dist/memory/cloud/sync-describe.d.ts +28 -0
  228. package/dist/memory/cloud/sync-describe.js +92 -0
  229. package/dist/memory/cloud/sync-disk.d.ts +9 -1
  230. package/dist/memory/cloud/sync-disk.js +137 -33
  231. package/dist/memory/cloud/sync-flow-versions.d.ts +26 -0
  232. package/dist/memory/cloud/sync-flow-versions.js +42 -0
  233. package/dist/memory/impact/impact-store.js +32 -15
  234. package/dist/memory/intent/intent-shard.d.ts +41 -266
  235. package/dist/memory/intent/intent-tools.js +20 -61
  236. package/dist/memory/intent/record-request.d.ts +27 -0
  237. package/dist/memory/intent/record-request.js +88 -0
  238. package/dist/memory/intent/settled-words.js +9 -1
  239. package/dist/memory/journal/drive-flow.d.ts +3 -0
  240. package/dist/memory/journal/drive-flow.js +11 -41
  241. package/dist/memory/journal/envelope-store.js +1 -1
  242. package/dist/memory/journal/envelope.d.ts +6 -154
  243. package/dist/memory/journal/episode-log.d.ts +107 -0
  244. package/dist/memory/journal/episode-log.js +302 -0
  245. package/dist/memory/journal/journal-recorder.d.ts +7 -0
  246. package/dist/memory/journal/journal-recorder.js +22 -9
  247. package/dist/memory/journal/on-disk/ambient-file.d.ts +1 -7
  248. package/dist/memory/journal/on-disk/ambient-file.js +1 -1
  249. package/dist/memory/journal/on-disk/workspace-gitignore.d.ts +24 -3
  250. package/dist/memory/journal/on-disk/workspace-gitignore.js +38 -7
  251. package/dist/memory/journal/on-disk/workspace-tiers.js +7 -0
  252. package/dist/memory/journal/self-observation.js +3 -1
  253. package/dist/memory/journal/session-end.js +23 -9
  254. package/dist/memory/journal/session-journal.js +39 -20
  255. package/dist/memory/project/artifact-root-resolver.d.ts +14 -1
  256. package/dist/memory/project/artifact-root-resolver.js +68 -23
  257. package/dist/memory/project/artifact-root.d.ts +17 -3
  258. package/dist/memory/project/artifact-root.js +47 -9
  259. package/dist/memory/project/fs/fs-port.d.ts +5 -0
  260. package/dist/memory/project/fs/fs-port.js +13 -0
  261. package/dist/memory/project/learned-routes.d.ts +3 -4
  262. package/dist/memory/project/learned-routes.js +3 -11
  263. package/dist/memory/project/link-directory.js +5 -2
  264. package/dist/memory/project/root-claims.d.ts +3 -1
  265. package/dist/memory/project/root-claims.js +41 -7
  266. package/dist/memory/project/session-root.d.ts +1 -1
  267. package/dist/memory/project/session-root.js +1 -15
  268. package/dist/memory/project/sync-status.js +5 -6
  269. package/dist/memory/recall/memory-tools.js +2 -2
  270. package/dist/memory/recall/platform-memory.d.ts +3 -1
  271. package/dist/memory/recall/platform-memory.js +9 -1
  272. package/dist/memory/recall/project-memory.js +15 -19
  273. package/dist/portal/bridge/auth-failure-reason.d.ts +13 -0
  274. package/dist/portal/bridge/auth-failure-reason.js +19 -0
  275. package/dist/portal/bridge/bridge.d.ts +19 -4
  276. package/dist/portal/bridge/bridge.js +150 -177
  277. package/dist/portal/bridge/harness-request.d.ts +15 -0
  278. package/dist/portal/bridge/harness-request.js +19 -0
  279. package/dist/portal/bridge/origin/origin-follow.d.ts +46 -0
  280. package/dist/portal/bridge/origin/origin-follow.js +110 -0
  281. package/dist/portal/bridge/pairing-token.d.ts +6 -0
  282. package/dist/portal/bridge/pairing-token.js +47 -16
  283. package/dist/portal/bridge/protocol-skew.d.ts +27 -2
  284. package/dist/portal/bridge/protocol-skew.js +66 -2
  285. package/dist/portal/bridge/session-nonces.d.ts +46 -0
  286. package/dist/portal/bridge/session-nonces.js +72 -0
  287. package/dist/portal/input/viewport-tools.d.ts +31 -0
  288. package/dist/portal/input/viewport-tools.js +106 -15
  289. package/dist/portal/pool/bounded-close.d.ts +23 -0
  290. package/dist/portal/pool/bounded-close.js +38 -0
  291. package/dist/portal/pool/browser-pool.d.ts +44 -39
  292. package/dist/portal/pool/browser-pool.js +247 -95
  293. package/dist/portal/pool/context-permissions.d.ts +9 -1
  294. package/dist/portal/pool/context-permissions.js +26 -0
  295. package/dist/portal/pool/lease-emulation.d.ts +37 -0
  296. package/dist/portal/pool/lease-emulation.js +29 -0
  297. package/dist/portal/pool/playwright-launcher.d.ts +6 -0
  298. package/dist/portal/pool/playwright-launcher.js +74 -7
  299. package/dist/portal/pool/pool-contract.d.ts +23 -1
  300. package/dist/portal/pool/pool-lease.d.ts +128 -0
  301. package/dist/portal/pool/pool-lease.js +49 -0
  302. package/dist/portal/pool/zero-install.d.ts +8 -1
  303. package/dist/portal/pool/zero-install.js +24 -2
  304. package/dist/portal/production/production-activation.d.ts +136 -0
  305. package/dist/portal/production/production-activation.js +173 -0
  306. package/dist/portal/production/production-drive.d.ts +52 -0
  307. package/dist/portal/production/production-drive.js +301 -0
  308. package/dist/portal/production/production-hello.d.ts +23 -0
  309. package/dist/portal/production/production-hello.js +23 -0
  310. package/dist/portal/realm/web-realm.js +42 -15
  311. package/dist/portal/session/control-envelope.d.ts +1 -1
  312. package/dist/portal/session/dev-server/served-document.d.ts +0 -5
  313. package/dist/portal/session/dev-server/served-document.js +6 -8
  314. package/dist/portal/session/facts/handshake-facts.d.ts +8 -1
  315. package/dist/portal/session/first-run-wiring.d.ts +3 -36
  316. package/dist/portal/session/first-run-wiring.js +10 -103
  317. package/dist/portal/session/live-control-tools.js +61 -19
  318. package/dist/portal/session/no-session-next-action.d.ts +11 -0
  319. package/dist/portal/session/no-session-next-action.js +40 -15
  320. package/dist/portal/session/no-session-watch.d.ts +7 -0
  321. package/dist/portal/session/no-session-watch.js +67 -23
  322. package/dist/portal/session/output-budget.d.ts +10 -0
  323. package/dist/portal/session/output-budget.js +16 -0
  324. package/dist/portal/session/presence/session-lease.d.ts +2 -0
  325. package/dist/portal/session/presence/session-lease.js +8 -0
  326. package/dist/portal/session/recorded-gaps.d.ts +15 -11
  327. package/dist/portal/session/recorded-gaps.js +39 -18
  328. package/dist/portal/session/serving-directory.d.ts +24 -2
  329. package/dist/portal/session/serving-directory.js +93 -5
  330. package/dist/portal/session/session-info.d.ts +26 -0
  331. package/dist/portal/session/session-info.js +20 -0
  332. package/dist/portal/session/session-manager.d.ts +35 -3
  333. package/dist/portal/session/session-manager.js +69 -14
  334. package/dist/portal/session/session-successor.js +1 -9
  335. package/dist/portal/session/session-tools.js +22 -4
  336. package/dist/portal/session/session.d.ts +10 -10
  337. package/dist/portal/session/session.js +37 -29
  338. package/dist/portal/session/zero-install-first-call.d.ts +7 -2
  339. package/dist/portal/session/zero-install-first-call.js +43 -20
  340. package/dist/start-wiring.d.ts +2 -2
  341. package/dist/start-wiring.js +17 -3
  342. package/dist/status-payload.d.ts +11 -1
  343. package/dist/status-payload.js +7 -1
  344. package/dist/surface/agent-presence-grace.d.ts +11 -0
  345. package/dist/surface/agent-presence-grace.js +34 -0
  346. package/dist/surface/http-server.d.ts +12 -1
  347. package/dist/surface/http-server.js +64 -15
  348. package/dist/surface/mcp/faults/mcp-outage.d.ts +12 -2
  349. package/dist/surface/mcp/faults/mcp-outage.js +19 -1
  350. package/dist/surface/mcp/mcp-proxy.d.ts +17 -74
  351. package/dist/surface/mcp/mcp-proxy.js +194 -267
  352. package/dist/surface/mcp/mcp.d.ts +20 -3
  353. package/dist/surface/mcp/mcp.js +88 -25
  354. package/dist/surface/mcp/proxy/drive-calls.d.ts +44 -0
  355. package/dist/surface/mcp/proxy/drive-calls.js +114 -5
  356. package/dist/surface/mcp/proxy/proxy-boot.d.ts +11 -0
  357. package/dist/surface/mcp/proxy/proxy-boot.js +1 -0
  358. package/dist/surface/mcp/proxy/proxy-daemon-probe.d.ts +6 -0
  359. package/dist/surface/mcp/proxy/proxy-daemon-probe.js +14 -1
  360. package/dist/surface/mcp/proxy/proxy-handshake.d.ts +34 -2
  361. package/dist/surface/mcp/proxy/proxy-handshake.js +76 -8
  362. package/dist/surface/mcp/server-instructions.js +35 -16
  363. package/dist/surface/mcp/shared-params.d.ts +8 -0
  364. package/dist/surface/mcp/shared-params.js +15 -1
  365. package/dist/surface/mcp/sse-frame-parser.d.ts +11 -0
  366. package/dist/surface/mcp/sse-frame-parser.js +18 -0
  367. package/dist/surface/mcp/surface-vocabulary.d.ts +2 -0
  368. package/dist/surface/mcp/surface-vocabulary.js +13 -0
  369. package/dist/surface/mcp/tool-catalog-cache.d.ts +2 -0
  370. package/dist/surface/mcp/tool-catalog-cache.js +14 -4
  371. package/dist/surface/tools/account-tool.d.ts +4 -3
  372. package/dist/surface/tools/account-tool.js +20 -31
  373. package/dist/surface/tools/act/act-danger.d.ts +2 -0
  374. package/dist/surface/tools/act/act-danger.js +41 -14
  375. package/dist/surface/tools/act/act-observation.d.ts +11 -0
  376. package/dist/surface/tools/act/act-observation.js +33 -0
  377. package/dist/surface/tools/act/act-preflight.js +10 -3
  378. package/dist/surface/tools/act/act-sequence-retry.js +2 -1
  379. package/dist/surface/tools/act/act-target.js +19 -5
  380. package/dist/surface/tools/act/durable.js +1 -1
  381. package/dist/surface/tools/act/navigation/navigate-arrival.d.ts +9 -7
  382. package/dist/surface/tools/act/navigation/navigate-arrival.js +11 -14
  383. package/dist/surface/tools/act/unsettled-find.d.ts +36 -0
  384. package/dist/surface/tools/act/unsettled-find.js +71 -0
  385. package/dist/surface/tools/act-sequence-tool.js +53 -24
  386. package/dist/surface/tools/act-tools.d.ts +2 -3
  387. package/dist/surface/tools/act-tools.js +49 -47
  388. package/dist/surface/tools/agent/compact-envelope.d.ts +2 -2
  389. package/dist/surface/tools/agent/for-the-agent.js +41 -3
  390. package/dist/surface/tools/assert/assert-grade.js +8 -3
  391. package/dist/surface/tools/assert/assert-verdict.js +4 -2
  392. package/dist/surface/tools/browser-tools.js +7 -4
  393. package/dist/surface/tools/chat-drives.js +50 -25
  394. package/dist/surface/tools/coverage-tools.js +1 -1
  395. package/dist/surface/tools/dynamic-tools.d.ts +8 -0
  396. package/dist/surface/tools/dynamic-tools.js +89 -34
  397. package/dist/surface/tools/empty-session-list.d.ts +18 -25
  398. package/dist/surface/tools/empty-session-list.js +67 -38
  399. package/dist/surface/tools/error-recovery.d.ts +17 -7
  400. package/dist/surface/tools/error-recovery.js +53 -20
  401. package/dist/surface/tools/explore-tools.d.ts +10 -0
  402. package/dist/surface/tools/explore-tools.js +72 -19
  403. package/dist/surface/tools/feedback-tools.js +23 -2
  404. package/dist/surface/tools/gap-novelty.d.ts +6 -0
  405. package/dist/surface/tools/gap-novelty.js +9 -0
  406. package/dist/surface/tools/gaps/capability-absences.js +4 -3
  407. package/dist/surface/tools/harness-explore.d.ts +1 -1
  408. package/dist/surface/tools/harness-explore.js +6 -4
  409. package/dist/surface/tools/harness-gate.d.ts +43 -21
  410. package/dist/surface/tools/harness-gate.js +55 -81
  411. package/dist/surface/tools/harness-script.d.ts +2 -0
  412. package/dist/surface/tools/harness-script.js +11 -6
  413. package/dist/surface/tools/harness-toolset.js +3 -4
  414. package/dist/surface/tools/invoke-tool.d.ts +0 -8
  415. package/dist/surface/tools/invoke-tool.js +164 -178
  416. package/dist/surface/tools/lease-hint.d.ts +9 -0
  417. package/dist/surface/tools/lease-hint.js +22 -3
  418. package/dist/surface/tools/lease-permissions.d.ts +1 -1
  419. package/dist/surface/tools/lease-readiness.d.ts +55 -0
  420. package/dist/surface/tools/lease-readiness.js +150 -2
  421. package/dist/surface/tools/lease-tools.d.ts +3 -75
  422. package/dist/surface/tools/lease-tools.js +124 -188
  423. package/dist/surface/tools/map-tools.d.ts +20 -0
  424. package/dist/surface/tools/map-tools.js +145 -0
  425. package/dist/surface/tools/merge-tools.js +11 -7
  426. package/dist/surface/tools/next-step.js +6 -3
  427. package/dist/surface/tools/observe-tools.js +46 -35
  428. package/dist/surface/tools/platform-moment.d.ts +3 -12
  429. package/dist/surface/tools/platform-moment.js +12 -24
  430. package/dist/surface/tools/read/complete-snapshot.d.ts +7 -1
  431. package/dist/surface/tools/read/complete-snapshot.js +13 -2
  432. package/dist/surface/tools/read/query-paginate.js +6 -0
  433. package/dist/surface/tools/read/query-shape.d.ts +9 -0
  434. package/dist/surface/tools/read/query-shape.js +15 -0
  435. package/dist/surface/tools/read/snapshot-unmounted-note.d.ts +1 -0
  436. package/dist/surface/tools/read/snapshot-unmounted-note.js +73 -0
  437. package/dist/surface/tools/read-tools.js +5 -5
  438. package/dist/surface/tools/real-input-attempt.d.ts +11 -0
  439. package/dist/surface/tools/real-input-attempt.js +206 -38
  440. package/dist/surface/tools/reconcile-tools.js +21 -8
  441. package/dist/surface/tools/reticle-result.d.ts +3 -0
  442. package/dist/surface/tools/reticle-result.js +8 -1
  443. package/dist/surface/tools/run-report.d.ts +22 -0
  444. package/dist/surface/tools/run-report.js +141 -0
  445. package/dist/surface/tools/session-ports.d.ts +57 -0
  446. package/dist/surface/tools/session-ports.js +102 -0
  447. package/dist/surface/tools/tool-kit.d.ts +58 -4
  448. package/dist/surface/tools/tool-kit.js +140 -6
  449. package/dist/surface/tools/tool-surface.d.ts +2 -0
  450. package/dist/surface/tools/tool-surface.js +45 -0
  451. package/dist/surface/tools/tools.js +49 -87
  452. package/dist/telemetry/automation-hint.d.ts +5 -0
  453. package/dist/telemetry/automation-hint.js +7 -0
  454. package/dist/telemetry/cli-telemetry.d.ts +22 -0
  455. package/dist/telemetry/cli-telemetry.js +80 -11
  456. package/dist/telemetry/daemon-telemetry.d.ts +3 -1
  457. package/dist/telemetry/daemon-telemetry.js +9 -2
  458. package/dist/telemetry/feedback-cli.d.ts +1 -1
  459. package/dist/telemetry/feedback-cli.js +8 -3
  460. package/dist/telemetry/feedback.d.ts +1 -1
  461. package/dist/telemetry/feedback.js +51 -4
  462. package/dist/telemetry/harness-run.d.ts +3 -3
  463. package/dist/telemetry/harness-run.js +18 -7
  464. package/dist/telemetry/hud-events.d.ts +1 -1
  465. package/dist/telemetry/hud-metrics.d.ts +6 -3
  466. package/dist/telemetry/hud-metrics.js +20 -8
  467. package/dist/telemetry/install-source.js +1 -1
  468. package/dist/telemetry/mcp-connection.d.ts +1 -1
  469. package/dist/telemetry/mcp-connection.js +21 -2
  470. package/dist/telemetry/onboarding-firsts.d.ts +6 -1
  471. package/dist/telemetry/onboarding-firsts.js +41 -1
  472. package/dist/telemetry/proxy-telemetry.d.ts +42 -0
  473. package/dist/telemetry/proxy-telemetry.js +70 -1
  474. package/dist/telemetry/session-metrics.d.ts +1 -3
  475. package/dist/telemetry/session-metrics.js +16 -12
  476. package/dist/telemetry/telemetry.d.ts +9 -1
  477. package/dist/telemetry/telemetry.js +16 -1
  478. package/dist/telemetry/verification-of.d.ts +3 -1
  479. package/dist/telemetry/verification-of.js +7 -1
  480. package/dist/wire-journal.js +12 -2
  481. package/docs/README.md +4 -2
  482. package/docs/actions.mdx +7 -6
  483. package/docs/adapters.md +2 -1
  484. package/docs/agent-cheatsheet.md +19 -5
  485. package/docs/architecture.md +13 -10
  486. package/docs/autodrive.md +6 -5
  487. package/docs/benchmarks.md +2 -2
  488. package/docs/capabilities.mdx +1 -1
  489. package/docs/cli/affected.mdx +1 -1
  490. package/docs/cli/cloud.mdx +6 -6
  491. package/docs/cli/doctor.mdx +3 -1
  492. package/docs/cli/feedback.mdx +11 -7
  493. package/docs/cli/gate.mdx +1 -1
  494. package/docs/cli/help.mdx +1 -1
  495. package/docs/cli/init.mdx +20 -16
  496. package/docs/cli/mcp.mdx +5 -2
  497. package/docs/cli/open.mdx +5 -2
  498. package/docs/cli/report.mdx +1 -1
  499. package/docs/cli/restart.mdx +1 -1
  500. package/docs/cli/rollback.mdx +4 -4
  501. package/docs/cli/serve.mdx +7 -5
  502. package/docs/cli/setup.mdx +1 -1
  503. package/docs/cli/status.mdx +6 -2
  504. package/docs/cli/stop.mdx +3 -3
  505. package/docs/cli/telemetry.mdx +5 -1
  506. package/docs/cli/try.mdx +8 -8
  507. package/docs/cli/update.mdx +8 -5
  508. package/docs/cli/verify.mdx +12 -5
  509. package/docs/cli/version.mdx +1 -1
  510. package/docs/cli.mdx +10 -6
  511. package/docs/debugging.md +1 -1
  512. package/docs/deploy-checks.md +8 -6
  513. package/docs/desktop.mdx +14 -18
  514. package/docs/enterprise.md +6 -6
  515. package/docs/environment.mdx +5 -3
  516. package/docs/faq.mdx +9 -6
  517. package/docs/first-drive.md +19 -9
  518. package/docs/flows.md +3 -4
  519. package/docs/for-agents.md +1 -1
  520. package/docs/frameworks.mdx +34 -11
  521. package/docs/getting-started.md +46 -29
  522. package/docs/http-transport.md +2 -2
  523. package/docs/human-control.md +8 -8
  524. package/docs/index.mdx +2 -2
  525. package/docs/install-agentic.mdx +18 -19
  526. package/docs/install-manual.mdx +8 -4
  527. package/docs/integration-patterns.md +5 -5
  528. package/docs/multi-agent-testing.md +7 -5
  529. package/docs/packages/browser.mdx +34 -2
  530. package/docs/packages/core.mdx +2 -1
  531. package/docs/packages/electron.mdx +15 -3
  532. package/docs/packages/eslint-plugin.mdx +1 -1
  533. package/docs/packages/next.mdx +17 -5
  534. package/docs/packages/react.mdx +8 -1
  535. package/docs/packages/server.mdx +3 -3
  536. package/docs/packages/tauri.mdx +3 -3
  537. package/docs/packages/vite-plugin.mdx +1 -1
  538. package/docs/packages.mdx +19 -6
  539. package/docs/platform-integration.md +12 -4
  540. package/docs/predicates.mdx +18 -7
  541. package/docs/production-mode.md +108 -0
  542. package/docs/prompt-capture.md +99 -0
  543. package/docs/quickstart.mdx +14 -12
  544. package/docs/recipes.mdx +9 -8
  545. package/docs/required-checks.md +3 -2
  546. package/docs/skill-file.mdx +4 -3
  547. package/docs/skill-setup.md +2 -2
  548. package/docs/skill.md +62 -70
  549. package/docs/state-files.md +1 -0
  550. package/docs/state-management.mdx +11 -9
  551. package/docs/system-map.md +14 -13
  552. package/docs/telemetry.md +32 -24
  553. package/docs/testing.md +9 -5
  554. package/docs/tools/act-and-wait.mdx +17 -13
  555. package/docs/tools/act-sequence.mdx +40 -66
  556. package/docs/tools/act.mdx +7 -5
  557. package/docs/tools/assert.mdx +1 -1
  558. package/docs/tools/look.mdx +1 -1
  559. package/docs/tools/navigate.mdx +1 -1
  560. package/docs/tools/network.mdx +13 -11
  561. package/docs/tools/overview.mdx +3 -3
  562. package/docs/tools/query.mdx +3 -3
  563. package/docs/tools/session-and-feedback.mdx +9 -6
  564. package/docs/tools/sessions.mdx +7 -0
  565. package/docs/tools/snapshot.mdx +9 -7
  566. package/docs/tools/tools-and-run.mdx +11 -10
  567. package/docs/tools/verify.mdx +1 -1
  568. package/docs/troubleshooting.mdx +21 -9
  569. package/docs/usage.md +58 -43
  570. package/docs/use-cases.mdx +2 -2
  571. package/docs/vs-chrome-devtools-mcp.mdx +5 -5
  572. package/docs/vs-playwright-mcp.mdx +5 -4
  573. package/docs/what-is-recorded.md +12 -7
  574. package/docs/what-is-reticle.mdx +2 -2
  575. package/docs/why-reticle.mdx +1 -1
  576. package/package.json +9 -12
  577. package/dist/command/dev/stale-issue-guard.d.ts +0 -34
  578. package/dist/command/dev/stale-issue-guard.js +0 -69
@@ -0,0 +1,37 @@
1
+ /**
2
+ * What a lease can emulate: the two media features a person sets in their OS, and the width.
3
+ *
4
+ * Without them, prefers-reduced-motion and prefers-color-scheme could not be set on a leased tab,
5
+ * so the CSS half of reduced motion and the dark theme could not be checked live. A lease is a
6
+ * Playwright context, which takes all three before the first paint and the media again per call.
7
+ */
8
+ export declare const ColorScheme: {
9
+ readonly LIGHT: "light";
10
+ readonly DARK: "dark";
11
+ readonly NO_PREFERENCE: "no-preference";
12
+ };
13
+ export type ColorScheme = (typeof ColorScheme)[keyof typeof ColorScheme];
14
+ export declare const ReducedMotion: {
15
+ readonly REDUCE: "reduce";
16
+ readonly NO_PREFERENCE: "no-preference";
17
+ };
18
+ export type ReducedMotion = (typeof ReducedMotion)[keyof typeof ReducedMotion];
19
+ /** The media features a page reads with matchMedia. */
20
+ export interface LeaseMedia {
21
+ colorScheme?: ColorScheme;
22
+ reducedMotion?: ReducedMotion;
23
+ }
24
+ /** What a lease opens with: the media, and a viewport. */
25
+ export interface LeaseEmulation extends LeaseMedia {
26
+ viewport?: {
27
+ width: number;
28
+ height: number;
29
+ };
30
+ }
31
+ /** The size a page reports for itself, or undefined when it cannot be read. */
32
+ export declare function readViewport(page: {
33
+ evaluate?(script: string): Promise<unknown>;
34
+ }): Promise<{
35
+ width: number;
36
+ height: number;
37
+ } | undefined>;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * What a lease can emulate: the two media features a person sets in their OS, and the width.
3
+ *
4
+ * Without them, prefers-reduced-motion and prefers-color-scheme could not be set on a leased tab,
5
+ * so the CSS half of reduced motion and the dark theme could not be checked live. A lease is a
6
+ * Playwright context, which takes all three before the first paint and the media again per call.
7
+ */
8
+ export const ColorScheme = {
9
+ LIGHT: 'light',
10
+ DARK: 'dark',
11
+ NO_PREFERENCE: 'no-preference',
12
+ };
13
+ export const ReducedMotion = { REDUCE: 'reduce', NO_PREFERENCE: 'no-preference' };
14
+ /** The page's own layout viewport, read back after a resize. */
15
+ const VIEWPORT_READ_SCRIPT = '[window.innerWidth, window.innerHeight]';
16
+ /** The size a page reports for itself, or undefined when it cannot be read. */
17
+ export async function readViewport(page) {
18
+ if (page.evaluate === undefined) {
19
+ return undefined;
20
+ }
21
+ try {
22
+ const size = await page.evaluate(VIEWPORT_READ_SCRIPT);
23
+ const [width, height] = Array.isArray(size) ? size : [];
24
+ return 'number' === typeof width && 'number' === typeof height ? { width, height } : undefined;
25
+ }
26
+ catch {
27
+ return undefined;
28
+ }
29
+ }
@@ -31,6 +31,12 @@ export declare function screenshotOptions(opts: ScreenshotOptions): {
31
31
  type?: 'jpeg';
32
32
  quality?: number;
33
33
  scale?: 'css';
34
+ clip?: {
35
+ x: number;
36
+ y: number;
37
+ width: number;
38
+ height: number;
39
+ };
34
40
  };
35
41
  /**
36
42
  * A step screenshot with Reticle's own UI out of it. The step path injects nothing into the page
@@ -6,12 +6,19 @@
6
6
  * Headless by default — the pool exists for fault-tolerant headless multi-agent testing.
7
7
  */
8
8
  import { BrowserLaunchKind } from '@reticlehq/core/telemetry';
9
- import { HIDE_RETICLE_CHROME_CSS, RETICLE_OVERLAY_SELECTOR } from '@reticlehq/core';
9
+ import { ActionType, HIDE_RETICLE_CHROME_CSS, RETICLE_OVERLAY_SELECTOR } from '@reticlehq/core';
10
10
  import { launchChromium } from '../../launch-chromium.js';
11
11
  import { getSessionMetrics } from '../../telemetry/session-metrics.js';
12
12
  import { classifyConnectFailure } from '../../telemetry/connect-failure.js';
13
13
  import { chromiumInstallCommand, chromiumInstallDepsCommand, bundledPlaywrightVersion, } from '../../command/cli/doctor/browser/chromium-hint.js';
14
14
  import { installNetworkMocks } from '../input/network-mock.js';
15
+ import { performGesture } from '../input/real-input.js';
16
+ /** A key addresses focus, not a point; the gesture driver takes a box for every action. */
17
+ const NO_BOX = { x: 0, y: 0, width: 0, height: 0 };
18
+ const sleepFor = (ms) => new Promise((r) => setTimeout(r, ms));
19
+ // Every request, as a predicate: the mock installer clears the any-URL glob, and must not clear the
20
+ // production guard with it.
21
+ const ANY_URL = () => true;
15
22
  /**
16
23
  * Reticle paints its own UI (presenter HUD, glow, annotator marks, tour) into the page. It is
17
24
  * time-varying, since the activity log and border state change with every command, so capturing it
@@ -35,7 +42,11 @@ export function screenshotOptions(opts) {
35
42
  if (true === opts.cssScale && opts.jpegQuality !== undefined) {
36
43
  return { fullPage: false, type: 'jpeg', quality: opts.jpegQuality, scale: 'css' };
37
44
  }
38
- const base = { ...SCREENSHOT_DETERMINISM, fullPage: true === opts.fullPage };
45
+ const base = {
46
+ ...SCREENSHOT_DETERMINISM,
47
+ fullPage: true === opts.fullPage,
48
+ ...(opts.clip === undefined ? {} : { clip: opts.clip }),
49
+ };
39
50
  return opts.jpegQuality === undefined
40
51
  ? base
41
52
  : { ...base, type: 'jpeg', quality: opts.jpegQuality };
@@ -84,7 +95,13 @@ function wrapBrowser(browser) {
84
95
  return {
85
96
  isConnected: () => browser.isConnected(),
86
97
  newContext: async (opts) => {
87
- const context = await browser.newContext(true === opts?.ignoreHTTPSErrors ? { ignoreHTTPSErrors: true } : undefined);
98
+ // Media and viewport ride on the context, so the first paint of the first page has them.
99
+ const { ignoreHTTPSErrors, ...emulate } = opts ?? {};
100
+ const contextOpts = {
101
+ ...(true === ignoreHTTPSErrors ? { ignoreHTTPSErrors: true } : {}),
102
+ ...emulate,
103
+ };
104
+ const context = await browser.newContext(0 < Object.keys(contextOpts).length ? contextOpts : undefined);
88
105
  return {
89
106
  newPage: async () => {
90
107
  const page = await context.newPage();
@@ -109,7 +126,24 @@ function wrapBrowser(browser) {
109
126
  await page.mouse.move(x + 1, y);
110
127
  await page.mouse.move(x, y);
111
128
  },
129
+ // The same driver `reticle drive` presses with, so a held key and a chord read alike.
130
+ emulateMedia: (media) => page.emulateMedia(media),
131
+ press: (args) => performGesture(page, ActionType.PRESS, NO_BOX, args, sleepFor),
112
132
  installMocks: (rules) => installNetworkMocks(page, [...rules]),
133
+ // Registered after any mocks, so it is asked first; what it lets go falls back to them.
134
+ guardRequests: async (decide) => {
135
+ await page.route(ANY_URL, (route) => {
136
+ const request = route.request();
137
+ const refusal = decide(request.method(), request.url());
138
+ return refusal === undefined
139
+ ? route.fallback()
140
+ : route.fulfill({
141
+ status: 403,
142
+ contentType: 'application/json',
143
+ body: JSON.stringify({ error: refusal }),
144
+ });
145
+ });
146
+ },
113
147
  setViewport: (size) => page.setViewportSize(size),
114
148
  bringToFront: () => page.bringToFront(),
115
149
  onCrash: (handler) => page.on('crash', handler),
@@ -140,10 +174,43 @@ function wrapBrowser(browser) {
140
174
  *
141
175
  * Pinned to the playwright this process bundles. Unpinned, `npx` fetches the latest playwright and
142
176
  * installs ITS browser revision — a build this launcher will never look at — so the user follows the
143
- * advice, it succeeds, and the next launch fails identically. Shares one builder with `doctor` so the
144
- * two cannot suggest different commands for the same missing browser.
177
+ * advice, it succeeds, and the next launch fails identically. Shares one builder with `doctor` so
178
+ * the two cannot suggest different commands for the same missing browser.
179
+ *
180
+ * When Playwright's error names the executable the failed launch looked for, the message names
181
+ * it too, the way the preflight refusal and the doctor line already do. Without it the launch
182
+ * translation was the one surface that hid the evidence: a daemon whose HOME
183
+ * or PLAYWRIGHT_BROWSERS_PATH differs from the shell that ran the install keeps refusing after a
184
+ * successful install, and a bare command gives the reader no way to see that the lookup is aimed at
185
+ * a root nothing was installed into (#691).
145
186
  */
146
- const CHROMIUM_MISSING_HINT = `Chromium is not installed for Playwright. Run: ${chromiumInstallCommand(bundledPlaywrightVersion())}`;
187
+ function chromiumMissingHint(executablePath) {
188
+ const command = chromiumInstallCommand(bundledPlaywrightVersion());
189
+ return executablePath === undefined
190
+ ? `Chromium is not installed for Playwright. Run: ${command}`
191
+ : `Chromium is not installed for Playwright — looked for ${executablePath}. Run: ${command}`;
192
+ }
193
+ /**
194
+ * The executable Playwright's error says the failed launch looked for, or undefined when the
195
+ * error names none.
196
+ *
197
+ * Playwright reports the build the failed launch actually used — `Executable doesn't exist at
198
+ * <path>` — whether that is the bundled build, the RETICLE_CHROMIUM_PATH executable, or an
199
+ * installed Chrome or Edge. Reading it here keeps the hint honest: a fresh bundled-path lookup
200
+ * would name a build nobody tried whenever the launch used anything else.
201
+ */
202
+ function pathFromPlaywrightError(msg) {
203
+ // Playwright puts the path at the end of the line, and a Windows path can hold a space
204
+ // (for example C:\Users\Jo Doe). Read to the end of the line and trim the result.
205
+ const found = /executable doesn.?t exist at (.+)$/im.exec(msg);
206
+ if (null === found)
207
+ return undefined;
208
+ const captured = found[1];
209
+ if (undefined === captured)
210
+ return undefined;
211
+ const path = captured.trim();
212
+ return '' === path ? undefined : path;
213
+ }
147
214
  /**
148
215
  * A DIFFERENT first-run failure from the one above: the browser binary is already there, but the
149
216
  * host is missing the OS-level shared libraries (e.g. `libnspr4.so`) Playwright's own
@@ -190,7 +257,7 @@ export function chromiumLaunchHint(msg) {
190
257
  if (/host system is missing dependencies/i.test(msg))
191
258
  return CHROMIUM_MISSING_DEPS_HINT;
192
259
  if (/executable doesn.?t exist|playwright install|browsertype\.launch/i.test(msg)) {
193
- return CHROMIUM_MISSING_HINT;
260
+ return chromiumMissingHint(pathFromPlaywrightError(msg));
194
261
  }
195
262
  return undefined;
196
263
  }
@@ -5,6 +5,8 @@
5
5
  * `browser-pool.ts`, which imports IT. Real Playwright `Page`/`BrowserContext`/`Browser` satisfy
6
6
  * these structurally, which is how the pool stays testable without a real Chromium.
7
7
  */
8
+ import type { RealInputArgs, RealInputResult } from '../input/real-input.js';
9
+ import type { LeaseEmulation, LeaseMedia } from './lease-emulation.js';
8
10
  /** The minimal page surface the pool drives. Real Playwright `Page` satisfies this. */
9
11
  export interface PooledPage {
10
12
  goto(url: string, opts?: {
@@ -32,6 +34,13 @@ export interface PooledPage {
32
34
  * reports dispatched/settled while the styles never ran.
33
35
  */
34
36
  hover?(x: number, y: number): Promise<void>;
37
+ /**
38
+ * Press a key with the real keyboard; it goes to whatever holds focus. OPTIONAL, like `hover`: a
39
+ * page without it keeps the in-page dispatcher, whose synthetic Tab moves no focus.
40
+ */
41
+ press?(args: RealInputArgs): Promise<RealInputResult>;
42
+ /** Set prefers-color-scheme and prefers-reduced-motion. OPTIONAL: without it the media stay. */
43
+ emulateMedia?(media: LeaseMedia): Promise<void>;
35
44
  /** Evaluate a script in the page's current document. OPTIONAL: without it no reader is injected. */
36
45
  evaluate?(script: string): Promise<unknown>;
37
46
  /** Add an init script to run after document creation but before any page scripts run. */
@@ -41,6 +50,12 @@ export interface PooledPage {
41
50
  * makes `reticle_network_mock` refuse rather than claiming it stubbed a request it cannot intercept.
42
51
  */
43
52
  installMocks?(rules: readonly PooledMockRule[]): Promise<void>;
53
+ /**
54
+ * Answer every request this page sends through `decide`: a string refuses it (403, the string as
55
+ * the error), undefined lets it go. OPTIONAL, like `installMocks`. A production drive uses it so a
56
+ * refused request never reaches the live service.
57
+ */
58
+ guardRequests?(decide: (method: string, url: string) => string | undefined): Promise<void>;
44
59
  /**
45
60
  * Resize this page's viewport. OPTIONAL, like `installMocks`: a fake that does not implement it
46
61
  * makes `reticle_viewport` refuse rather than claim a resize the page never took.
@@ -125,7 +140,7 @@ export interface PooledBrowser {
125
140
  /** `ignoreHTTPSErrors` accepts a self-signed or local-CA certificate for this context only. */
126
141
  newContext(opts?: {
127
142
  ignoreHTTPSErrors?: boolean;
128
- }): Promise<PooledContext>;
143
+ } & LeaseEmulation): Promise<PooledContext>;
129
144
  close(): Promise<void>;
130
145
  /** Fires when the browser process dies/crashes so the pool can relaunch on the next acquire. */
131
146
  onDisconnected(handler: () => void): void;
@@ -138,4 +153,11 @@ export interface ScreenshotOptions {
138
153
  jpegQuality?: number;
139
154
  /** One image pixel per CSS pixel, so a high-density display does not double a step screenshot. */
140
155
  cssScale?: boolean;
156
+ /** One region of the page, in CSS pixels: what `reticle_screenshot { clip | ref }` asked for. */
157
+ clip?: {
158
+ x: number;
159
+ y: number;
160
+ width: number;
161
+ height: number;
162
+ };
141
163
  }
@@ -0,0 +1,128 @@
1
+ /**
2
+ * The pool's lease handle and lease record, its options, and its limits: the types and constants
3
+ * `BrowserPool` is built from.
4
+ */
5
+ import type { InitScriptHandle, Launcher, PooledBrowser, PooledContext, PooledPage } from './pool-contract.js';
6
+ /** A leased context+page for one flow. `release` frees the slot and closes the context. */
7
+ export interface Lease {
8
+ readonly sessionId: string;
9
+ readonly url: string;
10
+ readonly navStatus?: number;
11
+ release(): Promise<void>;
12
+ /**
13
+ * Hand the page the zero-install reader: evaluated in the live document, and added ahead of every
14
+ * document this lease loads next. False when there is no reader, or the page cannot run one.
15
+ * Rejects with `NotHtmlDocumentError` when the page is not an HTML document.
16
+ */
17
+ injectReader?(): Promise<boolean>;
18
+ /** Whether the page's document has not reached `complete` yet. False when it cannot be read. */
19
+ isLoading?(): Promise<boolean>;
20
+ }
21
+ /** Default lease time-to-live: a lease untouched for this long is presumed orphaned and reclaimed. */
22
+ export declare const DEFAULT_LEASE_TTL_MS: number;
23
+ /**
24
+ * How long a lease outlives the MCP connection that took it. Long enough for an agent whose
25
+ * connection only blipped to touch it again; short enough that a gone agent's window closes soon.
26
+ */
27
+ export declare const ORPHANED_LEASE_GRACE_MS = 30000;
28
+ /** Default cap on how long a lease's initial navigation may take before it fails (frees the slot). */
29
+ export declare const DEFAULT_NAV_TIMEOUT_MS = 30000;
30
+ /**
31
+ * How many reaped lease ids to remember. Only the most recent departure is ever asked about, so
32
+ * this is slack for a burst sweep, not a history.
33
+ */
34
+ export declare const MAX_REMEMBERED_REAPED_LEASES = 64;
35
+ export interface BrowserPoolOptions {
36
+ /** Max simultaneous leased contexts. Over-cap acquires queue. */
37
+ maxContexts: number;
38
+ /** Stable id generator for lease sessionIds (injected to stay clock-/random-free in logic). */
39
+ genSessionId: () => string;
40
+ /** Injected clock (ms). Defaults to Date.now; tests pass a controllable one. */
41
+ now?: () => number;
42
+ /** A lease untouched for longer than this is reclaimed by sweepExpired. */
43
+ leaseTtlMs?: number;
44
+ /** Per-lease navigation timeout — a page that won't load fails its own lease, never blocks a slot. */
45
+ navTimeoutMs?: number;
46
+ /**
47
+ * The zero-install reader, built where the daemon knows its own port and pairing token. A thunk so
48
+ * the ~450KB build is only read if some page ever needs it; undefined when there is none to give.
49
+ */
50
+ zeroInstallScript?: () => string | undefined;
51
+ /**
52
+ * Launches a browser with a window, for a lease somebody wants to watch. Launched only when the
53
+ * first headed lease is asked for. Absent: a headed lease is refused.
54
+ */
55
+ launchHeaded?: Launcher;
56
+ }
57
+ /** One browser the pool may hold, and the launch in flight for it. */
58
+ export interface BrowserSlot {
59
+ readonly launch: Launcher | undefined;
60
+ readonly headed: boolean;
61
+ browser?: PooledBrowser | undefined;
62
+ launching?: Promise<PooledBrowser> | undefined;
63
+ }
64
+ /** What a headed lease is refused with where no window can be opened. */
65
+ export declare const NO_HEADED_BROWSER = "no headed browser can be opened here";
66
+ /**
67
+ * An acquire that asked to be refused rather than queued found every slot taken (#1535). Queued,
68
+ * it waited behind the cap with no deadline and no status, and `reticle drive` reported the 60 s
69
+ * timeout as a daemon shutting down. The message names the cap and the one override for it.
70
+ */
71
+ export declare class PoolAtCapacityError extends Error {
72
+ readonly max: number;
73
+ constructor(max: number);
74
+ }
75
+ /**
76
+ * What an acquire that asked for an init script is refused with when the page cannot run one.
77
+ *
78
+ * A refusal rather than a lease: the caller asked for a stub of the bindings a desktop shell
79
+ * injects, and a tab opened without it would throw in the app's view and read as a broken app.
80
+ */
81
+ export declare const INIT_SCRIPT_UNSUPPORTED = "Init script failed: this page does not support init scripts, so the requested stub would not be there";
82
+ export interface ActiveLease {
83
+ /** Whether it lives in the headed browser: that browser's death is this lease's death. */
84
+ headed: boolean;
85
+ context: PooledContext;
86
+ page: PooledPage;
87
+ url: string;
88
+ /** Who took it (one id per MCP attach). Only that caller is handed it again. */
89
+ owner?: string;
90
+ /** Last time an agent touched this lease (acquire or any tool call); drives orphan reclaim. */
91
+ touchedAt: number;
92
+ /** When the connection that took it closed, until it is touched again. */
93
+ detachedAt?: number;
94
+ /**
95
+ * The websocket address the page's SDK reported it could not reach, if it said so.
96
+ *
97
+ * One string, overwritten — not a buffer. The SDK retries and logs each failure, so accumulating
98
+ * them would grow without bound for exactly the app that is already misconfigured, and every entry
99
+ * after the first says the same thing.
100
+ */
101
+ dialFailureUrl?: string;
102
+ /**
103
+ * The message of the most recent native dialog dismissed on this lease, if any.
104
+ *
105
+ * One string, overwritten — not a buffer, same reasoning as `dialFailureUrl`: this is diagnostic
106
+ * context for "why did the page look frozen for a moment", not a log an agent needs to replay.
107
+ */
108
+ lastDialogMessage?: string;
109
+ /**
110
+ * The disposable handle of the caller's init script, when the lease was opened with one — a stub
111
+ * of the bindings a desktop shell injects. Disposed with the lease, so a reload or a later
112
+ * navigation inside the lease keeps the stub.
113
+ */
114
+ hostStub?: InitScriptHandle;
115
+ /** The production guard on this page's requests, re-asserted after mocks so it is asked first. */
116
+ guard?: (method: string, url: string) => string | undefined;
117
+ /**
118
+ * The text of that init script, kept so a lease that asks for the SAME stub again is recognised and
119
+ * reused instead of being torn down and remade — see `hostStubScript` and the lease tool's reuse.
120
+ */
121
+ hostStubScript?: string;
122
+ /** What this lease was granted when it opened. It never changes on an open lease. */
123
+ permissions: readonly string[];
124
+ /** Whether its context accepts any TLS certificate (#1255). Fixed when the context is made. */
125
+ ignoresHTTPSErrors: boolean;
126
+ }
127
+ /** Whether the page's document has not finished loading. A page that cannot be asked counts as loaded. */
128
+ export declare function pageLoading(page: PooledPage): Promise<boolean>;
@@ -0,0 +1,49 @@
1
+ /**
2
+ * The pool's lease handle and lease record, its options, and its limits: the types and constants
3
+ * `BrowserPool` is built from.
4
+ */
5
+ /** Default lease time-to-live: a lease untouched for this long is presumed orphaned and reclaimed. */
6
+ export const DEFAULT_LEASE_TTL_MS = 5 * 60_000;
7
+ /**
8
+ * How long a lease outlives the MCP connection that took it. Long enough for an agent whose
9
+ * connection only blipped to touch it again; short enough that a gone agent's window closes soon.
10
+ */
11
+ export const ORPHANED_LEASE_GRACE_MS = 30_000;
12
+ /** Default cap on how long a lease's initial navigation may take before it fails (frees the slot). */
13
+ export const DEFAULT_NAV_TIMEOUT_MS = 30_000;
14
+ /**
15
+ * How many reaped lease ids to remember. Only the most recent departure is ever asked about, so
16
+ * this is slack for a burst sweep, not a history.
17
+ */
18
+ export const MAX_REMEMBERED_REAPED_LEASES = 64;
19
+ /** What a headed lease is refused with where no window can be opened. */
20
+ export const NO_HEADED_BROWSER = 'no headed browser can be opened here';
21
+ /**
22
+ * An acquire that asked to be refused rather than queued found every slot taken (#1535). Queued,
23
+ * it waited behind the cap with no deadline and no status, and `reticle drive` reported the 60 s
24
+ * timeout as a daemon shutting down. The message names the cap and the one override for it.
25
+ */
26
+ export class PoolAtCapacityError extends Error {
27
+ max;
28
+ constructor(max) {
29
+ super(`all ${String(max)} lease slots are in use. Release one (reticle_lease{action:"release"}, or ` +
30
+ 'stop a `reticle drive`), or raise RETICLE_MAX_CONTEXTS.');
31
+ this.max = max;
32
+ this.name = 'PoolAtCapacityError';
33
+ }
34
+ }
35
+ /**
36
+ * What an acquire that asked for an init script is refused with when the page cannot run one.
37
+ *
38
+ * A refusal rather than a lease: the caller asked for a stub of the bindings a desktop shell
39
+ * injects, and a tab opened without it would throw in the app's view and read as a broken app.
40
+ */
41
+ export const INIT_SCRIPT_UNSUPPORTED = 'Init script failed: this page does not support init scripts, so the requested stub would not be there';
42
+ /** Whether the page's document has not finished loading. A page that cannot be asked counts as loaded. */
43
+ export async function pageLoading(page) {
44
+ if (page.evaluate === undefined) {
45
+ return false;
46
+ }
47
+ const state = await page.evaluate('document.readyState');
48
+ return 'string' === typeof state && state !== 'complete';
49
+ }
@@ -10,14 +10,21 @@ export interface InjectedConnect {
10
10
  * ships (`real-input.ts`) — so the two cannot come to disagree about what a daemon-driven page needs.
11
11
  */
12
12
  export declare function injectedConnectArgs(opts: InjectedConnect): Record<string, unknown>;
13
+ /** What the reader script returns when it did nothing, because the page is not an HTML document. */
14
+ export declare const READER_NOT_HTML = "reticle:not-html-document";
13
15
  /**
14
16
  * The script for a page: install the SDK if the page has none, then connect it to this daemon.
15
17
  *
16
18
  * The guard is on the SINGLETON, not on a timer: a page that loaded its own SDK already holds
17
19
  * `__reticleInstance`, and evaluating a second copy would register a second session for one tab.
18
- * `connect` is a no-op once connected, so calling it on the page's own instance is safe.
20
+ * `connect` is a no-op once connected, so calling it on the page's own instance is safe, except that
21
+ * the `lease` mark lets that instance replace a token the bridge refused.
19
22
  */
20
23
  export declare function zeroInstallScript(bundle: string, opts: InjectedConnect): string;
24
+ /** The page is not an HTML document, so the lease did not give it the zero-install reader. */
25
+ export declare class NotHtmlDocumentError extends Error {
26
+ constructor();
27
+ }
21
28
  /**
22
29
  * The single-file build, or undefined when this install has none.
23
30
  *
@@ -19,20 +19,42 @@ const READER_SPECIFIER = '@reticlehq/browser/inject';
19
19
  export function injectedConnectArgs(opts) {
20
20
  return {
21
21
  allowNonLocalhost: true,
22
+ // Lets a page's own SDK take this token when the bridge refused the one its build baked in.
23
+ lease: true,
22
24
  ...(opts.token === undefined ? {} : { token: opts.token }),
23
25
  url: opts.url,
24
26
  };
25
27
  }
28
+ /** What the reader script returns when it did nothing, because the page is not an HTML document. */
29
+ export const READER_NOT_HTML = 'reticle:not-html-document';
30
+ /** The document types that the reader runs on. `document.contentType` is set before the root element. */
31
+ const HTML_CONTENT_TYPES = ['text/html', 'application/xhtml+xml'];
32
+ /*
33
+ * Stop on a page that is not an HTML document, for example an `.svg`. The bundle needs an HTML DOM;
34
+ * #1701 reports `Cannot read properties of null (reading 'appendChild')` on an SVG. The check
35
+ * reads `document.contentType`, because an init script runs before the parser makes the root
36
+ * element. The check binds no name, so it cannot collide with a name that the bundle declares.
37
+ */
38
+ const NOT_HTML_GUARD = `if (globalThis.document !== undefined && !${JSON.stringify(HTML_CONTENT_TYPES)}.includes(globalThis.document.contentType)) ` +
39
+ `return ${JSON.stringify(READER_NOT_HTML)};`;
26
40
  /**
27
41
  * The script for a page: install the SDK if the page has none, then connect it to this daemon.
28
42
  *
29
43
  * The guard is on the SINGLETON, not on a timer: a page that loaded its own SDK already holds
30
44
  * `__reticleInstance`, and evaluating a second copy would register a second session for one tab.
31
- * `connect` is a no-op once connected, so calling it on the page's own instance is safe.
45
+ * `connect` is a no-op once connected, so calling it on the page's own instance is safe, except that
46
+ * the `lease` mark lets that instance replace a token the bridge refused.
32
47
  */
33
48
  export function zeroInstallScript(bundle, opts) {
34
49
  const args = JSON.stringify(injectedConnectArgs(opts));
35
- return `(() => {\nif (!globalThis.__reticleInstance) {\n${bundle}\n}\nglobalThis.__reticleInstance.connect(${args});\n})();`;
50
+ return `(() => {\n${NOT_HTML_GUARD}\nif (!globalThis.__reticleInstance) {\n${bundle}\n}\nglobalThis.__reticleInstance.connect(${args});\n})();`;
51
+ }
52
+ /** The page is not an HTML document, so the lease did not give it the zero-install reader. */
53
+ export class NotHtmlDocumentError extends Error {
54
+ constructor() {
55
+ super('The page is not an HTML document, so the zero-install reader did not run.');
56
+ this.name = 'NotHtmlDocumentError';
57
+ }
36
58
  }
37
59
  let cached;
38
60
  /**
@@ -0,0 +1,136 @@
1
+ import { z } from 'zod';
2
+ import { HelloScope } from '@reticlehq/core';
3
+ import type { ProductionDrive, ProductionGrant } from './production-drive.js';
4
+ /**
5
+ * Turn `reticle_lease { production }` into a page that will connect on a live site, in one step.
6
+ *
7
+ * 1. Mint a single-use session nonce for the site's origin, bound to a production drive.
8
+ * 2. Ask the service for an activation ticket with the linked API key:
9
+ * `POST /v1/production-mode/tickets { workspaceId, nonce, bridgePort, scope, origin, bridge }`.
10
+ * 3. Hand back `<url>?reticle_activate=<ticket>` for the lease to open.
11
+ *
12
+ * The service decides who may activate (an owner or admin of a workspace with production mode on)
13
+ * and signs the ticket. No static secret leaves the machine: the page only ever sees the nonce.
14
+ */
15
+ /** Said when the service has no ticket route: an older or self-hosted service. */
16
+ export declare const PRODUCTION_MODE_NOT_OFFERED: string;
17
+ /** Said when this project has no linked cloud credentials to ask with. */
18
+ export declare const PRODUCTION_MODE_NOT_LINKED = "production mode needs a linked Reticle cloud account: run `reticle connect`, or set RETICLE_API_KEY";
19
+ /** The `production` argument of `reticle_lease { action: "acquire" }`. */
20
+ export declare const ProductionLeaseArgSchema: z.ZodObject<{
21
+ workspaceId: z.ZodString;
22
+ scope: z.ZodEnum<{
23
+ readonly OBSERVE: "observe";
24
+ readonly ACT: "act";
25
+ }>;
26
+ intent: z.ZodOptional<z.ZodString>;
27
+ }, z.core.$strip>;
28
+ export type TicketFetch = (url: string, init: {
29
+ method: string;
30
+ headers: Record<string, string>;
31
+ body: string;
32
+ signal?: AbortSignal;
33
+ }) => Promise<{
34
+ ok: boolean;
35
+ status: number;
36
+ json: () => Promise<unknown>;
37
+ }>;
38
+ /** The part of the nonce registry activation needs: the daemon's own, never one a page reaches. */
39
+ export interface NonceMinter {
40
+ mint(options: {
41
+ origin?: string;
42
+ production?: ProductionGrant;
43
+ }): {
44
+ nonce: string;
45
+ expiresAt: number;
46
+ production?: ProductionDrive;
47
+ };
48
+ }
49
+ export interface ActivationInput {
50
+ production: unknown;
51
+ url: string;
52
+ nonces: NonceMinter | undefined;
53
+ bridgePort: number | undefined;
54
+ cloud: () => Promise<{
55
+ url: string;
56
+ apiKey: string;
57
+ } | null>;
58
+ fetch?: TicketFetch;
59
+ }
60
+ export interface Activation {
61
+ /** The site, carrying the ticket. */
62
+ url: string;
63
+ drive: ProductionDrive;
64
+ scope: HelloScope;
65
+ expiresAt: number;
66
+ }
67
+ export declare function activateProduction(input: ActivationInput): Promise<Activation>;
68
+ /**
69
+ * The lease as the readiness wait sees it, minus the zero-install injector. An injected SDK would
70
+ * connect with the machine's pairing token as a development session, outside the policy; a
71
+ * production page connects only through its own activated loader.
72
+ */
73
+ export declare function leaseWithoutInjection<L extends {
74
+ isLoading?: () => Promise<boolean>;
75
+ }>(lease: L): {
76
+ isLoading?: () => Promise<boolean>;
77
+ };
78
+ /** `reticle_lease`'s `production` argument, described for the agent. */
79
+ export declare const PRODUCTION_LEASE_ARG: z.ZodOptional<z.ZodObject<{
80
+ workspaceId: z.ZodString;
81
+ scope: z.ZodEnum<{
82
+ readonly OBSERVE: "observe";
83
+ readonly ACT: "act";
84
+ }>;
85
+ intent: z.ZodOptional<z.ZodString>;
86
+ }, z.core.$strip>>;
87
+ /** What a production lease reports back. */
88
+ export declare const PRODUCTION_LEASE_OUTPUT: z.ZodOptional<z.ZodObject<{
89
+ scope: z.ZodString;
90
+ expiresAt: z.ZodNumber;
91
+ }, z.core.$strip>>;
92
+ /** The lease's ports activation reads. */
93
+ interface ActivationPorts {
94
+ nonces?: NonceMinter | undefined;
95
+ bridgePort?: number | undefined;
96
+ linkedCloud?: ((root?: string) => Promise<{
97
+ url: string;
98
+ apiKey: string;
99
+ } | null>) | undefined;
100
+ }
101
+ /** Activate when the lease asked for production, else nothing. */
102
+ export declare function activationFor(ports: ActivationPorts, asked: unknown, url: string, root: string | undefined): Promise<Activation | undefined>;
103
+ /**
104
+ * Guard a production lease's requests with its drive, and hand the readiness wait a lease it
105
+ * cannot inject into. A development lease passes through untouched.
106
+ */
107
+ export declare function guardedForProduction<L extends {
108
+ isLoading?: () => Promise<boolean>;
109
+ }>(pool: {
110
+ guardLease(id: string, decide: (method: string, url: string) => string | undefined): Promise<boolean>;
111
+ }, lease: L & {
112
+ sessionId: string;
113
+ }, activated: Activation | undefined): Promise<L | {
114
+ isLoading?: () => Promise<boolean>;
115
+ }>;
116
+ /** The `production` field of the lease result. */
117
+ export declare function summary(activated: Activation | undefined): {
118
+ production?: {
119
+ scope: HelloScope;
120
+ expiresAt: number;
121
+ };
122
+ };
123
+ /**
124
+ * Why an activated page never connected. The service redeems a ticket only for a browser signed in
125
+ * as the person who asked for it, and a leased browser starts signed out. The generic diagnosis
126
+ * blamed the page's CSP and said to allow the bridge for development only, which is wrong here.
127
+ */
128
+ export declare function notActivatedHint(url: string): string;
129
+ /**
130
+ * The permissions a lease is opened with. A production page on a public origin dials the bridge on
131
+ * loopback, which Chromium blocks unless a person grants Local Network Access, and a leased browser
132
+ * has no person. Granted on the lease's own origin only. Not a launch flag: a second
133
+ * `--disable-features` replaces the list Playwright launches with instead of adding to it.
134
+ */
135
+ export declare function leasePermissions(asked: readonly string[] | undefined, production: unknown): readonly string[] | undefined;
136
+ export {};