@agent-native/core 0.98.1 → 0.98.3

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 (165) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +18 -0
  3. package/corpus/core/docs/content/locales/ar-SA/pr-visual-recap.mdx +25 -1
  4. package/corpus/core/docs/content/locales/ar-SA/template-plan.mdx +1 -1
  5. package/corpus/core/docs/content/locales/de-DE/pr-visual-recap.mdx +25 -1
  6. package/corpus/core/docs/content/locales/de-DE/template-plan.mdx +1 -1
  7. package/corpus/core/docs/content/locales/es-ES/pr-visual-recap.mdx +25 -1
  8. package/corpus/core/docs/content/locales/es-ES/template-plan.mdx +1 -1
  9. package/corpus/core/docs/content/locales/fr-FR/pr-visual-recap.mdx +25 -1
  10. package/corpus/core/docs/content/locales/fr-FR/template-plan.mdx +1 -1
  11. package/corpus/core/docs/content/locales/hi-IN/pr-visual-recap.mdx +25 -1
  12. package/corpus/core/docs/content/locales/hi-IN/template-plan.mdx +1 -1
  13. package/corpus/core/docs/content/locales/ja-JP/pr-visual-recap.mdx +25 -1
  14. package/corpus/core/docs/content/locales/ja-JP/template-plan.mdx +1 -1
  15. package/corpus/core/docs/content/locales/ko-KR/pr-visual-recap.mdx +25 -1
  16. package/corpus/core/docs/content/locales/ko-KR/template-plan.mdx +1 -1
  17. package/corpus/core/docs/content/locales/pt-BR/pr-visual-recap.mdx +25 -1
  18. package/corpus/core/docs/content/locales/pt-BR/template-plan.mdx +1 -1
  19. package/corpus/core/docs/content/locales/zh-CN/pr-visual-recap.mdx +25 -1
  20. package/corpus/core/docs/content/locales/zh-CN/template-plan.mdx +1 -1
  21. package/corpus/core/docs/content/locales/zh-TW/pr-visual-recap.mdx +25 -1
  22. package/corpus/core/docs/content/locales/zh-TW/template-plan.mdx +1 -1
  23. package/corpus/core/docs/content/pr-visual-recap.mdx +50 -1
  24. package/corpus/core/docs/content/template-plan.mdx +1 -1
  25. package/corpus/core/package.json +1 -1
  26. package/corpus/core/src/agent/production-agent.ts +2 -2
  27. package/corpus/core/src/cli/plan-local.ts +43 -11
  28. package/corpus/core/src/cli/pr-visual-recap-workflow.ts +2 -9
  29. package/corpus/core/src/cli/recap.ts +356 -4
  30. package/corpus/core/src/cli/skills-content/local-files.ts +17 -12
  31. package/corpus/core/src/client/analytics.ts +96 -14
  32. package/corpus/core/src/client/index.ts +7 -0
  33. package/corpus/core/src/client/session-replay.ts +10 -0
  34. package/corpus/core/src/client/settings/DemoModeSection.tsx +10 -34
  35. package/corpus/core/src/client/settings/SettingsPanel.tsx +31 -211
  36. package/corpus/core/src/client/settings/agent-settings-search.ts +219 -0
  37. package/corpus/core/src/client/settings/index.ts +4 -0
  38. package/corpus/core/src/client/url-scrub.ts +13 -0
  39. package/corpus/core/src/client/use-demo-mode-status.ts +44 -0
  40. package/corpus/core/src/demo/actions/toggle-demo-mode.ts +2 -2
  41. package/corpus/core/src/demo/config.ts +6 -6
  42. package/corpus/core/src/demo/redact.ts +18 -76
  43. package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +21 -4
  44. package/corpus/templates/analytics/AGENTS.md +8 -0
  45. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +18 -4
  46. package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +429 -244
  47. package/corpus/templates/analytics/app/components/layout/command-palette-search.ts +93 -0
  48. package/corpus/templates/analytics/app/hooks/use-replay-storage-status.ts +2 -1
  49. package/corpus/templates/analytics/app/lib/demo-chart-trend.ts +169 -0
  50. package/corpus/templates/analytics/app/pages/Settings.tsx +8 -45
  51. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +205 -70
  52. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +32 -16
  53. package/corpus/templates/analytics/app/pages/settings/settings-search.ts +126 -0
  54. package/corpus/templates/analytics/changelog/2026-07-12-command-menu-loading-placeholders-now-stay-below-available-r.md +6 -0
  55. package/corpus/templates/analytics/changelog/2026-07-12-command-menu-search-now-prioritizes-the-best-match.md +6 -0
  56. package/corpus/templates/analytics/changelog/2026-07-12-daily-dashboard-emails-reliably-include-the-complete-dashboa.md +6 -0
  57. package/corpus/templates/analytics/changelog/2026-07-12-demo-charts-preserve-source-movement.md +6 -0
  58. package/corpus/templates/analytics/changelog/2026-07-12-demo-mode-charts-trend-upward.md +6 -0
  59. package/corpus/templates/analytics/changelog/2026-07-12-replay-storage-settings-stay-readable-at-narrow-widths.md +6 -0
  60. package/corpus/templates/analytics/changelog/2026-07-12-session-replays-preserve-recorded-styling-and-keep-malformed.md +6 -0
  61. package/corpus/templates/analytics/server/jobs/dashboard-report.ts +2 -0
  62. package/corpus/templates/analytics/server/lib/dashboard-report.ts +17 -33
  63. package/corpus/templates/clips/app/components/player/video-player.tsx +5 -1
  64. package/corpus/templates/clips/changelog/2026-07-11-clips-no-longer-stay-stuck-on-preparing-clip-when-they-are-r.md +6 -0
  65. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +2 -2
  66. package/corpus/templates/content/changelog/2026-07-12-the-left-sidebar-stays-fixed-horizontally-while-scrolling-on.md +6 -0
  67. package/corpus/templates/plan/.agents/skills/visual-plan/references/local-files.md +17 -12
  68. package/corpus/templates/plan/.agents/skills/visual-recap/references/local-files.md +17 -12
  69. package/corpus/templates/plan/actions/validate-local-plan-source.ts +4 -4
  70. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +2 -1
  71. package/corpus/templates/plan/app/lib/plan-local-bridge.ts +41 -0
  72. package/corpus/templates/plan/app/lib/plan-tracking.ts +3 -0
  73. package/corpus/templates/plan/app/pages/PlansPage.tsx +9 -9
  74. package/corpus/templates/plan/app/root.tsx +13 -3
  75. package/corpus/templates/plan/changelog/2026-07-12-local-plan-source-now-stays-on-device.md +6 -0
  76. package/dist/agent/production-agent.js +2 -2
  77. package/dist/agent/production-agent.js.map +1 -1
  78. package/dist/cli/plan-local.d.ts +6 -6
  79. package/dist/cli/plan-local.d.ts.map +1 -1
  80. package/dist/cli/plan-local.js +36 -7
  81. package/dist/cli/plan-local.js.map +1 -1
  82. package/dist/cli/pr-visual-recap-workflow.d.ts +2 -8
  83. package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -1
  84. package/dist/cli/pr-visual-recap-workflow.js +2 -8
  85. package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
  86. package/dist/cli/recap.d.ts +22 -1
  87. package/dist/cli/recap.d.ts.map +1 -1
  88. package/dist/cli/recap.js +286 -2
  89. package/dist/cli/recap.js.map +1 -1
  90. package/dist/cli/skills-content/local-files.d.ts +1 -1
  91. package/dist/cli/skills-content/local-files.d.ts.map +1 -1
  92. package/dist/cli/skills-content/local-files.js +17 -12
  93. package/dist/cli/skills-content/local-files.js.map +1 -1
  94. package/dist/client/analytics.d.ts +8 -0
  95. package/dist/client/analytics.d.ts.map +1 -1
  96. package/dist/client/analytics.js +77 -13
  97. package/dist/client/analytics.js.map +1 -1
  98. package/dist/client/index.d.ts +3 -2
  99. package/dist/client/index.d.ts.map +1 -1
  100. package/dist/client/index.js +3 -2
  101. package/dist/client/index.js.map +1 -1
  102. package/dist/client/session-replay.d.ts +2 -0
  103. package/dist/client/session-replay.d.ts.map +1 -1
  104. package/dist/client/session-replay.js +7 -0
  105. package/dist/client/session-replay.js.map +1 -1
  106. package/dist/client/settings/DemoModeSection.d.ts +3 -3
  107. package/dist/client/settings/DemoModeSection.d.ts.map +1 -1
  108. package/dist/client/settings/DemoModeSection.js +8 -27
  109. package/dist/client/settings/DemoModeSection.js.map +1 -1
  110. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  111. package/dist/client/settings/SettingsPanel.js +41 -191
  112. package/dist/client/settings/SettingsPanel.js.map +1 -1
  113. package/dist/client/settings/agent-settings-search.d.ts +16 -0
  114. package/dist/client/settings/agent-settings-search.d.ts.map +1 -0
  115. package/dist/client/settings/agent-settings-search.js +178 -0
  116. package/dist/client/settings/agent-settings-search.js.map +1 -0
  117. package/dist/client/settings/index.d.ts +1 -0
  118. package/dist/client/settings/index.d.ts.map +1 -1
  119. package/dist/client/settings/index.js +1 -0
  120. package/dist/client/settings/index.js.map +1 -1
  121. package/dist/client/url-scrub.d.ts.map +1 -1
  122. package/dist/client/url-scrub.js +14 -0
  123. package/dist/client/url-scrub.js.map +1 -1
  124. package/dist/client/use-demo-mode-status.d.ts +12 -0
  125. package/dist/client/use-demo-mode-status.d.ts.map +1 -0
  126. package/dist/client/use-demo-mode-status.js +30 -0
  127. package/dist/client/use-demo-mode-status.js.map +1 -0
  128. package/dist/collab/routes.d.ts +2 -2
  129. package/dist/demo/actions/toggle-demo-mode.js +2 -2
  130. package/dist/demo/actions/toggle-demo-mode.js.map +1 -1
  131. package/dist/demo/config.js +6 -6
  132. package/dist/demo/config.js.map +1 -1
  133. package/dist/demo/redact.d.ts +7 -5
  134. package/dist/demo/redact.d.ts.map +1 -1
  135. package/dist/demo/redact.js +19 -54
  136. package/dist/demo/redact.js.map +1 -1
  137. package/dist/notifications/routes.d.ts +2 -2
  138. package/dist/observability/routes.d.ts +5 -5
  139. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  140. package/dist/secrets/routes.d.ts +9 -9
  141. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  142. package/dist/server/transcribe-voice.d.ts +1 -1
  143. package/docs/content/locales/ar-SA/pr-visual-recap.mdx +25 -1
  144. package/docs/content/locales/ar-SA/template-plan.mdx +1 -1
  145. package/docs/content/locales/de-DE/pr-visual-recap.mdx +25 -1
  146. package/docs/content/locales/de-DE/template-plan.mdx +1 -1
  147. package/docs/content/locales/es-ES/pr-visual-recap.mdx +25 -1
  148. package/docs/content/locales/es-ES/template-plan.mdx +1 -1
  149. package/docs/content/locales/fr-FR/pr-visual-recap.mdx +25 -1
  150. package/docs/content/locales/fr-FR/template-plan.mdx +1 -1
  151. package/docs/content/locales/hi-IN/pr-visual-recap.mdx +25 -1
  152. package/docs/content/locales/hi-IN/template-plan.mdx +1 -1
  153. package/docs/content/locales/ja-JP/pr-visual-recap.mdx +25 -1
  154. package/docs/content/locales/ja-JP/template-plan.mdx +1 -1
  155. package/docs/content/locales/ko-KR/pr-visual-recap.mdx +25 -1
  156. package/docs/content/locales/ko-KR/template-plan.mdx +1 -1
  157. package/docs/content/locales/pt-BR/pr-visual-recap.mdx +25 -1
  158. package/docs/content/locales/pt-BR/template-plan.mdx +1 -1
  159. package/docs/content/locales/zh-CN/pr-visual-recap.mdx +25 -1
  160. package/docs/content/locales/zh-CN/template-plan.mdx +1 -1
  161. package/docs/content/locales/zh-TW/pr-visual-recap.mdx +25 -1
  162. package/docs/content/locales/zh-TW/template-plan.mdx +1 -1
  163. package/docs/content/pr-visual-recap.mdx +50 -1
  164. package/docs/content/template-plan.mdx +1 -1
  165. package/package.json +2 -2
@@ -89,6 +89,13 @@ export type ConfigureTrackingOptions = {
89
89
  /** First-party analytics track endpoint. */
90
90
  endpoint?: string;
91
91
  getDefaultProps?: GetDefaultProps;
92
+ /**
93
+ * Disable content-capturing analytics such as interaction autocapture and
94
+ * session replay while retaining pageviews, explicit events, and Sentry.
95
+ */
96
+ contentCapture?: boolean;
97
+ /** Resolve content capture synchronously for each browser pathname. */
98
+ contentCaptureForPath?: (pathname: string) => boolean;
92
99
  sessionReplay?: boolean | SessionReplayOptions;
93
100
  /**
94
101
  * First-party, Sentry-style error capture. Auto-captures uncaught errors
@@ -132,6 +139,8 @@ let _errorCaptureDisposer: (() => void) | null = null;
132
139
  let _sessionReplayModuleForCapture:
133
140
  | typeof import("./session-replay.js")
134
141
  | null = null;
142
+ let _trackingContentCaptureEnabled = true;
143
+ let _contentCaptureForPath: ((pathname: string) => boolean) | null = null;
135
144
  // Buffer for setSentryUser calls made before Sentry has initialized.
136
145
  // `undefined` means "no pending update"; `null` means "pending clear".
137
146
  let _pendingSentryUser: SentryUser | null | undefined = undefined;
@@ -575,7 +584,10 @@ function ensureAmplitude(): boolean {
575
584
  const key = (import.meta.env as Record<string, string | undefined>)
576
585
  ?.VITE_AMPLITUDE_API_KEY;
577
586
  if (!key) return false;
578
- amplitude.init(key, { autocapture: true });
587
+ // Standard pageviews and explicit events are emitted below. Keep SDK-level
588
+ // DOM/network autocapture off so rendered user content is never collected as
589
+ // an implicit analytics side effect.
590
+ amplitude.init(key, { autocapture: false });
579
591
  _amplitudeInitialized = true;
580
592
  return true;
581
593
  }
@@ -896,7 +908,11 @@ export function setSentryUser(
896
908
  clearTrackingIdentity();
897
909
  }
898
910
  _trackingIdentityResolved = true;
899
- if (shouldRetryReplay && _sessionReplayOptions?.requireSignedInUser) {
911
+ if (
912
+ shouldRetryReplay &&
913
+ _trackingContentCaptureEnabled &&
914
+ _sessionReplayOptions?.requireSignedInUser
915
+ ) {
900
916
  void startConfiguredSessionReplay(_sessionReplayOptions);
901
917
  }
902
918
  if (_sentryInitialized) {
@@ -1004,6 +1020,11 @@ export function configureTracking(options: ConfigureTrackingOptions): void {
1004
1020
  if (options.getDefaultProps) {
1005
1021
  _getDefaultProps = options.getDefaultProps;
1006
1022
  }
1023
+ _contentCaptureForPath = options.contentCaptureForPath ?? null;
1024
+ _trackingContentCaptureEnabled =
1025
+ _contentCaptureForPath && typeof window !== "undefined"
1026
+ ? _contentCaptureForPath(window.location.pathname)
1027
+ : options.contentCapture !== false;
1007
1028
  if (typeof window !== "undefined") {
1008
1029
  ensureSentry();
1009
1030
  ensureAmplitude();
@@ -1011,14 +1032,37 @@ export function configureTracking(options: ConfigureTrackingOptions): void {
1011
1032
  installLlmConnectionRefresh();
1012
1033
  installTrackingAuthSessionRefresh();
1013
1034
  installPageviewTracking();
1014
- maybeInstallSessionReplay(options.sessionReplay, {
1015
- endpoint: options.endpoint,
1016
- publicKey,
1017
- });
1035
+ maybeInstallSessionReplay(
1036
+ options.sessionReplay,
1037
+ {
1038
+ endpoint: options.endpoint,
1039
+ publicKey,
1040
+ },
1041
+ _trackingContentCaptureEnabled,
1042
+ );
1018
1043
  maybeInstallErrorCapture(options.errorCapture);
1019
1044
  }
1020
1045
  }
1021
1046
 
1047
+ export function setTrackingContentCaptureEnabled(enabled: boolean): void {
1048
+ if (_trackingContentCaptureEnabled === enabled) return;
1049
+ _trackingContentCaptureEnabled = enabled;
1050
+ if (enabled) {
1051
+ if (_sessionReplayOptions) {
1052
+ void startConfiguredSessionReplay(_sessionReplayOptions);
1053
+ }
1054
+ } else {
1055
+ void stopSessionReplay("content-capture-disabled");
1056
+ }
1057
+ }
1058
+
1059
+ function syncTrackingContentCaptureForLocation(): void {
1060
+ if (!_contentCaptureForPath) return;
1061
+ setTrackingContentCaptureEnabled(
1062
+ _contentCaptureForPath(window.location.pathname),
1063
+ );
1064
+ }
1065
+
1022
1066
  /**
1023
1067
  * Lazily load the session-replay module so error capture can read the active
1024
1068
  * replay id and surface manual captures on the replay timeline without a
@@ -1254,11 +1298,12 @@ function replayEndpointFromTrackingEndpoint(value: string): string | undefined {
1254
1298
  function maybeInstallSessionReplay(
1255
1299
  config: boolean | SessionReplayOptions | undefined,
1256
1300
  tracking?: { endpoint?: string; publicKey?: string },
1301
+ start = true,
1257
1302
  ): void {
1258
1303
  if (typeof window === "undefined") return;
1259
1304
  const options = configuredSessionReplayOptions(config, tracking);
1260
- if (!options) return;
1261
1305
  _sessionReplayOptions = options;
1306
+ if (!options || !start) return;
1262
1307
  void startConfiguredSessionReplay(options);
1263
1308
  }
1264
1309
 
@@ -1284,11 +1329,24 @@ async function startConfiguredSessionReplay(
1284
1329
  ): Promise<SessionReplayStartResult | null> {
1285
1330
  if (_sessionReplayStartPromise) return _sessionReplayStartPromise;
1286
1331
  _sessionReplayStartPromise = (async () => {
1332
+ if (!_trackingContentCaptureEnabled) {
1333
+ return { started: false, reason: "disabled" as const };
1334
+ }
1287
1335
  if (!(await waitForSessionReplayAuthIfRequired(options))) {
1288
1336
  return { started: false, reason: "missing-user-id" as const };
1289
1337
  }
1338
+ if (!_trackingContentCaptureEnabled) {
1339
+ return { started: false, reason: "disabled" as const };
1340
+ }
1290
1341
  const mod = await import("./session-replay.js");
1291
- return mod.startSessionReplay(options);
1342
+ if (!_trackingContentCaptureEnabled) {
1343
+ return { started: false, reason: "disabled" as const };
1344
+ }
1345
+ return mod.startSessionReplay({
1346
+ ...options,
1347
+ shouldStart: () =>
1348
+ _trackingContentCaptureEnabled && (options.shouldStart?.() ?? true),
1349
+ });
1292
1350
  })()
1293
1351
  .catch(() => ({ started: false, reason: "import-failed" as const }))
1294
1352
  .finally(() => {
@@ -1300,23 +1358,37 @@ async function startConfiguredSessionReplay(
1300
1358
  export async function startSessionReplay(
1301
1359
  options: SessionReplayOptions = {},
1302
1360
  ): Promise<SessionReplayStartResult> {
1361
+ if (!_trackingContentCaptureEnabled) {
1362
+ return { started: false, reason: "disabled" };
1363
+ }
1303
1364
  const configured = configuredSessionReplayOptions(options) ?? options;
1304
1365
  if (!(await waitForSessionReplayAuthIfRequired(configured))) {
1305
1366
  return { started: false, reason: "missing-user-id" };
1306
1367
  }
1307
1368
  const mod = await import("./session-replay.js");
1308
- return mod.startSessionReplay(configured);
1369
+ return mod.startSessionReplay({
1370
+ ...configured,
1371
+ shouldStart: () =>
1372
+ _trackingContentCaptureEnabled && (configured.shouldStart?.() ?? true),
1373
+ });
1309
1374
  }
1310
1375
 
1311
1376
  export async function maybeStartSessionReplay(
1312
1377
  options: SessionReplayOptions = {},
1313
1378
  ): Promise<SessionReplayStartResult> {
1379
+ if (!_trackingContentCaptureEnabled) {
1380
+ return { started: false, reason: "disabled" };
1381
+ }
1314
1382
  const configured = configuredSessionReplayOptions(options) ?? options;
1315
1383
  if (!(await waitForSessionReplayAuthIfRequired(configured))) {
1316
1384
  return { started: false, reason: "missing-user-id" };
1317
1385
  }
1318
1386
  const mod = await import("./session-replay.js");
1319
- return mod.maybeStartSessionReplay(configured);
1387
+ return mod.maybeStartSessionReplay({
1388
+ ...configured,
1389
+ shouldStart: () =>
1390
+ _trackingContentCaptureEnabled && (configured.shouldStart?.() ?? true),
1391
+ });
1320
1392
  }
1321
1393
 
1322
1394
  export async function stopSessionReplay(reason = "manual"): Promise<void> {
@@ -1371,15 +1443,17 @@ function pageviewKey(): string {
1371
1443
 
1372
1444
  function pageviewProperties(reason: string): Record<string, unknown> {
1373
1445
  const properties: Record<string, unknown> = {
1374
- url: scrubUrl(window.location.href),
1446
+ url: !_trackingContentCaptureEnabled
1447
+ ? window.location.origin + window.location.pathname
1448
+ : scrubUrl(window.location.href),
1375
1449
  path: window.location.pathname,
1376
1450
  hostname: window.location.hostname,
1377
1451
  navigation_type: reason,
1378
1452
  };
1379
- if (window.location.search) {
1453
+ if (_trackingContentCaptureEnabled && window.location.search) {
1380
1454
  properties.search = scrubUrl(window.location.search);
1381
1455
  }
1382
- if (typeof document !== "undefined") {
1456
+ if (_trackingContentCaptureEnabled && typeof document !== "undefined") {
1383
1457
  if (document.referrer) {
1384
1458
  properties.referrer = scrubUrl(document.referrer);
1385
1459
  }
@@ -1400,6 +1474,9 @@ function emitPageview(reason: string): void {
1400
1474
  }
1401
1475
 
1402
1476
  function schedulePageview(reason: string): void {
1477
+ if (!_trackingContentCaptureEnabled) {
1478
+ void stopSessionReplay("local-plan-privacy");
1479
+ }
1403
1480
  const run = () => emitPageview(reason);
1404
1481
  const pendingStartupContext: Array<Promise<void>> = [];
1405
1482
  if (_llmConnectionRefresh && !_llmConnectionStatus) {
@@ -1436,17 +1513,22 @@ function installPageviewTracking(): void {
1436
1513
 
1437
1514
  window.history.pushState = function pushState(...args) {
1438
1515
  const result = originalPushState.apply(this, args);
1516
+ syncTrackingContentCaptureForLocation();
1439
1517
  schedulePageview("pushState");
1440
1518
  return result;
1441
1519
  };
1442
1520
 
1443
1521
  window.history.replaceState = function replaceState(...args) {
1444
1522
  const result = originalReplaceState.apply(this, args);
1523
+ syncTrackingContentCaptureForLocation();
1445
1524
  schedulePageview("replaceState");
1446
1525
  return result;
1447
1526
  };
1448
1527
 
1449
- window.addEventListener("popstate", () => schedulePageview("popstate"));
1528
+ window.addEventListener("popstate", () => {
1529
+ syncTrackingContentCaptureForLocation();
1530
+ schedulePageview("popstate");
1531
+ });
1450
1532
  }
1451
1533
 
1452
1534
  function sendAgentNativeAnalytics(
@@ -192,6 +192,10 @@ export {
192
192
  getChangeVersion,
193
193
  bumpChangeVersion,
194
194
  } from "./use-change-version.js";
195
+ export {
196
+ useDemoModeStatus,
197
+ type DemoModeStatus,
198
+ } from "./use-demo-mode-status.js";
195
199
  export { useReconciledState } from "./use-external-value.js";
196
200
  export {
197
201
  buildDynamicAgentSuggestions,
@@ -677,6 +681,7 @@ export {
677
681
  SettingsPanel,
678
682
  SettingsTabsPage,
679
683
  SecretsSection,
684
+ getAgentSettingsSearchTabs,
680
685
  openBuilderConnectPopup,
681
686
  useAgentSettingsTabs,
682
687
  useBuilderConnectFlow,
@@ -686,6 +691,7 @@ export {
686
691
  type BuilderConnectFlowOptions,
687
692
  type BuilderConnectStartOptions,
688
693
  type BuilderStatus,
694
+ type AgentSettingsSearchTab,
689
695
  type OpenBuilderConnectPopupOptions,
690
696
  type SecretsSectionProps,
691
697
  type SettingsPanelProps,
@@ -751,6 +757,7 @@ export {
751
757
  trackEvent,
752
758
  trackSessionStatus,
753
759
  configureTracking,
760
+ setTrackingContentCaptureEnabled,
754
761
  maybeStartSessionReplay,
755
762
  startSessionReplay,
756
763
  stopSessionReplay,
@@ -109,6 +109,8 @@ export interface SessionReplayNetworkOptions {
109
109
 
110
110
  export interface SessionReplayOptions {
111
111
  enabled?: boolean;
112
+ /** Rechecked immediately before rrweb starts to cancel deferred startup. */
113
+ shouldStart?: () => boolean;
112
114
  publicKey?: string;
113
115
  endpoint?: string;
114
116
  requireSignedInUser?: boolean;
@@ -208,6 +210,7 @@ interface NormalizedSessionReplayOptions {
208
210
  /** Null disables network capture entirely. */
209
211
  network: NormalizedCaptureOptions | null;
210
212
  extraProperties?: SessionReplayOptions["extraProperties"];
213
+ shouldStart?: SessionReplayOptions["shouldStart"];
211
214
  }
212
215
 
213
216
  interface NormalizedCaptureOptions {
@@ -656,6 +659,7 @@ function normalizeOptions(
656
659
  DEFAULT_MAX_NETWORK_EVENTS,
657
660
  ),
658
661
  extraProperties: options.extraProperties,
662
+ shouldStart: options.shouldStart,
659
663
  };
660
664
  }
661
665
 
@@ -1950,6 +1954,9 @@ export async function startSessionReplay(
1950
1954
  options: SessionReplayOptions = {},
1951
1955
  ): Promise<SessionReplayStartResult> {
1952
1956
  if (options.enabled === false) return { started: false, reason: "disabled" };
1957
+ if (options.shouldStart && !options.shouldStart()) {
1958
+ return { started: false, reason: "disabled" };
1959
+ }
1953
1960
  if (typeof window === "undefined" || typeof document === "undefined") {
1954
1961
  return { started: false, reason: "not-browser" };
1955
1962
  }
@@ -2032,6 +2039,9 @@ async function startSessionReplayRecorder(
2032
2039
  } catch {
2033
2040
  return { started: false, reason: "import-failed", sessionId, sampled };
2034
2041
  }
2042
+ if (normalized.shouldStart && !normalized.shouldStart()) {
2043
+ return { started: false, reason: "disabled", sessionId, sampled };
2044
+ }
2035
2045
 
2036
2046
  const replaySession = getOrCreateReplaySession(sessionId);
2037
2047
  state.options = normalized;
@@ -1,7 +1,7 @@
1
1
  /**
2
- * <DemoModeSection /> — toggle that replaces contact/free-text names, emails,
3
- * and numbers with realistic fake data everywhere (UI + what the agent sees)
4
- * while preserving labels, IDs, and structure so the app keeps working.
2
+ * <DemoModeSection /> — toggle that replaces emails and numbers with realistic
3
+ * fake data everywhere (UI + what the agent sees) while preserving names,
4
+ * free text, labels, IDs, and structure so the app keeps working.
5
5
  *
6
6
  * The toggle is stored in application_state under `demo-mode`
7
7
  * (`{ enabled: boolean }`) and written via `PUT
@@ -13,40 +13,18 @@
13
13
  */
14
14
 
15
15
  import { IconEyeOff } from "@tabler/icons-react";
16
- import { useQuery } from "@tanstack/react-query";
17
16
  import { useEffect, useState } from "react";
18
17
 
19
18
  import { agentNativePath } from "../api-path.js";
20
- import { useChangeVersion } from "../use-change-version.js";
19
+ import { useDemoModeStatus } from "../use-demo-mode-status.js";
21
20
 
22
- interface DemoStatus {
23
- enabled?: boolean;
24
- forced?: boolean;
25
- }
26
-
27
- const DEMO_STATUS_URL = agentNativePath("/_agent-native/demo/status");
28
21
  const DEMO_MODE_WRITE_URL = agentNativePath(
29
22
  "/_agent-native/application-state/demo-mode",
30
23
  );
31
24
 
32
25
  export function DemoModeSection() {
33
26
  const [enabled, setEnabled] = useState<boolean | null>(null);
34
- const demoModeVersion = useChangeVersion("app-state:demo-mode");
35
-
36
- const { data } = useQuery({
37
- queryKey: ["agent-native", "demo-mode", demoModeVersion],
38
- queryFn: async () => {
39
- const res = await fetch(DEMO_STATUS_URL, {
40
- credentials: "same-origin",
41
- });
42
- if (!res.ok) return null;
43
- return (await res.json()) as DemoStatus | null;
44
- },
45
- staleTime: Infinity,
46
- });
47
-
48
- const serverEnabled = data?.enabled;
49
- const forced = data?.forced === true;
27
+ const { enabled: serverEnabled, forced, isLoading } = useDemoModeStatus();
50
28
 
51
29
  // Surface the server value once it arrives (and on subsequent polls), but
52
30
  // never clobber an in-flight optimistic toggle with a stale read. When
@@ -54,12 +32,10 @@ export function DemoModeSection() {
54
32
  useEffect(() => {
55
33
  if (forced) {
56
34
  setEnabled(true);
57
- } else if (typeof serverEnabled === "boolean") {
35
+ } else if (!isLoading) {
58
36
  setEnabled((prev) => (prev === null ? serverEnabled : prev));
59
- } else if (serverEnabled === undefined && data !== undefined) {
60
- setEnabled((prev) => (prev === null ? false : prev));
61
37
  }
62
- }, [serverEnabled, forced, data]);
38
+ }, [serverEnabled, forced, isLoading]);
63
39
 
64
40
  const toggle = async (next: boolean) => {
65
41
  if (forced) return;
@@ -88,9 +64,9 @@ export function DemoModeSection() {
88
64
  Enable demo mode
89
65
  </div>
90
66
  <p className="text-[10px] text-muted-foreground mt-0.5">
91
- Replace contact/free-text names, emails, and numbers with realistic
92
- fake data everywhere — in the UI and what the agent sees. Labels, IDs,
93
- and structure are preserved so the app keeps working.
67
+ Replace emails and numbers with realistic fake data everywhere — in
68
+ the UI and what the agent sees. Names, free text, labels, IDs, and
69
+ structure are preserved so the app keeps working.
94
70
  </p>
95
71
  {forced && (
96
72
  <p className="text-[10px] text-muted-foreground mt-0.5">