@reticlehq/browser 3.7.0 → 3.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/dist/actions/action-report.d.ts +10 -0
  2. package/dist/actions/action-report.js +59 -14
  3. package/dist/actions/actions-dom.d.ts +4 -0
  4. package/dist/actions/actions-dom.js +20 -4
  5. package/dist/actions/actions.d.ts +1 -0
  6. package/dist/actions/actions.js +94 -46
  7. package/dist/actions/appeared-text.js +2 -2
  8. package/dist/actions/click-target.d.ts +1 -0
  9. package/dist/actions/click-target.js +14 -0
  10. package/dist/actions/danger-context.d.ts +2 -1
  11. package/dist/actions/danger-context.js +43 -17
  12. package/dist/actions/scroll.d.ts +2 -0
  13. package/dist/actions/scroll.js +10 -2
  14. package/dist/activate.d.ts +14 -0
  15. package/dist/activate.js +43 -0
  16. package/dist/busy.d.ts +3 -0
  17. package/dist/busy.js +42 -0
  18. package/dist/commands/commands.js +45 -17
  19. package/dist/connect-options.d.ts +12 -1
  20. package/dist/connect-options.js +18 -1
  21. package/dist/dom/a11y.d.ts +0 -2
  22. package/dist/dom/a11y.js +103 -363
  23. package/dist/dom/chart.d.ts +3 -2
  24. package/dist/dom/chart.js +3 -2
  25. package/dist/dom/dom-ignore.d.ts +6 -0
  26. package/dist/dom/dom-ignore.js +60 -5
  27. package/dist/dom/layout-audit.d.ts +15 -0
  28. package/dist/dom/layout-audit.js +208 -0
  29. package/dist/dom/paint-context.d.ts +15 -0
  30. package/dist/dom/paint-context.js +78 -0
  31. package/dist/dom/query-finders.d.ts +6 -0
  32. package/dist/dom/query-finders.js +216 -0
  33. package/dist/dom/query.d.ts +1 -1
  34. package/dist/dom/query.js +154 -227
  35. package/dist/dom/shadow-registry.d.ts +1 -0
  36. package/dist/dom/shadow-registry.js +27 -0
  37. package/dist/dom/snapshot.d.ts +5 -0
  38. package/dist/dom/snapshot.js +87 -35
  39. package/dist/dom/stable-selector.d.ts +1 -0
  40. package/dist/dom/stable-selector.js +19 -0
  41. package/dist/dom/text-match.d.ts +12 -0
  42. package/dist/dom/text-match.js +115 -0
  43. package/dist/dom/theme.d.ts +1 -0
  44. package/dist/dom/theme.js +21 -9
  45. package/dist/dom/virtualized.js +5 -1
  46. package/dist/dom/visibility.d.ts +7 -0
  47. package/dist/dom/visibility.js +322 -0
  48. package/dist/index.d.ts +4 -2
  49. package/dist/index.js +7 -1
  50. package/dist/observers/blind-spots.js +3 -2
  51. package/dist/observers/canvas.d.ts +18 -0
  52. package/dist/observers/canvas.js +76 -0
  53. package/dist/observers/dom.js +68 -19
  54. package/dist/observers/field.d.ts +11 -0
  55. package/dist/observers/field.js +117 -13
  56. package/dist/observers/install-all.js +4 -0
  57. package/dist/observers/media.d.ts +2 -0
  58. package/dist/observers/media.js +32 -0
  59. package/dist/observers/net-detail/network-body.d.ts +2 -0
  60. package/dist/observers/net-detail/network-body.js +36 -9
  61. package/dist/observers/net-detail/network-event-stream.d.ts +5 -0
  62. package/dist/observers/net-detail/network-event-stream.js +55 -0
  63. package/dist/observers/net-detail/network-frames.d.ts +2 -0
  64. package/dist/observers/net-detail/network-frames.js +39 -0
  65. package/dist/observers/net-detail/network-response-body.d.ts +3 -0
  66. package/dist/observers/net-detail/network-response-body.js +97 -0
  67. package/dist/observers/network.js +111 -101
  68. package/dist/observers/route.d.ts +2 -0
  69. package/dist/observers/route.js +33 -4
  70. package/dist/presenter/chrome/presenter-report-copy.d.ts +0 -5
  71. package/dist/presenter/chrome/presenter-report-copy.js +0 -14
  72. package/dist/presenter/hud-telemetry.js +1 -1
  73. package/dist/presenter/presenter-chat-views.d.ts +3 -4
  74. package/dist/presenter/presenter-chat-views.js +47 -20
  75. package/dist/presenter/presenter-config.d.ts +1 -0
  76. package/dist/presenter/presenter-config.js +1 -0
  77. package/dist/presenter/presenter-frame.d.ts +3 -2
  78. package/dist/presenter/presenter-frame.js +24 -15
  79. package/dist/presenter/presenter-harness-row.d.ts +4 -15
  80. package/dist/presenter/presenter-harness-row.js +11 -50
  81. package/dist/presenter/presenter-report-styles.js +0 -17
  82. package/dist/presenter/presenter-report.d.ts +1 -2
  83. package/dist/presenter/presenter-report.js +4 -54
  84. package/dist/presenter/presenter-run-state.js +2 -1
  85. package/dist/presenter/presenter-settings.d.ts +2 -3
  86. package/dist/presenter/presenter-settings.js +14 -17
  87. package/dist/presenter/presenter-shell.d.ts +6 -4
  88. package/dist/presenter/presenter-shell.js +37 -7
  89. package/dist/presenter/presenter.js +32 -11
  90. package/dist/registry/store-adapters.d.ts +5 -2
  91. package/dist/registry/store-adapters.js +40 -10
  92. package/dist/reticle-inject.js +700 -645
  93. package/dist/reticle.d.ts +4 -2
  94. package/dist/reticle.js +36 -6
  95. package/dist/security/page-location.d.ts +2 -0
  96. package/dist/security/page-location.js +7 -0
  97. package/dist/security/serialization.js +1 -1
  98. package/dist/storage-keys.d.ts +1 -0
  99. package/dist/storage-keys.js +1 -0
  100. package/dist/timers/native/native-timers.d.ts +1 -0
  101. package/dist/timers/native/native-timers.js +5 -0
  102. package/dist/transport/transport.d.ts +1 -0
  103. package/dist/transport/transport.js +18 -0
  104. package/package.json +6 -2
package/dist/reticle.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { EventType, RETICLE_URL_PARAM, HudVisibility, type ReticleEvent } from '@reticlehq/core';
2
2
  import { type CapabilitiesInput } from './registry/capabilities.js';
3
- import type { ReticleConnectOptions } from './connect-options.js';
3
+ import { type ReticleConnectOptions } from './connect-options.js';
4
+ export { helloMode, shouldBlockProduction } from './connect-options.js';
4
5
  export type { ReticleConnectOptions };
5
- export declare function shouldBlockProduction(nodeEnv: string | undefined, allowInProduction: boolean): boolean;
6
6
  export declare function withBridgePath(bridgeUrl: string): {
7
7
  url: string;
8
8
  adjusted: boolean;
@@ -43,7 +43,9 @@ export declare class Reticle {
43
43
  #private;
44
44
  connect(options?: ReticleConnectOptions): void;
45
45
  get connected(): boolean;
46
+ routes(patterns: readonly string[]): void;
46
47
  signal(name: string, data?: Record<string, unknown>): void;
48
+ busy<T>(work: Promise<T>): Promise<T>;
47
49
  state(name: string, value: unknown): void;
48
50
  renderCommit(commits: number): void;
49
51
  describe(input: CapabilitiesInput): void;
package/dist/reticle.js CHANGED
@@ -1,4 +1,6 @@
1
1
  import { setPresenterViewer, setPresenterVisible } from './dom/dom-ignore.js';
2
+ import { trackBusy } from './busy.js';
3
+ import { declareRoutes } from './observers/route.js';
2
4
  import { setOutwardPolicy } from './actions/danger-context.js';
3
5
  import { coverageMarkers, notApplicableFor } from './dom/addressing/coverage-markers.js';
4
6
  import { EventType, RETICLE_DEFAULT_PORT, RETICLE_PROTOCOL_VERSION, RETICLE_URL_PARAM, RETICLE_WS_PATH, bridgeWsUrl, ReticleCommand, MessageKind, SESSION_AUTO, SessionState, TRANSPORT_LIMITS, buildRedactionPolicy, isLoopbackHostname, isLocalPage, setActiveRedactionPolicy, wireRedactionKeys, RETICLE_ROOT_GLOBAL, RETICLE_SDK_VERSION_GLOBAL, CONTRACT_FINGERPRINT, CONTRACT_PARTS, newDocumentId, NO_EDITS_OBSERVED, PresenterMode, CommandActor, HudCorner, HudVisibility, } from '@reticlehq/core';
@@ -14,6 +16,8 @@ import { registerCapabilities, setCapabilitiesListener, hasCapabilities, } from
14
16
  import { installAllObservers, runTeardowns } from './observers/install-all.js';
15
17
  import { setTestIdAttr } from './dom/addressing/testid-attr.js';
16
18
  import { setNetworkBodyMaxChars } from './observers/net-detail/network-body.js';
19
+ import { pageHref } from './security/page-location.js';
20
+ import { scrubKnownSecrets } from './security/serialization.js';
17
21
  import { installOverlay } from './presenter/chrome/overlay.js';
18
22
  import { LOG_ACTOR, LOG_KIND, LOG_RESULT } from './presenter/chrome/log-kinds.js';
19
23
  import { actionVerb } from './presenter/chrome/presenter-verbs.js';
@@ -22,9 +26,8 @@ import { resetClock } from './timers/clock.js';
22
26
  import { nativeWarn } from './timers/console/native-console.js';
23
27
  import { installRecorder } from './recorder/recorder.js';
24
28
  import { Annotator } from './review/annotator.js';
25
- export function shouldBlockProduction(nodeEnv, allowInProduction) {
26
- return 'production' === nodeEnv && !allowInProduction;
27
- }
29
+ import { helloMode, leaseToken, shouldBlockProduction, } from './connect-options.js';
30
+ export { helloMode, shouldBlockProduction } from './connect-options.js';
28
31
  export function withBridgePath(bridgeUrl) {
29
32
  let parsed;
30
33
  try {
@@ -153,6 +156,7 @@ export class Reticle {
153
156
  #annotator;
154
157
  #eventCount = 0;
155
158
  #token;
159
+ #mode = {};
156
160
  #sdkVersion;
157
161
  #captureBodies = false;
158
162
  #sourceMapping = undefined;
@@ -160,8 +164,15 @@ export class Reticle {
160
164
  #redactKeys = [];
161
165
  #actHandle;
162
166
  connect(options = {}) {
163
- if (this.#connected)
167
+ if (this.#connected) {
168
+ const leased = leaseToken(options, this.#token);
169
+ if (leased !== undefined) {
170
+ this.#token = leased;
171
+ this.#transport?.redialAfterRefusal();
172
+ }
173
+ this.#adoptLateProjectId(options);
164
174
  return;
175
+ }
165
176
  if ('undefined' === typeof window || 'undefined' === typeof document)
166
177
  return;
167
178
  const proc = globalThis.process;
@@ -198,6 +209,7 @@ export class Reticle {
198
209
  this.#token =
199
210
  options.token !== undefined && options.token.length > 0 ? options.token : undefined;
200
211
  this.#projectId = identity.projectId;
212
+ this.#mode = helloMode(options);
201
213
  this.#applyRedaction(options.redact);
202
214
  this.#start = performance.now();
203
215
  this.#registry = createCommandRegistry();
@@ -344,9 +356,17 @@ export class Reticle {
344
356
  get connected() {
345
357
  return this.#connected;
346
358
  }
359
+ routes(patterns) {
360
+ declareRoutes(patterns);
361
+ }
347
362
  signal(name, data = {}) {
348
363
  this.#emit(EventType.SIGNAL, { name, data });
349
364
  }
365
+ busy(work) {
366
+ return trackBusy(work, (name, data) => {
367
+ this.signal(name, data);
368
+ });
369
+ }
350
370
  state(name, value) {
351
371
  this.#emit(EventType.STATE_CHANGE, { name, value });
352
372
  }
@@ -407,16 +427,26 @@ export class Reticle {
407
427
  setActiveRedactionPolicy(buildRedactionPolicy(config, nativeWarn));
408
428
  this.#redactKeys = wireRedactionKeys(config);
409
429
  }
430
+ #adoptLateProjectId(options) {
431
+ if (this.#projectId !== undefined)
432
+ return;
433
+ const late = resolveConnectIdentity(options, window.location.search).projectId;
434
+ if (late === undefined)
435
+ return;
436
+ this.#projectId = late;
437
+ this.#transport?.reannounce();
438
+ }
410
439
  #hello() {
411
440
  return {
412
441
  kind: MessageKind.HELLO,
413
442
  protocolVersion: RETICLE_PROTOCOL_VERSION,
414
443
  sessionId: this.#session,
415
444
  ...(this.#projectId === undefined ? {} : { projectId: this.#projectId }),
416
- url: location.href,
417
- title: document.title,
445
+ url: pageHref(),
446
+ title: scrubKnownSecrets(document.title),
418
447
  adapters: adapterNames(),
419
448
  ...(this.#token === undefined ? {} : { token: this.#token }),
449
+ ...this.#mode,
420
450
  hasCapabilities: hasCapabilities(),
421
451
  channels: declaredChannels(),
422
452
  platform: declaredPlatform(),
@@ -0,0 +1,2 @@
1
+ export declare function pageHref(): string;
2
+ export declare function pageRoute(withHash?: boolean): string;
@@ -0,0 +1,7 @@
1
+ import { redactUrl } from '@reticlehq/core';
2
+ export function pageHref() {
3
+ return redactUrl(location.href);
4
+ }
5
+ export function pageRoute(withHash = true) {
6
+ return redactUrl(`${location.pathname}${location.search}${withHash ? location.hash : ''}`);
7
+ }
@@ -29,7 +29,7 @@ function sanitize(value, state, depth, key) {
29
29
  if (null === value || 'boolean' === typeof value)
30
30
  return value;
31
31
  if ('string' === typeof value) {
32
- return boundedString(value, state, 'error' === key?.toLowerCase()
32
+ return boundedString(scrubKnownSecrets(value), state, 'error' === key?.toLowerCase()
33
33
  ? TRANSPORT_LIMITS.MAX_ERROR_LENGTH
34
34
  : TRANSPORT_LIMITS.MAX_STRING_LENGTH);
35
35
  }
@@ -5,6 +5,7 @@ export declare const ReticleStorageKey: {
5
5
  readonly PRESENTER_LOG_OWNER: "reticle-presenter-log-owner";
6
6
  readonly PRESENTER_SETTINGS: "reticle-presenter-settings";
7
7
  readonly PRESENTER_MINIMISED: "reticle-presenter-minimised";
8
+ readonly PRESENTER_OPEN: "reticle-presenter-open";
8
9
  readonly PRESENTER_VIEW: "reticle-presenter-view";
9
10
  readonly CAROUSEL_DISMISSED: "reticle.carousel.dismissed";
10
11
  readonly ANNOTATION_HISTORY: "reticle.annotations.history.v1";
@@ -5,6 +5,7 @@ export const ReticleStorageKey = {
5
5
  PRESENTER_LOG_OWNER: 'reticle-presenter-log-owner',
6
6
  PRESENTER_SETTINGS: 'reticle-presenter-settings',
7
7
  PRESENTER_MINIMISED: 'reticle-presenter-minimised',
8
+ PRESENTER_OPEN: 'reticle-presenter-open',
8
9
  PRESENTER_VIEW: 'reticle-presenter-view',
9
10
  CAROUSEL_DISMISSED: 'reticle.carousel.dismissed',
10
11
  ANNOTATION_HISTORY: 'reticle.annotations.history.v1',
@@ -8,4 +8,5 @@ interface FrameOutcome {
8
8
  export declare const boundedFrame: (budgetMs?: number) => Promise<FrameOutcome>;
9
9
  export declare const nativeFrame: () => Promise<void>;
10
10
  export declare const settle: (budgetMs?: number) => Promise<FrameOutcome>;
11
+ export declare function asSettleBudget(raw: unknown): number | undefined;
11
12
  export {};
@@ -46,3 +46,8 @@ export const settle = async (budgetMs = FRAME_BUDGET_MS) => {
46
46
  await Promise.resolve();
47
47
  return boundedFrame(budgetMs);
48
48
  };
49
+ export function asSettleBudget(raw) {
50
+ if ('number' !== typeof raw || !Number.isFinite(raw))
51
+ return undefined;
52
+ return Math.max(0, Math.min(raw, FRAME_BUDGET_MS));
53
+ }
@@ -26,6 +26,7 @@ export declare class Transport {
26
26
  constructor(deps: TransportDeps);
27
27
  connect(): void;
28
28
  sendEvent(event: ReticleEvent): void;
29
+ redialAfterRefusal(): void;
29
30
  reannounce(): void;
30
31
  close(): void;
31
32
  }
@@ -27,6 +27,7 @@ export class Transport {
27
27
  #insertOrder = 0;
28
28
  #closed = false;
29
29
  #refused = false;
30
+ #redialOnRefusal = false;
30
31
  #disconnectedSince;
31
32
  #reconnectDelay = RECONNECT_DELAY_MS;
32
33
  #lost = false;
@@ -94,6 +95,11 @@ export class Transport {
94
95
  ws.onclose = (event) => {
95
96
  this.#ws = undefined;
96
97
  if (event.code === WS_POLICY_VIOLATION) {
98
+ if (this.#redialOnRefusal && !this.#closed) {
99
+ this.#redialOnRefusal = false;
100
+ this.#open();
101
+ return;
102
+ }
97
103
  this.#refused = true;
98
104
  const reason = event.reason.length > 0 ? event.reason : 'policy violation';
99
105
  nativeWarn(`[reticle] bridge refused the connection: ${reason} — not retrying until you come back to this tab.`);
@@ -197,6 +203,18 @@ export class Transport {
197
203
  type: event.type,
198
204
  });
199
205
  }
206
+ redialAfterRefusal() {
207
+ if (this.#closed) {
208
+ return;
209
+ }
210
+ if (this.#refused && this.#ws === undefined) {
211
+ this.#refused = false;
212
+ this.#reconnectDelay = RECONNECT_DELAY_MS;
213
+ this.#open();
214
+ return;
215
+ }
216
+ this.#redialOnRefusal = true;
217
+ }
200
218
  reannounce() {
201
219
  if (this.#ws === undefined || this.#ws.readyState !== WebSocket.OPEN)
202
220
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reticlehq/browser",
3
- "version": "3.7.0",
3
+ "version": "3.8.1",
4
4
  "description": "Reticle browser SDK — installs observers, builds semantic snapshots, executes actions, talks to the bridge.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -15,10 +15,14 @@
15
15
  "./inject": {
16
16
  "types": "./dist/reticle-inject.d.ts",
17
17
  "default": "./dist/reticle-inject.js"
18
+ },
19
+ "./activate": {
20
+ "types": "./dist/activate.d.ts",
21
+ "default": "./dist/activate.js"
18
22
  }
19
23
  },
20
24
  "dependencies": {
21
- "@reticlehq/core": "3.7.0"
25
+ "@reticlehq/core": "3.8.1"
22
26
  },
23
27
  "devDependencies": {
24
28
  "@iconify-json/heroicons-outline": "^1.2.1",