@reticlehq/browser 2.2.1 → 2.3.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 (271) hide show
  1. package/dist/actions/actions-dom.d.ts +0 -1
  2. package/dist/actions/actions-dom.js +0 -1
  3. package/dist/actions/actions.d.ts +3 -1
  4. package/dist/actions/actions.js +55 -36
  5. package/dist/actions/scroll.d.ts +0 -1
  6. package/dist/actions/scroll.js +0 -1
  7. package/dist/actions/value-input.d.ts +33 -0
  8. package/dist/actions/value-input.js +63 -0
  9. package/dist/commands/commands.d.ts +0 -1
  10. package/dist/commands/commands.js +15 -7
  11. package/dist/dom/a11y.d.ts +0 -2
  12. package/dist/dom/a11y.js +54 -24
  13. package/dist/dom/auto-anchor.d.ts +0 -1
  14. package/dist/dom/auto-anchor.js +0 -1
  15. package/dist/dom/blind-spots.d.ts +0 -1
  16. package/dist/dom/blind-spots.js +0 -1
  17. package/dist/dom/chart.d.ts +0 -1
  18. package/dist/dom/chart.js +0 -1
  19. package/dist/dom/desktop-capture.d.ts +36 -0
  20. package/dist/dom/desktop-capture.js +113 -0
  21. package/dist/dom/dom-ignore.d.ts +7 -1
  22. package/dist/dom/dom-ignore.js +1 -2
  23. package/dist/dom/occlusion.d.ts +0 -1
  24. package/dist/dom/occlusion.js +0 -1
  25. package/dist/dom/query.d.ts +0 -1
  26. package/dist/dom/query.js +61 -13
  27. package/dist/dom/realm.d.ts +30 -0
  28. package/dist/dom/realm.js +58 -0
  29. package/dist/dom/refs.d.ts +0 -1
  30. package/dist/dom/refs.js +0 -1
  31. package/dist/dom/shadow-registry.d.ts +40 -0
  32. package/dist/dom/shadow-registry.js +165 -0
  33. package/dist/dom/snapshot.d.ts +2 -2
  34. package/dist/dom/snapshot.js +21 -4
  35. package/dist/dom/source.d.ts +0 -1
  36. package/dist/dom/source.js +0 -1
  37. package/dist/dom/theme.d.ts +0 -1
  38. package/dist/dom/theme.js +0 -1
  39. package/dist/dom/virtualized.d.ts +19 -0
  40. package/dist/dom/virtualized.js +80 -0
  41. package/dist/index.d.ts +0 -1
  42. package/dist/index.js +0 -1
  43. package/dist/observers/animation.d.ts +0 -1
  44. package/dist/observers/animation.js +0 -1
  45. package/dist/observers/blind-spots.d.ts +16 -4
  46. package/dist/observers/blind-spots.js +65 -11
  47. package/dist/observers/console.d.ts +0 -1
  48. package/dist/observers/console.js +0 -1
  49. package/dist/observers/dom.d.ts +0 -2
  50. package/dist/observers/dom.js +67 -9
  51. package/dist/observers/download.d.ts +6 -0
  52. package/dist/observers/download.js +103 -0
  53. package/dist/observers/focus.d.ts +0 -1
  54. package/dist/observers/focus.js +0 -1
  55. package/dist/observers/frames.d.ts +12 -0
  56. package/dist/observers/frames.js +67 -0
  57. package/dist/observers/health.d.ts +0 -1
  58. package/dist/observers/health.js +30 -2
  59. package/dist/observers/install-all.d.ts +5 -0
  60. package/dist/observers/install-all.js +63 -0
  61. package/dist/observers/ipc.d.ts +22 -0
  62. package/dist/observers/ipc.js +121 -0
  63. package/dist/observers/network-body.d.ts +17 -1
  64. package/dist/observers/network-body.js +26 -1
  65. package/dist/observers/network-redact.d.ts +0 -1
  66. package/dist/observers/network-redact.js +6 -3
  67. package/dist/observers/network-stream.d.ts +23 -0
  68. package/dist/observers/network-stream.js +102 -0
  69. package/dist/observers/network.d.ts +11 -1
  70. package/dist/observers/network.js +7 -1
  71. package/dist/observers/perf.d.ts +0 -1
  72. package/dist/observers/perf.js +0 -1
  73. package/dist/observers/route.d.ts +0 -1
  74. package/dist/observers/route.js +0 -1
  75. package/dist/observers/scroll.d.ts +0 -1
  76. package/dist/observers/scroll.js +0 -1
  77. package/dist/observers/sdk-failure.d.ts +28 -0
  78. package/dist/observers/sdk-failure.js +60 -0
  79. package/dist/observers/state.d.ts +0 -1
  80. package/dist/observers/state.js +0 -1
  81. package/dist/observers/storage.d.ts +0 -1
  82. package/dist/observers/storage.js +0 -1
  83. package/dist/observers/types.d.ts +0 -1
  84. package/dist/observers/types.js +0 -1
  85. package/dist/patching/capture-method.d.ts +0 -1
  86. package/dist/patching/capture-method.js +0 -1
  87. package/dist/presenter/overlay.d.ts +0 -1
  88. package/dist/presenter/overlay.js +0 -1
  89. package/dist/presenter/presenter-config.d.ts +0 -1
  90. package/dist/presenter/presenter-config.js +0 -1
  91. package/dist/presenter/presenter-controls.d.ts +0 -1
  92. package/dist/presenter/presenter-controls.js +0 -1
  93. package/dist/presenter/presenter-effects.d.ts +0 -1
  94. package/dist/presenter/presenter-effects.js +0 -1
  95. package/dist/presenter/presenter-glow.d.ts +0 -1
  96. package/dist/presenter/presenter-glow.js +0 -1
  97. package/dist/presenter/presenter-log.d.ts +0 -1
  98. package/dist/presenter/presenter-log.js +0 -1
  99. package/dist/presenter/presenter-run-state.d.ts +0 -1
  100. package/dist/presenter/presenter-run-state.js +0 -1
  101. package/dist/presenter/presenter-styles.d.ts +0 -1
  102. package/dist/presenter/presenter-styles.js +0 -1
  103. package/dist/presenter/presenter-tally.d.ts +0 -1
  104. package/dist/presenter/presenter-tally.js +0 -1
  105. package/dist/presenter/presenter-test-helpers.d.ts +0 -1
  106. package/dist/presenter/presenter-test-helpers.js +0 -1
  107. package/dist/presenter/presenter-verbs.d.ts +0 -1
  108. package/dist/presenter/presenter-verbs.js +0 -1
  109. package/dist/presenter/presenter.d.ts +0 -1
  110. package/dist/presenter/presenter.js +0 -1
  111. package/dist/recorder/recorder-styles.d.ts +0 -1
  112. package/dist/recorder/recorder-styles.js +0 -1
  113. package/dist/recorder/recorder.d.ts +0 -1
  114. package/dist/recorder/recorder.js +0 -1
  115. package/dist/registry/adapters.d.ts +0 -1
  116. package/dist/registry/adapters.js +0 -1
  117. package/dist/registry/capabilities.d.ts +0 -1
  118. package/dist/registry/capabilities.js +0 -1
  119. package/dist/registry/commit-and-signal.d.ts +0 -1
  120. package/dist/registry/commit-and-signal.js +0 -1
  121. package/dist/registry/domains.d.ts +0 -1
  122. package/dist/registry/domains.js +0 -1
  123. package/dist/registry/emitter.d.ts +0 -1
  124. package/dist/registry/emitter.js +0 -1
  125. package/dist/registry/store-adapters.d.ts +14 -6
  126. package/dist/registry/store-adapters.js +0 -1
  127. package/dist/registry/stores.d.ts +0 -1
  128. package/dist/registry/stores.js +8 -1
  129. package/dist/reticle-presenter-helpers.d.ts +0 -1
  130. package/dist/reticle-presenter-helpers.js +0 -1
  131. package/dist/reticle.d.ts +3 -2
  132. package/dist/reticle.js +10 -31
  133. package/dist/review/annotator.d.ts +0 -1
  134. package/dist/review/annotator.js +0 -1
  135. package/dist/review/mark-anchor.d.ts +0 -1
  136. package/dist/review/mark-anchor.js +0 -1
  137. package/dist/security/serialization.d.ts +0 -1
  138. package/dist/security/serialization.js +0 -1
  139. package/dist/timers/clock.d.ts +0 -1
  140. package/dist/timers/clock.js +0 -1
  141. package/dist/timers/native-console.d.ts +0 -1
  142. package/dist/timers/native-console.js +0 -1
  143. package/dist/timers/native-timers.d.ts +0 -1
  144. package/dist/timers/native-timers.js +0 -1
  145. package/dist/transport/transport.d.ts +2 -6
  146. package/dist/transport/transport.js +93 -17
  147. package/package.json +8 -3
  148. package/dist/actions/actions-dom.d.ts.map +0 -1
  149. package/dist/actions/actions-dom.js.map +0 -1
  150. package/dist/actions/actions.d.ts.map +0 -1
  151. package/dist/actions/actions.js.map +0 -1
  152. package/dist/actions/scroll.d.ts.map +0 -1
  153. package/dist/actions/scroll.js.map +0 -1
  154. package/dist/commands/commands.d.ts.map +0 -1
  155. package/dist/commands/commands.js.map +0 -1
  156. package/dist/dom/a11y.d.ts.map +0 -1
  157. package/dist/dom/a11y.js.map +0 -1
  158. package/dist/dom/auto-anchor.d.ts.map +0 -1
  159. package/dist/dom/auto-anchor.js.map +0 -1
  160. package/dist/dom/blind-spots.d.ts.map +0 -1
  161. package/dist/dom/blind-spots.js.map +0 -1
  162. package/dist/dom/chart.d.ts.map +0 -1
  163. package/dist/dom/chart.js.map +0 -1
  164. package/dist/dom/dom-ignore.d.ts.map +0 -1
  165. package/dist/dom/dom-ignore.js.map +0 -1
  166. package/dist/dom/occlusion.d.ts.map +0 -1
  167. package/dist/dom/occlusion.js.map +0 -1
  168. package/dist/dom/query.d.ts.map +0 -1
  169. package/dist/dom/query.js.map +0 -1
  170. package/dist/dom/refs.d.ts.map +0 -1
  171. package/dist/dom/refs.js.map +0 -1
  172. package/dist/dom/snapshot.d.ts.map +0 -1
  173. package/dist/dom/snapshot.js.map +0 -1
  174. package/dist/dom/source.d.ts.map +0 -1
  175. package/dist/dom/source.js.map +0 -1
  176. package/dist/dom/theme.d.ts.map +0 -1
  177. package/dist/dom/theme.js.map +0 -1
  178. package/dist/index.d.ts.map +0 -1
  179. package/dist/index.js.map +0 -1
  180. package/dist/observers/animation.d.ts.map +0 -1
  181. package/dist/observers/animation.js.map +0 -1
  182. package/dist/observers/blind-spots.d.ts.map +0 -1
  183. package/dist/observers/blind-spots.js.map +0 -1
  184. package/dist/observers/console.d.ts.map +0 -1
  185. package/dist/observers/console.js.map +0 -1
  186. package/dist/observers/dom.d.ts.map +0 -1
  187. package/dist/observers/dom.js.map +0 -1
  188. package/dist/observers/focus.d.ts.map +0 -1
  189. package/dist/observers/focus.js.map +0 -1
  190. package/dist/observers/health.d.ts.map +0 -1
  191. package/dist/observers/health.js.map +0 -1
  192. package/dist/observers/network-body.d.ts.map +0 -1
  193. package/dist/observers/network-body.js.map +0 -1
  194. package/dist/observers/network-redact.d.ts.map +0 -1
  195. package/dist/observers/network-redact.js.map +0 -1
  196. package/dist/observers/network.d.ts.map +0 -1
  197. package/dist/observers/network.js.map +0 -1
  198. package/dist/observers/perf.d.ts.map +0 -1
  199. package/dist/observers/perf.js.map +0 -1
  200. package/dist/observers/route.d.ts.map +0 -1
  201. package/dist/observers/route.js.map +0 -1
  202. package/dist/observers/scroll.d.ts.map +0 -1
  203. package/dist/observers/scroll.js.map +0 -1
  204. package/dist/observers/state.d.ts.map +0 -1
  205. package/dist/observers/state.js.map +0 -1
  206. package/dist/observers/storage.d.ts.map +0 -1
  207. package/dist/observers/storage.js.map +0 -1
  208. package/dist/observers/types.d.ts.map +0 -1
  209. package/dist/observers/types.js.map +0 -1
  210. package/dist/patching/capture-method.d.ts.map +0 -1
  211. package/dist/patching/capture-method.js.map +0 -1
  212. package/dist/presenter/overlay.d.ts.map +0 -1
  213. package/dist/presenter/overlay.js.map +0 -1
  214. package/dist/presenter/presenter-config.d.ts.map +0 -1
  215. package/dist/presenter/presenter-config.js.map +0 -1
  216. package/dist/presenter/presenter-controls.d.ts.map +0 -1
  217. package/dist/presenter/presenter-controls.js.map +0 -1
  218. package/dist/presenter/presenter-effects.d.ts.map +0 -1
  219. package/dist/presenter/presenter-effects.js.map +0 -1
  220. package/dist/presenter/presenter-glow.d.ts.map +0 -1
  221. package/dist/presenter/presenter-glow.js.map +0 -1
  222. package/dist/presenter/presenter-log.d.ts.map +0 -1
  223. package/dist/presenter/presenter-log.js.map +0 -1
  224. package/dist/presenter/presenter-run-state.d.ts.map +0 -1
  225. package/dist/presenter/presenter-run-state.js.map +0 -1
  226. package/dist/presenter/presenter-styles.d.ts.map +0 -1
  227. package/dist/presenter/presenter-styles.js.map +0 -1
  228. package/dist/presenter/presenter-tally.d.ts.map +0 -1
  229. package/dist/presenter/presenter-tally.js.map +0 -1
  230. package/dist/presenter/presenter-test-helpers.d.ts.map +0 -1
  231. package/dist/presenter/presenter-test-helpers.js.map +0 -1
  232. package/dist/presenter/presenter-verbs.d.ts.map +0 -1
  233. package/dist/presenter/presenter-verbs.js.map +0 -1
  234. package/dist/presenter/presenter.d.ts.map +0 -1
  235. package/dist/presenter/presenter.js.map +0 -1
  236. package/dist/recorder/recorder-styles.d.ts.map +0 -1
  237. package/dist/recorder/recorder-styles.js.map +0 -1
  238. package/dist/recorder/recorder.d.ts.map +0 -1
  239. package/dist/recorder/recorder.js.map +0 -1
  240. package/dist/registry/adapters.d.ts.map +0 -1
  241. package/dist/registry/adapters.js.map +0 -1
  242. package/dist/registry/capabilities.d.ts.map +0 -1
  243. package/dist/registry/capabilities.js.map +0 -1
  244. package/dist/registry/commit-and-signal.d.ts.map +0 -1
  245. package/dist/registry/commit-and-signal.js.map +0 -1
  246. package/dist/registry/domains.d.ts.map +0 -1
  247. package/dist/registry/domains.js.map +0 -1
  248. package/dist/registry/emitter.d.ts.map +0 -1
  249. package/dist/registry/emitter.js.map +0 -1
  250. package/dist/registry/store-adapters.d.ts.map +0 -1
  251. package/dist/registry/store-adapters.js.map +0 -1
  252. package/dist/registry/stores.d.ts.map +0 -1
  253. package/dist/registry/stores.js.map +0 -1
  254. package/dist/reticle-presenter-helpers.d.ts.map +0 -1
  255. package/dist/reticle-presenter-helpers.js.map +0 -1
  256. package/dist/reticle.d.ts.map +0 -1
  257. package/dist/reticle.js.map +0 -1
  258. package/dist/review/annotator.d.ts.map +0 -1
  259. package/dist/review/annotator.js.map +0 -1
  260. package/dist/review/mark-anchor.d.ts.map +0 -1
  261. package/dist/review/mark-anchor.js.map +0 -1
  262. package/dist/security/serialization.d.ts.map +0 -1
  263. package/dist/security/serialization.js.map +0 -1
  264. package/dist/timers/clock.d.ts.map +0 -1
  265. package/dist/timers/clock.js.map +0 -1
  266. package/dist/timers/native-console.d.ts.map +0 -1
  267. package/dist/timers/native-console.js.map +0 -1
  268. package/dist/timers/native-timers.d.ts.map +0 -1
  269. package/dist/timers/native-timers.js.map +0 -1
  270. package/dist/transport/transport.d.ts.map +0 -1
  271. package/dist/transport/transport.js.map +0 -1
@@ -66,4 +66,3 @@ export function installScroll(emit) {
66
66
  io?.disconnect();
67
67
  };
68
68
  }
69
- //# sourceMappingURL=scroll.js.map
@@ -0,0 +1,28 @@
1
+ import type { Emit } from './types.js';
2
+ /**
3
+ * Where in the SDK a failure happened. A fixed vocabulary of OUR module names — never a file path,
4
+ * never anything derived from the user's app — so the field stays low-cardinality and non-identifying
5
+ * while still telling a maintainer which subsystem to open.
6
+ */
7
+ export declare const SdkSite: {
8
+ readonly CONNECT: "connect";
9
+ readonly DOM_OBSERVER: "dom_observer";
10
+ readonly NETWORK_OBSERVER: "network_observer";
11
+ readonly CONSOLE_OBSERVER: "console_observer";
12
+ readonly IPC_OBSERVER: "ipc_observer";
13
+ readonly HEALTH_OBSERVER: "health_observer";
14
+ readonly ROUTER_OBSERVER: "router_observer";
15
+ readonly ANIMATION_OBSERVER: "animation_observer";
16
+ readonly STORE_ADAPTER: "store_adapter";
17
+ readonly SNAPSHOT: "snapshot";
18
+ readonly ACTION: "action";
19
+ readonly COMMAND: "command";
20
+ readonly RECORDER: "recorder";
21
+ readonly TRANSPORT: "transport";
22
+ };
23
+ export type SdkSite = (typeof SdkSite)[keyof typeof SdkSite];
24
+ /**
25
+ * Report that a piece of the SDK failed. Never throws, and never prevents the caller from doing what
26
+ * it was going to do anyway (which is almost always: carry on degraded).
27
+ */
28
+ export declare function reportSdkFailure(emit: Emit, site: SdkSite, error: unknown): void;
@@ -0,0 +1,60 @@
1
+ /**
2
+ * The SDK reporting its OWN failures.
3
+ *
4
+ * Half of Reticle runs inside the page, and that half was completely silent. Every `catch` in the SDK
5
+ * swallows by design — correctly, because an instrumentation layer must never break the app it
6
+ * observes — but the consequence was that an observer throwing on page load just produced a quieter
7
+ * product. No error, no signal, no way to know. A user would report "Reticle doesn't see my network
8
+ * calls" and there would be nothing on our side to look at.
9
+ *
10
+ * Two properties make this safe to add:
11
+ *
12
+ * 1. IT MAKES NO NETWORK REQUEST. The report rides the bridge WebSocket the SDK is already connected
13
+ * to — localhost, the same channel every other event uses. The published promise that the SDK
14
+ * talks only to a local bridge stays exactly true, and the daemon decides what (if anything) goes
15
+ * anywhere else. Adding an outbound call from inside someone's app would have been a different
16
+ * product with a different privacy posture.
17
+ * 2. IT CANNOT BREAK THE APP. Reporting is wrapped in its own try/catch and is strictly additive to
18
+ * an existing `catch` block. A failure to report a failure is discarded.
19
+ */
20
+ import { EventType } from '@reticlehq/core';
21
+ /**
22
+ * Where in the SDK a failure happened. A fixed vocabulary of OUR module names — never a file path,
23
+ * never anything derived from the user's app — so the field stays low-cardinality and non-identifying
24
+ * while still telling a maintainer which subsystem to open.
25
+ */
26
+ export const SdkSite = {
27
+ CONNECT: 'connect',
28
+ DOM_OBSERVER: 'dom_observer',
29
+ NETWORK_OBSERVER: 'network_observer',
30
+ CONSOLE_OBSERVER: 'console_observer',
31
+ IPC_OBSERVER: 'ipc_observer',
32
+ HEALTH_OBSERVER: 'health_observer',
33
+ ROUTER_OBSERVER: 'router_observer',
34
+ ANIMATION_OBSERVER: 'animation_observer',
35
+ STORE_ADAPTER: 'store_adapter',
36
+ SNAPSHOT: 'snapshot',
37
+ ACTION: 'action',
38
+ COMMAND: 'command',
39
+ RECORDER: 'recorder',
40
+ TRANSPORT: 'transport',
41
+ };
42
+ /** Cap the message here too — the server strips variables, but an unbounded string is a bad idea twice. */
43
+ const MAX_MESSAGE = 500;
44
+ /**
45
+ * Report that a piece of the SDK failed. Never throws, and never prevents the caller from doing what
46
+ * it was going to do anyway (which is almost always: carry on degraded).
47
+ */
48
+ export function reportSdkFailure(emit, site, error) {
49
+ try {
50
+ const message = error instanceof Error ? error.message : String(error);
51
+ emit(EventType.SDK_FAILED, {
52
+ site,
53
+ message: message.slice(0, MAX_MESSAGE),
54
+ ...(error instanceof Error ? { errorType: error.constructor.name.slice(0, 64) } : {}),
55
+ });
56
+ }
57
+ catch {
58
+ /* a failure report must never become a second failure */
59
+ }
60
+ }
@@ -17,4 +17,3 @@ export declare function diffState(prev: unknown, next: unknown): StateChange[];
17
17
  */
18
18
  export declare function installStoreState(emit: Emit): Teardown;
19
19
  export {};
20
- //# sourceMappingURL=state.d.ts.map
@@ -84,4 +84,3 @@ export function installStoreState(emit) {
84
84
  active.clear();
85
85
  };
86
86
  }
87
- //# sourceMappingURL=state.js.map
@@ -20,4 +20,3 @@ export declare function readStorage(area?: string): StorageSnapshot | Record<str
20
20
  * method access) and re-dispatched via `.call(this)`. Fully reversible; values redacted like the reads.
21
21
  */
22
22
  export declare function installStorage(emit: Emit): Teardown;
23
- //# sourceMappingURL=storage.d.ts.map
@@ -174,4 +174,3 @@ export function installStorage(emit) {
174
174
  proto.clear = origClear;
175
175
  };
176
176
  }
177
- //# sourceMappingURL=storage.js.map
@@ -18,4 +18,3 @@ export type Teardown = () => void;
18
18
  export declare function observeSafely(observation: () => void): void;
19
19
  /** Like observeSafely, but for reading a value the observation needs; undefined if the read throws. */
20
20
  export declare function observeValue<T>(read: () => T): T | undefined;
21
- //# sourceMappingURL=types.d.ts.map
@@ -27,4 +27,3 @@ export function observeValue(read) {
27
27
  return undefined;
28
28
  }
29
29
  }
30
- //# sourceMappingURL=types.js.map
@@ -24,4 +24,3 @@ export declare function captureMethod<T, K extends keyof T>(target: T, key: K):
24
24
  * `set` is an unbound function, and naming that intention once beats disabling the rule at each use.
25
25
  */
26
26
  export declare function captureValueSetter(proto: object): ((this: HTMLElement, value: string) => void) | undefined;
27
- //# sourceMappingURL=capture-method.d.ts.map
@@ -34,4 +34,3 @@ export function captureValueSetter(proto) {
34
34
  const setter = captureMethod(descriptor, 'set');
35
35
  return setter;
36
36
  }
37
- //# sourceMappingURL=capture-method.js.map
@@ -9,4 +9,3 @@ export interface OverlayHandle {
9
9
  /** A tiny in-page status chip: connection + event count. Off by default. */
10
10
  export declare function installOverlay(): OverlayHandle;
11
11
  export {};
12
- //# sourceMappingURL=overlay.d.ts.map
@@ -28,4 +28,3 @@ export function installOverlay() {
28
28
  },
29
29
  };
30
30
  }
31
- //# sourceMappingURL=overlay.js.map
@@ -83,4 +83,3 @@ export declare const DATA_ON = "data-on";
83
83
  /** Overlay-root attribute toggled when the panel is minimised to a bar. */
84
84
  export declare const MIN_ATTR = "data-reticle-min";
85
85
  export declare const THROTTLED_ATTR = "data-reticle-throttled";
86
- //# sourceMappingURL=presenter-config.d.ts.map
@@ -48,4 +48,3 @@ export const DATA_ON = 'data-on';
48
48
  /** Overlay-root attribute toggled when the panel is minimised to a bar. */
49
49
  export const MIN_ATTR = 'data-reticle-min';
50
50
  export const THROTTLED_ATTR = 'data-reticle-throttled';
51
- //# sourceMappingURL=presenter-config.js.map
@@ -71,4 +71,3 @@ export declare class ControlPanel {
71
71
  setState(state: SessionState, text?: string, tone?: PresenterTone): void;
72
72
  }
73
73
  export { DATA_RETICLE_STATE };
74
- //# sourceMappingURL=presenter-controls.d.ts.map
@@ -365,4 +365,3 @@ export class ControlPanel {
365
365
  }
366
366
  }
367
367
  export { DATA_RETICLE_STATE };
368
- //# sourceMappingURL=presenter-controls.js.map
@@ -11,4 +11,3 @@ export declare function ringAround(ring: HTMLElement | undefined, rect: DOMRect)
11
11
  export declare function spawnRipple(root: HTMLElement | undefined, x: number, y: number): void;
12
12
  /** Pace for the human so an action is watchable, not instant. */
13
13
  export declare function pace(ms: number): Promise<void>;
14
- //# sourceMappingURL=presenter-effects.d.ts.map
@@ -37,4 +37,3 @@ export function spawnRipple(root, x, y) {
37
37
  export function pace(ms) {
38
38
  return new Promise((res) => nativeSetTimeout(res, ms));
39
39
  }
40
- //# sourceMappingURL=presenter-effects.js.map
@@ -40,4 +40,3 @@ export declare class GlowController {
40
40
  teardown(): void;
41
41
  }
42
42
  export {};
43
- //# sourceMappingURL=presenter-glow.d.ts.map
@@ -123,4 +123,3 @@ export class GlowController {
123
123
  }, this.#glowFadeMs);
124
124
  }
125
125
  }
126
- //# sourceMappingURL=presenter-glow.js.map
@@ -40,4 +40,3 @@ export declare function formatElapsed(ms: number): string;
40
40
  * Uses createElement/textContent (never innerHTML) so arbitrary narration text can't inject markup.
41
41
  */
42
42
  export declare function appendLogRow(container: HTMLElement, kind: LogKind, text: string, ts: string, logMax: number): LogHandle;
43
- //# sourceMappingURL=presenter-log.d.ts.map
@@ -115,4 +115,3 @@ export function appendLogRow(container, kind, text, ts, logMax) {
115
115
  },
116
116
  };
117
117
  }
118
- //# sourceMappingURL=presenter-log.js.map
@@ -45,4 +45,3 @@ interface RunStateInput {
45
45
  */
46
46
  export declare function buildRunState(input: RunStateInput): PresenterRunState;
47
47
  export {};
48
- //# sourceMappingURL=presenter-run-state.d.ts.map
@@ -34,4 +34,3 @@ export function buildRunState(input) {
34
34
  log: input.runLog.map((e) => ({ ...e })),
35
35
  };
36
36
  }
37
- //# sourceMappingURL=presenter-run-state.js.map
@@ -4,4 +4,3 @@
4
4
  * pure style data (no behavior). LOG_CSS + CONTROLS_CSS are composed in at the end as before.
5
5
  */
6
6
  export declare const PRESENTER_CSS = "\n[data-reticle-glow]{position:fixed;inset:0;pointer-events:none;z-index:2147483600;opacity:0;\n transition:opacity .25s ease;box-shadow:inset 0 0 0 3px rgba(99,102,241,.9),inset 0 0 28px 6px rgba(99,102,241,.45);}\n[data-reticle-glow][data-on=\"1\"]{opacity:1;animation:reticle-pulse 1.6s ease-in-out infinite;}\n[data-reticle-glow][data-on=\"1\"][data-busy=\"1\"]{animation:reticle-shimmer 1.1s ease-in-out infinite;}\n@keyframes reticle-pulse{0%,100%{box-shadow:inset 0 0 0 3px rgba(99,102,241,.9),inset 0 0 22px 4px rgba(99,102,241,.35)}\n 50%{box-shadow:inset 0 0 0 3px rgba(124,127,242,1),inset 0 0 40px 10px rgba(99,102,241,.6)}}\n@keyframes reticle-shimmer{0%,100%{box-shadow:inset 0 0 0 3px rgba(124,127,242,1),inset 0 0 34px 8px rgba(99,102,241,.55)}\n 50%{box-shadow:inset 0 0 0 3px rgba(140,142,255,1),inset 0 0 48px 12px rgba(99,102,241,.7)}}\n[data-reticle-cursor]{position:fixed;top:0;left:0;width:22px;height:22px;margin:-11px 0 0 -11px;\n border:2px solid #6366f1;border-radius:50%;background:rgba(99,102,241,.25);pointer-events:none;\n z-index:2147483646;opacity:0;transition:transform .32s cubic-bezier(.22,1,.36,1),opacity .2s ease;}\n[data-reticle-cursor][data-on=\"1\"]{opacity:1;}\n[data-reticle-cursor]::after{content:\"\";position:absolute;inset:7px;border-radius:50%;background:#6366f1;}\n[data-reticle-ripple]{position:fixed;width:14px;height:14px;margin:-7px 0 0 -7px;border-radius:50%;\n background:rgba(99,102,241,.5);pointer-events:none;z-index:2147483645;animation:reticle-ripple .5s ease-out forwards;}\n@keyframes reticle-ripple{from{transform:scale(.4);opacity:.8}to{transform:scale(5);opacity:0}}\n[data-reticle-ring]{position:fixed;pointer-events:none;z-index:2147483644;border:2px solid #22c55e;border-radius:8px;\n box-shadow:0 0 0 3px rgba(34,197,94,.25);opacity:0;transition:opacity .15s ease;}\n[data-reticle-ring][data-on=\"1\"]{opacity:1;}\n[data-reticle-hud]{\n --reticle-accent:#7c83ff;--reticle-accent-soft:rgba(124,131,255,.16);\n --reticle-bg:rgba(13,15,22,.92);--reticle-bg2:rgba(19,22,32,.88);\n --reticle-fg:#e9ebf2;--reticle-muted:#9aa0b2;--reticle-faint:#6a7186;\n --reticle-line:rgba(255,255,255,.09);--reticle-line2:rgba(255,255,255,.05);\n --reticle-read:#54d2e6;--reticle-ok:#3dd7a6;--reticle-bad:#ff7a7a;\n --reticle-font:\"Inter\",system-ui,-apple-system,\"Segoe UI\",Roboto,\"Helvetica Neue\",Arial,sans-serif;\n --reticle-serif:\"IBM Plex Serif\",Georgia,\"Times New Roman\",serif;\n position:fixed;left:50%;right:auto;bottom:20px;box-sizing:border-box;\n width:384px;height:468px;max-width:calc(100vw - 32px);max-height:calc(100vh - 32px);\n display:flex;flex-direction:column;overflow:hidden;text-align:left;z-index:2147483647;pointer-events:none;\n font-family:var(--reticle-font);font-size:13px;line-height:1.5;color:var(--reticle-fg);-webkit-font-smoothing:antialiased;\n background:linear-gradient(180deg,var(--reticle-bg),var(--reticle-bg2));\n /* No backdrop-filter here, deliberately. blur(24px) on this panel was measured as the single most\n expensive thing the whole SDK does: a backdrop blur must re-sample everything behind it whenever\n that content changes, and on a page repainting at 60fps that is continuous full-panel work. On\n the hostile fixture it cost +4.0pp of main thread \u2014 five times the rest of the presenter, and\n more than every observer combined. Removing it took total main-thread time from 2.15s to 1.67s\n over an 8s window. The panel background is ~85% opaque, so the glass effect it bought was\n marginal. If you want it back, add it here and expect to pay that. */\n border:1px solid var(--reticle-line);border-radius:20px;\n box-shadow:0 28px 70px -18px rgba(0,0,0,.66),0 0 0 1px rgba(0,0,0,.35),inset 0 1px 0 rgba(255,255,255,.07),0 0 54px -22px var(--reticle-accent);\n opacity:0;transform:translateX(-50%) translateY(14px) scale(.985);\n transition:opacity .3s ease,transform .42s cubic-bezier(.16,1,.3,1),height .42s cubic-bezier(.16,1,.3,1),border-radius .42s ease,box-shadow .35s ease;}\n[data-reticle-overlay][data-reticle-state=\"paused\"] [data-reticle-hud]{--reticle-accent:#f6b44c;--reticle-accent-soft:rgba(246,180,76,.16);}\n[data-reticle-overlay][data-reticle-state=\"ended\"] [data-reticle-hud]{--reticle-accent:#3dd7a6;--reticle-accent-soft:rgba(61,215,166,.14);}\n[data-reticle-hud]::before{content:\"\";position:absolute;inset:0;border-radius:inherit;pointer-events:none;\n background:radial-gradient(130% 90% at 50% 0%,var(--reticle-accent-soft),transparent 60%);}\n[data-reticle-hud]>*{position:relative;}\n[data-reticle-hud][data-on=\"1\"]{opacity:1;transform:translateX(-50%) translateY(0) scale(1);}\n/* Click-through: the glassy panel itself never blocks the app \u2014 only its interactive controls\n capture clicks (buttons / inputs), so a human can click straight through the HUD to the page.\n The log auto-scrolls, so it stays click-through too (drag-scroll is traded for click-through). */\n[data-reticle-hud] button,[data-reticle-hud] input,[data-reticle-hud] textarea,\n[data-reticle-hud] select,[data-reticle-hud] [contenteditable]{pointer-events:auto;}\n/* When minimised to a pill, the whole bar is the (single) click target to restore. */\n[data-reticle-overlay][data-reticle-min=\"1\"] [data-reticle-hud][data-on=\"1\"]{pointer-events:auto;}\n[data-reticle-hud] .reticle-hud-head{display:flex;align-items:center;gap:8px;flex:none;\n padding:12px 12px 12px 15px;border-bottom:1px solid var(--reticle-line2);}\n[data-reticle-hud] .reticle-dot{width:9px;height:9px;border-radius:50%;flex:none;background:var(--reticle-accent);\n animation:reticle-breathe 2.6s ease-in-out infinite;}\n@keyframes reticle-breathe{0%,100%{box-shadow:0 0 0 0 var(--reticle-accent),0 0 7px 1px var(--reticle-accent);opacity:.85}\n 50%{box-shadow:0 0 0 4px var(--reticle-accent-soft),0 0 15px 3px var(--reticle-accent);opacity:1}}\n[data-reticle-hud] .reticle-brand{font-family:var(--reticle-serif);font-weight:500;font-size:15px;letter-spacing:.01em;color:var(--reticle-fg);}\n[data-reticle-hud] .reticle-head-sp{flex:1;}\n[data-reticle-hud] .reticle-live{display:none;flex:1;min-width:0;color:var(--reticle-muted);font-size:12.5px;\n white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}\n[data-reticle-hud] .reticle-maxhint{display:none;flex:none;color:var(--reticle-faint);font-size:13px;line-height:1;}\n[data-reticle-hud] .reticle-act-strip{flex:none;padding:7px 15px;border-bottom:1px solid var(--reticle-line2);background:rgba(0,0,0,.14);}\n[data-reticle-hud] .reticle-act{display:block;color:var(--reticle-muted);font-size:11.5px;\n white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}\n[data-reticle-hud] [data-reticle-min-btn]{flex:none;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;\n width:26px;height:26px;border-radius:8px;border:1px solid var(--reticle-line);background:rgba(255,255,255,.04);\n color:var(--reticle-muted);font-size:15px;line-height:1;transition:background .15s,color .15s,transform .1s;}\n[data-reticle-hud] [data-reticle-min-btn]:hover{color:var(--reticle-fg);background:rgba(255,255,255,.08);}\n[data-reticle-hud] [data-reticle-min-btn]:active{transform:scale(.94);}\n[data-reticle-hud] .reticle-pass{color:var(--reticle-ok);}[data-reticle-hud] .reticle-fail{color:var(--reticle-bad);}\n[data-reticle-hud] .reticle-tally{flex:none;display:inline-flex;align-items:center;gap:8px;font-size:11.5px;\n font-weight:600;font-variant-numeric:tabular-nums;letter-spacing:.01em;}\n[data-reticle-hud] .reticle-tally[hidden]{display:none;}\n[data-reticle-hud] .reticle-tally .reticle-t-pass{color:var(--reticle-ok);}\n[data-reticle-hud] .reticle-tally .reticle-t-fail{color:var(--reticle-bad);}\n[data-reticle-hud] .reticle-tally [data-z=\"1\"]{opacity:.4;}\n@keyframes reticle-tally-pop{0%{transform:scale(1)}38%{transform:scale(1.3)}100%{transform:scale(1)}}\n[data-reticle-hud] .reticle-tally [data-bump=\"1\"]{display:inline-block;animation:reticle-tally-pop .36s cubic-bezier(.16,1,.3,1);}\n[data-reticle-hud] .reticle-chip{display:none;flex:none;font-size:9px;font-weight:600;letter-spacing:.08em;\n padding:2px 7px;border-radius:6px;vertical-align:middle;}\n[data-reticle-hud] .reticle-chip[data-mode=\"reading\"]{display:inline-block;color:var(--reticle-read);\n background:rgba(84,210,230,.12);border:1px solid rgba(84,210,230,.32);}\n[data-reticle-hud] .reticle-chip[data-mode=\"acting\"]{display:inline-block;color:var(--reticle-accent);\n background:var(--reticle-accent-soft);border:1px solid var(--reticle-accent);}\n[data-reticle-hud] .reticle-chip[data-mode=\"idle\"]{display:none;}\n[data-reticle-overlay][data-reticle-min=\"1\"] [data-reticle-hud]{height:50px;border-radius:25px;cursor:pointer;}\n[data-reticle-overlay][data-reticle-min=\"1\"] [data-reticle-hud] .reticle-hud-head{border-bottom:none;height:50px;padding:0 12px 0 16px;}\n[data-reticle-overlay][data-reticle-min=\"1\"] [data-reticle-hud] .reticle-brand,\n[data-reticle-overlay][data-reticle-min=\"1\"] [data-reticle-hud] .reticle-chip,\n[data-reticle-overlay][data-reticle-min=\"1\"] [data-reticle-hud] .reticle-head-sp,\n[data-reticle-overlay][data-reticle-min=\"1\"] [data-reticle-hud] [data-reticle-min-btn],\n[data-reticle-overlay][data-reticle-min=\"1\"] [data-reticle-hud] .reticle-ctl,\n[data-reticle-overlay][data-reticle-min=\"1\"] [data-reticle-hud] .reticle-badge,\n[data-reticle-overlay][data-reticle-min=\"1\"] [data-reticle-hud] .reticle-act-strip,\n[data-reticle-overlay][data-reticle-min=\"1\"] [data-reticle-hud] [data-reticle-log],\n[data-reticle-overlay][data-reticle-min=\"1\"] [data-reticle-hud] [data-reticle-foot],\n[data-reticle-overlay][data-reticle-min=\"1\"] [data-reticle-hud] .reticle-banner{display:none;}\n[data-reticle-overlay][data-reticle-min=\"1\"] [data-reticle-hud] .reticle-live{display:block;}\n[data-reticle-overlay][data-reticle-min=\"1\"] [data-reticle-hud] .reticle-maxhint{display:inline-flex;}\n[data-reticle-mode=\"reading\"] [data-reticle-glow][data-on=\"1\"]{\n box-shadow:inset 0 0 0 3px rgba(34,211,238,.9),inset 0 0 28px 6px rgba(34,211,238,.4);}\n[data-reticle-mode=\"reading\"] [data-reticle-ring]{border-color:#22d3ee;\n box-shadow:0 0 0 3px rgba(34,211,238,.25);}\n[data-reticle-overlay][data-reticle-throttled=\"1\"] [data-reticle-glow][data-on=\"1\"]{\n box-shadow:inset 0 0 0 3px rgba(251,191,36,.9),inset 0 0 28px 6px rgba(251,191,36,.45);}\n[data-reticle-overlay][data-reticle-throttled=\"1\"] [data-reticle-hud]{--reticle-accent:#fbbf24;--reticle-accent-soft:rgba(251,191,36,.16);}\n\n[data-reticle-log]{flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain;display:flex;flex-direction:column;\n gap:7px;padding:12px 14px;scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.16) transparent;}\n[data-reticle-log]::-webkit-scrollbar{width:9px;}\n[data-reticle-log]::-webkit-scrollbar-thumb{background:rgba(255,255,255,.14);border-radius:9px;border:2px solid transparent;background-clip:content-box;}\n[data-reticle-log]::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,.26);background-clip:content-box;}\n[data-reticle-log-row]{display:flex;align-items:baseline;gap:8px;font-size:12px;line-height:1.45;\n animation:reticle-row-in .26s cubic-bezier(.16,1,.3,1);}\n@keyframes reticle-row-in{from{opacity:0;transform:translateY(5px);}to{opacity:1;transform:none;}}\n[data-reticle-log-ts]{flex:none;color:var(--reticle-faint);font-size:10px;font-variant-numeric:tabular-nums;padding-top:1px;}\n[data-reticle-log] .reticle-log-text{flex:1;min-width:0;color:#d6dae4;overflow-wrap:anywhere;word-break:break-word;}\n[data-reticle-log] .reticle-res{flex:none;font-weight:700;}\n[data-reticle-log-row][data-kind=\"human\"]{align-self:flex-end;max-width:88%;\n background:var(--reticle-accent-soft);border:1px solid var(--reticle-accent);border-radius:13px 13px 4px 13px;padding:6px 11px;}\n[data-reticle-log-row][data-kind=\"human\"] [data-reticle-log-ts]{display:none;}\n[data-reticle-log-row][data-kind=\"human\"] .reticle-log-text{color:var(--reticle-fg);}\n\n\n[data-reticle-hud] .reticle-ctl{pointer-events:auto;cursor:pointer;flex:none;display:inline-flex;align-items:center;justify-content:center;\n height:26px;padding:0 11px;border-radius:8px;border:1px solid var(--reticle-line);background:rgba(255,255,255,.04);\n color:var(--reticle-muted);font-family:var(--reticle-font);font-size:11px;font-weight:500;letter-spacing:.01em;line-height:1;\n transition:background .15s,color .15s,border-color .15s,transform .1s;}\n[data-reticle-hud] .reticle-ctl:hover{color:var(--reticle-fg);background:rgba(255,255,255,.09);}\n[data-reticle-hud] .reticle-ctl:active{transform:scale(.95);}\n[data-reticle-hud] .reticle-ctl:disabled{opacity:.35;cursor:default;}\n[data-reticle-hud] [data-reticle-end]{color:#ff9aa2;border-color:rgba(255,107,107,.22);}\n[data-reticle-hud] [data-reticle-end]:hover{color:#ff7a7a;border-color:rgba(255,107,107,.5);background:rgba(255,107,107,.1);}\n[data-reticle-hud] .reticle-badge{display:none;align-items:center;flex:none;font-weight:600;letter-spacing:.1em;font-size:9px;\n color:var(--reticle-accent);border:1px solid var(--reticle-accent);background:var(--reticle-accent-soft);padding:2px 8px;border-radius:999px;}\n[data-reticle-overlay][data-reticle-state=\"paused\"] [data-reticle-badge]{display:inline-flex;}\n[data-reticle-hud] [data-reticle-foot]{flex:none;padding:10px 12px 12px;border-top:1px solid var(--reticle-line2);background:rgba(0,0,0,.16);}\n[data-reticle-hud] .reticle-composer{display:flex;align-items:flex-end;gap:6px;background:rgba(255,255,255,.05);\n border:1px solid var(--reticle-line);border-radius:14px;padding:5px 6px 5px 14px;transition:border-color .15s,box-shadow .15s;}\n[data-reticle-hud] .reticle-composer:focus-within{border-color:var(--reticle-accent);box-shadow:0 0 0 3px var(--reticle-accent-soft);}\n[data-reticle-hud] .reticle-msg{flex:1;min-width:0;pointer-events:auto;background:transparent;border:none;outline:none;resize:none;\n box-sizing:border-box;color:var(--reticle-fg);font-family:var(--reticle-font);font-size:13px;line-height:18px;\n height:28px;min-height:28px;max-height:96px;padding:5px 0;overflow-y:auto;\n scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.14) transparent;}\n[data-reticle-hud] .reticle-msg::-webkit-scrollbar{width:9px;}\n[data-reticle-hud] .reticle-msg::-webkit-scrollbar-thumb{background:rgba(255,255,255,.14);border-radius:9px;border:2px solid transparent;background-clip:content-box;}\n[data-reticle-hud] .reticle-msg::placeholder{color:var(--reticle-faint);}\n[data-reticle-hud] .reticle-msg:disabled{opacity:.5;}\n[data-reticle-hud] .reticle-send{flex:none;width:30px;height:30px;padding:0;border-radius:10px;border:none;cursor:pointer;pointer-events:auto;\n background:var(--reticle-accent);color:#0b0d14;display:inline-flex;align-items:center;justify-content:center;transition:filter .15s,transform .1s;}\n[data-reticle-hud] .reticle-send svg{display:block;}\n[data-reticle-hud] .reticle-send:hover{filter:brightness(1.12);}\n[data-reticle-hud] .reticle-send:active{transform:scale(.9);}\n[data-reticle-hud] .reticle-send:disabled{opacity:.4;cursor:default;}\n[data-reticle-hud] .reticle-banner{display:none;flex:none;padding:8px 15px;color:var(--reticle-accent);\n font-size:11.5px;font-weight:500;border-bottom:1px solid var(--reticle-line2);background:var(--reticle-accent-soft);}\n[data-reticle-overlay][data-reticle-state=\"ended\"] [data-reticle-banner]{display:block;}\n/* Export row: hidden during a live session; revealed when ended so the run can be copied/saved. */\n[data-reticle-hud] .reticle-export{display:none;align-items:center;gap:8px;margin-top:9px;}\n[data-reticle-overlay][data-reticle-state=\"ended\"] [data-reticle-hud] .reticle-export{display:flex;}\n[data-reticle-hud] .reticle-export-msg{color:var(--reticle-ok);font-size:11px;opacity:0;transition:opacity .15s;}\n[data-reticle-hud] .reticle-export-msg[data-show=\"1\"]{opacity:1;}\n[data-reticle-overlay][data-reticle-state=\"paused\"] [data-reticle-glow][data-on=\"1\"]{animation:none;\n box-shadow:inset 0 0 0 3px rgba(246,180,76,.9),inset 0 0 30px 6px rgba(246,180,76,.4);}\n[data-reticle-overlay][data-reticle-state=\"ended\"] [data-reticle-glow][data-on=\"1\"]{animation:none;\n box-shadow:inset 0 0 0 2px rgba(61,215,166,.55);}\n/* Handoff tones tell the human the agent's mode at a glance. waiting = calm teal \"your turn\" (no\n alarm); ask = amber \"answer me\" with a pulse; warn = amber \"agent crashed\" with a pulse. Each leads\n the banner with an icon and overrides the calm ended-green accent. */\n[data-reticle-overlay][data-reticle-tone=\"waiting\"] [data-reticle-hud]{--reticle-accent:#38bdf8;--reticle-accent-soft:rgba(56,189,248,.16);}\n[data-reticle-overlay][data-reticle-tone=\"waiting\"] [data-reticle-banner]{font-weight:600;color:#7dd3fc;}\n[data-reticle-overlay][data-reticle-tone=\"waiting\"] [data-reticle-banner]::before{content:\"\\270B \";}\n[data-reticle-overlay][data-reticle-tone=\"waiting\"] [data-reticle-glow][data-on=\"1\"]{animation:none;\n box-shadow:inset 0 0 0 2px rgba(56,189,248,.5);}\n[data-reticle-overlay][data-reticle-tone=\"ask\"] [data-reticle-hud],\n[data-reticle-overlay][data-reticle-tone=\"warn\"] [data-reticle-hud]{--reticle-accent:#fb923c;--reticle-accent-soft:rgba(251,146,60,.18);}\n[data-reticle-overlay][data-reticle-tone=\"ask\"] [data-reticle-banner],\n[data-reticle-overlay][data-reticle-tone=\"warn\"] [data-reticle-banner]{font-weight:600;color:#fdba74;}\n[data-reticle-overlay][data-reticle-tone=\"ask\"] [data-reticle-banner]::before{content:\"\\2753 \";}\n[data-reticle-overlay][data-reticle-tone=\"warn\"] [data-reticle-banner]::before{content:\"\\26A0\\FE0F \";}\n[data-reticle-overlay][data-reticle-tone=\"ask\"] [data-reticle-glow][data-on=\"1\"],\n[data-reticle-overlay][data-reticle-tone=\"warn\"] [data-reticle-glow][data-on=\"1\"]{animation:reticle-warn-pulse 1.5s ease-in-out infinite;\n box-shadow:inset 0 0 0 2px rgba(251,146,60,.7);}\n@keyframes reticle-warn-pulse{0%,100%{box-shadow:inset 0 0 0 2px rgba(251,146,60,.32);}\n 50%{box-shadow:inset 0 0 0 3px rgba(251,146,60,.85),inset 0 0 26px 5px rgba(251,146,60,.34);}}\n/* Replay-a-flow row: the human re-runs a saved flow with no agent. Hidden until flows are pushed.\n Bounded + self-scrolling: it sits between the flex:1 log and the flex:none composer, so without a\n height cap a long flow list would squeeze the log to nothing and push the message input past the\n panel's overflow:hidden clip. flex:none + max-height + overflow-y keep the log and input always\n visible; extra flow chips scroll inside this section instead of growing the panel. */\n[data-reticle-hud] .reticle-flows{display:none;flex:none;flex-wrap:wrap;align-content:flex-start;gap:6px;\n padding:9px 12px;border-top:1px solid var(--reticle-line2);max-height:88px;overflow-y:auto;overscroll-behavior:contain;}\n[data-reticle-hud] .reticle-flows[data-has=\"1\"]{display:flex;}\n[data-reticle-hud] .reticle-flows::-webkit-scrollbar{width:9px;}\n[data-reticle-hud] .reticle-flows::-webkit-scrollbar-thumb{background:rgba(255,255,255,.14);border-radius:9px;border:2px solid transparent;background-clip:content-box;}\n[data-reticle-hud] .reticle-flows-cap{flex:0 0 100%;margin-bottom:1px;color:var(--reticle-faint);font-size:9.5px;letter-spacing:.09em;text-transform:uppercase;}\n[data-reticle-hud] .reticle-flow{pointer-events:auto;cursor:pointer;display:inline-flex;align-items:center;gap:5px;height:24px;padding:0 10px;\n border-radius:7px;border:1px solid var(--reticle-line);background:rgba(255,255,255,.04);color:var(--reticle-muted);\n font-family:var(--reticle-font);font-size:11px;font-weight:500;transition:background .15s,color .15s,border-color .15s,transform .1s;}\n[data-reticle-hud] .reticle-flow:hover{color:var(--reticle-fg);background:var(--reticle-accent-soft);border-color:var(--reticle-accent);}\n[data-reticle-hud] .reticle-flow:active{transform:scale(.95);}\n";
7
- //# sourceMappingURL=presenter-styles.d.ts.map
@@ -124,4 +124,3 @@ export const PRESENTER_CSS = `
124
124
  [data-reticle-overlay][data-reticle-throttled="1"] [data-reticle-hud]{--reticle-accent:#fbbf24;--reticle-accent-soft:rgba(251,191,36,.16);}
125
125
  ${LOG_CSS}
126
126
  ${CONTROLS_CSS}`;
127
- //# sourceMappingURL=presenter-styles.js.map
@@ -17,4 +17,3 @@ export declare function countVerdicts(runLog: {
17
17
  export declare function renderTally(el: HTMLElement | undefined, runLog: {
18
18
  result?: LogResult;
19
19
  }[], prev: TallyCounts): TallyCounts;
20
- //# sourceMappingURL=presenter-tally.d.ts.map
@@ -35,4 +35,3 @@ export function renderTally(el, runLog, prev) {
35
35
  `<span class="reticle-t-fail"${dimF}${bumpFail}>✗ ${String(next.fails)}</span>`;
36
36
  return next;
37
37
  }
38
- //# sourceMappingURL=presenter-tally.js.map
@@ -13,4 +13,3 @@ export interface GlowFlips {
13
13
  stop: () => void;
14
14
  }
15
15
  export declare function trackGlowFlips(glow: HTMLElement): GlowFlips;
16
- //# sourceMappingURL=presenter-test-helpers.d.ts.map
@@ -39,4 +39,3 @@ export function trackGlowFlips(glow) {
39
39
  stop: () => obs.disconnect(),
40
40
  };
41
41
  }
42
- //# sourceMappingURL=presenter-test-helpers.js.map
@@ -1,2 +1 @@
1
1
  export declare function actionVerb(action: string): string;
2
- //# sourceMappingURL=presenter-verbs.d.ts.map
@@ -26,4 +26,3 @@ export function actionVerb(action) {
26
26
  return action;
27
27
  }
28
28
  }
29
- //# sourceMappingURL=presenter-verbs.js.map
@@ -84,4 +84,3 @@ export declare class Presenter {
84
84
  /** Fly the cursor to an element, play the action's effect, then pace for the human. */
85
85
  beforeAct(refId: string, action: string, label: string): Promise<void>;
86
86
  }
87
- //# sourceMappingURL=presenter.d.ts.map
@@ -421,4 +421,3 @@ export class Presenter {
421
421
  spawnRipple(this.#root, cx, cy);
422
422
  }
423
423
  }
424
- //# sourceMappingURL=presenter.js.map
@@ -9,4 +9,3 @@ export declare const BTN_CSS: string;
9
9
  export declare const NAME_CSS: string;
10
10
  export declare const STATUS_CSS: string;
11
11
  export declare const MENU_CSS: string;
12
- //# sourceMappingURL=recorder-styles.d.ts.map
@@ -42,4 +42,3 @@ export const NAME_CSS = [
42
42
  ].join(';');
43
43
  export const STATUS_CSS = ['opacity:.75', 'margin-left:4px'].join(';');
44
44
  export const MENU_CSS = ['display:flex', 'gap:6px', 'align-items:center', 'flex-wrap:wrap'].join(';');
45
- //# sourceMappingURL=recorder-styles.js.map
@@ -57,4 +57,3 @@ export declare function compileRecording(name: string, steps: FlowStep[], annota
57
57
  /** Install the floating recorder toolbar. Default off; gated by the host (reticle.ts recorder flag). */
58
58
  export declare function installRecorder(deps: RecorderDeps): RecorderHandle;
59
59
  export {};
60
- //# sourceMappingURL=recorder.d.ts.map
@@ -451,4 +451,3 @@ class Recorder {
451
451
  export function installRecorder(deps) {
452
452
  return new Recorder(deps);
453
453
  }
454
- //# sourceMappingURL=recorder.js.map
@@ -28,4 +28,3 @@ export declare function readComponentState(el: Element): unknown;
28
28
  */
29
29
  export declare function elementHasHoverHandlers(el: Element): boolean;
30
30
  export declare function adapterNames(): string[];
31
- //# sourceMappingURL=adapters.d.ts.map
@@ -44,4 +44,3 @@ export function elementHasHoverHandlers(el) {
44
44
  export function adapterNames() {
45
45
  return adapters.map((a) => a.name);
46
46
  }
47
- //# sourceMappingURL=adapters.js.map
@@ -22,4 +22,3 @@ export declare function registerCapabilities(input: CapabilitiesInput): void;
22
22
  export declare function getCapabilities(): Capabilities;
23
23
  /** Whether the app has advertised any capabilities (used in the HELLO flag). */
24
24
  export declare function hasCapabilities(): boolean;
25
- //# sourceMappingURL=capabilities.d.ts.map
@@ -45,4 +45,3 @@ export function hasCapabilities() {
45
45
  capabilities.stores.length > 0 ||
46
46
  capabilities.flows.length > 0);
47
47
  }
48
- //# sourceMappingURL=capabilities.js.map
@@ -6,4 +6,3 @@
6
6
  */
7
7
  import type { ReticleEmitter } from './emitter.js';
8
8
  export declare function commitAndSignal<T>(emitter: ReticleEmitter, mutate: () => T, name: string, data?: Record<string, unknown>): T;
9
- //# sourceMappingURL=commit-and-signal.d.ts.map
@@ -9,4 +9,3 @@ export function commitAndSignal(emitter, mutate, name, data) {
9
9
  emitter.signal(name, data);
10
10
  return result;
11
11
  }
12
- //# sourceMappingURL=commit-and-signal.js.map
@@ -12,4 +12,3 @@ export interface ReticleDomain {
12
12
  stores?: readonly string[];
13
13
  }
14
14
  export declare function registerReticleDomain(domain: ReticleDomain): void;
15
- //# sourceMappingURL=domains.d.ts.map
@@ -16,4 +16,3 @@ export function registerReticleDomain(domain) {
16
16
  input.stores = [...domain.stores];
17
17
  registerCapabilities(input);
18
18
  }
19
- //# sourceMappingURL=domains.js.map
@@ -25,4 +25,3 @@ export interface CreateReticleEmitterOptions {
25
25
  * made at module load — before `reticle.connect` — starts working the moment Reticle connects.
26
26
  */
27
27
  export declare function createReticleEmitter(options?: CreateReticleEmitterOptions): ReticleEmitter;
28
- //# sourceMappingURL=emitter.d.ts.map
@@ -24,4 +24,3 @@ export function createReticleEmitter(options = {}) {
24
24
  },
25
25
  };
26
26
  }
27
- //# sourceMappingURL=emitter.js.map
@@ -60,10 +60,19 @@ export interface QuerySnapshot {
60
60
  * ```
61
61
  */
62
62
  export declare function tanstackQueryStore(client: QueryClientLike): StoreLike;
63
- /** The minimum of a Jotai vanilla store this adapter touches. */
64
- interface JotaiStoreLike {
65
- get: (atom: object) => unknown;
66
- sub: (atom: object, listener: () => void) => () => void;
63
+ /**
64
+ * The minimum of a Jotai vanilla store this adapter touches, generic in the ATOM type.
65
+ *
66
+ * `atom: object` was rejected by TypeScript for a real store and the reason is contravariance, not
67
+ * pedantry: Jotai's `get` is `<Value>(atom: Atom<Value>) => Value`, and a function that requires an
68
+ * `Atom` cannot stand in for one that accepts any `object`. So `jotaiStore(createStore(), …)` did
69
+ * not compile — the adapter was advertised, shipped, and unusable from TypeScript without a cast,
70
+ * which the shape-matched fake in the sibling test could never reveal because the fake was written
71
+ * to the same belief the adapter was.
72
+ */
73
+ interface JotaiStoreLike<A> {
74
+ get: (atom: A) => unknown;
75
+ sub: (atom: A, listener: () => void) => () => void;
67
76
  }
68
77
  /**
69
78
  * Expose a chosen set of Jotai atoms as one Reticle store.
@@ -76,7 +85,7 @@ interface JotaiStoreLike {
76
85
  * registerStore('app', jotaiStore(getDefaultStore(), { cart: cartAtom, user: userAtom }));
77
86
  * ```
78
87
  */
79
- export declare function jotaiStore(store: JotaiStoreLike, atoms: Record<string, object>): StoreLike;
88
+ export declare function jotaiStore<A>(store: JotaiStoreLike<A>, atoms: Record<string, A>): StoreLike;
80
89
  /** The minimum of an XState actor this adapter touches. */
81
90
  interface ActorLike {
82
91
  getSnapshot: () => unknown;
@@ -125,4 +134,3 @@ export declare function pushStore(initial: unknown): {
125
134
  push: (value: unknown) => void;
126
135
  };
127
136
  export {};
128
- //# sourceMappingURL=store-adapters.d.ts.map
@@ -132,4 +132,3 @@ export function pushStore(initial) {
132
132
  },
133
133
  };
134
134
  }
135
- //# sourceMappingURL=store-adapters.js.map
@@ -48,4 +48,3 @@ export declare function readStoresWithTruncation(only?: string): {
48
48
  stores: Record<string, unknown>;
49
49
  truncation?: Record<string, TruncationReport>;
50
50
  };
51
- //# sourceMappingURL=stores.d.ts.map
@@ -42,6 +42,14 @@ export function registerStore(name, source, subscribe) {
42
42
  notifyRegistered(name, getter, sub);
43
43
  return;
44
44
  }
45
+ if (typeof source !== 'function') {
46
+ const hasSubscribe = typeof source === 'object' && source !== null && 'subscribe' in source;
47
+ nativeWarn(`[reticle] store "${name}" is neither a getter function nor a {getState, subscribe} store` +
48
+ (hasSubscribe
49
+ ? ` — it has subscribe but no getState. Wrap it with an adapter or add getState.`
50
+ : '.'));
51
+ return;
52
+ }
45
53
  stores.set(name, source);
46
54
  if (subscribe !== undefined) {
47
55
  subscribers.set(name, subscribe);
@@ -141,4 +149,3 @@ function warnSilentStoreOnce(name) {
141
149
  `changes are invisible: no STATE_CHANGE events, no state diffs in causal summaries, and a state ` +
142
150
  `predicate will never see it update. Pass the store object (or a subscribe callback) to fix.`);
143
151
  }
144
- //# sourceMappingURL=stores.js.map
@@ -16,4 +16,3 @@ export declare function modeForCommand(commandName: string): PresenterMode;
16
16
  * element". Falls back to the bare verb when no target is in the args.
17
17
  */
18
18
  export declare function presentStatus(commandName: string, args?: Record<string, unknown>): string;
19
- //# sourceMappingURL=reticle-presenter-helpers.d.ts.map
@@ -78,4 +78,3 @@ function queryTarget(q) {
78
78
  return name !== undefined ? `"${value}" (${name})` : `"${value}"`;
79
79
  return name !== undefined ? `"${name}"` : undefined;
80
80
  }
81
- //# sourceMappingURL=reticle-presenter-helpers.js.map
package/dist/reticle.d.ts CHANGED
@@ -64,7 +64,9 @@ export interface ReticleConnectOptions {
64
64
  * behind `import.meta.env.DEV` so the SDK is dead-code-eliminated from prod bundles entirely.
65
65
  */
66
66
  export declare function shouldBlockProduction(nodeEnv: string | undefined, allowInProduction: boolean): boolean;
67
- export declare function connectionPolicy(pageHostname: string, bridgeUrl: string, allowNonLocalhost: boolean, token: string | undefined): {
67
+ export declare function connectionPolicy(pageHostname: string, bridgeUrl: string, allowNonLocalhost: boolean, token: string | undefined,
68
+ /** The page's protocol. Desktop webviews (file:, app:, tauri:) are local despite a non-loopback host. */
69
+ pageProtocol?: string): {
68
70
  allowed: boolean;
69
71
  reason?: string;
70
72
  };
@@ -134,4 +136,3 @@ export declare class Reticle {
134
136
  endSession(): void;
135
137
  disconnect(): void;
136
138
  }
137
- //# sourceMappingURL=reticle.d.ts.map
package/dist/reticle.js CHANGED
@@ -1,20 +1,9 @@
1
- import { EventType, RETICLE_DEFAULT_PORT, RETICLE_PROTOCOL_VERSION, RETICLE_URL_PARAM, bridgeWsUrl, ReticleCommand, MessageKind, SESSION_AUTO, SessionState, TRANSPORT_LIMITS, isLoopbackHostname, } from '@reticlehq/core';
1
+ import { EventType, RETICLE_DEFAULT_PORT, RETICLE_PROTOCOL_VERSION, RETICLE_URL_PARAM, bridgeWsUrl, ReticleCommand, MessageKind, SESSION_AUTO, SessionState, TRANSPORT_LIMITS, isLoopbackHostname, isLocalPage, } from '@reticlehq/core';
2
2
  import { createCommandRegistry, RELOAD_CACHE_BUST_PARAM, } from './commands/commands.js';
3
3
  import { Transport } from './transport/transport.js';
4
4
  import { adapterNames } from './registry/adapters.js';
5
5
  import { registerCapabilities, hasCapabilities, } from './registry/capabilities.js';
6
- import { installDom } from './observers/dom.js';
7
- import { installStorage } from './observers/storage.js';
8
- import { installStoreState } from './observers/state.js';
9
- import { installFocus } from './observers/focus.js';
10
- import { installBlindSpots } from './observers/blind-spots.js';
11
- import { installNetwork } from './observers/network.js';
12
- import { installPerf } from './observers/perf.js';
13
- import { installRoute } from './observers/route.js';
14
- import { installConsole } from './observers/console.js';
15
- import { installAnimation } from './observers/animation.js';
16
- import { installScroll } from './observers/scroll.js';
17
- import { installHealth } from './observers/health.js';
6
+ import { installAllObservers } from './observers/install-all.js';
18
7
  import { installOverlay } from './presenter/overlay.js';
19
8
  import { Presenter, LOG_KIND, LOG_RESULT, } from './presenter/presenter.js';
20
9
  import { actionVerb } from './presenter/presenter-verbs.js';
@@ -32,7 +21,9 @@ import { Annotator } from './review/annotator.js';
32
21
  export function shouldBlockProduction(nodeEnv, allowInProduction) {
33
22
  return nodeEnv === 'production' && !allowInProduction;
34
23
  }
35
- export function connectionPolicy(pageHostname, bridgeUrl, allowNonLocalhost, token) {
24
+ export function connectionPolicy(pageHostname, bridgeUrl, allowNonLocalhost, token,
25
+ /** The page's protocol. Desktop webviews (file:, app:, tauri:) are local despite a non-loopback host. */
26
+ pageProtocol = 'http:') {
36
27
  let bridge;
37
28
  try {
38
29
  bridge = new URL(bridgeUrl);
@@ -53,7 +44,7 @@ export function connectionPolicy(pageHostname, bridgeUrl, allowNonLocalhost, tok
53
44
  if (remoteBridge && bridge.protocol !== 'wss:') {
54
45
  return { allowed: false, reason: 'a non-local Reticle bridge must use wss://' };
55
46
  }
56
- const remote = !isLoopbackHostname(pageHostname) || remoteBridge;
47
+ const remote = !isLocalPage(pageProtocol, pageHostname) || remoteBridge;
57
48
  if (!remote)
58
49
  return { allowed: true };
59
50
  if (!allowNonLocalhost) {
@@ -176,7 +167,7 @@ export class Reticle {
176
167
  // reload permanently pollutes the URL the app and the agent see.
177
168
  stripReloadCacheBustParam();
178
169
  const url = options.url ?? bridgeWsUrl(RETICLE_DEFAULT_PORT);
179
- const policy = connectionPolicy(window.location.hostname, url, options.allowNonLocalhost === true, options.token);
170
+ const policy = connectionPolicy(window.location.hostname, url, options.allowNonLocalhost === true, options.token, window.location.protocol);
180
171
  if (!policy.allowed) {
181
172
  globalThis.console.warn(`[Reticle] ${policy.reason ?? 'connection blocked'}`);
182
173
  return;
@@ -223,20 +214,9 @@ export class Reticle {
223
214
  },
224
215
  });
225
216
  const emit = this.#emit;
226
- this.#teardowns = [
227
- installNetwork(emit, { captureBodies: options.captureNetworkBodies === true }),
228
- installPerf(emit),
229
- installRoute(emit),
230
- installConsole(emit),
231
- installAnimation(emit),
232
- installScroll(emit),
233
- installDom(emit),
234
- installStorage(emit), // storage WRITES → STORAGE_CHANGE diffs (pull remains the fallback)
235
- installStoreState(emit), // subscribed-store mutations → STATE_CHANGE path diffs
236
- installFocus(emit), // element focus movement → FOCUS_CHANGE (focus-to-body = a regression)
237
- installBlindSpots(emit), // cross-origin iframes the SDK can't see → BLIND_SPOT (coverage: partial)
238
- installHealth(emit), // page visibility/focus health + heartbeat
239
- ];
217
+ this.#teardowns = installAllObservers(emit, {
218
+ captureBodies: options.captureNetworkBodies === true,
219
+ });
240
220
  if (options.overlay === true) {
241
221
  this.#overlay = installOverlay();
242
222
  this.#overlay.update({ connected: true, events: 0 });
@@ -445,4 +425,3 @@ export class Reticle {
445
425
  }
446
426
  }
447
427
  }
448
- //# sourceMappingURL=reticle.js.map
@@ -33,4 +33,3 @@ export declare class Annotator {
33
33
  }
34
34
  /** Construct + mount the annotator (mirrors installRecorder's ergonomics). */
35
35
  export declare function installAnnotator(deps: AnnotatorDeps): Annotator;
36
- //# sourceMappingURL=annotator.d.ts.map