@reticlehq/browser 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +17 -0
  3. package/dist/actions/actions-dom.d.ts +29 -0
  4. package/dist/actions/actions-dom.d.ts.map +1 -0
  5. package/dist/actions/actions-dom.js +153 -0
  6. package/dist/actions/actions-dom.js.map +1 -0
  7. package/dist/actions/actions.d.ts +92 -0
  8. package/dist/actions/actions.d.ts.map +1 -0
  9. package/dist/actions/actions.js +348 -0
  10. package/dist/actions/actions.js.map +1 -0
  11. package/dist/actions/scroll.d.ts +19 -0
  12. package/dist/actions/scroll.d.ts.map +1 -0
  13. package/dist/actions/scroll.js +44 -0
  14. package/dist/actions/scroll.js.map +1 -0
  15. package/dist/commands/commands.d.ts +5 -0
  16. package/dist/commands/commands.d.ts.map +1 -0
  17. package/dist/commands/commands.js +246 -0
  18. package/dist/commands/commands.js.map +1 -0
  19. package/dist/dom/a11y.d.ts +20 -0
  20. package/dist/dom/a11y.d.ts.map +1 -0
  21. package/dist/dom/a11y.js +263 -0
  22. package/dist/dom/a11y.js.map +1 -0
  23. package/dist/dom/auto-anchor.d.ts +66 -0
  24. package/dist/dom/auto-anchor.d.ts.map +1 -0
  25. package/dist/dom/auto-anchor.js +75 -0
  26. package/dist/dom/auto-anchor.js.map +1 -0
  27. package/dist/dom/dom-ignore.d.ts +7 -0
  28. package/dist/dom/dom-ignore.d.ts.map +1 -0
  29. package/dist/dom/dom-ignore.js +21 -0
  30. package/dist/dom/dom-ignore.js.map +1 -0
  31. package/dist/dom/query.d.ts +6 -0
  32. package/dist/dom/query.d.ts.map +1 -0
  33. package/dist/dom/query.js +236 -0
  34. package/dist/dom/query.js.map +1 -0
  35. package/dist/dom/refs.d.ts +15 -0
  36. package/dist/dom/refs.d.ts.map +1 -0
  37. package/dist/dom/refs.js +36 -0
  38. package/dist/dom/refs.js.map +1 -0
  39. package/dist/dom/snapshot.d.ts +22 -0
  40. package/dist/dom/snapshot.d.ts.map +1 -0
  41. package/dist/dom/snapshot.js +171 -0
  42. package/dist/dom/snapshot.js.map +1 -0
  43. package/dist/dom/theme.d.ts +26 -0
  44. package/dist/dom/theme.d.ts.map +1 -0
  45. package/dist/dom/theme.js +90 -0
  46. package/dist/dom/theme.js.map +1 -0
  47. package/dist/index.d.ts +25 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +32 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/observers/animation.d.ts +4 -0
  52. package/dist/observers/animation.d.ts.map +1 -0
  53. package/dist/observers/animation.js +35 -0
  54. package/dist/observers/animation.js.map +1 -0
  55. package/dist/observers/console.d.ts +4 -0
  56. package/dist/observers/console.d.ts.map +1 -0
  57. package/dist/observers/console.js +58 -0
  58. package/dist/observers/console.js.map +1 -0
  59. package/dist/observers/dom.d.ts +4 -0
  60. package/dist/observers/dom.d.ts.map +1 -0
  61. package/dist/observers/dom.js +96 -0
  62. package/dist/observers/dom.js.map +1 -0
  63. package/dist/observers/health.d.ts +8 -0
  64. package/dist/observers/health.d.ts.map +1 -0
  65. package/dist/observers/health.js +33 -0
  66. package/dist/observers/health.js.map +1 -0
  67. package/dist/observers/network.d.ts +11 -0
  68. package/dist/observers/network.d.ts.map +1 -0
  69. package/dist/observers/network.js +128 -0
  70. package/dist/observers/network.js.map +1 -0
  71. package/dist/observers/route.d.ts +4 -0
  72. package/dist/observers/route.d.ts.map +1 -0
  73. package/dist/observers/route.js +56 -0
  74. package/dist/observers/route.js.map +1 -0
  75. package/dist/observers/scroll.d.ts +4 -0
  76. package/dist/observers/scroll.d.ts.map +1 -0
  77. package/dist/observers/scroll.js +42 -0
  78. package/dist/observers/scroll.js.map +1 -0
  79. package/dist/observers/types.d.ts +6 -0
  80. package/dist/observers/types.d.ts.map +1 -0
  81. package/dist/observers/types.js +2 -0
  82. package/dist/observers/types.js.map +1 -0
  83. package/dist/presenter/overlay.d.ts +12 -0
  84. package/dist/presenter/overlay.d.ts.map +1 -0
  85. package/dist/presenter/overlay.js +31 -0
  86. package/dist/presenter/overlay.js.map +1 -0
  87. package/dist/presenter/presenter-config.d.ts +86 -0
  88. package/dist/presenter/presenter-config.d.ts.map +1 -0
  89. package/dist/presenter/presenter-config.js +51 -0
  90. package/dist/presenter/presenter-config.js.map +1 -0
  91. package/dist/presenter/presenter-controls.d.ts +74 -0
  92. package/dist/presenter/presenter-controls.d.ts.map +1 -0
  93. package/dist/presenter/presenter-controls.js +360 -0
  94. package/dist/presenter/presenter-controls.js.map +1 -0
  95. package/dist/presenter/presenter-effects.d.ts +14 -0
  96. package/dist/presenter/presenter-effects.d.ts.map +1 -0
  97. package/dist/presenter/presenter-effects.js +40 -0
  98. package/dist/presenter/presenter-effects.js.map +1 -0
  99. package/dist/presenter/presenter-glow.d.ts +43 -0
  100. package/dist/presenter/presenter-glow.d.ts.map +1 -0
  101. package/dist/presenter/presenter-glow.js +126 -0
  102. package/dist/presenter/presenter-glow.js.map +1 -0
  103. package/dist/presenter/presenter-log.d.ts +43 -0
  104. package/dist/presenter/presenter-log.d.ts.map +1 -0
  105. package/dist/presenter/presenter-log.js +118 -0
  106. package/dist/presenter/presenter-log.js.map +1 -0
  107. package/dist/presenter/presenter-run-state.d.ts +48 -0
  108. package/dist/presenter/presenter-run-state.d.ts.map +1 -0
  109. package/dist/presenter/presenter-run-state.js +37 -0
  110. package/dist/presenter/presenter-run-state.js.map +1 -0
  111. package/dist/presenter/presenter-styles.d.ts +7 -0
  112. package/dist/presenter/presenter-styles.d.ts.map +1 -0
  113. package/dist/presenter/presenter-styles.js +118 -0
  114. package/dist/presenter/presenter-styles.js.map +1 -0
  115. package/dist/presenter/presenter-tally.d.ts +20 -0
  116. package/dist/presenter/presenter-tally.d.ts.map +1 -0
  117. package/dist/presenter/presenter-tally.js +38 -0
  118. package/dist/presenter/presenter-tally.js.map +1 -0
  119. package/dist/presenter/presenter-verbs.d.ts +2 -0
  120. package/dist/presenter/presenter-verbs.d.ts.map +1 -0
  121. package/dist/presenter/presenter-verbs.js +29 -0
  122. package/dist/presenter/presenter-verbs.js.map +1 -0
  123. package/dist/presenter/presenter.d.ts +89 -0
  124. package/dist/presenter/presenter.d.ts.map +1 -0
  125. package/dist/presenter/presenter.js +428 -0
  126. package/dist/presenter/presenter.js.map +1 -0
  127. package/dist/recorder/recorder-styles.d.ts +12 -0
  128. package/dist/recorder/recorder-styles.d.ts.map +1 -0
  129. package/dist/recorder/recorder-styles.js +45 -0
  130. package/dist/recorder/recorder-styles.js.map +1 -0
  131. package/dist/recorder/recorder.d.ts +60 -0
  132. package/dist/recorder/recorder.d.ts.map +1 -0
  133. package/dist/recorder/recorder.js +436 -0
  134. package/dist/recorder/recorder.js.map +1 -0
  135. package/dist/registry/adapters.d.ts +31 -0
  136. package/dist/registry/adapters.d.ts.map +1 -0
  137. package/dist/registry/adapters.js +47 -0
  138. package/dist/registry/adapters.js.map +1 -0
  139. package/dist/registry/capabilities.d.ts +25 -0
  140. package/dist/registry/capabilities.d.ts.map +1 -0
  141. package/dist/registry/capabilities.js +48 -0
  142. package/dist/registry/capabilities.js.map +1 -0
  143. package/dist/registry/commit-and-signal.d.ts +9 -0
  144. package/dist/registry/commit-and-signal.d.ts.map +1 -0
  145. package/dist/registry/commit-and-signal.js +12 -0
  146. package/dist/registry/commit-and-signal.js.map +1 -0
  147. package/dist/registry/domains.d.ts +15 -0
  148. package/dist/registry/domains.d.ts.map +1 -0
  149. package/dist/registry/domains.js +19 -0
  150. package/dist/registry/domains.js.map +1 -0
  151. package/dist/registry/emitter.d.ts +28 -0
  152. package/dist/registry/emitter.d.ts.map +1 -0
  153. package/dist/registry/emitter.js +27 -0
  154. package/dist/registry/emitter.js.map +1 -0
  155. package/dist/registry/stores.d.ts +9 -0
  156. package/dist/registry/stores.d.ts.map +1 -0
  157. package/dist/registry/stores.js +30 -0
  158. package/dist/registry/stores.js.map +1 -0
  159. package/dist/reticle-presenter-helpers.d.ts +19 -0
  160. package/dist/reticle-presenter-helpers.d.ts.map +1 -0
  161. package/dist/reticle-presenter-helpers.js +81 -0
  162. package/dist/reticle-presenter-helpers.js.map +1 -0
  163. package/dist/reticle.d.ts +113 -0
  164. package/dist/reticle.d.ts.map +1 -0
  165. package/dist/reticle.js +379 -0
  166. package/dist/reticle.js.map +1 -0
  167. package/dist/review/annotator.d.ts +36 -0
  168. package/dist/review/annotator.d.ts.map +1 -0
  169. package/dist/review/annotator.js +321 -0
  170. package/dist/review/annotator.js.map +1 -0
  171. package/dist/review/mark-anchor.d.ts +23 -0
  172. package/dist/review/mark-anchor.d.ts.map +1 -0
  173. package/dist/review/mark-anchor.js +74 -0
  174. package/dist/review/mark-anchor.js.map +1 -0
  175. package/dist/security/serialization.d.ts +6 -0
  176. package/dist/security/serialization.d.ts.map +1 -0
  177. package/dist/security/serialization.js +103 -0
  178. package/dist/security/serialization.js.map +1 -0
  179. package/dist/timers/clock.d.ts +6 -0
  180. package/dist/timers/clock.d.ts.map +1 -0
  181. package/dist/timers/clock.js +80 -0
  182. package/dist/timers/clock.js.map +1 -0
  183. package/dist/timers/native-timers.d.ts +37 -0
  184. package/dist/timers/native-timers.d.ts.map +1 -0
  185. package/dist/timers/native-timers.js +79 -0
  186. package/dist/timers/native-timers.js.map +1 -0
  187. package/dist/transport/transport.d.ts +54 -0
  188. package/dist/transport/transport.d.ts.map +1 -0
  189. package/dist/transport/transport.js +182 -0
  190. package/dist/transport/transport.js.map +1 -0
  191. package/package.json +52 -0
@@ -0,0 +1,379 @@
1
+ import { EventType, RETICLE_DEFAULT_PORT, RETICLE_PROTOCOL_VERSION, RETICLE_URL_PARAM, RETICLE_WS_PATH, ReticleCommand, MessageKind, SESSION_AUTO, SessionState, TRANSPORT_LIMITS, isLoopbackHostname, } from '@reticlehq/core';
2
+ import { createCommandRegistry } from './commands/commands.js';
3
+ import { Transport } from './transport/transport.js';
4
+ import { adapterNames } from './registry/adapters.js';
5
+ import { registerCapabilities, hasCapabilities, } from './registry/capabilities.js';
6
+ import { installDom } from './observers/dom.js';
7
+ import { installNetwork } from './observers/network.js';
8
+ import { installRoute } from './observers/route.js';
9
+ import { installConsole } from './observers/console.js';
10
+ import { installAnimation } from './observers/animation.js';
11
+ import { installScroll } from './observers/scroll.js';
12
+ import { installHealth } from './observers/health.js';
13
+ import { installOverlay } from './presenter/overlay.js';
14
+ import { Presenter, LOG_KIND, LOG_RESULT, } from './presenter/presenter.js';
15
+ import { actionVerb } from './presenter/presenter-verbs.js';
16
+ import { str, refLabel, modeForCommand, presentStatus } from './reticle-presenter-helpers.js';
17
+ import { resetClock } from './timers/clock.js';
18
+ import { installRecorder } from './recorder/recorder.js';
19
+ import { Annotator } from './review/annotator.js';
20
+ /**
21
+ * Runtime backstop for the dev-only SDK: block connecting when the build reports production, unless
22
+ * explicitly overridden. Pure so it's testable; connect() reads NODE_ENV safely (process may be absent
23
+ * in a raw browser). This is defense-in-depth — the primary guard is the consumer gating the import
24
+ * behind `import.meta.env.DEV` so the SDK is dead-code-eliminated from prod bundles entirely.
25
+ */
26
+ export function shouldBlockProduction(nodeEnv, allowInProduction) {
27
+ return nodeEnv === 'production' && !allowInProduction;
28
+ }
29
+ export function connectionPolicy(pageHostname, bridgeUrl, allowNonLocalhost, token) {
30
+ let bridge;
31
+ try {
32
+ bridge = new URL(bridgeUrl);
33
+ }
34
+ catch {
35
+ return { allowed: false, reason: 'invalid Reticle bridge URL' };
36
+ }
37
+ if (bridge.protocol !== 'ws:' && bridge.protocol !== 'wss:') {
38
+ return { allowed: false, reason: 'Reticle bridge URL must use ws:// or wss://' };
39
+ }
40
+ if ((token?.length ?? 0) > TRANSPORT_LIMITS.MAX_TOKEN_LENGTH) {
41
+ return {
42
+ allowed: false,
43
+ reason: `Reticle pairing token exceeds ${String(TRANSPORT_LIMITS.MAX_TOKEN_LENGTH)} characters`,
44
+ };
45
+ }
46
+ const remoteBridge = !isLoopbackHostname(bridge.hostname);
47
+ if (remoteBridge && bridge.protocol !== 'wss:') {
48
+ return { allowed: false, reason: 'a non-local Reticle bridge must use wss://' };
49
+ }
50
+ const remote = !isLoopbackHostname(pageHostname) || remoteBridge;
51
+ if (!remote)
52
+ return { allowed: true };
53
+ if (!allowNonLocalhost) {
54
+ return {
55
+ allowed: false,
56
+ reason: 'Reticle is disabled outside localhost unless allowNonLocalhost is explicitly enabled',
57
+ };
58
+ }
59
+ if (token === undefined || token.length === 0) {
60
+ return { allowed: false, reason: 'a pairing token is required outside localhost' };
61
+ }
62
+ return { allowed: true };
63
+ }
64
+ /** HUD summary when the SDK self-ends a session because the bridge (server/agent) became unreachable. */
65
+ const BRIDGE_LOST_SUMMARY = 'Session ended — lost connection to Reticle (the agent is no longer running).';
66
+ /**
67
+ * Resolve the session label. An absent label or the `auto` sentinel yields a fresh per-tab id (via
68
+ * the injected generator) so multi-tab / new-tab routes never collide; any other label is used
69
+ * verbatim so tabs can intentionally share a session. `gen` is injected to keep this clock-free.
70
+ */
71
+ export function resolveSessionLabel(option, gen) {
72
+ return option === undefined || option === SESSION_AUTO ? gen() : option;
73
+ }
74
+ // Re-exported from the protocol (the wire contract) so callers/tests can import it from the SDK too.
75
+ export { RETICLE_URL_PARAM };
76
+ /**
77
+ * Extract Reticle identity overrides from a `location.search` string. Pure (takes the string, not the
78
+ * window) so it's testable without a DOM. Explicit connect() options still win over these.
79
+ */
80
+ export function reticleParamsFromSearch(search) {
81
+ const params = new URLSearchParams(search);
82
+ const out = {};
83
+ const session = params.get(RETICLE_URL_PARAM.SESSION);
84
+ const projectId = params.get(RETICLE_URL_PARAM.PROJECT);
85
+ if (session !== null && session.length > 0)
86
+ out.session = session;
87
+ if (projectId !== null && projectId.length > 0)
88
+ out.projectId = projectId;
89
+ return out;
90
+ }
91
+ /**
92
+ * Resolve the session + project identity for a connection: an explicit, non-`auto` option wins;
93
+ * otherwise a launcher-stamped URL param is used; otherwise undefined (caller generates a per-tab id).
94
+ * Crucially `auto` is treated like "unset" so an app that passes the auto sentinel still lets a pooled
95
+ * launcher correlate the lease via __reticle_session. Pure for testability.
96
+ */
97
+ export function resolveConnectIdentity(options, search) {
98
+ const url = reticleParamsFromSearch(search);
99
+ const explicitSession = options.session !== undefined && options.session !== SESSION_AUTO ? options.session : undefined;
100
+ const projectId = options.projectId ?? url.projectId;
101
+ return {
102
+ session: explicitSession ?? url.session,
103
+ projectId: projectId !== undefined && projectId.length > 0 ? projectId : undefined,
104
+ };
105
+ }
106
+ /**
107
+ * The browser-side orchestrator. Wires observers -> events -> bridge, and bridge
108
+ * commands -> handlers. Embedded in the host app (dev only).
109
+ */
110
+ export class Reticle {
111
+ #transport;
112
+ #registry = new Map();
113
+ #teardowns = [];
114
+ #connected = false;
115
+ #session = 'default';
116
+ #start = 0;
117
+ #overlay;
118
+ #presenter;
119
+ #recorder;
120
+ #annotator;
121
+ #eventCount = 0;
122
+ #token;
123
+ #projectId;
124
+ /** Act-row log handle for the in-flight act/act_sequence, so its outcome stamps the right row. */
125
+ #actHandle;
126
+ connect(options = {}) {
127
+ if (this.#connected)
128
+ return;
129
+ if (typeof window === 'undefined' || typeof document === 'undefined')
130
+ return;
131
+ // Dev-only backstop: refuse to activate in a production build (SSR healthcheck, prod bundle opened
132
+ // on localhost). `process` may not exist in a raw browser, so read NODE_ENV off globalThis.
133
+ const proc = globalThis.process;
134
+ const nodeEnv = proc?.env?.NODE_ENV;
135
+ if (shouldBlockProduction(nodeEnv, options.allowInProduction === true)) {
136
+ globalThis.console.warn('[Reticle] disabled in production (NODE_ENV=production). Gate the import behind ' +
137
+ 'import.meta.env.DEV, or pass allowInProduction:true to override.');
138
+ return;
139
+ }
140
+ const url = options.url ?? `ws://localhost:${String(RETICLE_DEFAULT_PORT)}${RETICLE_WS_PATH}`;
141
+ const policy = connectionPolicy(window.location.hostname, url, options.allowNonLocalhost === true, options.token);
142
+ if (!policy.allowed) {
143
+ globalThis.console.warn(`[Reticle] ${policy.reason ?? 'connection blocked'}`);
144
+ return;
145
+ }
146
+ // A pooled/headless launcher can stamp identity via namespaced URL params; explicit (non-auto)
147
+ // options win, but the `auto` sentinel defers to the URL param so leases correlate.
148
+ const identity = resolveConnectIdentity(options, window.location.search);
149
+ this.#session = resolveSessionLabel(identity.session, () => typeof globalThis.crypto?.randomUUID === 'function'
150
+ ? `s${globalThis.crypto.randomUUID()}`
151
+ : `s${Date.now().toString(36)}`);
152
+ this.#token =
153
+ options.token !== undefined && options.token.length > 0 ? options.token : undefined;
154
+ this.#projectId = identity.projectId;
155
+ this.#start = performance.now();
156
+ this.#registry = createCommandRegistry();
157
+ this.#transport = new Transport({
158
+ url,
159
+ hello: () => this.#hello(),
160
+ handleCommand: (command) => this.#handleCommand(command),
161
+ // Show the presenter HUD as soon as the agent bridge connects — the user immediately sees
162
+ // the glow border and narration panel, even before the first tool call lands.
163
+ onConnected: () => this.#presenter?.sessionStart(),
164
+ // Liveness fallback: if the bridge stays unreachable (the agent killed the server process),
165
+ // no server-pushed end can arrive — so end the run we're presenting ourselves. A returning
166
+ // agent revives it via the normal sessionStart() path on its next command.
167
+ onConnectionLost: () => {
168
+ if (this.#presenter?.sessionActive === true) {
169
+ this.#presenter.setState(SessionState.ENDED, BRIDGE_LOST_SUMMARY);
170
+ }
171
+ },
172
+ // First-connect never succeeded ⇒ the bridge is unreachable at this URL. Tell the developer
173
+ // exactly what went wrong and how to fix it, instead of retrying silently forever.
174
+ onUnreachable: ({ url: tried, attempts }) => {
175
+ globalThis.console.warn(`[Reticle] could not reach the bridge at ${tried} after ${String(attempts)} attempts. ` +
176
+ `Is the Reticle daemon running on that port? If your app runs in a container/devcontainer/WSL, ` +
177
+ `the daemon is on a different host — set the WS URL explicitly (Vite: VITE_RETICLE_WS_URL, ` +
178
+ `or reticle.connect({ url })). Still retrying…`);
179
+ },
180
+ });
181
+ const emit = this.#emit;
182
+ this.#teardowns = [
183
+ installNetwork(emit),
184
+ installRoute(emit),
185
+ installConsole(emit),
186
+ installAnimation(emit),
187
+ installScroll(emit),
188
+ installDom(emit),
189
+ installHealth(emit), // page visibility/focus health + heartbeat
190
+ ];
191
+ if (options.overlay === true) {
192
+ this.#overlay = installOverlay();
193
+ this.#overlay.update({ connected: true, events: 0 });
194
+ }
195
+ if (options.present !== false) {
196
+ const presenterOptions = {};
197
+ if (options.pace !== undefined)
198
+ presenterOptions.paceMs = options.pace;
199
+ if (options.narrationDwellMs !== undefined) {
200
+ presenterOptions.narrationDwellMs = options.narrationDwellMs;
201
+ }
202
+ if (options.border !== undefined)
203
+ presenterOptions.border = options.border;
204
+ if (options.logMax !== undefined)
205
+ presenterOptions.logMax = options.logMax;
206
+ if (options.endedFadeMs !== undefined)
207
+ presenterOptions.endedFadeMs = options.endedFadeMs;
208
+ if (options.idleEndMs !== undefined)
209
+ presenterOptions.idleEndMs = options.idleEndMs;
210
+ presenterOptions.sessionId = this.#session;
211
+ // The panel calls this when the human pauses/resumes/ends or sends a message. We emit a
212
+ // HUMAN_CONTROL event over the existing transport; #emit stamps `t` from the elapsed clock.
213
+ presenterOptions.onControl = (intent) => this.#emit(EventType.HUMAN_CONTROL, intent.text !== undefined
214
+ ? { kind: intent.kind, text: intent.text }
215
+ : { kind: intent.kind });
216
+ this.#presenter = new Presenter(presenterOptions);
217
+ // Mount the overlay. The session (glow + HUD) activates on bridge connect via onConnected,
218
+ // so the presenter is visible as soon as the agent is reachable — not just on first command.
219
+ this.#presenter.mount();
220
+ }
221
+ if (options.recorder === true) {
222
+ this.#recorder = installRecorder({ emit, now: () => Date.now() });
223
+ this.#recorder.mount();
224
+ }
225
+ // The "Flag a bug" annotator rides with the presenter (the human surface) unless explicitly off.
226
+ if (options.annotate ?? options.present !== false) {
227
+ const presenter = this.#presenter;
228
+ this.#annotator = new Annotator({
229
+ emit,
230
+ now: () => Date.now(),
231
+ // Echo the flag into the live panel so the human watches their bug report land in the log.
232
+ onMark: (note, label) => presenter?.log(LOG_KIND.HUMAN, `🚩 ${label}: ${note}`),
233
+ });
234
+ this.#annotator.mount();
235
+ }
236
+ this.#transport.connect();
237
+ this.#connected = true;
238
+ }
239
+ /** Whether the in-page SDK is connected to the bridge (read by createReticleEmitter, P5a). */
240
+ get connected() {
241
+ return this.#connected;
242
+ }
243
+ /** Surface an arbitrary app-domain observation the DOM can't express (plan/03 §7). */
244
+ signal(name, data = {}) {
245
+ this.#emit(EventType.SIGNAL, { name, data });
246
+ }
247
+ /** Report a framework/store state change the agent can observe and assert on. */
248
+ state(name, value) {
249
+ this.#emit(EventType.STATE_CHANGE, { name, value });
250
+ }
251
+ /** Advertise the app's testable surface so the agent learns it without reading source. */
252
+ describe(input) {
253
+ registerCapabilities(input);
254
+ }
255
+ /** Live-control: end the session programmatically from the host app (drives the panel to ended). */
256
+ endSession() {
257
+ this.#presenter?.setState(SessionState.ENDED);
258
+ }
259
+ disconnect() {
260
+ if (!this.#connected)
261
+ return;
262
+ for (const teardown of this.#teardowns)
263
+ teardown();
264
+ this.#teardowns = [];
265
+ this.#transport?.close();
266
+ this.#transport = undefined;
267
+ this.#overlay?.destroy();
268
+ this.#overlay = undefined;
269
+ this.#presenter?.sessionEnd(); // fade the border out before tearing the overlay down
270
+ this.#presenter?.destroy();
271
+ this.#presenter = undefined;
272
+ this.#recorder?.destroy();
273
+ this.#recorder = undefined;
274
+ this.#annotator?.destroy();
275
+ this.#annotator = undefined;
276
+ resetClock(); // restore any frozen timers
277
+ this.#connected = false;
278
+ }
279
+ #emit = (type, data, ref) => {
280
+ const event = {
281
+ t: Math.round(performance.now() - this.#start),
282
+ type,
283
+ sessionId: this.#session,
284
+ ref,
285
+ data,
286
+ };
287
+ this.#transport?.sendEvent(event);
288
+ this.#eventCount += 1;
289
+ this.#overlay?.update({ connected: true, events: this.#eventCount });
290
+ // On a route change, re-scope the HUD's replay-flow chips to the page we're now on.
291
+ if (type === EventType.ROUTE_CHANGE)
292
+ this.#presenter?.refilterFlows();
293
+ };
294
+ #hello() {
295
+ return {
296
+ kind: MessageKind.HELLO,
297
+ protocolVersion: RETICLE_PROTOCOL_VERSION,
298
+ sessionId: this.#session,
299
+ ...(this.#projectId === undefined ? {} : { projectId: this.#projectId }),
300
+ url: location.href,
301
+ title: document.title,
302
+ adapters: adapterNames(),
303
+ ...(this.#token === undefined ? {} : { token: this.#token }),
304
+ hasCapabilities: hasCapabilities(),
305
+ };
306
+ }
307
+ async #handleCommand(command) {
308
+ // NARRATE: the agent tells the human what it's about to do / decide (presenter HUD).
309
+ if (command.name === ReticleCommand.NARRATE) {
310
+ this.#presenter?.sessionStart(); // first agent activity → reveal the glow + panel
311
+ this.#presenter?.narrate(str(command.args['text']), str(command.args['level'], 'info'));
312
+ return { ok: true, result: { shown: this.#presenter !== undefined } };
313
+ }
314
+ // SESSION_CONFIG: the agent tunes the session for the app (currently the idle-end window).
315
+ if (command.name === ReticleCommand.SESSION_CONFIG) {
316
+ const idleEndMs = command.args['idleEndMs'];
317
+ if (typeof idleEndMs === 'number')
318
+ this.#presenter?.setIdleEndMs(idleEndMs);
319
+ return { ok: true, result: { applied: this.#presenter !== undefined, idleEndMs } };
320
+ }
321
+ // Bridge → browser presenter pushes (PRESENTER state echo / FLOWS replay list). The presenter owns
322
+ // the parsing; here we only report whether a panel was mounted to apply it. setState-only, so a
323
+ // PRESENTER echo of a HUMAN_CONTROL can't loop back into a re-emit.
324
+ if (command.name === ReticleCommand.PRESENTER || command.name === ReticleCommand.FLOWS) {
325
+ this.#presenter?.handlePush(command);
326
+ return { ok: true, result: { applied: this.#presenter !== undefined } };
327
+ }
328
+ const handler = this.#registry.get(command.name);
329
+ if (handler === undefined) {
330
+ return { ok: false, error: `unknown command '${command.name}'` };
331
+ }
332
+ this.#presenter?.sessionStart(); // first agent command → reveal the glow + panel
333
+ await this.#presentBefore(command);
334
+ try {
335
+ const result = await handler(command.args);
336
+ this.#actHandle?.result(LOG_RESULT.PASS);
337
+ return { ok: true, result };
338
+ }
339
+ catch (error) {
340
+ this.#actHandle?.result(LOG_RESULT.FAIL);
341
+ return { ok: false, error: error instanceof Error ? error.message : String(error) };
342
+ }
343
+ finally {
344
+ this.#actHandle = undefined;
345
+ this.#presenter?.scheduleIdle();
346
+ }
347
+ }
348
+ /** Drive the presenter (cursor/effects/status) before the real action runs. */
349
+ async #presentBefore(command) {
350
+ const p = this.#presenter;
351
+ if (p === undefined)
352
+ return;
353
+ p.setMode(modeForCommand(command.name)); // paint reading vs acting intent first
354
+ this.#actHandle = undefined;
355
+ if (command.name === ReticleCommand.ACT) {
356
+ const ref = str(command.args['ref']);
357
+ const label = refLabel(ref);
358
+ this.#actHandle = p.log(LOG_KIND.ACT, `${actionVerb(str(command.args['action']))} ${label}`);
359
+ await p.beforeAct(ref, str(command.args['action']), label);
360
+ }
361
+ else if (command.name === ReticleCommand.ACT_SEQUENCE) {
362
+ const steps = Array.isArray(command.args['steps']) ? command.args['steps'] : [];
363
+ for (const step of steps) {
364
+ const s = step;
365
+ const ref = str(s.ref);
366
+ const label = refLabel(ref);
367
+ // one log row per step; the last handle carries the sequence outcome glyph
368
+ this.#actHandle = p.log(LOG_KIND.ACT, `${actionVerb(str(s.action))} ${label}`);
369
+ await p.beforeAct(ref, str(s.action), label);
370
+ }
371
+ }
372
+ else {
373
+ const label = presentStatus(command.name, command.args);
374
+ p.status(label);
375
+ p.log(LOG_KIND.READ, label);
376
+ }
377
+ }
378
+ }
379
+ //# sourceMappingURL=reticle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reticle.js","sourceRoot":"","sources":["../src/reticle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import { EventType } from '@reticlehq/core';
2
+ /**
3
+ * The human "annotate the bug where you see it" surface. A dev toggles annotate mode, clicks the
4
+ * element that looks wrong, types what's wrong, and Reticle pins a numbered marker + emits a HUMAN_MARK
5
+ * event the agent drains (reticle_review). The mark carries the element's re-resolvable anchor and —
6
+ * when available — the source file:line, so the agent fixes the exact element/code, not a guess.
7
+ *
8
+ * Self-contained and dev-only: every node carries a `data-reticle-mark` attribute so Reticle's own
9
+ * observers ignore it (see dom-ignore.ts), and clicks on its own UI never become marks.
10
+ */
11
+ /** Injected so the SDK wires the real emit/clock and tests can drive both. */
12
+ export interface AnnotatorDeps {
13
+ emit: (type: EventType, data: Record<string, unknown>) => void;
14
+ now: () => number;
15
+ /**
16
+ * Optional: called after a mark is sent so the SDK can echo it into the live presenter panel — the
17
+ * human sees their flag land in the same activity log they watch the agent in. No-op when the
18
+ * presenter isn't mounted.
19
+ */
20
+ onMark?: (note: string, label: string) => void;
21
+ }
22
+ export declare class Annotator {
23
+ #private;
24
+ constructor(deps: AnnotatorDeps);
25
+ /** Whether annotate mode is currently capturing clicks. */
26
+ get active(): boolean;
27
+ /** Number of marks sent this session (drives the pin numbering). */
28
+ get markCount(): number;
29
+ mount(): void;
30
+ destroy(): void;
31
+ /** Turn annotate mode on/off. With no argument, flips the current state. */
32
+ toggle(on?: boolean): void;
33
+ }
34
+ /** Construct + mount the annotator (mirrors installRecorder's ergonomics). */
35
+ export declare function installAnnotator(deps: AnnotatorDeps): Annotator;
36
+ //# sourceMappingURL=annotator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"annotator.d.ts","sourceRoot":"","sources":["../../src/review/annotator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAO5C;;;;;;;;GAQG;AAEH,8EAA8E;AAC9E,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC/D,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB;;;;OAIG;IACH,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAChD;AAkDD,qBAAa,SAAS;;gBAkBR,IAAI,EAAE,aAAa;IAM/B,2DAA2D;IAC3D,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,oEAAoE;IACpE,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,KAAK,IAAI,IAAI;IAuCb,OAAO,IAAI,IAAI;IA0Bf,4EAA4E;IAC5E,MAAM,CAAC,EAAE,CAAC,EAAE,OAAO,GAAG,IAAI;CA4J3B;AAgBD,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,aAAa,GAAG,SAAS,CAI/D"}