@agent-native/core 0.99.0 → 0.99.2

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 (184) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +23 -0
  3. package/corpus/core/package.json +1 -1
  4. package/corpus/core/src/agent/production-agent.ts +33 -38
  5. package/corpus/core/src/audit/config.ts +0 -1
  6. package/corpus/core/src/chat-threads/store.ts +57 -41
  7. package/corpus/core/src/cli/pr-visual-recap-workflow.ts +1 -1
  8. package/corpus/core/src/client/AssistantChat.tsx +1 -2
  9. package/corpus/core/src/client/analytics.ts +13 -0
  10. package/corpus/core/src/client/chat/message-components.tsx +15 -3
  11. package/corpus/core/src/client/chat/tool-call-display.tsx +18 -1
  12. package/corpus/core/src/client/extensions/EmbeddedExtension.tsx +5 -9
  13. package/corpus/core/src/client/extensions/ExtensionViewer.tsx +0 -133
  14. package/corpus/core/src/client/index.ts +7 -0
  15. package/corpus/core/src/client/settings/DemoModeSection.tsx +9 -65
  16. package/corpus/core/src/client/settings/SettingsPanel.tsx +1 -1
  17. package/corpus/core/src/client/use-db-sync.ts +3 -15
  18. package/corpus/core/src/client/use-demo-mode-status.ts +16 -30
  19. package/corpus/core/src/demo/browser-state.ts +47 -0
  20. package/corpus/core/src/demo/fetch-interceptor.ts +12 -59
  21. package/corpus/core/src/deploy/workspace-deploy.ts +2 -2
  22. package/corpus/core/src/server/action-discovery.ts +0 -1
  23. package/corpus/core/src/server/agent-chat/action-filters-a2a.ts +13 -0
  24. package/corpus/core/src/server/agent-teams.ts +17 -0
  25. package/corpus/core/src/server/core-routes-plugin.ts +0 -30
  26. package/corpus/core/src/server/google-oauth.ts +6 -2
  27. package/corpus/core/src/templates/workspace-core/.agents/skills/native-navigation/SKILL.md +67 -0
  28. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +48 -7
  29. package/corpus/templates/analytics/AGENTS.md +4 -4
  30. package/corpus/templates/analytics/actions/compose-dashboard.ts +12 -1
  31. package/corpus/templates/analytics/actions/dashboard-mutation-api.ts +15 -4
  32. package/corpus/templates/analytics/actions/mutate-dashboard.ts +2 -1
  33. package/corpus/templates/analytics/actions/update-dashboard.ts +14 -0
  34. package/corpus/templates/analytics/app/assets/replay-cursor.svg +17 -0
  35. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +4 -3
  36. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +21 -27
  37. package/corpus/templates/analytics/app/global.css +17 -9
  38. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/DashboardFilterBar.tsx +32 -4
  39. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +4 -1
  40. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/interpolate.ts +21 -0
  41. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/types.ts +14 -0
  42. package/corpus/templates/analytics/app/pages/monitoring/errors/IssueDetail.tsx +1 -1
  43. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +77 -23
  44. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +4 -6
  45. package/corpus/templates/analytics/changelog/2026-07-13-all-time-dashboard-filters-no-longer-send-invalid-dates-to-b.md +6 -0
  46. package/corpus/templates/analytics/changelog/2026-07-13-dashboard-charts-now-honor-the-selected-time-range-by-defaul.md +6 -0
  47. package/corpus/templates/analytics/changelog/2026-07-13-error-issue-titles-wrap-instead-of-overflowing.md +6 -0
  48. package/corpus/templates/analytics/changelog/2026-07-13-keep-real-authorized-identities-in-analytics-incident-lookup.md +6 -0
  49. package/corpus/templates/analytics/changelog/2026-07-13-saving-a-new-dashboard-view-no-longer-fails-with-a-server-er.md +6 -0
  50. package/corpus/templates/analytics/changelog/2026-07-13-session-replay-cursors-stay-hidden-until-their-first-recorde.md +6 -0
  51. package/corpus/templates/analytics/changelog/2026-07-13-session-replay-links-now-support-cmd-click-and-middle-click-.md +6 -0
  52. package/corpus/templates/analytics/changelog/2026-07-13-the-analytics-agents-tab-is-available-again-from-the-main-na.md +6 -0
  53. package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +3 -3
  54. package/corpus/templates/analytics/server/lib/agent-readable-resource-context.ts +4 -0
  55. package/corpus/templates/analytics/server/lib/dashboard-time-scope.ts +170 -0
  56. package/corpus/templates/analytics/server/lib/dashboards-store.ts +43 -4
  57. package/corpus/templates/analytics/server/lib/error-capture.ts +30 -67
  58. package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +20 -5
  59. package/corpus/templates/analytics/server/lib/session-replay-agent-context.ts +1 -1
  60. package/corpus/templates/analytics/server/lib/session-replay.ts +5 -111
  61. package/corpus/templates/analytics/server/plugins/agent-chat.ts +6 -0
  62. package/corpus/templates/assets/app/routes/library.tsx +3 -4
  63. package/corpus/templates/assets/changelog/2026-07-13-internal-library-links-open-in-new-tabs.md +6 -0
  64. package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +43 -40
  65. package/corpus/templates/calendar/app/pages/ManageBookingPage.tsx +6 -8
  66. package/corpus/templates/calendar/changelog/2026-07-13-booking-links-and-previews-open-in-new-tabs.md +6 -0
  67. package/corpus/templates/clips/app/components/library/recording-card.tsx +27 -26
  68. package/corpus/templates/clips/app/components/library/space-card.tsx +4 -6
  69. package/corpus/templates/clips/app/components/player/sign-in-prompt-dialog.tsx +4 -7
  70. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +19 -9
  71. package/corpus/templates/clips/app/routes/share.$shareId.tsx +5 -3
  72. package/corpus/templates/clips/changelog/2026-07-13-recording-links-open-in-new-tabs.md +6 -0
  73. package/corpus/templates/content/app/components/editor/ContentReferencePreview.tsx +6 -8
  74. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +5 -3
  75. package/corpus/templates/content/app/components/editor/database/FormView.tsx +6 -9
  76. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +18 -16
  77. package/corpus/templates/content/changelog/2026-07-13-document-links-open-in-new-tabs.md +6 -0
  78. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +33 -16
  79. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +18 -1
  80. package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +4 -4
  81. package/corpus/templates/design/app/pages/DesignSystems.tsx +8 -10
  82. package/corpus/templates/design/app/pages/Index.tsx +6 -1
  83. package/corpus/templates/design/app/pages/Present.tsx +12 -6
  84. package/corpus/templates/design/changelog/2026-07-13-design-navigation-links-open-in-new-tabs.md +6 -0
  85. package/corpus/templates/design/changelog/2026-07-13-design-session-replays-include-preview-iframes.md +6 -0
  86. package/corpus/templates/forms/app/pages/FormBuilderPage.tsx +11 -11
  87. package/corpus/templates/forms/app/pages/FormsListPage.tsx +6 -8
  88. package/corpus/templates/forms/changelog/2026-07-13-form-navigation-links-open-in-new-tabs.md +6 -0
  89. package/corpus/templates/mail/app/pages/DraftQueuePage.tsx +3 -8
  90. package/corpus/templates/mail/changelog/2026-07-13-settings-links-open-in-new-tabs.md +6 -0
  91. package/dist/agent/production-agent.d.ts +9 -0
  92. package/dist/agent/production-agent.d.ts.map +1 -1
  93. package/dist/agent/production-agent.js +25 -37
  94. package/dist/agent/production-agent.js.map +1 -1
  95. package/dist/audit/config.d.ts.map +1 -1
  96. package/dist/audit/config.js +0 -1
  97. package/dist/audit/config.js.map +1 -1
  98. package/dist/chat-threads/store.d.ts.map +1 -1
  99. package/dist/chat-threads/store.js +47 -33
  100. package/dist/chat-threads/store.js.map +1 -1
  101. package/dist/cli/pr-visual-recap-workflow.d.ts +1 -1
  102. package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -1
  103. package/dist/cli/pr-visual-recap-workflow.js +1 -1
  104. package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
  105. package/dist/client/AssistantChat.d.ts.map +1 -1
  106. package/dist/client/AssistantChat.js +1 -1
  107. package/dist/client/AssistantChat.js.map +1 -1
  108. package/dist/client/analytics.d.ts.map +1 -1
  109. package/dist/client/analytics.js +11 -0
  110. package/dist/client/analytics.js.map +1 -1
  111. package/dist/client/chat/message-components.d.ts.map +1 -1
  112. package/dist/client/chat/message-components.js +9 -3
  113. package/dist/client/chat/message-components.js.map +1 -1
  114. package/dist/client/chat/tool-call-display.d.ts +3 -1
  115. package/dist/client/chat/tool-call-display.d.ts.map +1 -1
  116. package/dist/client/chat/tool-call-display.js +10 -2
  117. package/dist/client/chat/tool-call-display.js.map +1 -1
  118. package/dist/client/extensions/EmbeddedExtension.js +2 -6
  119. package/dist/client/extensions/EmbeddedExtension.js.map +1 -1
  120. package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
  121. package/dist/client/extensions/ExtensionViewer.js +2 -59
  122. package/dist/client/extensions/ExtensionViewer.js.map +1 -1
  123. package/dist/client/index.d.ts +2 -0
  124. package/dist/client/index.d.ts.map +1 -1
  125. package/dist/client/index.js +2 -0
  126. package/dist/client/index.js.map +1 -1
  127. package/dist/client/settings/DemoModeSection.d.ts +1 -13
  128. package/dist/client/settings/DemoModeSection.d.ts.map +1 -1
  129. package/dist/client/settings/DemoModeSection.js +5 -52
  130. package/dist/client/settings/DemoModeSection.js.map +1 -1
  131. package/dist/client/settings/SettingsPanel.js +1 -1
  132. package/dist/client/settings/SettingsPanel.js.map +1 -1
  133. package/dist/client/use-db-sync.d.ts.map +1 -1
  134. package/dist/client/use-db-sync.js +3 -7
  135. package/dist/client/use-db-sync.js.map +1 -1
  136. package/dist/client/use-demo-mode-status.d.ts +3 -4
  137. package/dist/client/use-demo-mode-status.d.ts.map +1 -1
  138. package/dist/client/use-demo-mode-status.js +8 -23
  139. package/dist/client/use-demo-mode-status.js.map +1 -1
  140. package/dist/collab/struct-routes.d.ts +1 -1
  141. package/dist/demo/browser-state.d.ts +10 -0
  142. package/dist/demo/browser-state.d.ts.map +1 -0
  143. package/dist/demo/browser-state.js +49 -0
  144. package/dist/demo/browser-state.js.map +1 -0
  145. package/dist/demo/fetch-interceptor.d.ts +2 -7
  146. package/dist/demo/fetch-interceptor.d.ts.map +1 -1
  147. package/dist/demo/fetch-interceptor.js +12 -56
  148. package/dist/demo/fetch-interceptor.js.map +1 -1
  149. package/dist/deploy/workspace-deploy.js +2 -2
  150. package/dist/deploy/workspace-deploy.js.map +1 -1
  151. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  152. package/dist/notifications/routes.d.ts +2 -2
  153. package/dist/observability/routes.d.ts +5 -5
  154. package/dist/resources/handlers.d.ts +3 -3
  155. package/dist/secrets/routes.d.ts +9 -9
  156. package/dist/server/action-discovery.d.ts.map +1 -1
  157. package/dist/server/action-discovery.js +0 -1
  158. package/dist/server/action-discovery.js.map +1 -1
  159. package/dist/server/agent-chat/action-filters-a2a.d.ts.map +1 -1
  160. package/dist/server/agent-chat/action-filters-a2a.js +11 -1
  161. package/dist/server/agent-chat/action-filters-a2a.js.map +1 -1
  162. package/dist/server/agent-teams.d.ts.map +1 -1
  163. package/dist/server/agent-teams.js +15 -1
  164. package/dist/server/agent-teams.js.map +1 -1
  165. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  166. package/dist/server/core-routes-plugin.js +0 -27
  167. package/dist/server/core-routes-plugin.js.map +1 -1
  168. package/dist/server/google-oauth.d.ts.map +1 -1
  169. package/dist/server/google-oauth.js +6 -2
  170. package/dist/server/google-oauth.js.map +1 -1
  171. package/dist/server/transcribe-voice.d.ts +1 -1
  172. package/dist/templates/workspace-core/.agents/skills/native-navigation/SKILL.md +67 -0
  173. package/package.json +2 -2
  174. package/src/templates/workspace-core/.agents/skills/native-navigation/SKILL.md +67 -0
  175. package/corpus/core/src/demo/actions/toggle-demo-mode.ts +0 -23
  176. package/corpus/core/src/demo/config.ts +0 -57
  177. package/dist/demo/actions/toggle-demo-mode.d.ts +0 -8
  178. package/dist/demo/actions/toggle-demo-mode.d.ts.map +0 -1
  179. package/dist/demo/actions/toggle-demo-mode.js +0 -21
  180. package/dist/demo/actions/toggle-demo-mode.js.map +0 -1
  181. package/dist/demo/config.d.ts +0 -9
  182. package/dist/demo/config.d.ts.map +0 -1
  183. package/dist/demo/config.js +0 -58
  184. package/dist/demo/config.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"toggle-demo-mode.js","sourceRoot":"","sources":["../../../src/demo/actions/toggle-demo-mode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,2CAA2C,CAAC;AAE1E,eAAe,YAAY,CAAC;IAC1B,WAAW,EACT,4fAA4f;IAC9f,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,OAAO,EAAE,CAAC;aACP,OAAO,EAAE;aACT,QAAQ,CAAC,kDAAkD,CAAC;KAChE,CAAC;IACF,GAAG,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;QACzB,MAAM,aAAa,CAAC,WAAW,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QAC9C,OAAO;YACL,OAAO;YACP,OAAO,EAAE,OAAO;gBACd,CAAC,CAAC,4NAA4N;gBAC9N,CAAC,CAAC,8CAA8C;SACnD,CAAC;IACJ,CAAC;CACF,CAAC,CAAC","sourcesContent":["import { z } from \"zod\";\n\nimport { defineAction } from \"../../action.js\";\nimport { writeAppState } from \"../../application-state/script-helpers.js\";\n\nexport default defineAction({\n description:\n \"Turn demo mode on or off. When demo mode is on, the UI replaces every email address with anonymous@builder.io and supported dashboards reshape chart values for presentations. Agent-visible results use the same anonymous email and anonymize numbers while keeping names, free text, labels, IDs, dates, and structure intact. Use when the user asks to 'hide my data', 'turn on demo mode', 'anonymize this for a screen share / recording', or similar. This is the same toggle as the Demo mode switch in settings.\",\n schema: z.object({\n enabled: z\n .boolean()\n .describe(\"true to turn demo mode on, false to turn it off.\"),\n }),\n run: async ({ enabled }) => {\n await writeAppState(\"demo-mode\", { enabled });\n return {\n enabled,\n message: enabled\n ? \"Demo mode is ON — UI emails are anonymized and supported dashboard charts are reshaped for presentation. Agent-visible emails and numbers are also anonymized. Names, free text, labels, IDs, and structure are preserved.\"\n : \"Demo mode is OFF — real data is shown again.\",\n };\n },\n});\n"]}
@@ -1,9 +0,0 @@
1
- /** Deployment-wide force (hosted demo site). Zero cost — no I/O. */
2
- export declare function isDemoModeForced(): boolean;
3
- /**
4
- * Whether demo-mode redaction should run for the current request/user.
5
- * Cheap by design — safe to call before every action result; the expensive
6
- * walk only happens when this is true.
7
- */
8
- export declare function isDemoModeEnabled(): Promise<boolean>;
9
- //# sourceMappingURL=config.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/demo/config.ts"],"names":[],"mappings":"AAwBA,oEAAoE;AACpE,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC,CAsB1D"}
@@ -1,58 +0,0 @@
1
- /**
2
- * Demo mode gate.
3
- *
4
- * Demo mode replaces every email address with `anonymous@builder.io` and
5
- * anonymizes numbers in every action result — for both the UI and what the
6
- * agent sees — while preserving names, free text, labels, IDs, dates, URLs,
7
- * and structure so the app keeps working. The redaction WALK (see ./redact.ts)
8
- * is expensive on large payloads, so callers MUST gate it behind this function
9
- * and only walk when it returns true.
10
- *
11
- * This gate itself is intentionally cheap:
12
- * - An env-forced deployment (a hosted demo site) short-circuits with zero
13
- * I/O — `DEMO_MODE=true`.
14
- * - The per-user runtime toggle lives in `application_state` under the
15
- * `demo-mode` key (`{ enabled: boolean }`), written by the settings UI and
16
- * the `toggle-demo-mode` agent action. It's read behind a short in-process
17
- * TTL cache keyed by user, so a tight agent tool-call loop doesn't hit the
18
- * DB on every result.
19
- */
20
- import { readAppState } from "../application-state/script-helpers.js";
21
- const TTL_MS = 3_000;
22
- const cache = new Map();
23
- /** Deployment-wide force (hosted demo site). Zero cost — no I/O. */
24
- export function isDemoModeForced() {
25
- return process.env.DEMO_MODE === "true";
26
- }
27
- /**
28
- * Whether demo-mode redaction should run for the current request/user.
29
- * Cheap by design — safe to call before every action result; the expensive
30
- * walk only happens when this is true.
31
- */
32
- export async function isDemoModeEnabled() {
33
- if (isDemoModeForced())
34
- return true;
35
- try {
36
- let sessionKey = "_";
37
- try {
38
- const { getRequestUserEmail } = await import("../server/request-context.js");
39
- sessionKey = getRequestUserEmail() ?? process.env.AGENT_USER_EMAIL ?? "_";
40
- }
41
- catch {
42
- // request-context unavailable (CLI / non-server) — use default key
43
- }
44
- const now = Date.now();
45
- const hit = cache.get(sessionKey);
46
- if (hit && now - hit.at < TTL_MS)
47
- return hit.value;
48
- const state = await readAppState("demo-mode");
49
- const enabled = state?.enabled === true;
50
- cache.set(sessionKey, { value: enabled, at: now });
51
- return enabled;
52
- }
53
- catch {
54
- // No request context / DB unavailable — fail closed (no redaction).
55
- return false;
56
- }
57
- }
58
- //# sourceMappingURL=config.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/demo/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAC;AAEtE,MAAM,MAAM,GAAG,KAAK,CAAC;AACrB,MAAM,KAAK,GAAG,IAAI,GAAG,EAA0C,CAAC;AAEhE,oEAAoE;AACpE,MAAM,UAAU,gBAAgB;IAC9B,OAAO,OAAO,CAAC,GAAG,CAAC,SAAS,KAAK,MAAM,CAAC;AAC1C,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,IAAI,gBAAgB,EAAE;QAAE,OAAO,IAAI,CAAC;IACpC,IAAI,CAAC;QACH,IAAI,UAAU,GAAG,GAAG,CAAC;QACrB,IAAI,CAAC;YACH,MAAM,EAAE,mBAAmB,EAAE,GAC3B,MAAM,MAAM,CAAC,8BAA8B,CAAC,CAAC;YAC/C,UAAU,GAAG,mBAAmB,EAAE,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,GAAG,CAAC;QAC5E,CAAC;QAAC,MAAM,CAAC;YACP,mEAAmE;QACrE,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAClC,IAAI,GAAG,IAAI,GAAG,GAAG,GAAG,CAAC,EAAE,GAAG,MAAM;YAAE,OAAO,GAAG,CAAC,KAAK,CAAC;QACnD,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,WAAW,CAAC,CAAC;QAC9C,MAAM,OAAO,GAAG,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;QACxC,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;QACnD,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,MAAM,CAAC;QACP,oEAAoE;QACpE,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC","sourcesContent":["/**\n * Demo mode gate.\n *\n * Demo mode replaces every email address with `anonymous@builder.io` and\n * anonymizes numbers in every action result — for both the UI and what the\n * agent sees — while preserving names, free text, labels, IDs, dates, URLs,\n * and structure so the app keeps working. The redaction WALK (see ./redact.ts)\n * is expensive on large payloads, so callers MUST gate it behind this function\n * and only walk when it returns true.\n *\n * This gate itself is intentionally cheap:\n * - An env-forced deployment (a hosted demo site) short-circuits with zero\n * I/O — `DEMO_MODE=true`.\n * - The per-user runtime toggle lives in `application_state` under the\n * `demo-mode` key (`{ enabled: boolean }`), written by the settings UI and\n * the `toggle-demo-mode` agent action. It's read behind a short in-process\n * TTL cache keyed by user, so a tight agent tool-call loop doesn't hit the\n * DB on every result.\n */\nimport { readAppState } from \"../application-state/script-helpers.js\";\n\nconst TTL_MS = 3_000;\nconst cache = new Map<string, { value: boolean; at: number }>();\n\n/** Deployment-wide force (hosted demo site). Zero cost — no I/O. */\nexport function isDemoModeForced(): boolean {\n return process.env.DEMO_MODE === \"true\";\n}\n\n/**\n * Whether demo-mode redaction should run for the current request/user.\n * Cheap by design — safe to call before every action result; the expensive\n * walk only happens when this is true.\n */\nexport async function isDemoModeEnabled(): Promise<boolean> {\n if (isDemoModeForced()) return true;\n try {\n let sessionKey = \"_\";\n try {\n const { getRequestUserEmail } =\n await import(\"../server/request-context.js\");\n sessionKey = getRequestUserEmail() ?? process.env.AGENT_USER_EMAIL ?? \"_\";\n } catch {\n // request-context unavailable (CLI / non-server) — use default key\n }\n const now = Date.now();\n const hit = cache.get(sessionKey);\n if (hit && now - hit.at < TTL_MS) return hit.value;\n const state = await readAppState(\"demo-mode\");\n const enabled = state?.enabled === true;\n cache.set(sessionKey, { value: enabled, at: now });\n return enabled;\n } catch {\n // No request context / DB unavailable — fail closed (no redaction).\n return false;\n }\n}\n"]}