@reticlehq/server 3.8.1 → 3.9.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 (231) hide show
  1. package/LICENSE +201 -104
  2. package/NOTICE +5 -0
  3. package/README.md +1 -1
  4. package/bin/launch.js +13 -0
  5. package/bin/package.json +3 -0
  6. package/bin/reticle.js +66 -8
  7. package/dist/chromium-launch-options.d.ts +25 -0
  8. package/dist/chromium-launch-options.js +21 -1
  9. package/dist/command/cli/adhoc-verdict.js +34 -7
  10. package/dist/command/cli/answers/gate-exit.d.ts +6 -2
  11. package/dist/command/cli/answers/gate-exit.js +12 -2
  12. package/dist/command/cli/ci-hint.d.ts +44 -0
  13. package/dist/command/cli/ci-hint.js +72 -0
  14. package/dist/command/cli/cli-doctor.d.ts +6 -1
  15. package/dist/command/cli/cli-doctor.js +45 -4
  16. package/dist/command/cli/cli-flow-commands.d.ts +7 -1
  17. package/dist/command/cli/cli-flow-commands.js +39 -17
  18. package/dist/command/cli/cli-kill.d.ts +21 -0
  19. package/dist/command/cli/cli-kill.js +46 -3
  20. package/dist/command/cli/cli-parse.d.ts +5 -2
  21. package/dist/command/cli/cli-parse.js +10 -5
  22. package/dist/command/cli/cli-usage.js +3 -2
  23. package/dist/command/cli/cli-verify.d.ts +6 -1
  24. package/dist/command/cli/cli-verify.js +32 -13
  25. package/dist/command/cli/doctor/browser/chromium-hint.d.ts +6 -1
  26. package/dist/command/cli/doctor/browser/chromium-hint.js +11 -5
  27. package/dist/command/cli/doctor/doctor-fix.d.ts +44 -0
  28. package/dist/command/cli/doctor/doctor-fix.js +89 -0
  29. package/dist/command/cli/doctor/doctor-launcher-line.d.ts +23 -0
  30. package/dist/command/cli/doctor/doctor-launcher-line.js +60 -0
  31. package/dist/command/cli/doctor/doctor-rows.d.ts +4 -0
  32. package/dist/command/cli/doctor/doctor-rows.js +4 -0
  33. package/dist/command/cli/doctor-repairs.d.ts +64 -0
  34. package/dist/command/cli/doctor-repairs.js +214 -0
  35. package/dist/command/cli/drive/drive-command.js +3 -7
  36. package/dist/command/cli/first-use-checks.d.ts +41 -0
  37. package/dist/command/cli/first-use-checks.js +127 -0
  38. package/dist/command/cli/first-verdict-node.d.ts +3 -0
  39. package/dist/command/cli/first-verdict-node.js +189 -0
  40. package/dist/command/cli/first-verdict.d.ts +126 -0
  41. package/dist/command/cli/first-verdict.js +267 -0
  42. package/dist/command/cli/launch/sdk-version-match.d.ts +3 -2
  43. package/dist/command/cli/launch/sdk-version-match.js +3 -2
  44. package/dist/command/cli/lifecycle/daemon-lifecycle.js +6 -5
  45. package/dist/command/cli/mcp-command.js +13 -4
  46. package/dist/command/cli/ports/port-holder.d.ts +2 -0
  47. package/dist/command/cli/ports/port-holder.js +11 -3
  48. package/dist/command/cli/setup-mcp-cli.d.ts +27 -1
  49. package/dist/command/cli/setup-mcp-cli.js +98 -23
  50. package/dist/command/cli/status/status-lines.d.ts +1 -0
  51. package/dist/command/cli/status/status-lines.js +50 -17
  52. package/dist/command/cli/status-fields.js +17 -3
  53. package/dist/command/cli/try-command.d.ts +7 -0
  54. package/dist/command/cli/try-command.js +11 -3
  55. package/dist/command/cli.js +70 -33
  56. package/dist/command/daemon/binding/daemon-status-probe.d.ts +3 -1
  57. package/dist/command/daemon/binding/daemon-status-probe.js +4 -2
  58. package/dist/command/daemon/daemon-argv.d.ts +9 -0
  59. package/dist/command/daemon/daemon-argv.js +11 -0
  60. package/dist/command/daemon/daemon.d.ts +10 -3
  61. package/dist/command/daemon/daemon.js +17 -6
  62. package/dist/command/daemon/lifetime/daemon-exit.d.ts +24 -0
  63. package/dist/command/daemon/lifetime/daemon-exit.js +39 -0
  64. package/dist/command/daemon/lifetime/death-cause.d.ts +15 -0
  65. package/dist/command/daemon/lifetime/death-cause.js +130 -0
  66. package/dist/command/daemon/lifetime/heartbeat.d.ts +7 -15
  67. package/dist/command/daemon/lifetime/heartbeat.js +4 -13
  68. package/dist/command/daemon/port-state.d.ts +14 -0
  69. package/dist/command/daemon/port-state.js +31 -0
  70. package/dist/command/setup/agent-configs.d.ts +2 -0
  71. package/dist/command/setup/agent-configs.js +42 -15
  72. package/dist/command/setup/agent-next-steps.d.ts +77 -0
  73. package/dist/command/setup/agent-next-steps.js +284 -0
  74. package/dist/command/setup/agent-writer.js +11 -6
  75. package/dist/command/setup/init/init-host.js +2 -0
  76. package/dist/command/setup/init/init-runtime.d.ts +6 -1
  77. package/dist/command/setup/init/init-runtime.js +57 -21
  78. package/dist/command/setup/mcp-launcher.d.ts +3 -0
  79. package/dist/command/setup/mcp-launcher.js +11 -0
  80. package/dist/command/setup/setup-command.js +30 -12
  81. package/dist/command/setup/setup-mcp.d.ts +8 -0
  82. package/dist/command/setup/setup-mcp.js +47 -20
  83. package/dist/command/setup/start-dev-server.d.ts +8 -0
  84. package/dist/command/setup/start-dev-server.js +43 -0
  85. package/dist/command/version/identity/server-version.d.ts +2 -0
  86. package/dist/command/version/identity/server-version.js +2 -0
  87. package/dist/command/version/version-skew.d.ts +7 -0
  88. package/dist/command/version/version-skew.js +13 -2
  89. package/dist/features/license/license.d.ts +11 -71
  90. package/dist/features/license/license.js +43 -136
  91. package/dist/features/visual/desktop-capture.d.ts +33 -0
  92. package/dist/features/visual/desktop-capture.js +94 -0
  93. package/dist/features/visual/step-shots.js +139 -35
  94. package/dist/features/visual/visual-tools.d.ts +0 -18
  95. package/dist/features/visual/visual-tools.js +2 -81
  96. package/dist/import-graph.js +5 -6
  97. package/dist/index.d.ts +3 -1
  98. package/dist/index.js +14 -5
  99. package/dist/judgement/runs/run-ledger.d.ts +7 -5
  100. package/dist/judgement/runs/run-ledger.js +98 -69
  101. package/dist/judgement/runs/verification-sync.d.ts +6 -3
  102. package/dist/judgement/runs/verification-sync.js +21 -10
  103. package/dist/language/flows/flow-store-for-session.js +7 -5
  104. package/dist/language/flows/recording/tape/recordings.d.ts +2 -13
  105. package/dist/language/flows/recording/tape/recordings.js +41 -44
  106. package/dist/language/flows/replay.d.ts +17 -7
  107. package/dist/language/flows/replay.js +95 -44
  108. package/dist/launch-chromium.d.ts +1 -0
  109. package/dist/launch-chromium.js +49 -12
  110. package/dist/memory/cloud/sync-screenshots.js +6 -1
  111. package/dist/portal/bridge/bridge.d.ts +13 -4
  112. package/dist/portal/bridge/bridge.js +10 -9
  113. package/dist/portal/input/drive-error.d.ts +6 -0
  114. package/dist/portal/input/drive-error.js +9 -0
  115. package/dist/portal/input/network-mock.js +3 -2
  116. package/dist/portal/input/real-input-press.d.ts +34 -0
  117. package/dist/portal/input/real-input-press.js +150 -0
  118. package/dist/portal/input/real-input.d.ts +21 -23
  119. package/dist/portal/input/real-input.js +153 -194
  120. package/dist/portal/input/viewport-tools.js +6 -3
  121. package/dist/portal/pool/browser-pool.d.ts +5 -1
  122. package/dist/portal/pool/browser-pool.js +32 -38
  123. package/dist/portal/pool/context-permissions.d.ts +20 -17
  124. package/dist/portal/pool/context-permissions.js +63 -1
  125. package/dist/portal/pool/csp-widen.d.ts +62 -0
  126. package/dist/portal/pool/csp-widen.js +132 -0
  127. package/dist/portal/pool/lease-page-error.d.ts +29 -0
  128. package/dist/portal/pool/lease-page-error.js +18 -0
  129. package/dist/portal/pool/page-error-journal.d.ts +57 -0
  130. package/dist/portal/pool/page-error-journal.js +181 -0
  131. package/dist/portal/pool/playwright-launcher.js +21 -8
  132. package/dist/portal/pool/pool-contract.d.ts +22 -0
  133. package/dist/portal/pool/pool-lease.d.ts +35 -2
  134. package/dist/portal/pool/pool-lease.js +23 -0
  135. package/dist/portal/pool/zero-install.js +69 -1
  136. package/dist/portal/session/dev-server/dev-command.d.ts +8 -0
  137. package/dist/portal/session/dev-server/dev-command.js +56 -8
  138. package/dist/portal/session/no-session-diagnosis.js +10 -3
  139. package/dist/portal/session/no-session-next-action.d.ts +12 -0
  140. package/dist/portal/session/no-session-next-action.js +44 -4
  141. package/dist/portal/session/no-session-watch.js +3 -1
  142. package/dist/portal/session/page-commands/undeclared-command.d.ts +9 -3
  143. package/dist/portal/session/page-commands/undeclared-command.js +16 -7
  144. package/dist/portal/session/recorded-gaps.d.ts +1 -1
  145. package/dist/portal/session/recorded-gaps.js +5 -2
  146. package/dist/portal/session/session-manager.js +40 -21
  147. package/dist/portal/session/session.js +4 -3
  148. package/dist/portal/session/zero-install-first-call.d.ts +20 -1
  149. package/dist/portal/session/zero-install-first-call.js +34 -2
  150. package/dist/start-wiring.d.ts +29 -2
  151. package/dist/start-wiring.js +73 -9
  152. package/dist/surface/mcp/mcp-proxy.js +10 -2
  153. package/dist/surface/mcp/mcp.js +5 -3
  154. package/dist/surface/mcp/peer/agents-connected.d.ts +6 -0
  155. package/dist/surface/mcp/peer/agents-connected.js +58 -0
  156. package/dist/surface/mcp/proxy/proxy-daemon-probe.js +17 -5
  157. package/dist/surface/tools/act/act-preflight.js +37 -17
  158. package/dist/surface/tools/act/act-target.js +3 -1
  159. package/dist/surface/tools/act/after-match.d.ts +7 -0
  160. package/dist/surface/tools/act/after-match.js +33 -0
  161. package/dist/surface/tools/act/resolve-target.d.ts +2 -0
  162. package/dist/surface/tools/act/resolve-target.js +35 -8
  163. package/dist/surface/tools/act/sequence-grade.d.ts +3 -1
  164. package/dist/surface/tools/act/sequence-grade.js +8 -1
  165. package/dist/surface/tools/act-sequence-tool.js +3 -0
  166. package/dist/surface/tools/act-tools.js +12 -12
  167. package/dist/surface/tools/assert/assert-verdict.js +28 -1
  168. package/dist/surface/tools/browser-tools.js +75 -7
  169. package/dist/surface/tools/dynamic-tools.js +2 -1
  170. package/dist/surface/tools/empty-session-list.d.ts +2 -0
  171. package/dist/surface/tools/empty-session-list.js +4 -2
  172. package/dist/surface/tools/error-recovery.js +43 -22
  173. package/dist/surface/tools/invoke-tool.js +27 -20
  174. package/dist/surface/tools/lease-hint.d.ts +7 -0
  175. package/dist/surface/tools/lease-hint.js +10 -3
  176. package/dist/surface/tools/lease-readiness.d.ts +21 -0
  177. package/dist/surface/tools/lease-readiness.js +47 -0
  178. package/dist/surface/tools/lease-seed.d.ts +2 -0
  179. package/dist/surface/tools/lease-seed.js +2 -1
  180. package/dist/surface/tools/lease-tools.js +43 -15
  181. package/dist/surface/tools/real-input-attempt.js +70 -31
  182. package/dist/surface/tools/repeat-hint.d.ts +40 -0
  183. package/dist/surface/tools/repeat-hint.js +171 -0
  184. package/dist/surface/tools/run-report.d.ts +2 -2
  185. package/dist/surface/tools/run-report.js +27 -15
  186. package/dist/surface/tools/tool-kit.d.ts +12 -0
  187. package/dist/surface/tools/tool-kit.js +7 -0
  188. package/dist/surface/tools/tools.js +26 -13
  189. package/dist/telemetry/argument-shape.js +16 -7
  190. package/dist/telemetry/cli-telemetry.d.ts +10 -1
  191. package/dist/telemetry/cli-telemetry.js +15 -0
  192. package/dist/telemetry/init-telemetry.d.ts +2 -1
  193. package/dist/telemetry/init-telemetry.js +47 -2
  194. package/dist/telemetry/install-trace.js +23 -4
  195. package/dist/telemetry/onboarding-funnel.d.ts +19 -2
  196. package/dist/telemetry/onboarding-funnel.js +25 -3
  197. package/dist/telemetry/proxy-telemetry.d.ts +2 -1
  198. package/dist/telemetry/proxy-telemetry.js +2 -2
  199. package/dist/telemetry/session-metrics.d.ts +1 -1
  200. package/dist/telemetry/session-metrics.js +67 -27
  201. package/dist/telemetry/telemetry.d.ts +3 -1
  202. package/dist/telemetry/telemetry.js +60 -28
  203. package/dist/telemetry/tool-refused.d.ts +2 -2
  204. package/dist/telemetry/tool-refused.js +9 -2
  205. package/docs/architecture.md +3 -6
  206. package/docs/cli/doctor.mdx +41 -2
  207. package/docs/cli/help.mdx +4 -2
  208. package/docs/cli/license.mdx +4 -5
  209. package/docs/cli/setup.mdx +13 -2
  210. package/docs/cli/status.mdx +4 -0
  211. package/docs/cli.mdx +1 -1
  212. package/docs/deploy-checks.md +25 -0
  213. package/docs/desktop.mdx +1 -1
  214. package/docs/enterprise.md +15 -20
  215. package/docs/environment.mdx +1 -0
  216. package/docs/first-drive.md +1 -1
  217. package/docs/install-manual.mdx +16 -1
  218. package/docs/packages/engine.mdx +1 -1
  219. package/docs/packages/react.mdx +14 -2
  220. package/docs/packages/server.mdx +1 -1
  221. package/docs/packages/tauri.mdx +1 -1
  222. package/docs/packages/test.mdx +1 -1
  223. package/docs/packages/vite-plugin.mdx +1 -0
  224. package/docs/packages.mdx +1 -1
  225. package/docs/platform-integration.md +1 -1
  226. package/docs/skill.md +1 -1
  227. package/docs/telemetry.md +4 -2
  228. package/package.json +14 -10
  229. package/LICENSE-ENTERPRISE +0 -37
  230. package/dist/features/ee/audit-log.d.ts +0 -14
  231. package/dist/features/ee/audit-log.js +0 -11
@@ -0,0 +1,150 @@
1
+ import { clampHoldMs, DriveErrorCode, explicitCodeFromArgs, InputModeReason, pressKeyFromArgs, pressKeysFromArgs, pressModifiersFromArgs, } from '@reticlehq/core';
2
+ import { DriveError } from './drive-error.js';
3
+ /**
4
+ * Drive a `press` with a real keyboard — coordinate-free; the key goes to whatever holds focus.
5
+ * Key and modifiers come from the same core helpers the synthetic dispatcher uses, so the two paths
6
+ * cannot read the same args differently.
7
+ *
8
+ * A `holdMs` splits the chord into down / wait / up, the same shape the page uses for a held key.
9
+ * `keyboard.press` would send it instantly instead, reporting a hold-to-confirm that never held.
10
+ * The one thing this cannot reproduce is the auto-repeat a held key emits: the driver sends a single
11
+ * keydown, where the in-page path sends the repeats a browser would. Named rather than papered over
12
+ * — an app that counts repeats needs the synthetic path, and a caller that sees a held key do
13
+ * nothing now has a reason to try it.
14
+ */
15
+ export async function pressViaKeyboard(page, args, sleep, now) {
16
+ const key = pressKeyFromArgs(args);
17
+ const modifiers = pressModifiersFromArgs(args);
18
+ const chord = 0 < modifiers.length ? `${modifiers.join('+')}+${key}` : key;
19
+ const holdMs = clampHoldMs(args.holdMs);
20
+ if (0 === holdMs) {
21
+ // `press` DOES take a chord string ("Control+k"), so the tap path needs no splitting.
22
+ await page.keyboard.press(chord);
23
+ return 0;
24
+ }
25
+ /*
26
+ * `down`/`up` take ONE key each, unlike `press`: `down('Control+k')` throws
27
+ * `Unknown key: "Control+k"` — measured on a real Chromium, not assumed. The chord string the
28
+ * tap path uses therefore cannot express a hold, so the chord is split here: modifiers down in
29
+ * chord order, the key last, and released in reverse (key first, modifiers reversed), which is
30
+ * what a hand does and what an app's keyup bookkeeping expects.
31
+ *
32
+ * Without the split a held shortcut threw before a single key moved, the caller fell back to
33
+ * the synthetic path, and a real hold was impossible for any press with modifiers — the exact
34
+ * gesture `holdMs` exists for.
35
+ *
36
+ * ## Why every key that went down is tracked, and every exit path cleans up
37
+ *
38
+ * The down calls are the ones that MOVE the keyboard, and they can fail partway: `Control` goes
39
+ * down, the key after it rejects, and the driver's copy of `Control` is still held. That path
40
+ * used to fall straight to the caller's synthetic replay — which presses the same chord again on
41
+ * a keyboard that is already holding a modifier. Tracking what actually went down is what makes
42
+ * the cleanup below able to release the right keys, and only those: releasing a key that never
43
+ * went down is its own lie, and it would turn a clean failure into an unnecessary refusal.
44
+ */
45
+ const pressed = [];
46
+ const pressDown = async (k) => {
47
+ await page.keyboard.down(k);
48
+ pressed.push(k);
49
+ };
50
+ try {
51
+ for (const modifier of modifiers) {
52
+ await pressDown(modifier);
53
+ }
54
+ await pressDown(key);
55
+ }
56
+ catch (error) {
57
+ // The chord is PARTIALLY down. Release what is held before reporting the failure; if that
58
+ // cannot be proved, `releaseKeys` throws RELEASE_FAILED and the caller refuses the replay —
59
+ // the same rule as a failed release on the ordinary path, for the same reason. Only when the
60
+ // cleanup DOES succeed is the original error safe to hand back.
61
+ await releaseKeys(page, pressed);
62
+ throw error;
63
+ }
64
+ const startedAt = now();
65
+ try {
66
+ await sleep(holdMs);
67
+ }
68
+ catch (error) {
69
+ // The wait failed, and the caller is about to run the synthetic path — which presses this SAME
70
+ // key a second time. If the driver's copy stays down, a held modifier then colours every later
71
+ // action for the rest of the run. Best-effort on purpose: whatever went wrong with the wait is
72
+ // the error worth reporting. A cleanup that cannot be proved is the exception — that one is a
73
+ // stuck key, and it must reach the caller as a refusal rather than be swallowed.
74
+ try {
75
+ await releaseKeys(page, pressed);
76
+ }
77
+ catch {
78
+ throw new DriveError(DriveErrorCode.RELEASE_FAILED, 'the wait failed and the keys it pressed could not be released, so they may still be held');
79
+ }
80
+ throw error;
81
+ }
82
+ // NOT best-effort: on the ordinary path a failed release is a real failure the caller must hear
83
+ // about, and swallowing it would report a press whose key is still down.
84
+ await releaseKeys(page, pressed);
85
+ return now() - startedAt;
86
+ }
87
+ /**
88
+ * Release the given keys, in reverse press order, and report a failure as one that leaves the
89
+ * keyboard UNKNOWN rather than as an ordinary provider error.
90
+ *
91
+ * Every release is attempted even after one fails: a stuck `Control` is worse than a stuck letter,
92
+ * so a failure on one key must not skip the rest. The first failure is what is thrown, since it is
93
+ * the one that happened first, and it is wrapped in `DriveError` so the caller can tell "this
94
+ * gesture failed" from "this gesture may have left a key down" — the difference between a safe
95
+ * synthetic replay and an unsafe one.
96
+ */
97
+ async function releaseKeys(page, pressed) {
98
+ let failure;
99
+ for (const k of [...pressed].reverse()) {
100
+ try {
101
+ await page.keyboard.up(k);
102
+ }
103
+ catch (error) {
104
+ failure ??= error;
105
+ }
106
+ }
107
+ if (failure !== undefined) {
108
+ throw new DriveError(DriveErrorCode.RELEASE_FAILED, `the key was pressed but could not be released, so it may still be held: ${describeFailure(failure)}`);
109
+ }
110
+ }
111
+ /**
112
+ * A thrown value as a line a reader can act on.
113
+ *
114
+ * Not `String(error)`: a non-Error thrown value (a rejected plain object, an SDK that throws a
115
+ * record) stringifies to `[object Object]`, which names nothing and hides the one fact the message
116
+ * exists to carry. Anything that is neither an Error nor a string says so rather than pretending.
117
+ */
118
+ function describeFailure(error) {
119
+ if (error instanceof Error) {
120
+ return error.message;
121
+ }
122
+ return 'string' === typeof error ? error : 'an unknown error';
123
+ }
124
+ /**
125
+ * The `press`es this module will NOT drive: a chord that only the in-page dispatcher can express.
126
+ *
127
+ * `args.keys` asks for several keys held down TOGETHER, pressed in order and released in reverse.
128
+ * That is not a `page.keyboard.press` chord — a non-modifier key cannot appear before the last `+`
129
+ * — and a real keyboard cannot aim a key at a named element. `args.code` is the third: the driver
130
+ * presses by KEY name and offers no way to send a physical `code` that disagrees with it, so
131
+ * `{ text: 'z', code: 'KeyY' }` would strike a different key than the one asked for. All three are
132
+ * routed to the synthetic path by the caller, which reports the reason rather than pretending a
133
+ * different gesture happened.
134
+ *
135
+ * Ordered by how specifically the caller asked: `keys` then `code` name the KEY, `ref` names only
136
+ * the target. Two can apply at once, and the earlier one is the more unusual request — the reason
137
+ * should name that, not the generic "you passed a ref".
138
+ */
139
+ export function unspellablePressReason(ref, args) {
140
+ if (0 < pressKeysFromArgs(args).length) {
141
+ return InputModeReason.SYNTHETIC_MULTI_KEY_PRESS_PREFERRED;
142
+ }
143
+ if (explicitCodeFromArgs(args) !== undefined) {
144
+ return InputModeReason.SYNTHETIC_KEY_CODE_PRESS_PREFERRED;
145
+ }
146
+ if (0 < ref.length) {
147
+ return InputModeReason.SYNTHETIC_ELEMENT_PRESS_PREFERRED;
148
+ }
149
+ return undefined;
150
+ }
@@ -11,7 +11,8 @@
11
11
  */
12
12
  import { type ScriptCoverage } from './js-coverage.js';
13
13
  import type { Browser, Page } from 'playwright';
14
- import { ActionType, DriveErrorCode, InputMode, InputModeReason } from '@reticlehq/core';
14
+ import { DriveError } from './drive-error.js';
15
+ import { ActionType, InputMode } from '@reticlehq/core';
15
16
  import { type MockRule } from './network-mock.js';
16
17
  import { type NetworkDetail } from './network-detail.js';
17
18
  /** Viewport CSS-px box as returned by the INSPECT command (getBoundingClientRect). */
@@ -34,6 +35,8 @@ export type RealInputArgs = {
34
35
  key?: string;
35
36
  /** For press: modifier names (Meta/Control/Shift/Alt; aliases like `cmd` accepted). */
36
37
  modifiers?: string[];
38
+ /** For click: which mouse button to press (left, middle or right). Absent means left. */
39
+ button?: string;
37
40
  /**
38
41
  * For press: several keys held down TOGETHER, pressed in order and released in reverse. Read but
39
42
  * never forwarded — a chord with a non-modifier key has no `page.keyboard.press` spelling, so the
@@ -152,11 +155,8 @@ export interface OwnedRealInputProvider extends RealInputProvider {
152
155
  /** Close the owned browser. Idempotent. */
153
156
  dispose(): Promise<void>;
154
157
  }
155
- /** Structured, code-tagged failure so callers branch on cause, not message text. */
156
- export declare class DriveError extends Error {
157
- readonly code: DriveErrorCode;
158
- constructor(code: DriveErrorCode, message: string);
159
- }
158
+ export { DriveError };
159
+ export { unspellablePressReason } from './real-input-press.js';
160
160
  /** Center of a viewport box in CSS px. Pure — unit-tested directly. */
161
161
  export declare function boxCenter(box: ElementBox): {
162
162
  cx: number;
@@ -174,22 +174,6 @@ export declare function isPointerAction(action: ActionType): boolean;
174
174
  export declare function isRealInputAction(action: ActionType): boolean;
175
175
  type SleepFn = (ms: number) => Promise<void>;
176
176
  type ConnectFn = (url: string) => Promise<Browser>;
177
- /**
178
- * The `press`es this module will NOT drive: a chord that only the in-page dispatcher can express.
179
- *
180
- * `args.keys` asks for several keys held down TOGETHER, pressed in order and released in reverse.
181
- * That is not a `page.keyboard.press` chord — a non-modifier key cannot appear before the last `+`
182
- * — and a real keyboard cannot aim a key at a named element. `args.code` is the third: the driver
183
- * presses by KEY name and offers no way to send a physical `code` that disagrees with it, so
184
- * `{ text: 'z', code: 'KeyY' }` would strike a different key than the one asked for. All three are
185
- * routed to the synthetic path by the caller, which reports the reason rather than pretending a
186
- * different gesture happened.
187
- *
188
- * Ordered by how specifically the caller asked: `keys` then `code` name the KEY, `ref` names only
189
- * the target. Two can apply at once, and the earlier one is the more unusual request — the reason
190
- * should name that, not the generic "you passed a ref".
191
- */
192
- export declare function unspellablePressReason(ref: string, args: Record<string, unknown>): InputModeReason | undefined;
193
177
  /**
194
178
  * Shared gesture executor: drive a native gesture on an already-resolved Page. Used by both the
195
179
  * CDP-attached and the launched (drive) providers so the pointer logic lives in one place.
@@ -197,6 +181,16 @@ export declare function unspellablePressReason(ref: string, args: Record<string,
197
181
  export declare function performGesture(page: Page, action: ActionType, box: ElementBox, args: RealInputArgs, sleep: SleepFn,
198
182
  /** Injected so a test can assert the achieved hold deterministically; defaults to the real clock. */
199
183
  now?: () => number): Promise<RealInputResult>;
184
+ /**
185
+ * Run a real pointer gesture with Reticle's own UI out of the hit test, and put it back after.
186
+ *
187
+ * A real pointer goes to the topmost element under it. When the HUD sat over the app's control, a
188
+ * driven click went to the HUD and the verdict said the app did nothing; a drag ended short (#992).
189
+ * The restore runs whatever the gesture did, so the HUD does not stay unclickable for a person.
190
+ */
191
+ export declare function withChromePassThrough<T>(page: {
192
+ evaluate: (script: string) => Promise<unknown>;
193
+ }, gesture: () => Promise<T>): Promise<T>;
200
194
  /**
201
195
  * Capture a PNG from a Playwright page. Shared by the CDP + launched providers so the
202
196
  * screenshot path lives in one place (mirrors performGesture). Returns the raw PNG bytes.
@@ -278,6 +272,11 @@ export interface LaunchedProviderOptions {
278
272
  * inside-app view never loses fidelity to the outside-in view. Omitted → no network detail captured.
279
273
  */
280
274
  onNetworkDetail?: (detail: NetworkDetail) => void;
275
+ /**
276
+ * Reticle's own reader for a page with no SDK, as the lease pool gives one (see zero-install.ts).
277
+ * Undefined, or a loader that answers undefined, leaves such a page with no session.
278
+ */
279
+ zeroInstallScript?: () => string | undefined;
281
280
  }
282
281
  /** The only place the dynamic value import of Playwright lives for the launched (drive) path. */
283
282
  export declare const launchedChromium: LaunchFn;
@@ -342,4 +341,3 @@ export declare class LaunchedRealInputProvider implements OwnedRealInputProvider
342
341
  export declare function selectPage<T extends {
343
342
  url(): string;
344
343
  }>(pages: readonly T[], sessionUrl: string): T | undefined;
345
- export {};