@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
@@ -1,13 +1,15 @@
1
1
  /**
2
2
  * Pure, dependency-free, deterministic demo-mode redactor.
3
3
  *
4
- * Replaces sensitive values (names, emails, and free numbers) with stable fake
4
+ * Replaces sensitive values (emails and free numbers) with stable fake
5
5
  * substitutes so a demo looks coherent — the same input always maps to the
6
6
  * same fake. Crucially, it NEVER rewrites identifiers, structural tokens, or
7
- * timestamps: under-redaction is safe, corrupting an ID is not. The string
8
- * redactor uses a protect-first strategy (mask IDs with opaque placeholders
9
- * before any transform runs, restore them byte-identical afterwards), and the
10
- * structure-aware walker additionally protects leaf values by key name.
7
+ * timestamps. Names and other free text are deliberately left alone because
8
+ * guessing whether arbitrary text is a person's name is too inaccurate. The
9
+ * string redactor uses a protect-first strategy (mask IDs with opaque
10
+ * placeholders before any transform runs, restore them byte-identical
11
+ * afterwards), and the structure-aware walker additionally protects leaf
12
+ * values by key name.
11
13
  */
12
14
  /* ------------------------------------------------------------------ *
13
15
  * Seeded hash + PRNG (xmur3 seed → mulberry32 stream)
@@ -56,7 +58,7 @@ function pick(rng, pool) {
56
58
  * round-trips back through redaction (e.g. you edit a draft that's
57
59
  * already showing fake text, it autosaves, then refetches) it is passed
58
60
  * through UNCHANGED instead of being re-faked into something new. This
59
- * is what stops names/emails drifting on every edit.
61
+ * is what stops emails drifting on every edit.
60
62
  *
61
63
  * Leak-free by construction: no timers, a hard size cap, and lazy TTL purge
62
64
  * on write. Works the same per-tab in the browser and per-process on the
@@ -223,14 +225,6 @@ const LAST_NAMES = [
223
225
  /* ------------------------------------------------------------------ *
224
226
  * Fake value generators (deterministic in value + salt)
225
227
  * ------------------------------------------------------------------ */
226
- function fakeName(original, salt) {
227
- return memoFake("name", original, salt, () => {
228
- const rng = seededRng(`name:${original}`, salt);
229
- const first = pick(rng, FIRST_NAMES);
230
- const last = pick(rng, LAST_NAMES);
231
- return `${first} ${last}`;
232
- });
233
- }
234
228
  // Realistic-looking but safe stand-in domains: real consumer providers (the
235
229
  // local part is fake, so no real mailbox is implied) plus the canonical
236
230
  // reserved fictional-company domains (Contoso/Fabrikam/Northwind), which read
@@ -427,9 +421,6 @@ function unprotect(text, restore) {
427
421
  * Transforms (run only on protected text)
428
422
  * ------------------------------------------------------------------ */
429
423
  const EMAIL_RE = /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g;
430
- // 2+ capitalized words (each starts uppercase, allows internal lowercase /
431
- // apostrophes / hyphens). Single-letter middle initials allowed: `Sarah J Connor`.
432
- const FULL_NAME_RE = /\b[A-Z][a-zA-Z'’-]*(?:\s+[A-Z](?:[a-zA-Z'’-]*)?){1,3}\b/g;
433
424
  // A standalone numeric token: optional currency + sign, digits with optional
434
425
  // comma grouping and a single optional decimal part. Bounded so it is NOT
435
426
  // adjacent to a letter (placeholders already removed letter-mixed tokens, but
@@ -438,9 +429,6 @@ const NUMBER_RE = /(^|[^A-Za-z0-9_])([$€£]?)([+-]?)(\d[\d,]*(?:\.\d+)?)(?![A-
438
429
  function transformEmails(text, salt) {
439
430
  return text.replace(EMAIL_RE, (match) => fakeEmail(match, salt));
440
431
  }
441
- function transformNames(text, salt) {
442
- return text.replace(FULL_NAME_RE, (match) => fakeName(match, salt));
443
- }
444
432
  function isProbablyYear(digits) {
445
433
  if (digits.length !== 4)
446
434
  return false;
@@ -475,19 +463,17 @@ function transformNumbers(text, salt) {
475
463
  /* ------------------------------------------------------------------ *
476
464
  * Public: string redactor
477
465
  * ------------------------------------------------------------------ */
478
- function redactDemoStringInternal(text, salt, redactNames) {
466
+ function redactDemoStringInternal(text, salt) {
479
467
  if (typeof text !== "string" || text.length === 0)
480
468
  return text;
481
469
  const { text: masked, restore } = protect(text);
482
470
  let out = masked;
483
471
  out = transformEmails(out, salt);
484
- if (redactNames)
485
- out = transformNames(out, salt);
486
472
  out = transformNumbers(out, salt);
487
473
  return unprotect(out, restore);
488
474
  }
489
475
  export function redactDemoString(text, opts) {
490
- return redactDemoStringInternal(text, opts?.salt ?? "", true);
476
+ return redactDemoStringInternal(text, opts?.salt ?? "");
491
477
  }
492
478
  /* ------------------------------------------------------------------ *
493
479
  * Public: structure-aware redactor
@@ -495,29 +481,11 @@ export function redactDemoString(text, opts) {
495
481
  // Keys whose leaf values must NEVER be transformed (still recurse into nested
496
482
  // objects/arrays under them). Besides ids/urls/timestamps this also covers
497
483
  // code/query-bearing keys (`sql`, `query`, `expression`, `formula`, `code`):
498
- // prose-redacting a SQL string injects fake emails/numbers into it and rewrites
499
- // its leading tokens, producing `syntax error at or near "Henry"` /
500
- // `queries must start with SELECT or WITH`. The query must run untouched; its
501
- // RESULTS are what get redacted so the chart still shows fake values.
484
+ // redacting a SQL string mutates literals and can make the query semantically
485
+ // wrong or invalid. The query must run untouched; its RESULTS are what get
486
+ // redacted so the chart still shows fake values.
502
487
  const PROTECTED_KEY_RE = /^id$|(^|_)id$|Id$|Ids$|uuid|guid|slug|token|secret|password|passwd|apikey|api_key|hash|sha\d*|etag|cursor|nonce|sessionid|messageid|threadid|nodeid|(^|_)key$|keyid|(^|_)ref$|url$|uri$|href$|src$|path$|filename$|mimetype|mime|^sql$|sql$|query|expression|formula|^code$|createdat|updatedat|deletedat|expiresat|timestamp|.+at$|.+_at$/i;
503
- // UI labels and chart/dashboard titles often look like person names ("Maya
504
- // Davis (First-party)", "Clicks by Henry Moore") but are structural labels. Keep
505
- // them stable while still redacting free-text and contact-style person fields.
506
- const LABEL_TEXT_KEY_RE = /^(name|title|label)$/i;
507
488
  const MAX_DEPTH = 64;
508
- function isStandalonePersonNameLabel(text) {
509
- const trimmed = text.trim();
510
- if (!trimmed)
511
- return false;
512
- return /^[A-Z][a-zA-Z'’-]+(?:\s+[A-Z]\.?)?\s+[A-Z][a-zA-Z'’-]+$/.test(trimmed);
513
- }
514
- function shouldRedactNamesForChild(key, entry) {
515
- if (!LABEL_TEXT_KEY_RE.test(key))
516
- return true;
517
- // Preserve structural labels/titles, but do not let common contact-shaped
518
- // fields like `{ name: "Olivia Parker" }` leak real person names.
519
- return typeof entry === "string" ? isStandalonePersonNameLabel(entry) : true;
520
- }
521
489
  function isPlainObject(value) {
522
490
  if (value === null || typeof value !== "object")
523
491
  return false;
@@ -528,9 +496,6 @@ function isPlainObject(value) {
528
496
  const proto = Object.getPrototypeOf(value);
529
497
  return proto === Object.prototype || proto === null;
530
498
  }
531
- function redactDemoStringWithSalt(text, salt, redactNames) {
532
- return redactDemoStringInternal(text, salt, redactNames);
533
- }
534
499
  function redactNumberLeaf(value, salt) {
535
500
  if (!Number.isFinite(value))
536
501
  return value;
@@ -545,14 +510,14 @@ function redactNumberLeaf(value, salt) {
545
510
  return value;
546
511
  return n;
547
512
  }
548
- function walk(value, salt, depth, seen, redactNames) {
513
+ function walk(value, salt, depth, seen) {
549
514
  if (depth > MAX_DEPTH)
550
515
  return value;
551
516
  if (value === null || value === undefined)
552
517
  return value;
553
518
  const t = typeof value;
554
519
  if (t === "string") {
555
- return redactDemoStringWithSalt(value, salt, redactNames);
520
+ return redactDemoStringInternal(value, salt);
556
521
  }
557
522
  if (t === "number") {
558
523
  return redactNumberLeaf(value, salt);
@@ -566,7 +531,7 @@ function walk(value, salt, depth, seen, redactNames) {
566
531
  if (seen.has(value))
567
532
  return value;
568
533
  seen.add(value);
569
- const out = value.map((item) => walk(item, salt, depth + 1, seen, redactNames));
534
+ const out = value.map((item) => walk(item, salt, depth + 1, seen));
570
535
  seen.delete(value);
571
536
  return out;
572
537
  }
@@ -583,7 +548,7 @@ function walk(value, salt, depth, seen, redactNames) {
583
548
  !(entry instanceof Date)) {
584
549
  // Still recurse into nested structures, but the protected key does
585
550
  // not transform its own leaf value.
586
- out[key] = walk(entry, salt, depth + 1, seen, redactNames);
551
+ out[key] = walk(entry, salt, depth + 1, seen);
587
552
  }
588
553
  else {
589
554
  // Leaf under a protected key: pass through completely untouched.
@@ -591,7 +556,7 @@ function walk(value, salt, depth, seen, redactNames) {
591
556
  }
592
557
  continue;
593
558
  }
594
- out[key] = walk(entry, salt, depth + 1, seen, redactNames && shouldRedactNamesForChild(key, entry));
559
+ out[key] = walk(entry, salt, depth + 1, seen);
595
560
  }
596
561
  seen.delete(value);
597
562
  return out;
@@ -601,7 +566,7 @@ function walk(value, salt, depth, seen, redactNames) {
601
566
  }
602
567
  export function redactDemoData(value, opts) {
603
568
  const salt = opts?.salt ?? "";
604
- return walk(value, salt, 0, new WeakSet(), true);
569
+ return walk(value, salt, 0, new WeakSet());
605
570
  }
606
571
  /**
607
572
  * Clear the stable-mapping caches. Test-only — the caches are process-global
@@ -1 +1 @@
1
- {"version":3,"file":"redact.js","sourceRoot":"","sources":["../../src/demo/redact.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pure, dependency-free, deterministic demo-mode redactor.\n *\n * Replaces sensitive values (names, emails, and free numbers) with stable fake\n * substitutes so a demo looks coherent — the same input always maps to the\n * same fake. Crucially, it NEVER rewrites identifiers, structural tokens, or\n * timestamps: under-redaction is safe, corrupting an ID is not. The string\n * redactor uses a protect-first strategy (mask IDs with opaque placeholders\n * before any transform runs, restore them byte-identical afterwards), and the\n * structure-aware walker additionally protects leaf values by key name.\n */\n\nexport interface RedactOptions {\n salt?: string;\n}\n\n/* ------------------------------------------------------------------ *\n * Seeded hash + PRNG (xmur3 seed → mulberry32 stream)\n * ------------------------------------------------------------------ */\n\nfunction xmur3(str: string): () => number {\n let h = 1779033703 ^ str.length;\n for (let i = 0; i < str.length; i++) {\n h = Math.imul(h ^ str.charCodeAt(i), 3432918353);\n h = (h << 13) | (h >>> 19);\n }\n return function () {\n h = Math.imul(h ^ (h >>> 16), 2246822507);\n h = Math.imul(h ^ (h >>> 13), 3266489909);\n h ^= h >>> 16;\n return h >>> 0;\n };\n}\n\nfunction mulberry32(seed: number): () => number {\n let a = seed >>> 0;\n return function () {\n a = (a + 0x6d2b79f5) >>> 0;\n let t = a;\n t = Math.imul(t ^ (t >>> 15), t | 1);\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61);\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\n/** Deterministic PRNG seeded by `value + salt`. */\nfunction seededRng(value: string, salt: string): () => number {\n const seedFn = xmur3(`${value}${salt}`);\n return mulberry32(seedFn());\n}\n\nfunction pick<T>(rng: () => number, pool: readonly T[]): T {\n return pool[Math.floor(rng() * pool.length) % pool.length];\n}\n\n/* ------------------------------------------------------------------ *\n * Stable mapping cache (bounded, TTL, leak-free)\n *\n * The fake values are already a pure deterministic function of\n * (kind, salt, original), so identical input is always stable. This cache\n * adds two things on top:\n *\n * 1. A consistent forward map so the same original keeps the same fake for\n * the life of the entry, even if the algorithm/salt is ever tuned.\n * 2. Idempotency: every fake we emit is remembered, so when a fake value\n * round-trips back through redaction (e.g. you edit a draft that's\n * already showing fake text, it autosaves, then refetches) it is passed\n * through UNCHANGED instead of being re-faked into something new. This\n * is what stops names/emails drifting on every edit.\n *\n * Leak-free by construction: no timers, a hard size cap, and lazy TTL purge\n * on write. Works the same per-tab in the browser and per-process on the\n * server. Memoizing a pure function across users is safe — output depends\n * only on input.\n * ------------------------------------------------------------------ */\n\nconst CACHE_TTL_MS = 60 * 60 * 1000; // 1 hour\nconst CACHE_MAX = 5000;\n\n// original-key → { fake, at }. Insertion-ordered (Map) so the oldest key is\n// first — used for cap eviction.\nconst forwardCache = new Map<string, { value: string; at: number }>();\n// produced fake → last-seen timestamp (same bound/TTL policy).\nconst producedFakes = new Map<string, number>();\n\nfunction purge(map: Map<string, { at: number } | number>): void {\n const now = Date.now();\n for (const [k, v] of map) {\n const at = typeof v === \"number\" ? v : v.at;\n if (now - at > CACHE_TTL_MS) map.delete(k);\n else break; // insertion-ordered: first fresh entry ⇒ rest are fresher\n }\n while (map.size > CACHE_MAX) {\n const oldest = map.keys().next().value as string | undefined;\n if (oldest === undefined) break;\n map.delete(oldest);\n }\n}\n\nfunction rememberProduced(fake: string): string {\n if (fake.length === 0) return fake;\n producedFakes.delete(fake);\n producedFakes.set(fake, Date.now());\n if (producedFakes.size > CACHE_MAX) purge(producedFakes);\n return fake;\n}\n\nfunction isProducedFake(value: string): boolean {\n const at = producedFakes.get(value);\n if (at === undefined) return false;\n if (Date.now() - at > CACHE_TTL_MS) {\n producedFakes.delete(value);\n return false;\n }\n return true;\n}\n\n/**\n * Memoize a deterministic fake by (kind, salt, original). On a hit, the\n * entry's recency is refreshed (LRU-ish). The generated value is also\n * registered as a produced fake so it survives a round-trip unchanged.\n */\nfunction memoFake(\n kind: string,\n original: string,\n salt: string,\n gen: () => string,\n // Numbers opt out: a fake number collides with real numbers far too often\n // to safely treat \"looks like one we emitted\" as \"leave it alone\".\n idempotent = true,\n): string {\n // Already one of our fakes? Leave it exactly as-is (round-trip stable).\n if (idempotent && isProducedFake(original)) return original;\n\n const key = `${kind}${salt}${original}`;\n const hit = forwardCache.get(key);\n const now = Date.now();\n if (hit && now - hit.at <= CACHE_TTL_MS) {\n forwardCache.delete(key);\n forwardCache.set(key, { value: hit.value, at: now });\n return hit.value;\n }\n\n const value = gen();\n forwardCache.set(key, { value, at: now });\n if (forwardCache.size > CACHE_MAX) purge(forwardCache);\n if (idempotent) rememberProduced(value);\n return value;\n}\n\n/* ------------------------------------------------------------------ *\n * Curated name pools\n * ------------------------------------------------------------------ */\n\nconst FIRST_NAMES: readonly string[] = [\n \"Jane\",\n \"John\",\n \"Alex\",\n \"Maria\",\n \"Sam\",\n \"Olivia\",\n \"Liam\",\n \"Emma\",\n \"Noah\",\n \"Ava\",\n \"Lucas\",\n \"Mia\",\n \"Ethan\",\n \"Sofia\",\n \"Mason\",\n \"Isla\",\n \"Leo\",\n \"Aria\",\n \"Henry\",\n \"Zoe\",\n \"Owen\",\n \"Nora\",\n \"Caleb\",\n \"Lily\",\n \"Ryan\",\n \"Ruby\",\n \"Adam\",\n \"Chloe\",\n \"Eli\",\n \"Hazel\",\n \"Max\",\n \"Iris\",\n \"Ben\",\n \"Clara\",\n \"Theo\",\n \"Maya\",\n \"Felix\",\n \"Elena\",\n \"Jonah\",\n \"Greta\",\n];\n\nconst LAST_NAMES: readonly string[] = [\n \"Doe\",\n \"Smith\",\n \"Johnson\",\n \"Lee\",\n \"Brown\",\n \"Garcia\",\n \"Miller\",\n \"Davis\",\n \"Wilson\",\n \"Moore\",\n \"Taylor\",\n \"Anderson\",\n \"Thomas\",\n \"Jackson\",\n \"White\",\n \"Harris\",\n \"Martin\",\n \"Clark\",\n \"Lewis\",\n \"Walker\",\n \"Hall\",\n \"Young\",\n \"King\",\n \"Wright\",\n \"Hill\",\n \"Green\",\n \"Adams\",\n \"Baker\",\n \"Nelson\",\n \"Carter\",\n \"Mitchell\",\n \"Perez\",\n \"Roberts\",\n \"Turner\",\n \"Phillips\",\n \"Campbell\",\n \"Parker\",\n \"Evans\",\n \"Edwards\",\n \"Collins\",\n];\n\n/* ------------------------------------------------------------------ *\n * Fake value generators (deterministic in value + salt)\n * ------------------------------------------------------------------ */\n\nfunction fakeName(original: string, salt: string): string {\n return memoFake(\"name\", original, salt, () => {\n const rng = seededRng(`name:${original}`, salt);\n const first = pick(rng, FIRST_NAMES);\n const last = pick(rng, LAST_NAMES);\n return `${first} ${last}`;\n });\n}\n\n// Realistic-looking but safe stand-in domains: real consumer providers (the\n// local part is fake, so no real mailbox is implied) plus the canonical\n// reserved fictional-company domains (Contoso/Fabrikam/Northwind), which read\n// as real businesses but are intentional placeholders. No example.com.\nconst FAKE_EMAIL_DOMAINS: readonly string[] = [\n \"gmail.com\",\n \"outlook.com\",\n \"icloud.com\",\n \"yahoo.com\",\n \"proton.me\",\n \"hey.com\",\n \"fastmail.com\",\n \"contoso.com\",\n \"fabrikam.com\",\n \"northwind.com\",\n \"acme.io\",\n \"globex.net\",\n];\n\nfunction fakeEmail(original: string, salt: string): string {\n return memoFake(\"email\", original.toLowerCase(), salt, () => {\n const rng = seededRng(`email:${original.toLowerCase()}`, salt);\n const first = pick(rng, FIRST_NAMES).toLowerCase();\n const last = pick(rng, LAST_NAMES).toLowerCase();\n const domain = pick(rng, FAKE_EMAIL_DOMAINS);\n // Vary the local part so addresses don't all look templated.\n const shape = Math.floor(rng() * 6);\n let local: string;\n switch (shape) {\n case 0:\n local = `${first}.${last}`;\n break;\n case 1:\n local = `${first}${last}`;\n break;\n case 2:\n local = `${first[0]}${last}`;\n break;\n case 3:\n local = `${first}.${last}${1 + Math.floor(rng() * 89)}`;\n break;\n case 4:\n local = `${first}_${last}`;\n break;\n default:\n local = `${last}.${first}`;\n break;\n }\n return `${local}@${domain}`;\n });\n}\n\n/**\n * Replace every digit in `numericBody` with a freshly-generated digit while\n * preserving non-digit characters (grouping commas, decimal points) exactly.\n * The first digit is forced non-zero so the digit count is observable.\n */\nfunction fakeNumberBody(\n numericBody: string,\n original: string,\n salt: string,\n): string {\n // Stable per original token, but NOT registered as a produced fake — a\n // fake number coincides with real numbers too often to skip on round-trip.\n return memoFake(\n \"num\",\n original,\n salt,\n () => {\n const rng = seededRng(`num:${original}`, salt);\n let out = \"\";\n let seenDigit = false;\n for (const ch of numericBody) {\n if (ch >= \"0\" && ch <= \"9\") {\n let d: number;\n if (!seenDigit) {\n // Leading digit: 1-9 so length is preserved.\n d = 1 + Math.floor(rng() * 9);\n seenDigit = true;\n } else {\n d = Math.floor(rng() * 10);\n }\n out += String(d);\n } else {\n out += ch;\n }\n }\n return out;\n },\n false,\n );\n}\n\n/* ------------------------------------------------------------------ *\n * Protect-first tokenizer (ID-safety core)\n * ------------------------------------------------------------------ */\n\n/**\n * Patterns whose matches must be protected from ANY transform. Order matters:\n * the most structural / specific shapes come first so they win the scan.\n */\nconst PROTECT_PATTERNS: RegExp[] = [\n // URLs / URIs with a scheme.\n /\\b[a-zA-Z][a-zA-Z0-9+.-]*:\\/\\/[^\\s]+/g,\n /\\b(?:mailto|data|tel|urn):[^\\s]+/gi,\n // UUID.\n /\\b[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\\b/g,\n // JWT — three base64url segments separated by dots.\n /\\b[A-Za-z0-9_-]{4,}\\.[A-Za-z0-9_-]{4,}\\.[A-Za-z0-9_-]{4,}\\b/g,\n // ISO datetime / date.\n /\\b\\d{4}-\\d{2}-\\d{2}(?:[T ]\\d{2}:\\d{2}(?::\\d{2})?(?:\\.\\d+)?Z?)?\\b/g,\n // Bare clock time.\n /\\b\\d{1,2}:\\d{2}(?::\\d{2})?\\b/g,\n // Path-like tokens containing a slash (but not bare prose with slashes —\n // require no spaces and at least one slash with adjacent non-space).\n /(?:\\S*\\/\\S+)+/g,\n // nanoid / hex / base64-ish blobs: an unbroken [A-Za-z0-9_-] run that is\n // either long-with-a-digit, mixes letters AND digits at length >= 10, or\n // contains a `_`/`-` inside the run (real names/numbers never look so).\n /[A-Za-z0-9_-]+/g,\n];\n\nconst PLACEHOLDER_PREFIX = \"\u0001P\";\nconst PLACEHOLDER_SUFFIX = \"\u0001\";\n\nfunction makePlaceholder(index: number): string {\n return `${PLACEHOLDER_PREFIX}${index}${PLACEHOLDER_SUFFIX}`;\n}\n\n/** True if a `[A-Za-z0-9_-]+` run is identifier-shaped (must be protected). */\nfunction looksLikeIdentifierToken(tok: string): boolean {\n if (tok.length < 3) return false;\n const hasLetter = /[A-Za-z]/.test(tok);\n const hasDigit = /[0-9]/.test(tok);\n const hasSep = /[_-]/.test(tok);\n\n // A pure number (optionally with separators handled elsewhere) is NOT an\n // identifier here — the number rule handles those.\n if (!hasLetter && !hasSep) return false;\n\n // Long hex/base64-ish blob with a digit.\n if (tok.length >= 16 && hasDigit) return true;\n // nanoid-ish: length >= 10 mixing letters AND digits.\n if (tok.length >= 10 && hasLetter && hasDigit) return true;\n // Any token that has a `_`/`-` joined inside an unbroken run AND also\n // contains a digit or is long — e.g. `order-2024-abc`, `api_key_v2`.\n if (hasSep && (hasDigit || tok.length >= 10)) return true;\n // Mixed letters+digits adjacency (e.g. `abc123`, `v2`, `step3`) — protect so\n // the number rule never bites an embedded number.\n if (hasLetter && hasDigit) return true;\n\n return false;\n}\n\ninterface Protection {\n text: string;\n restore: Map<string, string>;\n}\n\n/**\n * Walk `text`, replace every protected substring with an opaque placeholder,\n * and return the masked text plus a restore map. Non-overlapping, left-to-right\n * earliest-match-wins so a transform literally cannot see a protected value.\n */\nfunction protect(text: string): Protection {\n const restore = new Map<string, string>();\n let counter = 0;\n\n // Collect all candidate matches across patterns, then resolve overlaps by\n // earliest start (and longest on tie).\n interface Span {\n start: number;\n end: number;\n value: string;\n }\n const spans: Span[] = [];\n\n for (let p = 0; p < PROTECT_PATTERNS.length; p++) {\n const re = new RegExp(\n PROTECT_PATTERNS[p].source,\n PROTECT_PATTERNS[p].flags,\n );\n let m: RegExpExecArray | null;\n while ((m = re.exec(text)) !== null) {\n const value = m[0];\n if (value.length === 0) {\n re.lastIndex++;\n continue;\n }\n const isTokenPattern = p === PROTECT_PATTERNS.length - 1;\n if (isTokenPattern && !looksLikeIdentifierToken(value)) {\n continue;\n }\n spans.push({ start: m.index, end: m.index + value.length, value });\n }\n }\n\n if (spans.length === 0) return { text, restore };\n\n spans.sort((a, b) =>\n a.start !== b.start ? a.start - b.start : b.end - a.end,\n );\n\n let out = \"\";\n let cursor = 0;\n for (const span of spans) {\n if (span.start < cursor) continue; // overlapped by an earlier protection\n out += text.slice(cursor, span.start);\n const ph = makePlaceholder(counter++);\n restore.set(ph, span.value);\n out += ph;\n cursor = span.end;\n }\n out += text.slice(cursor);\n\n return { text: out, restore };\n}\n\nfunction unprotect(text: string, restore: Map<string, string>): string {\n if (restore.size === 0) return text;\n let out = text;\n for (const [ph, original] of restore) {\n out = out.split(ph).join(original);\n }\n return out;\n}\n\n/* ------------------------------------------------------------------ *\n * Transforms (run only on protected text)\n * ------------------------------------------------------------------ */\n\nconst EMAIL_RE = /\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}\\b/g;\n\n// 2+ capitalized words (each starts uppercase, allows internal lowercase /\n// apostrophes / hyphens). Single-letter middle initials allowed: `Sarah J Connor`.\nconst FULL_NAME_RE = /\\b[A-Z][a-zA-Z'’-]*(?:\\s+[A-Z](?:[a-zA-Z'’-]*)?){1,3}\\b/g;\n\n// A standalone numeric token: optional currency + sign, digits with optional\n// comma grouping and a single optional decimal part. Bounded so it is NOT\n// adjacent to a letter (placeholders already removed letter-mixed tokens, but\n// this keeps the rule self-contained and safe on raw structured values too).\nconst NUMBER_RE =\n /(^|[^A-Za-z0-9_])([$€£]?)([+-]?)(\\d[\\d,]*(?:\\.\\d+)?)(?![A-Za-z0-9_])/g;\n\nfunction transformEmails(text: string, salt: string): string {\n return text.replace(EMAIL_RE, (match) => fakeEmail(match, salt));\n}\n\nfunction transformNames(text: string, salt: string): string {\n return text.replace(FULL_NAME_RE, (match) => fakeName(match, salt));\n}\n\nfunction isProbablyYear(digits: string): boolean {\n if (digits.length !== 4) return false;\n const n = Number(digits);\n return n >= 1900 && n <= 2099;\n}\n\nfunction transformNumbers(text: string, salt: string): string {\n return text.replace(\n NUMBER_RE,\n (_full, pre: string, currency: string, sign: string, body: string) => {\n const hasGrouping = body.includes(\",\");\n const hasDecimal = body.includes(\".\");\n const digitsOnly = body.replace(/[^0-9]/g, \"\");\n\n // Skip bare years like 2026.\n if (\n !currency &&\n !sign &&\n !hasGrouping &&\n !hasDecimal &&\n isProbablyYear(digitsOnly)\n ) {\n return `${pre}${currency}${sign}${body}`;\n }\n\n // Skip standalone integers < 1000 with no currency and no grouping\n // (rewriting \"3 unread\" / \"page 2\" looks broken and isn't sensitive).\n if (!currency && !hasGrouping && !hasDecimal) {\n const n = Number(digitsOnly);\n if (Number.isFinite(n) && n < 1000) {\n return `${pre}${currency}${sign}${body}`;\n }\n }\n\n const fakeBody = fakeNumberBody(body, `${currency}${sign}${body}`, salt);\n return `${pre}${currency}${sign}${fakeBody}`;\n },\n );\n}\n\n/* ------------------------------------------------------------------ *\n * Public: string redactor\n * ------------------------------------------------------------------ */\n\nfunction redactDemoStringInternal(\n text: string,\n salt: string,\n redactNames: boolean,\n): string {\n if (typeof text !== \"string\" || text.length === 0) return text;\n\n const { text: masked, restore } = protect(text);\n let out = masked;\n out = transformEmails(out, salt);\n if (redactNames) out = transformNames(out, salt);\n out = transformNumbers(out, salt);\n return unprotect(out, restore);\n}\n\nexport function redactDemoString(text: string, opts?: RedactOptions): string {\n return redactDemoStringInternal(text, opts?.salt ?? \"\", true);\n}\n\n/* ------------------------------------------------------------------ *\n * Public: structure-aware redactor\n * ------------------------------------------------------------------ */\n\n// Keys whose leaf values must NEVER be transformed (still recurse into nested\n// objects/arrays under them). Besides ids/urls/timestamps this also covers\n// code/query-bearing keys (`sql`, `query`, `expression`, `formula`, `code`):\n// prose-redacting a SQL string injects fake emails/numbers into it and rewrites\n// its leading tokens, producing `syntax error at or near \"Henry\"` /\n// `queries must start with SELECT or WITH`. The query must run untouched; its\n// RESULTS are what get redacted so the chart still shows fake values.\nconst PROTECTED_KEY_RE =\n /^id$|(^|_)id$|Id$|Ids$|uuid|guid|slug|token|secret|password|passwd|apikey|api_key|hash|sha\\d*|etag|cursor|nonce|sessionid|messageid|threadid|nodeid|(^|_)key$|keyid|(^|_)ref$|url$|uri$|href$|src$|path$|filename$|mimetype|mime|^sql$|sql$|query|expression|formula|^code$|createdat|updatedat|deletedat|expiresat|timestamp|.+at$|.+_at$/i;\n\n// UI labels and chart/dashboard titles often look like person names (\"Maya\n// Davis (First-party)\", \"Clicks by Henry Moore\") but are structural labels. Keep\n// them stable while still redacting free-text and contact-style person fields.\nconst LABEL_TEXT_KEY_RE = /^(name|title|label)$/i;\n\nconst MAX_DEPTH = 64;\n\nfunction isStandalonePersonNameLabel(text: string): boolean {\n const trimmed = text.trim();\n if (!trimmed) return false;\n return /^[A-Z][a-zA-Z'’-]+(?:\\s+[A-Z]\\.?)?\\s+[A-Z][a-zA-Z'’-]+$/.test(\n trimmed,\n );\n}\n\nfunction shouldRedactNamesForChild(key: string, entry: unknown): boolean {\n if (!LABEL_TEXT_KEY_RE.test(key)) return true;\n // Preserve structural labels/titles, but do not let common contact-shaped\n // fields like `{ name: \"Olivia Parker\" }` leak real person names.\n return typeof entry === \"string\" ? isStandalonePersonNameLabel(entry) : true;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== \"object\") return false;\n if (Array.isArray(value)) return false;\n if (value instanceof Date) return false;\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\nfunction redactDemoStringWithSalt(\n text: string,\n salt: string,\n redactNames: boolean,\n): string {\n return redactDemoStringInternal(text, salt, redactNames);\n}\n\nfunction redactNumberLeaf(value: number, salt: string): number {\n if (!Number.isFinite(value)) return value;\n const repr = String(value);\n // Re-use the string number transform but only if the representation is a\n // clean numeric token we can round-trip back to a JS number.\n const redacted = transformNumbers(repr, salt);\n if (redacted === repr) return value;\n const n = Number(redacted);\n if (!Number.isFinite(n)) return value;\n return n;\n}\n\nfunction walk(\n value: unknown,\n salt: string,\n depth: number,\n seen: WeakSet<object>,\n redactNames: boolean,\n): unknown {\n if (depth > MAX_DEPTH) return value;\n\n if (value === null || value === undefined) return value;\n\n const t = typeof value;\n\n if (t === \"string\") {\n return redactDemoStringWithSalt(value as string, salt, redactNames);\n }\n\n if (t === \"number\") {\n return redactNumberLeaf(value as number, salt);\n }\n\n if (t === \"boolean\" || t === \"bigint\" || t === \"function\" || t === \"symbol\") {\n return value;\n }\n\n if (value instanceof Date) return value;\n\n if (Array.isArray(value)) {\n if (seen.has(value)) return value;\n seen.add(value);\n const out = value.map((item) =>\n walk(item, salt, depth + 1, seen, redactNames),\n );\n seen.delete(value);\n return out;\n }\n\n if (isPlainObject(value)) {\n if (seen.has(value)) return value;\n seen.add(value);\n const out: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(value)) {\n const keyIsProtected = PROTECTED_KEY_RE.test(key);\n if (keyIsProtected) {\n if (\n entry !== null &&\n typeof entry === \"object\" &&\n !(entry instanceof Date)\n ) {\n // Still recurse into nested structures, but the protected key does\n // not transform its own leaf value.\n out[key] = walk(entry, salt, depth + 1, seen, redactNames);\n } else {\n // Leaf under a protected key: pass through completely untouched.\n out[key] = entry;\n }\n continue;\n }\n out[key] = walk(\n entry,\n salt,\n depth + 1,\n seen,\n redactNames && shouldRedactNamesForChild(key, entry),\n );\n }\n seen.delete(value);\n return out;\n }\n\n // Unknown object kind (Map, Set, class instance, etc.) — leave untouched.\n return value;\n}\n\nexport function redactDemoData<T>(value: T, opts?: RedactOptions): T {\n const salt = opts?.salt ?? \"\";\n return walk(value, salt, 0, new WeakSet<object>(), true) as T;\n}\n\n/**\n * Clear the stable-mapping caches. Test-only — the caches are process-global\n * (intentionally, so mappings stay stable for a tab's session), which would\n * otherwise let one test's produced fakes leak into another's assertions.\n */\nexport function __resetDemoRedactCacheForTests(): void {\n forwardCache.clear();\n producedFakes.clear();\n}\n"]}
1
+ {"version":3,"file":"redact.js","sourceRoot":"","sources":["../../src/demo/redact.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pure, dependency-free, deterministic demo-mode redactor.\n *\n * Replaces sensitive values (emails and free numbers) with stable fake\n * substitutes so a demo looks coherent — the same input always maps to the\n * same fake. Crucially, it NEVER rewrites identifiers, structural tokens, or\n * timestamps. Names and other free text are deliberately left alone because\n * guessing whether arbitrary text is a person's name is too inaccurate. The\n * string redactor uses a protect-first strategy (mask IDs with opaque\n * placeholders before any transform runs, restore them byte-identical\n * afterwards), and the structure-aware walker additionally protects leaf\n * values by key name.\n */\n\nexport interface RedactOptions {\n salt?: string;\n}\n\n/* ------------------------------------------------------------------ *\n * Seeded hash + PRNG (xmur3 seed → mulberry32 stream)\n * ------------------------------------------------------------------ */\n\nfunction xmur3(str: string): () => number {\n let h = 1779033703 ^ str.length;\n for (let i = 0; i < str.length; i++) {\n h = Math.imul(h ^ str.charCodeAt(i), 3432918353);\n h = (h << 13) | (h >>> 19);\n }\n return function () {\n h = Math.imul(h ^ (h >>> 16), 2246822507);\n h = Math.imul(h ^ (h >>> 13), 3266489909);\n h ^= h >>> 16;\n return h >>> 0;\n };\n}\n\nfunction mulberry32(seed: number): () => number {\n let a = seed >>> 0;\n return function () {\n a = (a + 0x6d2b79f5) >>> 0;\n let t = a;\n t = Math.imul(t ^ (t >>> 15), t | 1);\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61);\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\n/** Deterministic PRNG seeded by `value + salt`. */\nfunction seededRng(value: string, salt: string): () => number {\n const seedFn = xmur3(`${value}${salt}`);\n return mulberry32(seedFn());\n}\n\nfunction pick<T>(rng: () => number, pool: readonly T[]): T {\n return pool[Math.floor(rng() * pool.length) % pool.length];\n}\n\n/* ------------------------------------------------------------------ *\n * Stable mapping cache (bounded, TTL, leak-free)\n *\n * The fake values are already a pure deterministic function of\n * (kind, salt, original), so identical input is always stable. This cache\n * adds two things on top:\n *\n * 1. A consistent forward map so the same original keeps the same fake for\n * the life of the entry, even if the algorithm/salt is ever tuned.\n * 2. Idempotency: every fake we emit is remembered, so when a fake value\n * round-trips back through redaction (e.g. you edit a draft that's\n * already showing fake text, it autosaves, then refetches) it is passed\n * through UNCHANGED instead of being re-faked into something new. This\n * is what stops emails drifting on every edit.\n *\n * Leak-free by construction: no timers, a hard size cap, and lazy TTL purge\n * on write. Works the same per-tab in the browser and per-process on the\n * server. Memoizing a pure function across users is safe — output depends\n * only on input.\n * ------------------------------------------------------------------ */\n\nconst CACHE_TTL_MS = 60 * 60 * 1000; // 1 hour\nconst CACHE_MAX = 5000;\n\n// original-key → { fake, at }. Insertion-ordered (Map) so the oldest key is\n// first — used for cap eviction.\nconst forwardCache = new Map<string, { value: string; at: number }>();\n// produced fake → last-seen timestamp (same bound/TTL policy).\nconst producedFakes = new Map<string, number>();\n\nfunction purge(map: Map<string, { at: number } | number>): void {\n const now = Date.now();\n for (const [k, v] of map) {\n const at = typeof v === \"number\" ? v : v.at;\n if (now - at > CACHE_TTL_MS) map.delete(k);\n else break; // insertion-ordered: first fresh entry ⇒ rest are fresher\n }\n while (map.size > CACHE_MAX) {\n const oldest = map.keys().next().value as string | undefined;\n if (oldest === undefined) break;\n map.delete(oldest);\n }\n}\n\nfunction rememberProduced(fake: string): string {\n if (fake.length === 0) return fake;\n producedFakes.delete(fake);\n producedFakes.set(fake, Date.now());\n if (producedFakes.size > CACHE_MAX) purge(producedFakes);\n return fake;\n}\n\nfunction isProducedFake(value: string): boolean {\n const at = producedFakes.get(value);\n if (at === undefined) return false;\n if (Date.now() - at > CACHE_TTL_MS) {\n producedFakes.delete(value);\n return false;\n }\n return true;\n}\n\n/**\n * Memoize a deterministic fake by (kind, salt, original). On a hit, the\n * entry's recency is refreshed (LRU-ish). The generated value is also\n * registered as a produced fake so it survives a round-trip unchanged.\n */\nfunction memoFake(\n kind: string,\n original: string,\n salt: string,\n gen: () => string,\n // Numbers opt out: a fake number collides with real numbers far too often\n // to safely treat \"looks like one we emitted\" as \"leave it alone\".\n idempotent = true,\n): string {\n // Already one of our fakes? Leave it exactly as-is (round-trip stable).\n if (idempotent && isProducedFake(original)) return original;\n\n const key = `${kind}${salt}${original}`;\n const hit = forwardCache.get(key);\n const now = Date.now();\n if (hit && now - hit.at <= CACHE_TTL_MS) {\n forwardCache.delete(key);\n forwardCache.set(key, { value: hit.value, at: now });\n return hit.value;\n }\n\n const value = gen();\n forwardCache.set(key, { value, at: now });\n if (forwardCache.size > CACHE_MAX) purge(forwardCache);\n if (idempotent) rememberProduced(value);\n return value;\n}\n\n/* ------------------------------------------------------------------ *\n * Curated name pools\n * ------------------------------------------------------------------ */\n\nconst FIRST_NAMES: readonly string[] = [\n \"Jane\",\n \"John\",\n \"Alex\",\n \"Maria\",\n \"Sam\",\n \"Olivia\",\n \"Liam\",\n \"Emma\",\n \"Noah\",\n \"Ava\",\n \"Lucas\",\n \"Mia\",\n \"Ethan\",\n \"Sofia\",\n \"Mason\",\n \"Isla\",\n \"Leo\",\n \"Aria\",\n \"Henry\",\n \"Zoe\",\n \"Owen\",\n \"Nora\",\n \"Caleb\",\n \"Lily\",\n \"Ryan\",\n \"Ruby\",\n \"Adam\",\n \"Chloe\",\n \"Eli\",\n \"Hazel\",\n \"Max\",\n \"Iris\",\n \"Ben\",\n \"Clara\",\n \"Theo\",\n \"Maya\",\n \"Felix\",\n \"Elena\",\n \"Jonah\",\n \"Greta\",\n];\n\nconst LAST_NAMES: readonly string[] = [\n \"Doe\",\n \"Smith\",\n \"Johnson\",\n \"Lee\",\n \"Brown\",\n \"Garcia\",\n \"Miller\",\n \"Davis\",\n \"Wilson\",\n \"Moore\",\n \"Taylor\",\n \"Anderson\",\n \"Thomas\",\n \"Jackson\",\n \"White\",\n \"Harris\",\n \"Martin\",\n \"Clark\",\n \"Lewis\",\n \"Walker\",\n \"Hall\",\n \"Young\",\n \"King\",\n \"Wright\",\n \"Hill\",\n \"Green\",\n \"Adams\",\n \"Baker\",\n \"Nelson\",\n \"Carter\",\n \"Mitchell\",\n \"Perez\",\n \"Roberts\",\n \"Turner\",\n \"Phillips\",\n \"Campbell\",\n \"Parker\",\n \"Evans\",\n \"Edwards\",\n \"Collins\",\n];\n\n/* ------------------------------------------------------------------ *\n * Fake value generators (deterministic in value + salt)\n * ------------------------------------------------------------------ */\n\n// Realistic-looking but safe stand-in domains: real consumer providers (the\n// local part is fake, so no real mailbox is implied) plus the canonical\n// reserved fictional-company domains (Contoso/Fabrikam/Northwind), which read\n// as real businesses but are intentional placeholders. No example.com.\nconst FAKE_EMAIL_DOMAINS: readonly string[] = [\n \"gmail.com\",\n \"outlook.com\",\n \"icloud.com\",\n \"yahoo.com\",\n \"proton.me\",\n \"hey.com\",\n \"fastmail.com\",\n \"contoso.com\",\n \"fabrikam.com\",\n \"northwind.com\",\n \"acme.io\",\n \"globex.net\",\n];\n\nfunction fakeEmail(original: string, salt: string): string {\n return memoFake(\"email\", original.toLowerCase(), salt, () => {\n const rng = seededRng(`email:${original.toLowerCase()}`, salt);\n const first = pick(rng, FIRST_NAMES).toLowerCase();\n const last = pick(rng, LAST_NAMES).toLowerCase();\n const domain = pick(rng, FAKE_EMAIL_DOMAINS);\n // Vary the local part so addresses don't all look templated.\n const shape = Math.floor(rng() * 6);\n let local: string;\n switch (shape) {\n case 0:\n local = `${first}.${last}`;\n break;\n case 1:\n local = `${first}${last}`;\n break;\n case 2:\n local = `${first[0]}${last}`;\n break;\n case 3:\n local = `${first}.${last}${1 + Math.floor(rng() * 89)}`;\n break;\n case 4:\n local = `${first}_${last}`;\n break;\n default:\n local = `${last}.${first}`;\n break;\n }\n return `${local}@${domain}`;\n });\n}\n\n/**\n * Replace every digit in `numericBody` with a freshly-generated digit while\n * preserving non-digit characters (grouping commas, decimal points) exactly.\n * The first digit is forced non-zero so the digit count is observable.\n */\nfunction fakeNumberBody(\n numericBody: string,\n original: string,\n salt: string,\n): string {\n // Stable per original token, but NOT registered as a produced fake — a\n // fake number coincides with real numbers too often to skip on round-trip.\n return memoFake(\n \"num\",\n original,\n salt,\n () => {\n const rng = seededRng(`num:${original}`, salt);\n let out = \"\";\n let seenDigit = false;\n for (const ch of numericBody) {\n if (ch >= \"0\" && ch <= \"9\") {\n let d: number;\n if (!seenDigit) {\n // Leading digit: 1-9 so length is preserved.\n d = 1 + Math.floor(rng() * 9);\n seenDigit = true;\n } else {\n d = Math.floor(rng() * 10);\n }\n out += String(d);\n } else {\n out += ch;\n }\n }\n return out;\n },\n false,\n );\n}\n\n/* ------------------------------------------------------------------ *\n * Protect-first tokenizer (ID-safety core)\n * ------------------------------------------------------------------ */\n\n/**\n * Patterns whose matches must be protected from ANY transform. Order matters:\n * the most structural / specific shapes come first so they win the scan.\n */\nconst PROTECT_PATTERNS: RegExp[] = [\n // URLs / URIs with a scheme.\n /\\b[a-zA-Z][a-zA-Z0-9+.-]*:\\/\\/[^\\s]+/g,\n /\\b(?:mailto|data|tel|urn):[^\\s]+/gi,\n // UUID.\n /\\b[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\\b/g,\n // JWT — three base64url segments separated by dots.\n /\\b[A-Za-z0-9_-]{4,}\\.[A-Za-z0-9_-]{4,}\\.[A-Za-z0-9_-]{4,}\\b/g,\n // ISO datetime / date.\n /\\b\\d{4}-\\d{2}-\\d{2}(?:[T ]\\d{2}:\\d{2}(?::\\d{2})?(?:\\.\\d+)?Z?)?\\b/g,\n // Bare clock time.\n /\\b\\d{1,2}:\\d{2}(?::\\d{2})?\\b/g,\n // Path-like tokens containing a slash (but not bare prose with slashes —\n // require no spaces and at least one slash with adjacent non-space).\n /(?:\\S*\\/\\S+)+/g,\n // nanoid / hex / base64-ish blobs: an unbroken [A-Za-z0-9_-] run that is\n // either long-with-a-digit, mixes letters AND digits at length >= 10, or\n // contains a `_`/`-` inside the run (real names/numbers never look so).\n /[A-Za-z0-9_-]+/g,\n];\n\nconst PLACEHOLDER_PREFIX = \"\u0001P\";\nconst PLACEHOLDER_SUFFIX = \"\u0001\";\n\nfunction makePlaceholder(index: number): string {\n return `${PLACEHOLDER_PREFIX}${index}${PLACEHOLDER_SUFFIX}`;\n}\n\n/** True if a `[A-Za-z0-9_-]+` run is identifier-shaped (must be protected). */\nfunction looksLikeIdentifierToken(tok: string): boolean {\n if (tok.length < 3) return false;\n const hasLetter = /[A-Za-z]/.test(tok);\n const hasDigit = /[0-9]/.test(tok);\n const hasSep = /[_-]/.test(tok);\n\n // A pure number (optionally with separators handled elsewhere) is NOT an\n // identifier here — the number rule handles those.\n if (!hasLetter && !hasSep) return false;\n\n // Long hex/base64-ish blob with a digit.\n if (tok.length >= 16 && hasDigit) return true;\n // nanoid-ish: length >= 10 mixing letters AND digits.\n if (tok.length >= 10 && hasLetter && hasDigit) return true;\n // Any token that has a `_`/`-` joined inside an unbroken run AND also\n // contains a digit or is long — e.g. `order-2024-abc`, `api_key_v2`.\n if (hasSep && (hasDigit || tok.length >= 10)) return true;\n // Mixed letters+digits adjacency (e.g. `abc123`, `v2`, `step3`) — protect so\n // the number rule never bites an embedded number.\n if (hasLetter && hasDigit) return true;\n\n return false;\n}\n\ninterface Protection {\n text: string;\n restore: Map<string, string>;\n}\n\n/**\n * Walk `text`, replace every protected substring with an opaque placeholder,\n * and return the masked text plus a restore map. Non-overlapping, left-to-right\n * earliest-match-wins so a transform literally cannot see a protected value.\n */\nfunction protect(text: string): Protection {\n const restore = new Map<string, string>();\n let counter = 0;\n\n // Collect all candidate matches across patterns, then resolve overlaps by\n // earliest start (and longest on tie).\n interface Span {\n start: number;\n end: number;\n value: string;\n }\n const spans: Span[] = [];\n\n for (let p = 0; p < PROTECT_PATTERNS.length; p++) {\n const re = new RegExp(\n PROTECT_PATTERNS[p].source,\n PROTECT_PATTERNS[p].flags,\n );\n let m: RegExpExecArray | null;\n while ((m = re.exec(text)) !== null) {\n const value = m[0];\n if (value.length === 0) {\n re.lastIndex++;\n continue;\n }\n const isTokenPattern = p === PROTECT_PATTERNS.length - 1;\n if (isTokenPattern && !looksLikeIdentifierToken(value)) {\n continue;\n }\n spans.push({ start: m.index, end: m.index + value.length, value });\n }\n }\n\n if (spans.length === 0) return { text, restore };\n\n spans.sort((a, b) =>\n a.start !== b.start ? a.start - b.start : b.end - a.end,\n );\n\n let out = \"\";\n let cursor = 0;\n for (const span of spans) {\n if (span.start < cursor) continue; // overlapped by an earlier protection\n out += text.slice(cursor, span.start);\n const ph = makePlaceholder(counter++);\n restore.set(ph, span.value);\n out += ph;\n cursor = span.end;\n }\n out += text.slice(cursor);\n\n return { text: out, restore };\n}\n\nfunction unprotect(text: string, restore: Map<string, string>): string {\n if (restore.size === 0) return text;\n let out = text;\n for (const [ph, original] of restore) {\n out = out.split(ph).join(original);\n }\n return out;\n}\n\n/* ------------------------------------------------------------------ *\n * Transforms (run only on protected text)\n * ------------------------------------------------------------------ */\n\nconst EMAIL_RE = /\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}\\b/g;\n\n// A standalone numeric token: optional currency + sign, digits with optional\n// comma grouping and a single optional decimal part. Bounded so it is NOT\n// adjacent to a letter (placeholders already removed letter-mixed tokens, but\n// this keeps the rule self-contained and safe on raw structured values too).\nconst NUMBER_RE =\n /(^|[^A-Za-z0-9_])([$€£]?)([+-]?)(\\d[\\d,]*(?:\\.\\d+)?)(?![A-Za-z0-9_])/g;\n\nfunction transformEmails(text: string, salt: string): string {\n return text.replace(EMAIL_RE, (match) => fakeEmail(match, salt));\n}\n\nfunction isProbablyYear(digits: string): boolean {\n if (digits.length !== 4) return false;\n const n = Number(digits);\n return n >= 1900 && n <= 2099;\n}\n\nfunction transformNumbers(text: string, salt: string): string {\n return text.replace(\n NUMBER_RE,\n (_full, pre: string, currency: string, sign: string, body: string) => {\n const hasGrouping = body.includes(\",\");\n const hasDecimal = body.includes(\".\");\n const digitsOnly = body.replace(/[^0-9]/g, \"\");\n\n // Skip bare years like 2026.\n if (\n !currency &&\n !sign &&\n !hasGrouping &&\n !hasDecimal &&\n isProbablyYear(digitsOnly)\n ) {\n return `${pre}${currency}${sign}${body}`;\n }\n\n // Skip standalone integers < 1000 with no currency and no grouping\n // (rewriting \"3 unread\" / \"page 2\" looks broken and isn't sensitive).\n if (!currency && !hasGrouping && !hasDecimal) {\n const n = Number(digitsOnly);\n if (Number.isFinite(n) && n < 1000) {\n return `${pre}${currency}${sign}${body}`;\n }\n }\n\n const fakeBody = fakeNumberBody(body, `${currency}${sign}${body}`, salt);\n return `${pre}${currency}${sign}${fakeBody}`;\n },\n );\n}\n\n/* ------------------------------------------------------------------ *\n * Public: string redactor\n * ------------------------------------------------------------------ */\n\nfunction redactDemoStringInternal(text: string, salt: string): string {\n if (typeof text !== \"string\" || text.length === 0) return text;\n\n const { text: masked, restore } = protect(text);\n let out = masked;\n out = transformEmails(out, salt);\n out = transformNumbers(out, salt);\n return unprotect(out, restore);\n}\n\nexport function redactDemoString(text: string, opts?: RedactOptions): string {\n return redactDemoStringInternal(text, opts?.salt ?? \"\");\n}\n\n/* ------------------------------------------------------------------ *\n * Public: structure-aware redactor\n * ------------------------------------------------------------------ */\n\n// Keys whose leaf values must NEVER be transformed (still recurse into nested\n// objects/arrays under them). Besides ids/urls/timestamps this also covers\n// code/query-bearing keys (`sql`, `query`, `expression`, `formula`, `code`):\n// redacting a SQL string mutates literals and can make the query semantically\n// wrong or invalid. The query must run untouched; its RESULTS are what get\n// redacted so the chart still shows fake values.\nconst PROTECTED_KEY_RE =\n /^id$|(^|_)id$|Id$|Ids$|uuid|guid|slug|token|secret|password|passwd|apikey|api_key|hash|sha\\d*|etag|cursor|nonce|sessionid|messageid|threadid|nodeid|(^|_)key$|keyid|(^|_)ref$|url$|uri$|href$|src$|path$|filename$|mimetype|mime|^sql$|sql$|query|expression|formula|^code$|createdat|updatedat|deletedat|expiresat|timestamp|.+at$|.+_at$/i;\n\nconst MAX_DEPTH = 64;\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== \"object\") return false;\n if (Array.isArray(value)) return false;\n if (value instanceof Date) return false;\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\nfunction redactNumberLeaf(value: number, salt: string): number {\n if (!Number.isFinite(value)) return value;\n const repr = String(value);\n // Re-use the string number transform but only if the representation is a\n // clean numeric token we can round-trip back to a JS number.\n const redacted = transformNumbers(repr, salt);\n if (redacted === repr) return value;\n const n = Number(redacted);\n if (!Number.isFinite(n)) return value;\n return n;\n}\n\nfunction walk(\n value: unknown,\n salt: string,\n depth: number,\n seen: WeakSet<object>,\n): unknown {\n if (depth > MAX_DEPTH) return value;\n\n if (value === null || value === undefined) return value;\n\n const t = typeof value;\n\n if (t === \"string\") {\n return redactDemoStringInternal(value as string, salt);\n }\n\n if (t === \"number\") {\n return redactNumberLeaf(value as number, salt);\n }\n\n if (t === \"boolean\" || t === \"bigint\" || t === \"function\" || t === \"symbol\") {\n return value;\n }\n\n if (value instanceof Date) return value;\n\n if (Array.isArray(value)) {\n if (seen.has(value)) return value;\n seen.add(value);\n const out = value.map((item) => walk(item, salt, depth + 1, seen));\n seen.delete(value);\n return out;\n }\n\n if (isPlainObject(value)) {\n if (seen.has(value)) return value;\n seen.add(value);\n const out: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(value)) {\n const keyIsProtected = PROTECTED_KEY_RE.test(key);\n if (keyIsProtected) {\n if (\n entry !== null &&\n typeof entry === \"object\" &&\n !(entry instanceof Date)\n ) {\n // Still recurse into nested structures, but the protected key does\n // not transform its own leaf value.\n out[key] = walk(entry, salt, depth + 1, seen);\n } else {\n // Leaf under a protected key: pass through completely untouched.\n out[key] = entry;\n }\n continue;\n }\n out[key] = walk(entry, salt, depth + 1, seen);\n }\n seen.delete(value);\n return out;\n }\n\n // Unknown object kind (Map, Set, class instance, etc.) — leave untouched.\n return value;\n}\n\nexport function redactDemoData<T>(value: T, opts?: RedactOptions): T {\n const salt = opts?.salt ?? \"\";\n return walk(value, salt, 0, new WeakSet<object>()) as T;\n}\n\n/**\n * Clear the stable-mapping caches. Test-only — the caches are process-global\n * (intentionally, so mappings stay stable for a tab's session), which would\n * otherwise let one test's produced fakes leak into another's assertions.\n */\nexport function __resetDemoRedactCacheForTests(): void {\n forwardCache.clear();\n producedFakes.clear();\n}\n"]}
@@ -13,13 +13,13 @@
13
13
  export declare function createNotificationsHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<"" | import("./types.js").Notification[] | {
14
14
  count: number;
15
15
  updated?: undefined;
16
- ok?: undefined;
17
16
  error?: undefined;
17
+ ok?: undefined;
18
18
  } | {
19
19
  count?: undefined;
20
20
  updated: number;
21
- ok?: undefined;
22
21
  error?: undefined;
22
+ ok?: undefined;
23
23
  } | {
24
24
  count?: undefined;
25
25
  updated?: undefined;
@@ -41,28 +41,28 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
41
41
  thumbsUpRate: number;
42
42
  avgEvalScore: number;
43
43
  } | {
44
- error?: undefined;
45
- ok?: undefined;
46
44
  summary: import("./types.js").TraceSummary;
47
45
  spans: import("./types.js").TraceSpan[];
48
46
  id?: undefined;
49
- } | {
50
47
  error?: undefined;
51
48
  ok?: undefined;
49
+ } | {
52
50
  summary?: undefined;
53
51
  spans?: undefined;
54
52
  id: string;
55
- } | {
53
+ error?: undefined;
56
54
  ok?: undefined;
55
+ } | {
57
56
  summary?: undefined;
58
57
  spans?: undefined;
59
58
  id?: undefined;
60
59
  error: any;
60
+ ok?: undefined;
61
61
  } | {
62
- error?: undefined;
63
62
  summary?: undefined;
64
63
  spans?: undefined;
65
64
  id?: undefined;
65
+ error?: undefined;
66
66
  ok: boolean;
67
67
  }>>;
68
68
  //# sourceMappingURL=routes.d.ts.map
@@ -73,6 +73,7 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
73
73
  offset?: unknown;
74
74
  limit?: unknown;
75
75
  }, {
76
+ deleted?: undefined;
76
77
  jobs: {
77
78
  id: string;
78
79
  name: string;
@@ -83,7 +84,6 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
83
84
  updatedAt: string;
84
85
  }[];
85
86
  total: number;
86
- deleted?: undefined;
87
87
  jobId?: undefined;
88
88
  } | {
89
89
  jobs?: undefined;
@@ -91,9 +91,9 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
91
91
  deleted: boolean;
92
92
  jobId: string;
93
93
  } | {
94
+ deleted?: undefined;
94
95
  jobs?: undefined;
95
96
  total?: undefined;
96
- deleted?: undefined;
97
97
  jobId?: undefined;
98
98
  hits: Record<string, unknown>[];
99
99
  offset: number;
@@ -34,37 +34,37 @@ export declare function createListSecretsHandler(): import("h3").EventHandlerWit
34
34
  /** POST /_agent-native/secrets/:key — write a secret. */
35
35
  export declare function createWriteSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
36
36
  error: string;
37
- ok?: undefined;
38
37
  status?: undefined;
38
+ ok?: undefined;
39
39
  } | {
40
- error?: undefined;
41
40
  ok: boolean;
42
41
  status: string;
42
+ error?: undefined;
43
43
  } | {
44
- ok?: undefined;
45
44
  error: string;
46
45
  removed?: undefined;
46
+ ok?: undefined;
47
47
  } | {
48
- error?: undefined;
49
48
  ok: boolean;
50
49
  removed: boolean;
50
+ error?: undefined;
51
51
  }>>;
52
52
  /**
53
53
  * POST /_agent-native/secrets/:key/test — re-run the validator against the
54
54
  * current stored value without changing anything. Useful for the "Test" button.
55
55
  */
56
56
  export declare function createTestSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
57
- ok?: undefined;
58
57
  error: string;
59
58
  note?: undefined;
59
+ ok?: undefined;
60
60
  } | {
61
- error?: undefined;
62
61
  ok: boolean;
63
62
  note?: undefined;
64
- } | {
65
63
  error?: undefined;
64
+ } | {
66
65
  ok: boolean;
67
66
  note: string;
67
+ error?: undefined;
68
68
  } | {
69
69
  note?: undefined;
70
70
  ok: boolean;
@@ -95,12 +95,12 @@ export interface AdHocSecretPayload {
95
95
  export declare function createAdHocSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<AdHocSecretPayload[] | {
96
96
  error: string;
97
97
  } | {
98
- error?: undefined;
99
98
  ok: boolean;
100
99
  key: string;
101
- } | {
102
100
  error?: undefined;
101
+ } | {
103
102
  ok: boolean;
104
103
  removed: boolean;
104
+ error?: undefined;
105
105
  }>>;
106
106
  //# sourceMappingURL=routes.d.ts.map
@@ -27,11 +27,11 @@ export declare function resolveAgentEngineApiKeyWriteTarget(event: H3Event, scop
27
27
  export declare function createAgentEngineApiKeyHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
28
28
  error: any;
29
29
  } | {
30
- error?: undefined;
31
30
  ok: boolean;
32
31
  key: string;
33
32
  baseUrlKey?: string;
34
33
  scope: AgentEngineApiKeyScope;
34
+ error?: undefined;
35
35
  }>>;
36
36
  export {};
37
37
  //# sourceMappingURL=agent-engine-api-key-route.d.ts.map
@@ -20,7 +20,7 @@ export declare function createTranscribeVoiceHandler(): import("h3").EventHandle
20
20
  error: string;
21
21
  text?: undefined;
22
22
  } | {
23
- error?: undefined;
24
23
  text: string;
24
+ error?: undefined;
25
25
  }>>;
26
26
  //# sourceMappingURL=transcribe-voice.d.ts.map
@@ -123,6 +123,28 @@ npx @agent-native/core@latest recap doctor
123
123
  يثبت مجلد `visual-recap` المخصص له، ويضبط متغير المستودع
124
124
  `VISUAL_RECAP_SKILL_SOURCE=repo`.
125
125
 
126
+ ## اختيار المشغّل
127
+
128
+ يعمل سير العمل افتراضيًا على مشغّلات `ubuntu-latest` المستضافة من GitHub. لاستخدام مشغّل مستضاف آخر أو مشغّل ذاتي الاستضافة، اضبط متغير المستودع أو المؤسسة `VISUAL_RECAP_RUNS_ON` على سلسلة JSON صالحة أو مصفوفة JSON من تسميات المشغّل:
129
+
130
+ ```text
131
+ "ubuntu-latest"
132
+ ["self-hosted", "linux", "x64", "visual-recap"]
133
+ ```
134
+
135
+ علامات الاقتباس في JSON مطلوبة. تحدد هذه القيمة مشغّل مهمة `recap` الكاملة. لتكوينه أثناء الإعداد الموجّه، مرّر قيمة JSON نفسها إلى `--runs-on`، ثم تحقق من سير العمل وتوفر المشغّل باستخدام `doctor`:
136
+
137
+ ```bash
138
+ npx @agent-native/core@latest recap setup --runs-on '["self-hosted","linux","x64","visual-recap"]'
139
+ npx @agent-native/core@latest recap doctor
140
+ ```
141
+
142
+ تستخدم بوابة الأمان الخفيفة `ubuntu-latest` بشكل منفصل. يمكن للمستودعات التي تعطل مشغّلات GitHub المستضافة ضبط `VISUAL_RECAP_GATE_RUNS_ON` على تسمية نصية واحدة بلا JSON، أو استخدام `--gate-runs-on visual-recap-gate`. تُستخدم التسمية المخصصة فقط لمؤلفي `OWNER` أو `MEMBER` أو `COLLABORATOR` من المستودع نفسه؛ تُفرض `ubuntu-latest` على الفروع والمؤلفين الآخرين وقد تبقى عملياتهم بلا جدولة عند تعطيل مشغّلات GitHub المستضافة. استخدم مشغّلًا مخصصًا ويفضل أن يكون مؤقتًا؛ لا تسحب البوابة القياسية شجرة PR وتقيّم منطق سير العمل وبيانات PR الوصفية.
143
+
144
+ يرفض `recap doctor` بيانات JSON غير الصالحة أو غير المدعومة، ويبلغ عندما لا يعرض GitHub مشغّلًا متصلًا يطابق جميع التسميات المكوّنة. يظل تسجيل المشغّل وتثبيته وترقياته وسعته وصيانته من مسؤوليتك؛ يحدد Agent Native التسميات ولكنه لا يوفر المشغّل ولا يديره.
145
+
146
+ **الأمان:** يُفضّل استخدام مشغّلات ذاتية الاستضافة مؤقتة. يجب أن تخدم المشغّلات الدائمة ذاتية الاستضافة المستودعات الخاصة التي يقتصر المساهمون فيها على أشخاص موثوق بهم. يُغلق سير العمل بأمان قبل جدولة عمل ذاتي الاستضافة لمؤلفي PR غير الموثوق بهم في المستودعات العامة أو المتفرعة، لكن الجهاز الدائم يظل محتفظًا بحالة مساحة العمل والعمليات بين المهام. لا تضعف هذه البوابة ولا توجه مساهمات غير موثوقة إلى مشغّل دائم.
147
+
126
148
  ## تحديد الخلفية
127
149
 
128
150
  اختر وكيل الترميز الذي يقوم بتشغيل المهارة باستخدام متغير المستودع `VISUAL_RECAP_AGENT`:
@@ -460,10 +482,12 @@ jobs:
460
482
  model: ${{ vars.VISUAL_RECAP_MODEL || '' }}
461
483
  reasoning: ${{ vars.VISUAL_RECAP_REASONING || '' }}
462
484
  skill-source: ${{ vars.VISUAL_RECAP_SKILL_SOURCE || 'auto' }}
485
+ runs-on: ${{ vars.VISUAL_RECAP_RUNS_ON || '"ubuntu-latest"' }}
486
+ gate-runs-on: ${{ vars.VISUAL_RECAP_GATE_RUNS_ON || 'ubuntu-latest' }}
463
487
  # cli-version: "latest" # pin to a specific @agent-native/core version
464
488
  ```
465
489
 
466
- تنطبق نفس الأسرار والمتغيرات الموضحة في [Secrets and variables](#secrets-and-variables) - قم بتعيينها في إعدادات الريبو الخاصة بك بنفس الطريقة كما في متغير النسخ.
490
+ تنطبق الأسرار والمتغيرات نفسها الموضحة في [Secrets and variables](#secrets-and-variables). يمرر المتصل القابل لإعادة الاستخدام `VISUAL_RECAP_RUNS_ON` كـ `runs-on` للمهمة الكاملة، و`VISUAL_RECAP_GATE_RUNS_ON` كتسمية مفردة `gate-runs-on` للبوابة. يستخدم كلاهما `ubuntu-latest` عند الحذف.
467
491
 
468
492
  ### التثبيت عبر CLI
469
493
 
@@ -290,7 +290,7 @@ npx @agent-native/core@latest plan local serve --dir plans/<slug> --kind plan --
290
290
  ```
291
291
 
292
292
  يبدو شكل الجسر URL
293
- `https://plan.agent-native.com/local-plans/<slug>?bridge=http://127.0.0.1:...`.
293
+ `https://plan.agent-native.com/local-plans/local-<opaque-id>#bridge=http://127.0.0.1:...`.
294
294
  الصفحة هي عارض الخطة العادي، لكن المتصفح يجلب `plan.mdx`،
295
295
  `canvas.mdx`، و`prototype.mdx`، و`.plan-state.json`، وأصول الصور المحلية من
296
296
  جسر المضيف المحلي. لا تتم كتابة محتوى الخطة في قاعدة البيانات المستضافة وهي
@@ -123,6 +123,28 @@ Referenzdateien, mit denen der Skill geliefert wird. Wenn Ihr Repo absichtlich a
123
123
  pinnen den festgeschriebenen `visual-recap`-Ordner an und legen die Repository-Variable fest
124
124
  `VISUAL_RECAP_SKILL_SOURCE=repo`.
125
125
 
126
+ ## Runner-Auswahl
127
+
128
+ Standardmäßig wird der Workflow auf von GitHub gehosteten `ubuntu-latest`-Runnern ausgeführt. Um einen anderen gehosteten Runner oder einen eigenen selbst gehosteten Runner zu verwenden, setzen Sie die Repository- oder Organisationsvariable `VISUAL_RECAP_RUNS_ON` auf eine gültige JSON-Zeichenfolge oder ein JSON-Array mit Runner-Labels:
129
+
130
+ ```text
131
+ "ubuntu-latest"
132
+ ["self-hosted", "linux", "x64", "visual-recap"]
133
+ ```
134
+
135
+ Die JSON-Anführungszeichen sind erforderlich. Dieser Wert wählt den Runner für den vollständigen `recap`-Job. Übergeben Sie zur Konfiguration während der geführten Einrichtung denselben JSON-Wert an `--runs-on` und prüfen Sie anschließend den Workflow und die Verfügbarkeit des Runners mit `doctor`:
136
+
137
+ ```bash
138
+ npx @agent-native/core@latest recap setup --runs-on '["self-hosted","linux","x64","visual-recap"]'
139
+ npx @agent-native/core@latest recap doctor
140
+ ```
141
+
142
+ Das einfache Gate verwendet separat `ubuntu-latest`. Repositorys ohne von GitHub gehostete Runner können `VISUAL_RECAP_GATE_RUNS_ON` auf ein einzelnes Klartext-Label ohne JSON setzen oder `--gate-runs-on visual-recap-gate` verwenden. Das benutzerdefinierte Label gilt nur für `OWNER`-, `MEMBER`- oder `COLLABORATOR`-Autoren desselben Repositorys; Forks und andere Autoren werden auf `ubuntu-latest` gezwungen und können ohne GitHub-gehostete Runner ungeplant bleiben. Nutzen Sie einen dedizierten, möglichst kurzlebigen Runner: Das Standard-Gate checkt den PR-Baum nicht aus und wertet Workflow-Logik sowie PR-Metadaten aus.
143
+
144
+ `recap doctor` lehnt fehlerhaftes oder nicht unterstütztes JSON ab und meldet, wenn GitHub keinen Online-Runner bereitstellt, der alle konfigurierten Labels erfüllt. Registrierung, Installation, Upgrades, Kapazität und Wartung des Runners liegen weiterhin in Ihrer Verantwortung; Agent Native wählt die Labels aus, stellt oder betreibt den Runner jedoch nicht.
145
+
146
+ **Sicherheit:** Bevorzugen Sie kurzlebige selbst gehostete Runner. Persistente selbst gehostete Runner sollten nur privaten Repositorys mit vertrauenswürdigen Mitwirkenden dienen. Der Workflow bricht ab, bevor selbst gehostete Arbeit für nicht vertrauenswürdige Autoren öffentlicher oder Fork-PRs eingeplant wird, doch eine persistente Maschine behält zwischen Jobs weiterhin Arbeitsbereichs- und Prozesszustand. Schwächen Sie dieses Gate nicht ab und leiten Sie keine nicht vertrauenswürdigen Beiträge an einen persistenten Runner weiter.
147
+
126
148
  ## Backend-Auswahl
127
149
 
128
150
  Wählen Sie mit der Repository-Variable `VISUAL_RECAP_AGENT` aus, welcher Codierungsagent den Skill ausführt:
@@ -460,10 +482,12 @@ jobs:
460
482
  model: ${{ vars.VISUAL_RECAP_MODEL || '' }}
461
483
  reasoning: ${{ vars.VISUAL_RECAP_REASONING || '' }}
462
484
  skill-source: ${{ vars.VISUAL_RECAP_SKILL_SOURCE || 'auto' }}
485
+ runs-on: ${{ vars.VISUAL_RECAP_RUNS_ON || '"ubuntu-latest"' }}
486
+ gate-runs-on: ${{ vars.VISUAL_RECAP_GATE_RUNS_ON || 'ubuntu-latest' }}
463
487
  # cli-version: "latest" # pin to a specific @agent-native/core version
464
488
  ```
465
489
 
466
- Es gelten die gleichen Geheimnisse und Variablen wie in [Secrets and variables](#secrets-and-variables) beschrieben legen Sie sie in Ihren Repo-Einstellungen auf die gleiche Weise fest wie für die Kopiervariante.
490
+ Es gelten dieselben Geheimnisse und Variablen wie unter [Secrets and variables](#secrets-and-variables). Der wiederverwendbare Aufrufer leitet `VISUAL_RECAP_RUNS_ON` als `runs-on` für den vollständigen Job und `VISUAL_RECAP_GATE_RUNS_ON` als einfaches `gate-runs-on`-Label für das Gate weiter. Ohne Eingabe verwenden beide `ubuntu-latest`.
467
491
 
468
492
  ### Installation über CLI
469
493