@agent-native/core 0.121.2 → 0.122.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (460) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +139 -0
  3. package/corpus/core/docs/content/actions.mdx +2 -2
  4. package/corpus/core/docs/content/agent-surfaces.mdx +1 -1
  5. package/corpus/core/docs/content/authentication.mdx +2 -0
  6. package/corpus/core/docs/content/deployment.mdx +36 -0
  7. package/corpus/core/docs/content/http-api.mdx +266 -0
  8. package/corpus/core/docs/content/syncing-template-changes.mdx +159 -0
  9. package/corpus/core/package.json +2 -1
  10. package/corpus/core/src/a2a/activity.ts +38 -27
  11. package/corpus/core/src/agent/engine/builder-engine.ts +35 -4
  12. package/corpus/core/src/agent/run-manager.ts +20 -1
  13. package/corpus/core/src/agent/run-store.ts +4 -1
  14. package/corpus/core/src/agent/types.ts +28 -8
  15. package/corpus/core/src/chat-threads/store.ts +45 -0
  16. package/corpus/core/src/checkpoints/index.ts +2 -0
  17. package/corpus/core/src/checkpoints/route-match.ts +13 -0
  18. package/corpus/core/src/cli/create.ts +105 -17
  19. package/corpus/core/src/cli/index.ts +20 -0
  20. package/corpus/core/src/cli/template-baseline.ts +410 -0
  21. package/corpus/core/src/cli/template-sync.ts +1004 -0
  22. package/corpus/core/src/cli/templates-meta.ts +1 -0
  23. package/corpus/core/src/client/AssistantChat.tsx +38 -12
  24. package/corpus/core/src/client/NewWorkspaceAppFlow.tsx +75 -10
  25. package/corpus/core/src/client/chat/message-components.tsx +127 -66
  26. package/corpus/core/src/client/chat/tool-call-display.tsx +29 -5
  27. package/corpus/core/src/client/error-format.ts +18 -0
  28. package/corpus/core/src/client/org/OrgSwitcher.tsx +30 -8
  29. package/corpus/core/src/client/org/TeamPage.tsx +7 -6
  30. package/corpus/core/src/client/sse-event-processor.ts +3 -0
  31. package/corpus/core/src/data-widgets/index.ts +41 -0
  32. package/corpus/core/src/deploy/build.ts +11 -9
  33. package/corpus/core/src/integrations/webhook-handler.ts +63 -9
  34. package/corpus/core/src/org/auto-join-domain.ts +4 -3
  35. package/corpus/core/src/org/context.ts +108 -39
  36. package/corpus/core/src/org/index.ts +5 -0
  37. package/corpus/core/src/org/service-identity.ts +60 -0
  38. package/corpus/core/src/provider-api/index.ts +22 -1
  39. package/corpus/core/src/scripts/docs/search.ts +12 -1
  40. package/corpus/core/src/server/agent-chat/context-tools.ts +9 -4
  41. package/corpus/core/src/server/agent-chat/framework-prompts.ts +38 -66
  42. package/corpus/core/src/server/agent-chat-plugin.ts +17 -10
  43. package/corpus/core/src/server/agents-bundle.ts +84 -5
  44. package/corpus/core/src/server/auth.ts +4 -3
  45. package/corpus/core/src/server/builder-browser.ts +47 -19
  46. package/corpus/core/src/server/core-routes-plugin.ts +2 -2
  47. package/corpus/core/src/server/credential-provider.ts +209 -68
  48. package/corpus/core/src/server/index.ts +3 -0
  49. package/corpus/core/src/server/prompts/framework-core-compact.ts +6 -13
  50. package/corpus/core/src/server/prompts/framework-core.ts +9 -21
  51. package/corpus/core/src/server/prompts/index.ts +0 -1
  52. package/corpus/core/src/server/prompts/shared-rules.ts +19 -11
  53. package/corpus/core/src/server/ssr-handler.ts +13 -2
  54. package/corpus/core/src/settings/user-settings.ts +13 -1
  55. package/corpus/core/src/shared/cache-control.ts +141 -0
  56. package/corpus/core/src/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  57. package/corpus/core/src/templates/chat/_gitignore +1 -0
  58. package/corpus/core/src/templates/default/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  59. package/corpus/core/src/templates/headless/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  60. package/corpus/core/src/templates/workspace-core/.agents/skills/performance/SKILL.md +19 -0
  61. package/corpus/core/src/templates/workspace-core/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  62. package/corpus/core/src/templates/workspace-core/.agents/skills/visual-answer/SKILL.md +1 -0
  63. package/corpus/core/src/vite/agents-bundle-plugin.ts +7 -6
  64. package/corpus/core/src/vite/client.ts +5 -0
  65. package/corpus/templates/analytics/.agents/skills/adhoc-analysis/SKILL.md +4 -5
  66. package/corpus/templates/analytics/.agents/skills/admin-surfaces/SKILL.md +55 -0
  67. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +10 -0
  68. package/corpus/templates/analytics/.agents/skills/dashboard-management/references/template-catalog-and-demo.md +62 -0
  69. package/corpus/templates/analytics/.agents/skills/dashboard-ops/SKILL.md +85 -0
  70. package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +27 -2
  71. package/corpus/templates/analytics/.agents/skills/data-querying/references/inline-chart-embeds.md +139 -0
  72. package/corpus/templates/analytics/.agents/skills/monitoring/SKILL.md +77 -0
  73. package/corpus/templates/analytics/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  74. package/corpus/templates/analytics/AGENTS.md +91 -563
  75. package/corpus/templates/analytics/_gitignore +1 -0
  76. package/corpus/templates/analytics/actions/bigquery.ts +12 -4
  77. package/corpus/templates/analytics/actions/generate-chart.ts +5 -5
  78. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +30 -1
  79. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/DashboardFilterBar.tsx +3 -0
  80. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +1 -1
  81. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +1 -0
  82. package/corpus/templates/analytics/changelog/2026-07-24-analytics-finds-saved-dashboards-and-queries-far-more-reliab.md +6 -0
  83. package/corpus/templates/analytics/changelog/2026-07-24-notion-access-errors-now-explain-that-a-page-needs-sharing-w.md +6 -0
  84. package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +7 -0
  85. package/corpus/templates/analytics/server/lib/analytics-query-catalog.ts +191 -30
  86. package/corpus/templates/analytics/server/lib/bigquery.ts +11 -1
  87. package/corpus/templates/analytics/server/lib/notion.ts +15 -4
  88. package/corpus/templates/analytics/server/plugins/agent-chat.ts +10 -0
  89. package/corpus/templates/assets/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  90. package/corpus/templates/brain/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  91. package/corpus/templates/brain/_gitignore +1 -0
  92. package/corpus/templates/calendar/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  93. package/corpus/templates/calendar/_gitignore +1 -0
  94. package/corpus/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  95. package/corpus/templates/chat/_gitignore +1 -0
  96. package/corpus/templates/clips/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  97. package/corpus/templates/clips/.agents/skills/video-sharing/SKILL.md +34 -0
  98. package/corpus/templates/clips/AGENTS.md +5 -4
  99. package/corpus/templates/clips/_gitignore +1 -0
  100. package/corpus/templates/clips/actions/cleanup-transcript.ts +5 -0
  101. package/corpus/templates/clips/actions/get-recording-insights.ts +44 -8
  102. package/corpus/templates/clips/actions/get-recording-player-data.ts +39 -70
  103. package/corpus/templates/clips/actions/list-clip-views.ts +2 -4
  104. package/corpus/templates/clips/actions/list-recordings.ts +69 -19
  105. package/corpus/templates/clips/actions/list-viewers.ts +5 -2
  106. package/corpus/templates/clips/actions/regenerate-summary.ts +5 -1
  107. package/corpus/templates/clips/actions/request-transcript.ts +28 -1
  108. package/corpus/templates/clips/app/components/editor/stitch-manager.tsx +21 -1
  109. package/corpus/templates/clips/app/components/meetings/quick-ask-sidebar.tsx +14 -1
  110. package/corpus/templates/clips/app/components/player/insights-panel.tsx +8 -20
  111. package/corpus/templates/clips/app/components/player/recording-views-badge.tsx +335 -0
  112. package/corpus/templates/clips/app/components/player/video-player.tsx +13 -8
  113. package/corpus/templates/clips/app/components/sharing/share-ui.tsx +2 -1
  114. package/corpus/templates/clips/app/i18n/en-US.ts +13 -2
  115. package/corpus/templates/clips/app/lib/capture-permissions.ts +110 -0
  116. package/corpus/templates/clips/app/lib/recording-link.ts +32 -0
  117. package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +27 -0
  118. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +46 -15
  119. package/corpus/templates/clips/app/routes/record.tsx +77 -31
  120. package/corpus/templates/clips/app/routes/share.$shareId.tsx +42 -31
  121. package/corpus/templates/clips/changelog/2026-07-24-clip-pages-now-show-a-view-count-with-viewer-avatars-next-to.md +6 -0
  122. package/corpus/templates/clips/changelog/2026-07-24-clip-summaries-read-like-a-description-you-d-write-yourself-.md +6 -0
  123. package/corpus/templates/clips/changelog/2026-07-24-clip-view-counts-now-separate-human-views-from-agent-views-s.md +6 -0
  124. package/corpus/templates/clips/changelog/2026-07-24-clips-actions-can-now-be-called-by-org-service-tokens-so-ext.md +6 -0
  125. package/corpus/templates/clips/changelog/2026-07-24-clips-no-longer-briefly-shows-a-dock-icon-while-launching.md +6 -0
  126. package/corpus/templates/clips/changelog/2026-07-24-fixed-owner-and-editor-share-links-redirecting-to-the-record.md +6 -0
  127. package/corpus/templates/clips/changelog/2026-07-24-meeting-and-note-recordings-now-start-as-a-compact-pill-on-t.md +6 -0
  128. package/corpus/templates/clips/changelog/2026-07-24-new-clips-now-copy-a-shareable-link-instead-of-the-owner-onl.md +6 -0
  129. package/corpus/templates/clips/changelog/2026-07-24-opening-a-share-link-as-the-clip-s-owner-now-goes-straight-t.md +6 -0
  130. package/corpus/templates/clips/changelog/2026-07-24-permissions-and-rewind-controls-now-use-compact-consistent-h.md +6 -0
  131. package/corpus/templates/clips/changelog/2026-07-24-quitting-the-desktop-app-no-longer-shows-a-false-macos-crash.md +6 -0
  132. package/corpus/templates/clips/changelog/2026-07-24-screen-recording-permission-errors-now-name-the-exact-app-to.md +6 -0
  133. package/corpus/templates/clips/changelog/2026-07-24-the-desktop-app-now-copies-a-new-clip-s-share-link-to-your-c.md +6 -0
  134. package/corpus/templates/clips/changelog/2026-07-24-the-recording-toolbar-now-stays-above-other-apps-including-o.md +6 -0
  135. package/corpus/templates/clips/changelog/2026-07-24-transcript-captions-now-use-real-speech-timings-instead-of-a.md +6 -0
  136. package/corpus/templates/clips/changelog/2026-07-24-video-playback-no-longer-stutters-and-replays-the-last-momen.md +6 -0
  137. package/corpus/templates/clips/chrome-extension/src/background.ts +17 -1
  138. package/corpus/templates/clips/desktop/package.json +2 -0
  139. package/corpus/templates/clips/desktop/src/app.tsx +89 -0
  140. package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +9 -3
  141. package/corpus/templates/clips/desktop/src/lib/audio-meter.ts +51 -0
  142. package/corpus/templates/clips/desktop/src/lib/native-notification.ts +44 -0
  143. package/corpus/templates/clips/desktop/src/lib/recording-link.ts +67 -0
  144. package/corpus/templates/clips/desktop/src/overlays/live-audio-bars.tsx +35 -35
  145. package/corpus/templates/clips/desktop/src/overlays/live-transcript.tsx +3 -2
  146. package/corpus/templates/clips/desktop/src/overlays/recording-pill.tsx +47 -46
  147. package/corpus/templates/clips/desktop/src/styles.css +127 -78
  148. package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +7 -0
  149. package/corpus/templates/clips/desktop/src-tauri/Info.plist +6 -0
  150. package/corpus/templates/clips/desktop/src-tauri/capabilities/default.json +1 -0
  151. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +7 -3
  152. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +4 -1
  153. package/corpus/templates/clips/desktop/src-tauri/src/main.rs +8 -0
  154. package/corpus/templates/clips/desktop/src-tauri/src/recording_indicator.rs +21 -10
  155. package/corpus/templates/clips/desktop/src-tauri/src/util.rs +40 -0
  156. package/corpus/templates/clips/server/db/schema.ts +25 -0
  157. package/corpus/templates/clips/server/lib/agent-views.ts +145 -0
  158. package/corpus/templates/clips/server/lib/public-agent-context.ts +7 -0
  159. package/corpus/templates/clips/server/lib/recording-share-grant.ts +79 -0
  160. package/corpus/templates/clips/server/lib/recordings.ts +51 -3
  161. package/corpus/templates/clips/server/plugins/db.ts +23 -0
  162. package/corpus/templates/clips/server/routes/api/public-recording.get.ts +49 -17
  163. package/corpus/templates/clips/shared/recording-link.ts +43 -0
  164. package/corpus/templates/clips/shared/share-attribution.ts +4 -0
  165. package/corpus/templates/clips/shared/share-dashboard-redirect.ts +42 -0
  166. package/corpus/templates/clips/shared/view-analytics.ts +26 -0
  167. package/corpus/templates/content/.agents/skills/content/SKILL.md +5 -0
  168. package/corpus/templates/content/.agents/skills/content/references/local-file-mode.md +135 -0
  169. package/corpus/templates/content/.agents/skills/document-editing/SKILL.md +12 -0
  170. package/corpus/templates/content/.agents/skills/document-editing/references/databases.md +238 -0
  171. package/corpus/templates/content/.agents/skills/document-editing/references/document-behavior.md +91 -0
  172. package/corpus/templates/content/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  173. package/corpus/templates/content/AGENTS.md +62 -583
  174. package/corpus/templates/content/_gitignore +1 -0
  175. package/corpus/templates/design/.agents/skills/creative-context/SKILL.md +11 -0
  176. package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +50 -8
  177. package/corpus/templates/design/.agents/skills/design-generation/references/code-layers.md +81 -0
  178. package/corpus/templates/design/.agents/skills/design-generation/references/code-workspace.md +42 -0
  179. package/corpus/templates/design/.agents/skills/design-generation/references/editor-extensions.md +34 -0
  180. package/corpus/templates/design/.agents/skills/responsive-breakpoints/SKILL.md +4 -1
  181. package/corpus/templates/design/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  182. package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +17 -0
  183. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +8196 -0
  184. package/corpus/templates/design/.generated/bridge/embedded-wheel.generated.ts +265 -0
  185. package/corpus/templates/design/.generated/bridge/hit-test.generated.ts +642 -0
  186. package/corpus/templates/design/.generated/bridge/motion-preview.generated.ts +571 -0
  187. package/corpus/templates/design/.generated/bridge/nav.generated.ts +91 -0
  188. package/corpus/templates/design/.generated/bridge/sample.generated.ts +23 -0
  189. package/corpus/templates/design/.generated/bridge/shader-fill-preview.generated.ts +263 -0
  190. package/corpus/templates/design/.generated/bridge/shader-runtime.generated.ts +518 -0
  191. package/corpus/templates/design/.generated/bridge/tweak.generated.ts +20 -0
  192. package/corpus/templates/design/.generated/bridge/zoom.generated.ts +32 -0
  193. package/corpus/templates/design/AGENTS.md +88 -503
  194. package/corpus/templates/design/_gitignore +1 -0
  195. package/corpus/templates/dispatch/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  196. package/corpus/templates/dispatch/_gitignore +1 -0
  197. package/corpus/templates/dispatch/changelog/2026-07-24-signing-in-now-puts-you-in-your-companys-workspace.md +6 -0
  198. package/corpus/templates/forms/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  199. package/corpus/templates/forms/_gitignore +1 -0
  200. package/corpus/templates/forms/server/lib/public-form-ssr.ts +2 -2
  201. package/corpus/templates/macros/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  202. package/corpus/templates/macros/_gitignore +1 -0
  203. package/corpus/templates/mail/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  204. package/corpus/templates/mail/_gitignore +1 -0
  205. package/corpus/templates/plan/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  206. package/corpus/templates/plan/_gitignore +1 -0
  207. package/corpus/templates/slides/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  208. package/corpus/templates/slides/_gitignore +1 -0
  209. package/corpus/templates/slides/server/plugins/db.ts +4 -0
  210. package/corpus/templates/tasks/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  211. package/corpus/templates/tasks/AGENTS.md +1 -1
  212. package/corpus/templates/tasks/_gitignore +1 -0
  213. package/dist/a2a/activity.d.ts +4 -1
  214. package/dist/a2a/activity.d.ts.map +1 -1
  215. package/dist/a2a/activity.js +27 -16
  216. package/dist/a2a/activity.js.map +1 -1
  217. package/dist/agent/engine/builder-engine.d.ts +1 -0
  218. package/dist/agent/engine/builder-engine.d.ts.map +1 -1
  219. package/dist/agent/engine/builder-engine.js +31 -4
  220. package/dist/agent/engine/builder-engine.js.map +1 -1
  221. package/dist/agent/run-manager.d.ts.map +1 -1
  222. package/dist/agent/run-manager.js +18 -1
  223. package/dist/agent/run-manager.js.map +1 -1
  224. package/dist/agent/run-store.d.ts +1 -0
  225. package/dist/agent/run-store.d.ts.map +1 -1
  226. package/dist/agent/run-store.js +2 -1
  227. package/dist/agent/run-store.js.map +1 -1
  228. package/dist/agent/types.d.ts +12 -1
  229. package/dist/agent/types.d.ts.map +1 -1
  230. package/dist/agent/types.js +21 -1
  231. package/dist/agent/types.js.map +1 -1
  232. package/dist/chat-threads/store.d.ts +10 -0
  233. package/dist/chat-threads/store.d.ts.map +1 -1
  234. package/dist/chat-threads/store.js +41 -0
  235. package/dist/chat-threads/store.js.map +1 -1
  236. package/dist/checkpoints/index.d.ts +1 -0
  237. package/dist/checkpoints/index.d.ts.map +1 -1
  238. package/dist/checkpoints/index.js +1 -0
  239. package/dist/checkpoints/index.js.map +1 -1
  240. package/dist/checkpoints/route-match.d.ts +8 -0
  241. package/dist/checkpoints/route-match.d.ts.map +1 -0
  242. package/dist/checkpoints/route-match.js +13 -0
  243. package/dist/checkpoints/route-match.js.map +1 -0
  244. package/dist/cli/create.d.ts +35 -4
  245. package/dist/cli/create.d.ts.map +1 -1
  246. package/dist/cli/create.js +69 -19
  247. package/dist/cli/create.js.map +1 -1
  248. package/dist/cli/index.js +19 -0
  249. package/dist/cli/index.js.map +1 -1
  250. package/dist/cli/template-baseline.d.ts +54 -0
  251. package/dist/cli/template-baseline.d.ts.map +1 -0
  252. package/dist/cli/template-baseline.js +334 -0
  253. package/dist/cli/template-baseline.js.map +1 -0
  254. package/dist/cli/template-sync.d.ts +57 -0
  255. package/dist/cli/template-sync.d.ts.map +1 -0
  256. package/dist/cli/template-sync.js +787 -0
  257. package/dist/cli/template-sync.js.map +1 -0
  258. package/dist/cli/templates-meta.d.ts.map +1 -1
  259. package/dist/cli/templates-meta.js +1 -0
  260. package/dist/cli/templates-meta.js.map +1 -1
  261. package/dist/client/AssistantChat.d.ts +2 -1
  262. package/dist/client/AssistantChat.d.ts.map +1 -1
  263. package/dist/client/AssistantChat.js +38 -10
  264. package/dist/client/AssistantChat.js.map +1 -1
  265. package/dist/client/NewWorkspaceAppFlow.d.ts.map +1 -1
  266. package/dist/client/NewWorkspaceAppFlow.js +32 -2
  267. package/dist/client/NewWorkspaceAppFlow.js.map +1 -1
  268. package/dist/client/chat/message-components.d.ts +20 -0
  269. package/dist/client/chat/message-components.d.ts.map +1 -1
  270. package/dist/client/chat/message-components.js +81 -46
  271. package/dist/client/chat/message-components.js.map +1 -1
  272. package/dist/client/chat/tool-call-display.d.ts.map +1 -1
  273. package/dist/client/chat/tool-call-display.js +14 -6
  274. package/dist/client/chat/tool-call-display.js.map +1 -1
  275. package/dist/client/error-format.d.ts.map +1 -1
  276. package/dist/client/error-format.js +13 -0
  277. package/dist/client/error-format.js.map +1 -1
  278. package/dist/client/org/OrgSwitcher.d.ts +8 -1
  279. package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
  280. package/dist/client/org/OrgSwitcher.js +3 -2
  281. package/dist/client/org/OrgSwitcher.js.map +1 -1
  282. package/dist/client/org/TeamPage.d.ts.map +1 -1
  283. package/dist/client/org/TeamPage.js +1 -1
  284. package/dist/client/org/TeamPage.js.map +1 -1
  285. package/dist/client/sse-event-processor.d.ts.map +1 -1
  286. package/dist/client/sse-event-processor.js +3 -0
  287. package/dist/client/sse-event-processor.js.map +1 -1
  288. package/dist/collab/awareness.d.ts +2 -2
  289. package/dist/collab/awareness.d.ts.map +1 -1
  290. package/dist/data-widgets/index.d.ts +3 -0
  291. package/dist/data-widgets/index.d.ts.map +1 -1
  292. package/dist/data-widgets/index.js +33 -0
  293. package/dist/data-widgets/index.js.map +1 -1
  294. package/dist/deploy/build.d.ts.map +1 -1
  295. package/dist/deploy/build.js +11 -7
  296. package/dist/deploy/build.js.map +1 -1
  297. package/dist/eject/provider-api-definitions.d.ts +1 -0
  298. package/dist/eject/provider-api-definitions.d.ts.map +1 -1
  299. package/dist/integrations/webhook-handler.d.ts.map +1 -1
  300. package/dist/integrations/webhook-handler.js +46 -9
  301. package/dist/integrations/webhook-handler.js.map +1 -1
  302. package/dist/org/auto-join-domain.d.ts +3 -2
  303. package/dist/org/auto-join-domain.d.ts.map +1 -1
  304. package/dist/org/auto-join-domain.js +1 -1
  305. package/dist/org/auto-join-domain.js.map +1 -1
  306. package/dist/org/context.d.ts.map +1 -1
  307. package/dist/org/context.js +84 -28
  308. package/dist/org/context.js.map +1 -1
  309. package/dist/org/index.d.ts +1 -0
  310. package/dist/org/index.d.ts.map +1 -1
  311. package/dist/org/index.js +1 -0
  312. package/dist/org/index.js.map +1 -1
  313. package/dist/org/service-identity.d.ts +43 -0
  314. package/dist/org/service-identity.d.ts.map +1 -0
  315. package/dist/org/service-identity.js +34 -0
  316. package/dist/org/service-identity.js.map +1 -0
  317. package/dist/provider-api/actions/custom-provider-registration.d.ts +14 -14
  318. package/dist/provider-api/actions/provider-api.d.ts +13 -11
  319. package/dist/provider-api/actions/provider-api.d.ts.map +1 -1
  320. package/dist/provider-api/index.d.ts +4 -0
  321. package/dist/provider-api/index.d.ts.map +1 -1
  322. package/dist/provider-api/index.js +17 -1
  323. package/dist/provider-api/index.js.map +1 -1
  324. package/dist/resources/handlers.d.ts +1 -1
  325. package/dist/scripts/docs/search.d.ts.map +1 -1
  326. package/dist/scripts/docs/search.js +12 -1
  327. package/dist/scripts/docs/search.js.map +1 -1
  328. package/dist/server/agent-chat/context-tools.d.ts.map +1 -1
  329. package/dist/server/agent-chat/context-tools.js +3 -3
  330. package/dist/server/agent-chat/context-tools.js.map +1 -1
  331. package/dist/server/agent-chat/framework-prompts.d.ts +8 -3
  332. package/dist/server/agent-chat/framework-prompts.d.ts.map +1 -1
  333. package/dist/server/agent-chat/framework-prompts.js +33 -62
  334. package/dist/server/agent-chat/framework-prompts.js.map +1 -1
  335. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  336. package/dist/server/agent-chat-plugin.js +16 -10
  337. package/dist/server/agent-chat-plugin.js.map +1 -1
  338. package/dist/server/agents-bundle.d.ts +18 -0
  339. package/dist/server/agents-bundle.d.ts.map +1 -1
  340. package/dist/server/agents-bundle.js +70 -4
  341. package/dist/server/agents-bundle.js.map +1 -1
  342. package/dist/server/auth.d.ts.map +1 -1
  343. package/dist/server/auth.js +4 -3
  344. package/dist/server/auth.js.map +1 -1
  345. package/dist/server/builder-browser.d.ts.map +1 -1
  346. package/dist/server/builder-browser.js +43 -19
  347. package/dist/server/builder-browser.js.map +1 -1
  348. package/dist/server/core-routes-plugin.js +2 -2
  349. package/dist/server/core-routes-plugin.js.map +1 -1
  350. package/dist/server/credential-provider.d.ts +38 -2
  351. package/dist/server/credential-provider.d.ts.map +1 -1
  352. package/dist/server/credential-provider.js +142 -64
  353. package/dist/server/credential-provider.js.map +1 -1
  354. package/dist/server/index.d.ts +1 -1
  355. package/dist/server/index.d.ts.map +1 -1
  356. package/dist/server/index.js +1 -1
  357. package/dist/server/index.js.map +1 -1
  358. package/dist/server/prompts/framework-core-compact.d.ts +1 -1
  359. package/dist/server/prompts/framework-core-compact.d.ts.map +1 -1
  360. package/dist/server/prompts/framework-core-compact.js +7 -13
  361. package/dist/server/prompts/framework-core-compact.js.map +1 -1
  362. package/dist/server/prompts/framework-core.d.ts +1 -1
  363. package/dist/server/prompts/framework-core.d.ts.map +1 -1
  364. package/dist/server/prompts/framework-core.js +10 -21
  365. package/dist/server/prompts/framework-core.js.map +1 -1
  366. package/dist/server/prompts/index.d.ts +1 -1
  367. package/dist/server/prompts/index.d.ts.map +1 -1
  368. package/dist/server/prompts/index.js +1 -1
  369. package/dist/server/prompts/index.js.map +1 -1
  370. package/dist/server/prompts/shared-rules.d.ts +16 -10
  371. package/dist/server/prompts/shared-rules.d.ts.map +1 -1
  372. package/dist/server/prompts/shared-rules.js +19 -10
  373. package/dist/server/prompts/shared-rules.js.map +1 -1
  374. package/dist/server/ssr-handler.d.ts +1 -1
  375. package/dist/server/ssr-handler.d.ts.map +1 -1
  376. package/dist/server/ssr-handler.js +10 -3
  377. package/dist/server/ssr-handler.js.map +1 -1
  378. package/dist/settings/user-settings.d.ts.map +1 -1
  379. package/dist/settings/user-settings.js +13 -1
  380. package/dist/settings/user-settings.js.map +1 -1
  381. package/dist/shared/cache-control.d.ts +52 -0
  382. package/dist/shared/cache-control.d.ts.map +1 -1
  383. package/dist/shared/cache-control.js +107 -0
  384. package/dist/shared/cache-control.js.map +1 -1
  385. package/dist/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  386. package/dist/templates/chat/_gitignore +1 -0
  387. package/dist/templates/default/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  388. package/dist/templates/headless/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  389. package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +19 -0
  390. package/dist/templates/workspace-core/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  391. package/dist/templates/workspace-core/.agents/skills/visual-answer/SKILL.md +1 -0
  392. package/dist/vite/agents-bundle-plugin.d.ts.map +1 -1
  393. package/dist/vite/agents-bundle-plugin.js +8 -7
  394. package/dist/vite/agents-bundle-plugin.js.map +1 -1
  395. package/dist/vite/client.d.ts.map +1 -1
  396. package/dist/vite/client.js +2 -0
  397. package/dist/vite/client.js.map +1 -1
  398. package/docs/content/actions.mdx +2 -2
  399. package/docs/content/agent-surfaces.mdx +1 -1
  400. package/docs/content/authentication.mdx +2 -0
  401. package/docs/content/deployment.mdx +36 -0
  402. package/docs/content/http-api.mdx +266 -0
  403. package/docs/content/syncing-template-changes.mdx +159 -0
  404. package/package.json +4 -3
  405. package/src/a2a/activity.ts +38 -27
  406. package/src/agent/engine/builder-engine.ts +35 -4
  407. package/src/agent/run-manager.ts +20 -1
  408. package/src/agent/run-store.ts +4 -1
  409. package/src/agent/types.ts +28 -8
  410. package/src/chat-threads/store.ts +45 -0
  411. package/src/checkpoints/index.ts +2 -0
  412. package/src/checkpoints/route-match.ts +13 -0
  413. package/src/cli/create.ts +105 -17
  414. package/src/cli/index.ts +20 -0
  415. package/src/cli/template-baseline.ts +410 -0
  416. package/src/cli/template-sync.ts +1004 -0
  417. package/src/cli/templates-meta.ts +1 -0
  418. package/src/client/AssistantChat.tsx +38 -12
  419. package/src/client/NewWorkspaceAppFlow.tsx +75 -10
  420. package/src/client/chat/message-components.tsx +127 -66
  421. package/src/client/chat/tool-call-display.tsx +29 -5
  422. package/src/client/error-format.ts +18 -0
  423. package/src/client/org/OrgSwitcher.tsx +30 -8
  424. package/src/client/org/TeamPage.tsx +7 -6
  425. package/src/client/sse-event-processor.ts +3 -0
  426. package/src/data-widgets/index.ts +41 -0
  427. package/src/deploy/build.ts +11 -9
  428. package/src/integrations/webhook-handler.ts +63 -9
  429. package/src/org/auto-join-domain.ts +4 -3
  430. package/src/org/context.ts +108 -39
  431. package/src/org/index.ts +5 -0
  432. package/src/org/service-identity.ts +60 -0
  433. package/src/provider-api/index.ts +22 -1
  434. package/src/scripts/docs/search.ts +12 -1
  435. package/src/server/__snapshots__/agent-chat-plugin.surface.spec.ts.snap +25 -36
  436. package/src/server/agent-chat/context-tools.ts +9 -4
  437. package/src/server/agent-chat/framework-prompts.ts +38 -66
  438. package/src/server/agent-chat-plugin.ts +17 -10
  439. package/src/server/agents-bundle.ts +84 -5
  440. package/src/server/auth.ts +4 -3
  441. package/src/server/builder-browser.ts +47 -19
  442. package/src/server/core-routes-plugin.ts +2 -2
  443. package/src/server/credential-provider.ts +209 -68
  444. package/src/server/index.ts +3 -0
  445. package/src/server/prompts/framework-core-compact.ts +6 -13
  446. package/src/server/prompts/framework-core.ts +9 -21
  447. package/src/server/prompts/index.ts +0 -1
  448. package/src/server/prompts/shared-rules.ts +19 -11
  449. package/src/server/ssr-handler.ts +13 -2
  450. package/src/settings/user-settings.ts +13 -1
  451. package/src/shared/cache-control.ts +141 -0
  452. package/src/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  453. package/src/templates/chat/_gitignore +1 -0
  454. package/src/templates/default/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  455. package/src/templates/headless/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  456. package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +19 -0
  457. package/src/templates/workspace-core/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  458. package/src/templates/workspace-core/.agents/skills/visual-answer/SKILL.md +1 -0
  459. package/src/vite/agents-bundle-plugin.ts +7 -6
  460. package/src/vite/client.ts +5 -0
@@ -1 +1 @@
1
- {"version":3,"file":"ssr-handler.js","sourceRoot":"","sources":["../../src/server/ssr-handler.ts"],"names":[],"mappings":"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","sourcesContent":["import { defineEventHandler } from \"h3\";\n/**\n * Shared SSR catch-all handler for React Router framework mode.\n *\n * Templates wire this up via:\n *\n * // server/routes/[...page].get.ts\n * import { createH3SSRHandler } from \"@agent-native/core/server/ssr-handler\";\n * export default createH3SSRHandler(\n * () => import(\"virtual:react-router/server-build\"),\n * );\n *\n * The `getBuild` callback MUST live in the template's own source so Vite's\n * @react-router/dev plugin can resolve the `virtual:` module. Pulling the\n * import into core (e.g. via a re-export) puts it in node_modules where\n * Vite's SSR externalizer leaves it untouched and Node's ESM loader rejects\n * the unknown scheme — silently 302'ing every request to \"/\".\n */\nimport { createRequestHandler } from \"react-router\";\n\nimport { isMcpPublicPath } from \"../mcp/route-paths.js\";\nimport {\n DEFAULT_SSR_CACHE_HEADERS,\n DEFAULT_SPECULATION_RULES_PATH,\n} from \"../shared/cache-control.js\";\nimport {\n AGENT_NATIVE_SOCIAL_IMAGE_ALT,\n AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT,\n AGENT_NATIVE_SOCIAL_IMAGE_PATH,\n AGENT_NATIVE_SOCIAL_IMAGE_TYPE,\n AGENT_NATIVE_SOCIAL_IMAGE_WIDTH,\n withAgentNativeSocialImageCacheBuster,\n} from \"../shared/social-meta.js\";\nimport {\n getAppBasePathFromViteEnv,\n stripAppBasePath as canonicalStripAppBasePath,\n} from \"./app-base-path.js\";\nimport { captureError } from \"./capture-error.js\";\nimport { runWithRequestContext } from \"./request-context.js\";\nimport {\n getRealtimeClientConfigScript,\n getSentryClientConfigScript,\n} from \"./sentry-config.js\";\n\nexport {\n DEFAULT_SSR_CACHE_HEADERS,\n DEFAULT_SPECULATION_RULES_HEADER,\n DEFAULT_SSR_CACHE_CONTROL,\n} from \"../shared/cache-control.js\";\n\nfunction getAppBasePath(): string {\n return getAppBasePathFromViteEnv();\n}\n\nfunction stripAppBasePath(pathname: string): string {\n return canonicalStripAppBasePath(pathname, getAppBasePath());\n}\n\nfunction stripBasePath(pathname: string, basePath: string): string {\n if (!basePath) return pathname;\n if (pathname === basePath) return \"/\";\n if (pathname.startsWith(`${basePath}/`)) {\n return pathname.slice(basePath.length) || \"/\";\n }\n return pathname;\n}\n\nfunction requestWithPathname(\n request: Request,\n pathname: string,\n basePath: string,\n): Request {\n const url = new URL(request.url);\n let changed = false;\n if (basePath && pathname === \"/__manifest\") {\n const paths = url.searchParams.get(\"paths\");\n if (paths) {\n const strippedPaths = paths\n .split(\",\")\n .map((path) => stripBasePath(path, basePath))\n .join(\",\");\n if (strippedPaths !== paths) {\n url.searchParams.set(\"paths\", strippedPaths);\n changed = true;\n }\n }\n }\n if (url.pathname !== pathname) {\n url.pathname = pathname;\n changed = true;\n }\n if (!changed) return request;\n const init: RequestInit & { duplex?: \"half\" } = {\n method: request.method,\n headers: request.headers,\n signal: request.signal,\n };\n if (request.body && ![\"GET\", \"HEAD\"].includes(request.method.toUpperCase())) {\n init.body = request.body;\n init.duplex = \"half\";\n }\n return new Request(url, init);\n}\n\nfunction requestForAnonymousSsr(request: Request): Request {\n const headers = new Headers(request.headers);\n headers.delete(\"cookie\");\n headers.delete(\"authorization\");\n const init: RequestInit & { duplex?: \"half\" } = {\n method: request.method,\n headers,\n signal: request.signal,\n };\n if (request.body && ![\"GET\", \"HEAD\"].includes(request.method.toUpperCase())) {\n init.body = request.body;\n init.duplex = \"half\";\n }\n return new Request(request.url, init);\n}\n\nfunction prefixMountedPath(path: string, basePath: string): string {\n if (!basePath || !path.startsWith(\"/\") || path.startsWith(\"//\")) return path;\n if (path === basePath || path.startsWith(`${basePath}/`)) return path;\n return `${basePath}${path}`;\n}\n\nfunction prefixMountedHtml(html: string, basePath: string): string {\n if (!basePath) return html;\n const prefixedHtml = html\n .replace(\n /\\b(href|src|action|formaction|poster)=([\"'])(\\/(?!\\/)[^\"']*)\\2/g,\n (_match, attr: string, quote: string, path: string) =>\n `${attr}=${quote}${prefixMountedPath(path, basePath)}${quote}`,\n )\n .replace(/url\\(([\"']?)(\\/(?!\\/)[^)'\" ]+)\\1\\)/g, (_match, quote, path) => {\n const q = quote || \"\";\n return `url(${q}${prefixMountedPath(path, basePath)}${q})`;\n });\n\n // React Router serializes the server-side basename into its hydration\n // context. The request above is deliberately rendered mount-relative, so\n // that value is normally \"/\" even though the browser URL is mounted at a\n // workspace prefix such as \"/analytics\". If the client hydrates that\n // context unchanged, the mounted pathname no longer matches the route tree:\n // index redirects can stall and child pages can fall through to the 404.\n // Keep the serialized router state consistent with the URLs we just\n // prefixed. Template entry clients also set this defensively for older\n // responses, but the initial hydration state must be correct at the source.\n return prefixedHtml.replace(\n /(window\\.__reactRouterContext\\s*=\\s*\\{\\s*\"basename\"\\s*:\\s*)\"(?:\\\\.|[^\"\\\\])*\"/,\n `$1${JSON.stringify(basePath)}`,\n );\n}\n\nfunction injectHeadScript(html: string, script: string | null): string {\n if (!script) return html;\n const headCloseIdx = html.indexOf(\"</head>\");\n if (headCloseIdx === -1) return html;\n return html.slice(0, headCloseIdx) + script + html.slice(headCloseIdx);\n}\n\nconst OG_IMAGE_META_RE = /<meta\\b(?=[^>]*\\bproperty=([\"'])og:image\\1)[^>]*>/i;\nconst TWITTER_CARD_META_RE =\n /<meta\\b(?=[^>]*\\bname=([\"'])twitter:card\\1)[^>]*>/i;\nconst TWITTER_IMAGE_META_RE =\n /<meta\\b(?=[^>]*\\bname=([\"'])twitter:image\\1)[^>]*>/i;\n\nfunction defaultSocialImageUrl(requestUrl: string, basePath: string): string {\n return withAgentNativeSocialImageCacheBuster(\n new URL(\n prefixMountedPath(AGENT_NATIVE_SOCIAL_IMAGE_PATH, basePath),\n requestUrl,\n ).toString(),\n );\n}\n\nfunction injectDefaultSocialImageMeta(html: string, imageUrl: string): string {\n const headCloseIdx = html.indexOf(\"</head>\");\n if (headCloseIdx === -1) return html;\n\n const hasAnySocialImage =\n OG_IMAGE_META_RE.test(html) || TWITTER_IMAGE_META_RE.test(html);\n const tags: string[] = [];\n\n if (!hasAnySocialImage) {\n tags.push(`<meta property=\"og:image\" content=\"${imageUrl}\">`);\n tags.push(`<meta property=\"og:image:secure_url\" content=\"${imageUrl}\">`);\n tags.push(\n `<meta property=\"og:image:type\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_TYPE}\">`,\n );\n tags.push(\n `<meta property=\"og:image:width\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_WIDTH}\">`,\n );\n tags.push(\n `<meta property=\"og:image:height\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT}\">`,\n );\n tags.push(\n `<meta property=\"og:image:alt\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_ALT}\">`,\n );\n }\n if (!TWITTER_CARD_META_RE.test(html)) {\n tags.push(`<meta name=\"twitter:card\" content=\"summary_large_image\">`);\n }\n if (!hasAnySocialImage) {\n tags.push(`<meta name=\"twitter:image\" content=\"${imageUrl}\">`);\n tags.push(\n `<meta name=\"twitter:image:alt\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_ALT}\">`,\n );\n }\n\n if (tags.length === 0) return html;\n return html.slice(0, headCloseIdx) + tags.join(\"\") + html.slice(headCloseIdx);\n}\n\nfunction isSsrHtmlOrDataResponse(\n headers: Headers,\n status: number,\n pathname: string,\n): boolean {\n if (status < 200 || status >= 400) return false;\n const contentType = headers.get(\"content-type\")?.toLowerCase() ?? \"\";\n if (contentType.includes(\"text/html\")) return true;\n return pathname.endsWith(\".data\") && contentType.includes(\"text/x-script\");\n}\n\n/**\n * Apply the SSR cache policy to the response headers.\n *\n * ┌──────────────────────────────────────────────────────────────────────────┐\n * │ SSR IS A PUBLIC, HARD-CDN-CACHED SHELL — SERVED IDENTICALLY TO EVERYONE. │\n * │ │\n * │ Every SSR HTML / React Router `.data` response gets the same public │\n * │ stale-while-revalidate policy for ALL visitors, authenticated or not, so │\n * │ the edge serves one shared copy and never stampedes origin. │\n * │ │\n * │ DO NOT reintroduce per-user / cookie-based cache variation here (no │\n * │ `private`, no `no-store`, no `Vary: Cookie`, no \"authenticated → don't │\n * │ cache\" branch). That makes pages uncacheable for every logged-in visitor, │\n * │ which is slow and expensive — exactly the regression this guardrail │\n * │ prevents. The reason it is SAFE to hard-cache is that the SSR response is │\n * │ impersonal: `createH3SSRHandler` renders without reading the request's │\n * │ session/cookies, so there is no per-user data baked into the HTML. ALL │\n * │ per-user state (who's logged in, private records, access checks) is │\n * │ resolved CLIENT-SIDE after load. Keep it that way: if you need the SSR │\n * │ output to differ per user, the fix is to move that work client-side, not │\n * │ to disable caching here. │\n * └──────────────────────────────────────────────────────────────────────────┘\n */\nfunction applyDefaultSsrCacheHeader(\n headers: Headers,\n status: number,\n pathname: string,\n) {\n if (!isSsrHtmlOrDataResponse(headers, status, pathname)) return;\n\n // A public shell must never set a viewer cookie or vary by credentials.\n // Preserve harmless content-negotiation dimensions such as Accept-Encoding.\n headers.delete(\"set-cookie\");\n const vary = headers.get(\"vary\");\n if (vary) {\n const publicVary = vary\n .split(\",\")\n .map((value) => value.trim())\n .filter((value) => {\n const normalized = value.toLowerCase();\n return (\n normalized &&\n normalized !== \"*\" &&\n normalized !== \"cookie\" &&\n normalized !== \"authorization\"\n );\n });\n if (publicVary.length > 0) headers.set(\"vary\", publicVary.join(\", \"));\n else headers.delete(\"vary\");\n }\n\n // Netlify Functions/proxies are not cached by default. Set all three cache\n // headers: Cache-Control for browsers, CDN-Cache-Control for generic CDNs,\n // and Netlify-CDN-Cache-Control (with durable) so Netlify's shared cache\n // actually serves SSR HTML/.data from the edge instead of forwarding every\n // request to origin — for every visitor, authenticated or not.\n for (const [name, value] of Object.entries(DEFAULT_SSR_CACHE_HEADERS)) {\n headers.set(name, value);\n }\n}\n\nfunction applyDefaultSpeculationRulesHeader(\n headers: Headers,\n status: number,\n basePath: string,\n) {\n if (status < 200 || status >= 400) return;\n if (headers.has(\"speculation-rules\")) return;\n\n const contentType = headers.get(\"content-type\")?.toLowerCase() ?? \"\";\n if (!contentType.includes(\"text/html\")) return;\n\n // Cloudflare Speed Brain injects its own Speculation-Rules header when the\n // origin omits one. Those browser prefetches carry `Sec-Purpose: prefetch`,\n // and Cloudflare refuses cache-ineligible dynamic pages with a 503 before\n // the request can reach Netlify/origin. We publish an explicit no-op ruleset\n // by default so Cloudflare does not inject its edge prefetch rules. Preserve\n // an app-provided Speculation-Rules header above if a template deliberately\n // owns this behavior.\n const rulesPath = prefixMountedPath(DEFAULT_SPECULATION_RULES_PATH, basePath);\n headers.set(\"speculation-rules\", `\"${rulesPath}\"`);\n}\n\n/**\n * Strip document-level CSP from app HTML responses.\n *\n * Hosted templates inject framework bootstrap scripts, analytics, Sentry config,\n * and app-owned inline scripts whose exact bytes vary by build/template. Any\n * shared CSP header, even Report-Only, can block or noisily report Google Tag\n * Manager and those bootstraps. Extension iframes and webviews keep their own\n * route-specific sandboxes; normal app documents deliberately do not emit CSP.\n */\nfunction removeDocumentCsp(headers: Headers): void {\n headers.delete(\"content-security-policy\");\n headers.delete(\"content-security-policy-report-only\");\n}\n\nfunction isFrameworkOrAssetPath(pathname: string): boolean {\n return (\n isMcpPublicPath(pathname) ||\n pathname.startsWith(\"/.well-known/\") ||\n pathname.startsWith(\"/_agent_native/\") ||\n pathname.startsWith(\"/_agent-native/\") ||\n pathname.startsWith(\"/api/\") ||\n pathname.startsWith(\"/@vite/\") ||\n pathname.startsWith(\"/@id/\") ||\n pathname.startsWith(\"/@fs/\") ||\n pathname === \"/@react-refresh\" ||\n pathname === \"/__vite_ping\" ||\n pathname === \"/__open-in-editor\" ||\n pathname === \"/favicon.ico\" ||\n pathname === \"/favicon.png\" ||\n (/\\.\\w+$/.test(pathname) && !pathname.endsWith(\".data\"))\n );\n}\n\nasync function rewriteMountedResponse(\n response: Response,\n basePath: string,\n pathname: string,\n requestUrl: string,\n): Promise<Response> {\n const clientConfigScript =\n [getSentryClientConfigScript(), getRealtimeClientConfigScript()]\n .filter(Boolean)\n .join(\"\") || null;\n const headers = new Headers(response.headers);\n applyDefaultSsrCacheHeader(headers, response.status, pathname);\n applyDefaultSpeculationRulesHeader(headers, response.status, basePath);\n\n const location = headers.get(\"location\");\n if (location?.startsWith(\"/\") && !location.startsWith(\"//\")) {\n headers.set(\"location\", prefixMountedPath(location, basePath));\n }\n\n const contentType = headers.get(\"content-type\") ?? \"\";\n if (!contentType.toLowerCase().includes(\"text/html\")) {\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n }\n removeDocumentCsp(headers);\n if (!response.body) {\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n }\n\n const html = await response.text();\n headers.delete(\"content-length\");\n return new Response(\n injectHeadScript(\n injectDefaultSocialImageMeta(\n prefixMountedHtml(html, basePath),\n defaultSocialImageUrl(requestUrl, basePath),\n ),\n clientConfigScript,\n ),\n {\n status: response.status,\n statusText: response.statusText,\n headers,\n },\n );\n}\n\n/**\n * Create an h3 catch-all that hands page routes to React Router and\n * returns 404 for framework / asset paths that React Router doesn't own.\n */\nexport function createH3SSRHandler(getBuild: () => Promise<unknown> | unknown) {\n const handler = createRequestHandler(getBuild as any);\n return defineEventHandler(async (event) => {\n const basePath = getAppBasePath();\n const p = stripAppBasePath(event.url.pathname);\n if (isFrameworkOrAssetPath(p)) {\n return new Response(null, { status: 404 });\n }\n try {\n const request = requestForAnonymousSsr(\n requestWithPathname(event.req as Request, p, basePath),\n );\n // SSR renders an IMPERSONAL public shell — we deliberately do NOT read the\n // request's session/cookies here, and pin an explicitly anonymous request\n // context. That keeps the SSR HTML/.data identical for every visitor so it\n // can be hard-cached at the CDN for everyone (see applyDefaultSsrCacheHeader).\n //\n // Consequence: SSR loaders that call `getRequestUserEmail()` / `accessFilter()`\n // always see the unauthenticated branch and render public content only. Any\n // per-user view (private records, share-grant access, who's logged in) MUST\n // be resolved CLIENT-SIDE after load, never baked into SSR. Do not re-pin the\n // session here to \"fix\" a per-user page — that silently makes the page\n // uncacheable and/or leaks one user's data into another's cached copy.\n const ctx = { userEmail: undefined, orgId: undefined };\n if (request.method === \"HEAD\") {\n const getRequest = new Request(request.url, {\n method: \"GET\",\n headers: request.headers,\n signal: request.signal,\n });\n const response = await runWithRequestContext(ctx, () =>\n handler(getRequest),\n );\n return await rewriteMountedResponse(\n new Response(null, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n }),\n basePath,\n p,\n request.url,\n );\n }\n return await rewriteMountedResponse(\n await runWithRequestContext(ctx, () => handler(request)),\n basePath,\n p,\n request.url,\n );\n } catch (err) {\n // Log the full stack server-side, but never leak it to the client.\n // Stack traces expose file paths, library versions, and code structure\n // that aid reconnaissance attacks. In dev we surface the message text\n // so devtools shows something useful; in prod we return a bare 500.\n console.error(\"[ssr-handler] SSR error:\", err);\n captureError(err, {\n route: p,\n method: event.req.method,\n userAgent: event.req.headers.get(\"user-agent\") ?? undefined,\n tags: { renderMode: \"anonymous-public\", surface: \"ssr\" },\n });\n const isProd = process.env.NODE_ENV === \"production\";\n const body = isProd\n ? \"Internal Server Error\"\n : `Internal Server Error: ${(err as Error)?.message ?? err}`;\n return new Response(body, {\n status: 500,\n headers: { \"content-type\": \"text/plain\" },\n });\n }\n });\n}\n"]}
1
+ {"version":3,"file":"ssr-handler.js","sourceRoot":"","sources":["../../src/server/ssr-handler.ts"],"names":[],"mappings":"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","sourcesContent":["import { defineEventHandler } from \"h3\";\n/**\n * Shared SSR catch-all handler for React Router framework mode.\n *\n * Templates wire this up via:\n *\n * // server/routes/[...page].get.ts\n * import { createH3SSRHandler } from \"@agent-native/core/server/ssr-handler\";\n * export default createH3SSRHandler(\n * () => import(\"virtual:react-router/server-build\"),\n * );\n *\n * The `getBuild` callback MUST live in the template's own source so Vite's\n * @react-router/dev plugin can resolve the `virtual:` module. Pulling the\n * import into core (e.g. via a re-export) puts it in node_modules where\n * Vite's SSR externalizer leaves it untouched and Node's ESM loader rejects\n * the unknown scheme — silently 302'ing every request to \"/\".\n */\nimport { createRequestHandler } from \"react-router\";\n\nimport { isMcpPublicPath } from \"../mcp/route-paths.js\";\nimport {\n DEFAULT_SPECULATION_RULES_PATH,\n resolveSsrCacheHeaders,\n} from \"../shared/cache-control.js\";\nimport {\n AGENT_NATIVE_SOCIAL_IMAGE_ALT,\n AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT,\n AGENT_NATIVE_SOCIAL_IMAGE_PATH,\n AGENT_NATIVE_SOCIAL_IMAGE_TYPE,\n AGENT_NATIVE_SOCIAL_IMAGE_WIDTH,\n withAgentNativeSocialImageCacheBuster,\n} from \"../shared/social-meta.js\";\nimport {\n getAppBasePathFromViteEnv,\n stripAppBasePath as canonicalStripAppBasePath,\n} from \"./app-base-path.js\";\nimport { captureError } from \"./capture-error.js\";\nimport { runWithRequestContext } from \"./request-context.js\";\nimport {\n getRealtimeClientConfigScript,\n getSentryClientConfigScript,\n} from \"./sentry-config.js\";\n\nexport {\n DEFAULT_SSR_CACHE_HEADERS,\n DEFAULT_SPECULATION_RULES_HEADER,\n DEFAULT_SSR_CACHE_CONTROL,\n DISABLED_SSR_CACHE_HEADERS,\n isSsrCacheEnabled,\n resolveSsrCacheHeaders,\n SSR_CACHE_ENV_VAR,\n} from \"../shared/cache-control.js\";\n\nfunction getAppBasePath(): string {\n return getAppBasePathFromViteEnv();\n}\n\nfunction stripAppBasePath(pathname: string): string {\n return canonicalStripAppBasePath(pathname, getAppBasePath());\n}\n\nfunction stripBasePath(pathname: string, basePath: string): string {\n if (!basePath) return pathname;\n if (pathname === basePath) return \"/\";\n if (pathname.startsWith(`${basePath}/`)) {\n return pathname.slice(basePath.length) || \"/\";\n }\n return pathname;\n}\n\nfunction requestWithPathname(\n request: Request,\n pathname: string,\n basePath: string,\n): Request {\n const url = new URL(request.url);\n let changed = false;\n if (basePath && pathname === \"/__manifest\") {\n const paths = url.searchParams.get(\"paths\");\n if (paths) {\n const strippedPaths = paths\n .split(\",\")\n .map((path) => stripBasePath(path, basePath))\n .join(\",\");\n if (strippedPaths !== paths) {\n url.searchParams.set(\"paths\", strippedPaths);\n changed = true;\n }\n }\n }\n if (url.pathname !== pathname) {\n url.pathname = pathname;\n changed = true;\n }\n if (!changed) return request;\n const init: RequestInit & { duplex?: \"half\" } = {\n method: request.method,\n headers: request.headers,\n signal: request.signal,\n };\n if (request.body && ![\"GET\", \"HEAD\"].includes(request.method.toUpperCase())) {\n init.body = request.body;\n init.duplex = \"half\";\n }\n return new Request(url, init);\n}\n\nfunction requestForAnonymousSsr(request: Request): Request {\n const headers = new Headers(request.headers);\n headers.delete(\"cookie\");\n headers.delete(\"authorization\");\n const init: RequestInit & { duplex?: \"half\" } = {\n method: request.method,\n headers,\n signal: request.signal,\n };\n if (request.body && ![\"GET\", \"HEAD\"].includes(request.method.toUpperCase())) {\n init.body = request.body;\n init.duplex = \"half\";\n }\n return new Request(request.url, init);\n}\n\nfunction prefixMountedPath(path: string, basePath: string): string {\n if (!basePath || !path.startsWith(\"/\") || path.startsWith(\"//\")) return path;\n if (path === basePath || path.startsWith(`${basePath}/`)) return path;\n return `${basePath}${path}`;\n}\n\nfunction prefixMountedHtml(html: string, basePath: string): string {\n if (!basePath) return html;\n const prefixedHtml = html\n .replace(\n /\\b(href|src|action|formaction|poster)=([\"'])(\\/(?!\\/)[^\"']*)\\2/g,\n (_match, attr: string, quote: string, path: string) =>\n `${attr}=${quote}${prefixMountedPath(path, basePath)}${quote}`,\n )\n .replace(/url\\(([\"']?)(\\/(?!\\/)[^)'\" ]+)\\1\\)/g, (_match, quote, path) => {\n const q = quote || \"\";\n return `url(${q}${prefixMountedPath(path, basePath)}${q})`;\n });\n\n // React Router serializes the server-side basename into its hydration\n // context. The request above is deliberately rendered mount-relative, so\n // that value is normally \"/\" even though the browser URL is mounted at a\n // workspace prefix such as \"/analytics\". If the client hydrates that\n // context unchanged, the mounted pathname no longer matches the route tree:\n // index redirects can stall and child pages can fall through to the 404.\n // Keep the serialized router state consistent with the URLs we just\n // prefixed. Template entry clients also set this defensively for older\n // responses, but the initial hydration state must be correct at the source.\n return prefixedHtml.replace(\n /(window\\.__reactRouterContext\\s*=\\s*\\{\\s*\"basename\"\\s*:\\s*)\"(?:\\\\.|[^\"\\\\])*\"/,\n `$1${JSON.stringify(basePath)}`,\n );\n}\n\nfunction injectHeadScript(html: string, script: string | null): string {\n if (!script) return html;\n const headCloseIdx = html.indexOf(\"</head>\");\n if (headCloseIdx === -1) return html;\n return html.slice(0, headCloseIdx) + script + html.slice(headCloseIdx);\n}\n\nconst OG_IMAGE_META_RE = /<meta\\b(?=[^>]*\\bproperty=([\"'])og:image\\1)[^>]*>/i;\nconst TWITTER_CARD_META_RE =\n /<meta\\b(?=[^>]*\\bname=([\"'])twitter:card\\1)[^>]*>/i;\nconst TWITTER_IMAGE_META_RE =\n /<meta\\b(?=[^>]*\\bname=([\"'])twitter:image\\1)[^>]*>/i;\n\nfunction defaultSocialImageUrl(requestUrl: string, basePath: string): string {\n return withAgentNativeSocialImageCacheBuster(\n new URL(\n prefixMountedPath(AGENT_NATIVE_SOCIAL_IMAGE_PATH, basePath),\n requestUrl,\n ).toString(),\n );\n}\n\nfunction injectDefaultSocialImageMeta(html: string, imageUrl: string): string {\n const headCloseIdx = html.indexOf(\"</head>\");\n if (headCloseIdx === -1) return html;\n\n const hasAnySocialImage =\n OG_IMAGE_META_RE.test(html) || TWITTER_IMAGE_META_RE.test(html);\n const tags: string[] = [];\n\n if (!hasAnySocialImage) {\n tags.push(`<meta property=\"og:image\" content=\"${imageUrl}\">`);\n tags.push(`<meta property=\"og:image:secure_url\" content=\"${imageUrl}\">`);\n tags.push(\n `<meta property=\"og:image:type\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_TYPE}\">`,\n );\n tags.push(\n `<meta property=\"og:image:width\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_WIDTH}\">`,\n );\n tags.push(\n `<meta property=\"og:image:height\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT}\">`,\n );\n tags.push(\n `<meta property=\"og:image:alt\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_ALT}\">`,\n );\n }\n if (!TWITTER_CARD_META_RE.test(html)) {\n tags.push(`<meta name=\"twitter:card\" content=\"summary_large_image\">`);\n }\n if (!hasAnySocialImage) {\n tags.push(`<meta name=\"twitter:image\" content=\"${imageUrl}\">`);\n tags.push(\n `<meta name=\"twitter:image:alt\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_ALT}\">`,\n );\n }\n\n if (tags.length === 0) return html;\n return html.slice(0, headCloseIdx) + tags.join(\"\") + html.slice(headCloseIdx);\n}\n\nfunction isSsrHtmlOrDataResponse(\n headers: Headers,\n status: number,\n pathname: string,\n): boolean {\n if (status < 200 || status >= 400) return false;\n const contentType = headers.get(\"content-type\")?.toLowerCase() ?? \"\";\n if (contentType.includes(\"text/html\")) return true;\n return pathname.endsWith(\".data\") && contentType.includes(\"text/x-script\");\n}\n\n/**\n * Apply the SSR cache policy to the response headers.\n *\n * ┌──────────────────────────────────────────────────────────────────────────┐\n * │ SSR IS A PUBLIC, HARD-CDN-CACHED SHELL — SERVED IDENTICALLY TO EVERYONE. │\n * │ │\n * │ Every SSR HTML / React Router `.data` response gets the same public │\n * │ stale-while-revalidate policy for ALL visitors, authenticated or not, so │\n * │ the edge serves one shared copy and never stampedes origin. │\n * │ │\n * │ DO NOT reintroduce per-user / cookie-based cache variation here (no │\n * │ `private`, no `no-store`, no `Vary: Cookie`, no \"authenticated → don't │\n * │ cache\" branch). That makes pages uncacheable for every logged-in visitor, │\n * │ which is slow and expensive — exactly the regression this guardrail │\n * │ prevents. The reason it is SAFE to hard-cache is that the SSR response is │\n * │ impersonal: `createH3SSRHandler` renders without reading the request's │\n * │ session/cookies, so there is no per-user data baked into the HTML. ALL │\n * │ per-user state (who's logged in, private records, access checks) is │\n * │ resolved CLIENT-SIDE after load. Keep it that way: if you need the SSR │\n * │ output to differ per user, the fix is to move that work client-side, not │\n * │ to disable caching here. │\n * │ │\n * │ HOW LONG the shell is cached is deployment-wide and configurable through │\n * │ AGENT_NATIVE_SSR_CACHE (see `resolveSsrCacheHeaders`), for hosts that do │\n * │ not purge their CDN on deploy. What remains forbidden is PER-REQUEST / │\n * │ PER-USER variation — no `private`, no `Vary: Cookie`, no per-route escape │\n * │ hatch — because that is what poisons a shared CDN cache key. A value fixed │\n * │ for the whole deployment cannot. │\n * └──────────────────────────────────────────────────────────────────────────┘\n */\nfunction applyDefaultSsrCacheHeader(\n headers: Headers,\n status: number,\n pathname: string,\n) {\n if (!isSsrHtmlOrDataResponse(headers, status, pathname)) return;\n\n // A public shell must never set a viewer cookie or vary by credentials.\n // Preserve harmless content-negotiation dimensions such as Accept-Encoding.\n headers.delete(\"set-cookie\");\n const vary = headers.get(\"vary\");\n if (vary) {\n const publicVary = vary\n .split(\",\")\n .map((value) => value.trim())\n .filter((value) => {\n const normalized = value.toLowerCase();\n return (\n normalized &&\n normalized !== \"*\" &&\n normalized !== \"cookie\" &&\n normalized !== \"authorization\"\n );\n });\n if (publicVary.length > 0) headers.set(\"vary\", publicVary.join(\", \"));\n else headers.delete(\"vary\");\n }\n\n // Netlify Functions/proxies are not cached by default. Set all three cache\n // headers: Cache-Control for browsers, CDN-Cache-Control for generic CDNs,\n // and Netlify-CDN-Cache-Control (with durable) so Netlify's shared cache\n // actually serves SSR HTML/.data from the edge instead of forwarding every\n // request to origin — for every visitor, authenticated or not.\n for (const [name, value] of Object.entries(resolveSsrCacheHeaders())) {\n headers.set(name, value);\n }\n}\n\nfunction applyDefaultSpeculationRulesHeader(\n headers: Headers,\n status: number,\n basePath: string,\n) {\n if (status < 200 || status >= 400) return;\n if (headers.has(\"speculation-rules\")) return;\n\n const contentType = headers.get(\"content-type\")?.toLowerCase() ?? \"\";\n if (!contentType.includes(\"text/html\")) return;\n\n // Cloudflare Speed Brain injects its own Speculation-Rules header when the\n // origin omits one. Those browser prefetches carry `Sec-Purpose: prefetch`,\n // and Cloudflare refuses cache-ineligible dynamic pages with a 503 before\n // the request can reach Netlify/origin. We publish an explicit no-op ruleset\n // by default so Cloudflare does not inject its edge prefetch rules. Preserve\n // an app-provided Speculation-Rules header above if a template deliberately\n // owns this behavior.\n const rulesPath = prefixMountedPath(DEFAULT_SPECULATION_RULES_PATH, basePath);\n headers.set(\"speculation-rules\", `\"${rulesPath}\"`);\n}\n\n/**\n * Strip document-level CSP from app HTML responses.\n *\n * Hosted templates inject framework bootstrap scripts, analytics, Sentry config,\n * and app-owned inline scripts whose exact bytes vary by build/template. Any\n * shared CSP header, even Report-Only, can block or noisily report Google Tag\n * Manager and those bootstraps. Extension iframes and webviews keep their own\n * route-specific sandboxes; normal app documents deliberately do not emit CSP.\n */\nfunction removeDocumentCsp(headers: Headers): void {\n headers.delete(\"content-security-policy\");\n headers.delete(\"content-security-policy-report-only\");\n}\n\nfunction isFrameworkOrAssetPath(pathname: string): boolean {\n return (\n isMcpPublicPath(pathname) ||\n pathname.startsWith(\"/.well-known/\") ||\n pathname.startsWith(\"/_agent_native/\") ||\n pathname.startsWith(\"/_agent-native/\") ||\n pathname.startsWith(\"/api/\") ||\n pathname.startsWith(\"/@vite/\") ||\n pathname.startsWith(\"/@id/\") ||\n pathname.startsWith(\"/@fs/\") ||\n pathname === \"/@react-refresh\" ||\n pathname === \"/__vite_ping\" ||\n pathname === \"/__open-in-editor\" ||\n pathname === \"/favicon.ico\" ||\n pathname === \"/favicon.png\" ||\n (/\\.\\w+$/.test(pathname) && !pathname.endsWith(\".data\"))\n );\n}\n\nasync function rewriteMountedResponse(\n response: Response,\n basePath: string,\n pathname: string,\n requestUrl: string,\n): Promise<Response> {\n const clientConfigScript =\n [getSentryClientConfigScript(), getRealtimeClientConfigScript()]\n .filter(Boolean)\n .join(\"\") || null;\n const headers = new Headers(response.headers);\n applyDefaultSsrCacheHeader(headers, response.status, pathname);\n applyDefaultSpeculationRulesHeader(headers, response.status, basePath);\n\n const location = headers.get(\"location\");\n if (location?.startsWith(\"/\") && !location.startsWith(\"//\")) {\n headers.set(\"location\", prefixMountedPath(location, basePath));\n }\n\n const contentType = headers.get(\"content-type\") ?? \"\";\n if (!contentType.toLowerCase().includes(\"text/html\")) {\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n }\n removeDocumentCsp(headers);\n if (!response.body) {\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n }\n\n const html = await response.text();\n headers.delete(\"content-length\");\n return new Response(\n injectHeadScript(\n injectDefaultSocialImageMeta(\n prefixMountedHtml(html, basePath),\n defaultSocialImageUrl(requestUrl, basePath),\n ),\n clientConfigScript,\n ),\n {\n status: response.status,\n statusText: response.statusText,\n headers,\n },\n );\n}\n\n/**\n * Create an h3 catch-all that hands page routes to React Router and\n * returns 404 for framework / asset paths that React Router doesn't own.\n */\nexport function createH3SSRHandler(getBuild: () => Promise<unknown> | unknown) {\n const handler = createRequestHandler(getBuild as any);\n return defineEventHandler(async (event) => {\n const basePath = getAppBasePath();\n const p = stripAppBasePath(event.url.pathname);\n if (isFrameworkOrAssetPath(p)) {\n return new Response(null, { status: 404 });\n }\n try {\n const request = requestForAnonymousSsr(\n requestWithPathname(event.req as Request, p, basePath),\n );\n // SSR renders an IMPERSONAL public shell — we deliberately do NOT read the\n // request's session/cookies here, and pin an explicitly anonymous request\n // context. That keeps the SSR HTML/.data identical for every visitor so it\n // can be hard-cached at the CDN for everyone (see applyDefaultSsrCacheHeader).\n //\n // Consequence: SSR loaders that call `getRequestUserEmail()` / `accessFilter()`\n // always see the unauthenticated branch and render public content only. Any\n // per-user view (private records, share-grant access, who's logged in) MUST\n // be resolved CLIENT-SIDE after load, never baked into SSR. Do not re-pin the\n // session here to \"fix\" a per-user page — that silently makes the page\n // uncacheable and/or leaks one user's data into another's cached copy.\n const ctx = { userEmail: undefined, orgId: undefined };\n if (request.method === \"HEAD\") {\n const getRequest = new Request(request.url, {\n method: \"GET\",\n headers: request.headers,\n signal: request.signal,\n });\n const response = await runWithRequestContext(ctx, () =>\n handler(getRequest),\n );\n return await rewriteMountedResponse(\n new Response(null, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n }),\n basePath,\n p,\n request.url,\n );\n }\n return await rewriteMountedResponse(\n await runWithRequestContext(ctx, () => handler(request)),\n basePath,\n p,\n request.url,\n );\n } catch (err) {\n // Log the full stack server-side, but never leak it to the client.\n // Stack traces expose file paths, library versions, and code structure\n // that aid reconnaissance attacks. In dev we surface the message text\n // so devtools shows something useful; in prod we return a bare 500.\n console.error(\"[ssr-handler] SSR error:\", err);\n captureError(err, {\n route: p,\n method: event.req.method,\n userAgent: event.req.headers.get(\"user-agent\") ?? undefined,\n tags: { renderMode: \"anonymous-public\", surface: \"ssr\" },\n });\n const isProd = process.env.NODE_ENV === \"production\";\n const body = isProd\n ? \"Internal Server Error\"\n : `Internal Server Error: ${(err as Error)?.message ?? err}`;\n return new Response(body, {\n status: 500,\n headers: { \"content-type\": \"text/plain\" },\n });\n }\n });\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"user-settings.d.ts","sourceRoot":"","sources":["../../src/settings/user-settings.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,YAAY,CAAC;AAMpB,yEAAyE;AACzE,wBAAsB,cAAc,CAClC,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAEzC;AAED,sEAAsE;AACtE,wBAAsB,cAAc,CAClC,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,oCAAoC;AACpC,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,OAAO,CAAC,CAElB"}
1
+ {"version":3,"file":"user-settings.d.ts","sourceRoot":"","sources":["../../src/settings/user-settings.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,YAAY,CAAC;AAepB,yEAAyE;AACzE,wBAAsB,cAAc,CAClC,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAKzC;AAED,sEAAsE;AACtE,wBAAsB,cAAc,CAClC,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,oCAAoC;AACpC,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,OAAO,CAAC,CAElB"}
@@ -9,11 +9,23 @@
9
9
  */
10
10
  import { getSetting, putSetting, deleteSetting, } from "./store.js";
11
11
  function userKey(email, key) {
12
+ return `u:${email.trim().toLowerCase()}:${key}`;
13
+ }
14
+ /**
15
+ * Pre-normalization spelling. Callers pass the session email verbatim, so the
16
+ * same user could be written under `Alice@Builder.IO` and read under
17
+ * `alice@builder.io` — silently losing settings such as `active-org-id`.
18
+ */
19
+ function legacyUserKey(email, key) {
12
20
  return `u:${email}:${key}`;
13
21
  }
14
22
  /** Read a user-scoped setting. Returns null if not set for this user. */
15
23
  export async function getUserSetting(email, key) {
16
- return getSetting(userKey(email, key));
24
+ const normalized = await getSetting(userKey(email, key));
25
+ if (normalized !== null)
26
+ return normalized;
27
+ const legacy = legacyUserKey(email, key);
28
+ return legacy === userKey(email, key) ? null : getSetting(legacy);
17
29
  }
18
30
  /** Write a user-scoped setting. Always writes to the prefixed key. */
19
31
  export async function putUserSetting(email, key, value, options) {
@@ -1 +1 @@
1
- {"version":3,"file":"user-settings.js","sourceRoot":"","sources":["../../src/settings/user-settings.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,UAAU,EACV,UAAU,EACV,aAAa,GAEd,MAAM,YAAY,CAAC;AAEpB,SAAS,OAAO,CAAC,KAAa,EAAE,GAAW;IACzC,OAAO,KAAK,KAAK,IAAI,GAAG,EAAE,CAAC;AAC7B,CAAC;AAED,yEAAyE;AACzE,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,KAAa,EACb,GAAW;IAEX,OAAO,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;AACzC,CAAC;AAED,sEAAsE;AACtE,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,KAAa,EACb,GAAW,EACX,KAA8B,EAC9B,OAA2B;IAE3B,OAAO,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;AACzD,CAAC;AAED,oCAAoC;AACpC,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,KAAa,EACb,GAAW,EACX,OAA2B;IAE3B,OAAO,aAAa,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;AACrD,CAAC","sourcesContent":["/**\n * User-scoped settings helpers.\n *\n * Wraps the global settings store with per-user key prefixing.\n * Keys are stored as `u:<email>:<key>` in the settings table.\n *\n * No global fallback — each user starts with a clean slate. This\n * prevents one user's private data from leaking to other users.\n */\n\nimport {\n getSetting,\n putSetting,\n deleteSetting,\n type StoreWriteOptions,\n} from \"./store.js\";\n\nfunction userKey(email: string, key: string): string {\n return `u:${email}:${key}`;\n}\n\n/** Read a user-scoped setting. Returns null if not set for this user. */\nexport async function getUserSetting(\n email: string,\n key: string,\n): Promise<Record<string, unknown> | null> {\n return getSetting(userKey(email, key));\n}\n\n/** Write a user-scoped setting. Always writes to the prefixed key. */\nexport async function putUserSetting(\n email: string,\n key: string,\n value: Record<string, unknown>,\n options?: StoreWriteOptions,\n): Promise<void> {\n return putSetting(userKey(email, key), value, options);\n}\n\n/** Delete a user-scoped setting. */\nexport async function deleteUserSetting(\n email: string,\n key: string,\n options?: StoreWriteOptions,\n): Promise<boolean> {\n return deleteSetting(userKey(email, key), options);\n}\n"]}
1
+ {"version":3,"file":"user-settings.js","sourceRoot":"","sources":["../../src/settings/user-settings.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,UAAU,EACV,UAAU,EACV,aAAa,GAEd,MAAM,YAAY,CAAC;AAEpB,SAAS,OAAO,CAAC,KAAa,EAAE,GAAW;IACzC,OAAO,KAAK,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,IAAI,GAAG,EAAE,CAAC;AAClD,CAAC;AAED;;;;GAIG;AACH,SAAS,aAAa,CAAC,KAAa,EAAE,GAAW;IAC/C,OAAO,KAAK,KAAK,IAAI,GAAG,EAAE,CAAC;AAC7B,CAAC;AAED,yEAAyE;AACzE,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,KAAa,EACb,GAAW;IAEX,MAAM,UAAU,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;IACzD,IAAI,UAAU,KAAK,IAAI;QAAE,OAAO,UAAU,CAAC;IAC3C,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACzC,OAAO,MAAM,KAAK,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;AACpE,CAAC;AAED,sEAAsE;AACtE,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,KAAa,EACb,GAAW,EACX,KAA8B,EAC9B,OAA2B;IAE3B,OAAO,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;AACzD,CAAC;AAED,oCAAoC;AACpC,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,KAAa,EACb,GAAW,EACX,OAA2B;IAE3B,OAAO,aAAa,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;AACrD,CAAC","sourcesContent":["/**\n * User-scoped settings helpers.\n *\n * Wraps the global settings store with per-user key prefixing.\n * Keys are stored as `u:<email>:<key>` in the settings table.\n *\n * No global fallback — each user starts with a clean slate. This\n * prevents one user's private data from leaking to other users.\n */\n\nimport {\n getSetting,\n putSetting,\n deleteSetting,\n type StoreWriteOptions,\n} from \"./store.js\";\n\nfunction userKey(email: string, key: string): string {\n return `u:${email.trim().toLowerCase()}:${key}`;\n}\n\n/**\n * Pre-normalization spelling. Callers pass the session email verbatim, so the\n * same user could be written under `Alice@Builder.IO` and read under\n * `alice@builder.io` — silently losing settings such as `active-org-id`.\n */\nfunction legacyUserKey(email: string, key: string): string {\n return `u:${email}:${key}`;\n}\n\n/** Read a user-scoped setting. Returns null if not set for this user. */\nexport async function getUserSetting(\n email: string,\n key: string,\n): Promise<Record<string, unknown> | null> {\n const normalized = await getSetting(userKey(email, key));\n if (normalized !== null) return normalized;\n const legacy = legacyUserKey(email, key);\n return legacy === userKey(email, key) ? null : getSetting(legacy);\n}\n\n/** Write a user-scoped setting. Always writes to the prefixed key. */\nexport async function putUserSetting(\n email: string,\n key: string,\n value: Record<string, unknown>,\n options?: StoreWriteOptions,\n): Promise<void> {\n return putSetting(userKey(email, key), value, options);\n}\n\n/** Delete a user-scoped setting. */\nexport async function deleteUserSetting(\n email: string,\n key: string,\n options?: StoreWriteOptions,\n): Promise<boolean> {\n return deleteSetting(userKey(email, key), options);\n}\n"]}
@@ -7,6 +7,58 @@ export declare const DEFAULT_SSR_CACHE_HEADERS: {
7
7
  readonly "cdn-cache-control": "public, max-age=600, stale-while-revalidate=604800, stale-if-error=3600";
8
8
  readonly "netlify-cdn-cache-control": "public, max-age=600, stale-while-revalidate=604800, stale-if-error=3600";
9
9
  };
10
+ /**
11
+ * Deployment-wide override for the SSR shell cache policy.
12
+ *
13
+ * The default (`DEFAULT_SSR_CACHE_HEADERS`) is deliberately aggressive: SSR
14
+ * HTML and React Router `.data` are one impersonal public shell, so hosts that
15
+ * purge their CDN on deploy get near-static page loads for free. Two situations
16
+ * make that default wrong, and both are properties of the DEPLOYMENT, not of
17
+ * the request:
18
+ *
19
+ * 1. The host does not purge its CDN on deploy, so a shipped build can keep
20
+ * serving the previous shell for `max-age` + `stale-while-revalidate`.
21
+ * 2. The app's loaders return mutable public data, so a `useRevalidator()`
22
+ * after a mutation reads the browser's cached `.data` copy instead of
23
+ * fresh loader output.
24
+ *
25
+ * This override is intentionally global and env-driven rather than a
26
+ * per-route/per-request escape hatch. A response that varies by request is how
27
+ * one visitor's payload ends up in another visitor's shared CDN entry; a value
28
+ * fixed for the whole deployment cannot. Turning caching off does NOT make SSR
29
+ * personalized — `requestForAnonymousSsr` still strips cookies before render.
30
+ *
31
+ * Accepted values (case-insensitive):
32
+ * unset | "on" | "default" | "true" | "1" → the default policy, unchanged
33
+ * "off" | "false" | "0" | "none" | "no-store" | "disabled" → no caching
34
+ * "<n>" | "<n>s" | "<n>m" | "<n>h" → public caching with that freshness
35
+ */
36
+ export declare const SSR_CACHE_ENV_VAR = "AGENT_NATIVE_SSR_CACHE";
37
+ export declare const DISABLED_SSR_CACHE_CONTROL = "no-store";
38
+ export declare const DISABLED_SSR_CACHE_HEADERS: {
39
+ readonly "cache-control": "no-store";
40
+ readonly "cdn-cache-control": "no-store";
41
+ readonly "netlify-cdn-cache-control": "no-store";
42
+ };
43
+ export type SsrCachePolicy = {
44
+ kind: "default";
45
+ } | {
46
+ kind: "disabled";
47
+ } | {
48
+ kind: "maxAge";
49
+ seconds: number;
50
+ };
51
+ export type SsrCacheHeaders = Record<"cache-control" | "cdn-cache-control" | "netlify-cdn-cache-control", string>;
52
+ export declare function parseSsrCacheSetting(raw: string | undefined | null): SsrCachePolicy;
53
+ export declare function ssrCacheHeadersForPolicy(policy: SsrCachePolicy): SsrCacheHeaders;
54
+ /**
55
+ * Resolve the SSR cache headers for this deployment. Reads
56
+ * `AGENT_NATIVE_SSR_CACHE` and memoizes per distinct value so the hot SSR path
57
+ * does not re-parse on every response. The result is frozen and shared by every
58
+ * response — copy it before mutating.
59
+ */
60
+ export declare function resolveSsrCacheHeaders(env?: Record<string, string | undefined>): Readonly<SsrCacheHeaders>;
61
+ export declare function isSsrCacheEnabled(env?: Record<string, string | undefined>): boolean;
10
62
  export declare const DEFAULT_SPECULATION_RULES_PATH = "/_agent-native/speculation-rules.json";
11
63
  export declare const DEFAULT_SPECULATION_RULES_HEADER = "\"/_agent-native/speculation-rules.json\"";
12
64
  export declare const EMPTY_SPECULATION_RULES: {
@@ -1 +1 @@
1
- {"version":3,"file":"cache-control.d.ts","sourceRoot":"","sources":["../../src/shared/cache-control.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,4BAA4B,4EACkC,CAAC;AAE5E,eAAO,MAAM,yBAAyB,4EAA+B,CAAC;AAEtE,eAAO,MAAM,6BAA6B,4EAA4B,CAAC;AAEvE,eAAO,MAAM,qCAAqC,4EACpB,CAAC;AAE/B,eAAO,MAAM,yBAAyB;aACpC,eAAe;aACf,mBAAmB;aACnB,2BAA2B;CACnB,CAAC;AAEX,eAAO,MAAM,8BAA8B,0CACF,CAAC;AAE1C,eAAO,MAAM,gCAAgC,8CAAwC,CAAC;AAEtF,eAAO,MAAM,uBAAuB;aAClC,QAAQ;aACR,SAAS;CACD,CAAC"}
1
+ {"version":3,"file":"cache-control.d.ts","sourceRoot":"","sources":["../../src/shared/cache-control.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,4BAA4B,4EACkC,CAAC;AAE5E,eAAO,MAAM,yBAAyB,4EAA+B,CAAC;AAEtE,eAAO,MAAM,6BAA6B,4EAA4B,CAAC;AAEvE,eAAO,MAAM,qCAAqC,4EACpB,CAAC;AAE/B,eAAO,MAAM,yBAAyB;aACpC,eAAe;aACf,mBAAmB;aACnB,2BAA2B;CACnB,CAAC;AAEX;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,iBAAiB,2BAA2B,CAAC;AAE1D,eAAO,MAAM,0BAA0B,aAAa,CAAC;AAErD,eAAO,MAAM,0BAA0B;aACrC,eAAe;aACf,mBAAmB;aACnB,2BAA2B;CACnB,CAAC;AAEX,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GACpB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAExC,MAAM,MAAM,eAAe,GAAG,MAAM,CAClC,eAAe,GAAG,mBAAmB,GAAG,2BAA2B,EACnE,MAAM,CACP,CAAC;AAsBF,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAC7B,cAAc,CAsBhB;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,cAAc,GACrB,eAAe,CAcjB;AAKD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAEvB,GACd,QAAQ,CAAC,eAAe,CAAC,CAQ3B;AAED,wBAAgB,iBAAiB,CAC/B,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAEvB,GACd,OAAO,CAET;AAED,eAAO,MAAM,8BAA8B,0CACF,CAAC;AAE1C,eAAO,MAAM,gCAAgC,8CAAwC,CAAC;AAEtF,eAAO,MAAM,uBAAuB;aAClC,QAAQ;aACR,SAAS;CACD,CAAC"}
@@ -7,6 +7,113 @@ export const DEFAULT_SSR_CACHE_HEADERS = {
7
7
  "cdn-cache-control": DEFAULT_SSR_CDN_CACHE_CONTROL,
8
8
  "netlify-cdn-cache-control": DEFAULT_SSR_NETLIFY_CDN_CACHE_CONTROL,
9
9
  };
10
+ /**
11
+ * Deployment-wide override for the SSR shell cache policy.
12
+ *
13
+ * The default (`DEFAULT_SSR_CACHE_HEADERS`) is deliberately aggressive: SSR
14
+ * HTML and React Router `.data` are one impersonal public shell, so hosts that
15
+ * purge their CDN on deploy get near-static page loads for free. Two situations
16
+ * make that default wrong, and both are properties of the DEPLOYMENT, not of
17
+ * the request:
18
+ *
19
+ * 1. The host does not purge its CDN on deploy, so a shipped build can keep
20
+ * serving the previous shell for `max-age` + `stale-while-revalidate`.
21
+ * 2. The app's loaders return mutable public data, so a `useRevalidator()`
22
+ * after a mutation reads the browser's cached `.data` copy instead of
23
+ * fresh loader output.
24
+ *
25
+ * This override is intentionally global and env-driven rather than a
26
+ * per-route/per-request escape hatch. A response that varies by request is how
27
+ * one visitor's payload ends up in another visitor's shared CDN entry; a value
28
+ * fixed for the whole deployment cannot. Turning caching off does NOT make SSR
29
+ * personalized — `requestForAnonymousSsr` still strips cookies before render.
30
+ *
31
+ * Accepted values (case-insensitive):
32
+ * unset | "on" | "default" | "true" | "1" → the default policy, unchanged
33
+ * "off" | "false" | "0" | "none" | "no-store" | "disabled" → no caching
34
+ * "<n>" | "<n>s" | "<n>m" | "<n>h" → public caching with that freshness
35
+ */
36
+ export const SSR_CACHE_ENV_VAR = "AGENT_NATIVE_SSR_CACHE";
37
+ export const DISABLED_SSR_CACHE_CONTROL = "no-store";
38
+ export const DISABLED_SSR_CACHE_HEADERS = {
39
+ "cache-control": DISABLED_SSR_CACHE_CONTROL,
40
+ "cdn-cache-control": DISABLED_SSR_CACHE_CONTROL,
41
+ "netlify-cdn-cache-control": DISABLED_SSR_CACHE_CONTROL,
42
+ };
43
+ const ON_VALUES = new Set(["", "on", "default", "true", "1", "yes"]);
44
+ const OFF_VALUES = new Set([
45
+ "off",
46
+ "false",
47
+ "0",
48
+ "no",
49
+ "none",
50
+ "no-store",
51
+ "disabled",
52
+ ]);
53
+ const DURATION_RE = /^(\d+)\s*(s|sec|secs|seconds?|m|min|mins?|h|hours?)?$/;
54
+ const DURATION_MULTIPLIERS = {
55
+ s: 1,
56
+ m: 60,
57
+ h: 3600,
58
+ };
59
+ const MAX_SSR_CACHE_SECONDS = 31_536_000;
60
+ export function parseSsrCacheSetting(raw) {
61
+ const value = (raw ?? "").trim().toLowerCase();
62
+ if (ON_VALUES.has(value))
63
+ return { kind: "default" };
64
+ if (OFF_VALUES.has(value))
65
+ return { kind: "disabled" };
66
+ const match = DURATION_RE.exec(value);
67
+ if (match) {
68
+ const multiplier = DURATION_MULTIPLIERS[match[2]?.[0] ?? "s"] ?? 1;
69
+ const seconds = Math.min(Number(match[1]) * multiplier, MAX_SSR_CACHE_SECONDS);
70
+ return seconds > 0 ? { kind: "maxAge", seconds } : { kind: "disabled" };
71
+ }
72
+ // Unrecognized values fall back to the default rather than failing the
73
+ // deployment: a typo in this env var must never silently disable the CDN.
74
+ console.warn(`[agent-native] Ignoring unrecognized ${SSR_CACHE_ENV_VAR}=${raw}. ` +
75
+ `Expected "on", "off", or a duration such as "30s" / "5m".`);
76
+ return { kind: "default" };
77
+ }
78
+ export function ssrCacheHeadersForPolicy(policy) {
79
+ if (policy.kind === "default")
80
+ return { ...DEFAULT_SSR_CACHE_HEADERS };
81
+ if (policy.kind === "disabled")
82
+ return { ...DISABLED_SSR_CACHE_HEADERS };
83
+ // Mirror stale-while-revalidate onto the chosen freshness. Apps opt into a
84
+ // short max-age precisely because a long stale window is the problem; keeping
85
+ // the 7-day default SWR here would hand back the staleness they opted out of.
86
+ const control = `public, max-age=${policy.seconds}, ` +
87
+ `stale-while-revalidate=${policy.seconds}, stale-if-error=3600`;
88
+ return {
89
+ "cache-control": control,
90
+ "cdn-cache-control": control,
91
+ "netlify-cdn-cache-control": control,
92
+ };
93
+ }
94
+ let memoizedRaw;
95
+ let memoizedHeaders;
96
+ /**
97
+ * Resolve the SSR cache headers for this deployment. Reads
98
+ * `AGENT_NATIVE_SSR_CACHE` and memoizes per distinct value so the hot SSR path
99
+ * does not re-parse on every response. The result is frozen and shared by every
100
+ * response — copy it before mutating.
101
+ */
102
+ export function resolveSsrCacheHeaders(env = typeof process === "undefined"
103
+ ? {}
104
+ : process.env) {
105
+ const raw = env[SSR_CACHE_ENV_VAR];
106
+ if (memoizedHeaders && raw === memoizedRaw)
107
+ return memoizedHeaders;
108
+ memoizedRaw = raw;
109
+ memoizedHeaders = Object.freeze(ssrCacheHeadersForPolicy(parseSsrCacheSetting(raw)));
110
+ return memoizedHeaders;
111
+ }
112
+ export function isSsrCacheEnabled(env = typeof process === "undefined"
113
+ ? {}
114
+ : process.env) {
115
+ return parseSsrCacheSetting(env[SSR_CACHE_ENV_VAR]).kind !== "disabled";
116
+ }
10
117
  export const DEFAULT_SPECULATION_RULES_PATH = "/_agent-native/speculation-rules.json";
11
118
  export const DEFAULT_SPECULATION_RULES_HEADER = `"${DEFAULT_SPECULATION_RULES_PATH}"`;
12
119
  export const EMPTY_SPECULATION_RULES = {
@@ -1 +1 @@
1
- {"version":3,"file":"cache-control.js","sourceRoot":"","sources":["../../src/shared/cache-control.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,4BAA4B,GACvC,yEAAyE,CAAC;AAE5E,MAAM,CAAC,MAAM,yBAAyB,GAAG,4BAA4B,CAAC;AAEtE,MAAM,CAAC,MAAM,6BAA6B,GAAG,yBAAyB,CAAC;AAEvE,MAAM,CAAC,MAAM,qCAAqC,GAChD,4BAA4B,CAAC;AAE/B,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,eAAe,EAAE,yBAAyB;IAC1C,mBAAmB,EAAE,6BAA6B;IAClD,2BAA2B,EAAE,qCAAqC;CAC1D,CAAC;AAEX,MAAM,CAAC,MAAM,8BAA8B,GACzC,uCAAuC,CAAC;AAE1C,MAAM,CAAC,MAAM,gCAAgC,GAAG,IAAI,8BAA8B,GAAG,CAAC;AAEtF,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,QAAQ,EAAE,EAAE;IACZ,SAAS,EAAE,EAAE;CACL,CAAC","sourcesContent":["export const DEFAULT_PUBLIC_CACHE_CONTROL =\n \"public, max-age=600, stale-while-revalidate=604800, stale-if-error=3600\";\n\nexport const DEFAULT_SSR_CACHE_CONTROL = DEFAULT_PUBLIC_CACHE_CONTROL;\n\nexport const DEFAULT_SSR_CDN_CACHE_CONTROL = DEFAULT_SSR_CACHE_CONTROL;\n\nexport const DEFAULT_SSR_NETLIFY_CDN_CACHE_CONTROL =\n DEFAULT_PUBLIC_CACHE_CONTROL;\n\nexport const DEFAULT_SSR_CACHE_HEADERS = {\n \"cache-control\": DEFAULT_SSR_CACHE_CONTROL,\n \"cdn-cache-control\": DEFAULT_SSR_CDN_CACHE_CONTROL,\n \"netlify-cdn-cache-control\": DEFAULT_SSR_NETLIFY_CDN_CACHE_CONTROL,\n} as const;\n\nexport const DEFAULT_SPECULATION_RULES_PATH =\n \"/_agent-native/speculation-rules.json\";\n\nexport const DEFAULT_SPECULATION_RULES_HEADER = `\"${DEFAULT_SPECULATION_RULES_PATH}\"`;\n\nexport const EMPTY_SPECULATION_RULES = {\n prefetch: [],\n prerender: [],\n} as const;\n"]}
1
+ {"version":3,"file":"cache-control.js","sourceRoot":"","sources":["../../src/shared/cache-control.ts"],"names":[],"mappings":"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","sourcesContent":["export const DEFAULT_PUBLIC_CACHE_CONTROL =\n \"public, max-age=600, stale-while-revalidate=604800, stale-if-error=3600\";\n\nexport const DEFAULT_SSR_CACHE_CONTROL = DEFAULT_PUBLIC_CACHE_CONTROL;\n\nexport const DEFAULT_SSR_CDN_CACHE_CONTROL = DEFAULT_SSR_CACHE_CONTROL;\n\nexport const DEFAULT_SSR_NETLIFY_CDN_CACHE_CONTROL =\n DEFAULT_PUBLIC_CACHE_CONTROL;\n\nexport const DEFAULT_SSR_CACHE_HEADERS = {\n \"cache-control\": DEFAULT_SSR_CACHE_CONTROL,\n \"cdn-cache-control\": DEFAULT_SSR_CDN_CACHE_CONTROL,\n \"netlify-cdn-cache-control\": DEFAULT_SSR_NETLIFY_CDN_CACHE_CONTROL,\n} as const;\n\n/**\n * Deployment-wide override for the SSR shell cache policy.\n *\n * The default (`DEFAULT_SSR_CACHE_HEADERS`) is deliberately aggressive: SSR\n * HTML and React Router `.data` are one impersonal public shell, so hosts that\n * purge their CDN on deploy get near-static page loads for free. Two situations\n * make that default wrong, and both are properties of the DEPLOYMENT, not of\n * the request:\n *\n * 1. The host does not purge its CDN on deploy, so a shipped build can keep\n * serving the previous shell for `max-age` + `stale-while-revalidate`.\n * 2. The app's loaders return mutable public data, so a `useRevalidator()`\n * after a mutation reads the browser's cached `.data` copy instead of\n * fresh loader output.\n *\n * This override is intentionally global and env-driven rather than a\n * per-route/per-request escape hatch. A response that varies by request is how\n * one visitor's payload ends up in another visitor's shared CDN entry; a value\n * fixed for the whole deployment cannot. Turning caching off does NOT make SSR\n * personalized — `requestForAnonymousSsr` still strips cookies before render.\n *\n * Accepted values (case-insensitive):\n * unset | \"on\" | \"default\" | \"true\" | \"1\" → the default policy, unchanged\n * \"off\" | \"false\" | \"0\" | \"none\" | \"no-store\" | \"disabled\" → no caching\n * \"<n>\" | \"<n>s\" | \"<n>m\" | \"<n>h\" → public caching with that freshness\n */\nexport const SSR_CACHE_ENV_VAR = \"AGENT_NATIVE_SSR_CACHE\";\n\nexport const DISABLED_SSR_CACHE_CONTROL = \"no-store\";\n\nexport const DISABLED_SSR_CACHE_HEADERS = {\n \"cache-control\": DISABLED_SSR_CACHE_CONTROL,\n \"cdn-cache-control\": DISABLED_SSR_CACHE_CONTROL,\n \"netlify-cdn-cache-control\": DISABLED_SSR_CACHE_CONTROL,\n} as const;\n\nexport type SsrCachePolicy =\n | { kind: \"default\" }\n | { kind: \"disabled\" }\n | { kind: \"maxAge\"; seconds: number };\n\nexport type SsrCacheHeaders = Record<\n \"cache-control\" | \"cdn-cache-control\" | \"netlify-cdn-cache-control\",\n string\n>;\n\nconst ON_VALUES = new Set([\"\", \"on\", \"default\", \"true\", \"1\", \"yes\"]);\nconst OFF_VALUES = new Set([\n \"off\",\n \"false\",\n \"0\",\n \"no\",\n \"none\",\n \"no-store\",\n \"disabled\",\n]);\n\nconst DURATION_RE = /^(\\d+)\\s*(s|sec|secs|seconds?|m|min|mins?|h|hours?)?$/;\nconst DURATION_MULTIPLIERS: Record<string, number> = {\n s: 1,\n m: 60,\n h: 3600,\n};\n\nconst MAX_SSR_CACHE_SECONDS = 31_536_000;\n\nexport function parseSsrCacheSetting(\n raw: string | undefined | null,\n): SsrCachePolicy {\n const value = (raw ?? \"\").trim().toLowerCase();\n if (ON_VALUES.has(value)) return { kind: \"default\" };\n if (OFF_VALUES.has(value)) return { kind: \"disabled\" };\n\n const match = DURATION_RE.exec(value);\n if (match) {\n const multiplier = DURATION_MULTIPLIERS[match[2]?.[0] ?? \"s\"] ?? 1;\n const seconds = Math.min(\n Number(match[1]) * multiplier,\n MAX_SSR_CACHE_SECONDS,\n );\n return seconds > 0 ? { kind: \"maxAge\", seconds } : { kind: \"disabled\" };\n }\n\n // Unrecognized values fall back to the default rather than failing the\n // deployment: a typo in this env var must never silently disable the CDN.\n console.warn(\n `[agent-native] Ignoring unrecognized ${SSR_CACHE_ENV_VAR}=${raw}. ` +\n `Expected \"on\", \"off\", or a duration such as \"30s\" / \"5m\".`,\n );\n return { kind: \"default\" };\n}\n\nexport function ssrCacheHeadersForPolicy(\n policy: SsrCachePolicy,\n): SsrCacheHeaders {\n if (policy.kind === \"default\") return { ...DEFAULT_SSR_CACHE_HEADERS };\n if (policy.kind === \"disabled\") return { ...DISABLED_SSR_CACHE_HEADERS };\n // Mirror stale-while-revalidate onto the chosen freshness. Apps opt into a\n // short max-age precisely because a long stale window is the problem; keeping\n // the 7-day default SWR here would hand back the staleness they opted out of.\n const control =\n `public, max-age=${policy.seconds}, ` +\n `stale-while-revalidate=${policy.seconds}, stale-if-error=3600`;\n return {\n \"cache-control\": control,\n \"cdn-cache-control\": control,\n \"netlify-cdn-cache-control\": control,\n };\n}\n\nlet memoizedRaw: string | undefined;\nlet memoizedHeaders: Readonly<SsrCacheHeaders> | undefined;\n\n/**\n * Resolve the SSR cache headers for this deployment. Reads\n * `AGENT_NATIVE_SSR_CACHE` and memoizes per distinct value so the hot SSR path\n * does not re-parse on every response. The result is frozen and shared by every\n * response — copy it before mutating.\n */\nexport function resolveSsrCacheHeaders(\n env: Record<string, string | undefined> = typeof process === \"undefined\"\n ? {}\n : process.env,\n): Readonly<SsrCacheHeaders> {\n const raw = env[SSR_CACHE_ENV_VAR];\n if (memoizedHeaders && raw === memoizedRaw) return memoizedHeaders;\n memoizedRaw = raw;\n memoizedHeaders = Object.freeze(\n ssrCacheHeadersForPolicy(parseSsrCacheSetting(raw)),\n );\n return memoizedHeaders;\n}\n\nexport function isSsrCacheEnabled(\n env: Record<string, string | undefined> = typeof process === \"undefined\"\n ? {}\n : process.env,\n): boolean {\n return parseSsrCacheSetting(env[SSR_CACHE_ENV_VAR]).kind !== \"disabled\";\n}\n\nexport const DEFAULT_SPECULATION_RULES_PATH =\n \"/_agent-native/speculation-rules.json\";\n\nexport const DEFAULT_SPECULATION_RULES_HEADER = `\"${DEFAULT_SPECULATION_RULES_PATH}\"`;\n\nexport const EMPTY_SPECULATION_RULES = {\n prefetch: [],\n prerender: [],\n} as const;\n"]}
@@ -56,7 +56,29 @@ install → refresh scaffold skills → verify, then fix **app** code only.
56
56
  - Runs `skills update scaffold --project`
57
57
  - Runs `typecheck` when the project has that script
58
58
 
59
- 3. **If upgrade or typecheck fails**
59
+ 3. **Pull upstream template changes (optional, separate from the bump)**
60
+
61
+ `agent-native upgrade` moves package versions. It never touches files that
62
+ were copied out of a template at scaffold time, so template fixes and
63
+ improvements do not arrive with a bump.
64
+
65
+ ```bash
66
+ agent-native template status # recorded ref vs latest, drift counts
67
+ agent-native template diff # what upstream changed, read-only
68
+ agent-native template sync # 3-way merge it into the app
69
+ ```
70
+
71
+ `sync` defaults to the ref matching the installed `@agent-native/core`, so
72
+ run it after `upgrade`. It merges per file against a pristine baseline
73
+ stored in `refs/agent-native/template-baseline/<app-path>`; files upstream
74
+ did not touch are left alone, and real collisions get conflict markers.
75
+ After resolving markers, run `agent-native template accept` — the baseline
76
+ deliberately does not advance past an unresolved merge.
77
+
78
+ Apps scaffolded before provenance existed have no baseline. Create one
79
+ with `agent-native template baseline` before the first sync.
80
+
81
+ 4. **If upgrade or typecheck fails**
60
82
 
61
83
  - Read the concrete error
62
84
  - Fix **app** source, actions, config, or env — not framework packages
@@ -68,7 +90,7 @@ install → refresh scaffold skills → verify, then fix **app** code only.
68
90
  copied component; do not use that path to reproduce framework runtime
69
91
  behavior or hide version skew.
70
92
 
71
- 4. **Dry-run / partial runs**
93
+ 5. **Dry-run / partial runs**
72
94
 
73
95
  ```bash
74
96
  agent-native upgrade --dry-run
@@ -41,3 +41,4 @@ data/.sessions.json
41
41
  learnings.md
42
42
 
43
43
  .vercel/
44
+ .agent-native/
@@ -56,7 +56,29 @@ install → refresh scaffold skills → verify, then fix **app** code only.
56
56
  - Runs `skills update scaffold --project`
57
57
  - Runs `typecheck` when the project has that script
58
58
 
59
- 3. **If upgrade or typecheck fails**
59
+ 3. **Pull upstream template changes (optional, separate from the bump)**
60
+
61
+ `agent-native upgrade` moves package versions. It never touches files that
62
+ were copied out of a template at scaffold time, so template fixes and
63
+ improvements do not arrive with a bump.
64
+
65
+ ```bash
66
+ agent-native template status # recorded ref vs latest, drift counts
67
+ agent-native template diff # what upstream changed, read-only
68
+ agent-native template sync # 3-way merge it into the app
69
+ ```
70
+
71
+ `sync` defaults to the ref matching the installed `@agent-native/core`, so
72
+ run it after `upgrade`. It merges per file against a pristine baseline
73
+ stored in `refs/agent-native/template-baseline/<app-path>`; files upstream
74
+ did not touch are left alone, and real collisions get conflict markers.
75
+ After resolving markers, run `agent-native template accept` — the baseline
76
+ deliberately does not advance past an unresolved merge.
77
+
78
+ Apps scaffolded before provenance existed have no baseline. Create one
79
+ with `agent-native template baseline` before the first sync.
80
+
81
+ 4. **If upgrade or typecheck fails**
60
82
 
61
83
  - Read the concrete error
62
84
  - Fix **app** source, actions, config, or env — not framework packages
@@ -68,7 +90,7 @@ install → refresh scaffold skills → verify, then fix **app** code only.
68
90
  copied component; do not use that path to reproduce framework runtime
69
91
  behavior or hide version skew.
70
92
 
71
- 4. **Dry-run / partial runs**
93
+ 5. **Dry-run / partial runs**
72
94
 
73
95
  ```bash
74
96
  agent-native upgrade --dry-run
@@ -56,7 +56,29 @@ install → refresh scaffold skills → verify, then fix **app** code only.
56
56
  - Runs `skills update scaffold --project`
57
57
  - Runs `typecheck` when the project has that script
58
58
 
59
- 3. **If upgrade or typecheck fails**
59
+ 3. **Pull upstream template changes (optional, separate from the bump)**
60
+
61
+ `agent-native upgrade` moves package versions. It never touches files that
62
+ were copied out of a template at scaffold time, so template fixes and
63
+ improvements do not arrive with a bump.
64
+
65
+ ```bash
66
+ agent-native template status # recorded ref vs latest, drift counts
67
+ agent-native template diff # what upstream changed, read-only
68
+ agent-native template sync # 3-way merge it into the app
69
+ ```
70
+
71
+ `sync` defaults to the ref matching the installed `@agent-native/core`, so
72
+ run it after `upgrade`. It merges per file against a pristine baseline
73
+ stored in `refs/agent-native/template-baseline/<app-path>`; files upstream
74
+ did not touch are left alone, and real collisions get conflict markers.
75
+ After resolving markers, run `agent-native template accept` — the baseline
76
+ deliberately does not advance past an unresolved merge.
77
+
78
+ Apps scaffolded before provenance existed have no baseline. Create one
79
+ with `agent-native template baseline` before the first sync.
80
+
81
+ 4. **If upgrade or typecheck fails**
60
82
 
61
83
  - Read the concrete error
62
84
  - Fix **app** source, actions, config, or env — not framework packages
@@ -68,7 +90,7 @@ install → refresh scaffold skills → verify, then fix **app** code only.
68
90
  copied component; do not use that path to reproduce framework runtime
69
91
  behavior or hide version skew.
70
92
 
71
- 4. **Dry-run / partial runs**
93
+ 5. **Dry-run / partial runs**
72
94
 
73
95
  ```bash
74
96
  agent-native upgrade --dry-run
@@ -151,6 +151,23 @@ See the `authentication` skill for the full model and `guard:ssr-cache-shell`
151
151
  plus `ssr-handler.spec.ts` (`packages/core/src/server/ssr-handler.ts`) for the
152
152
  enforced contract.
153
153
 
154
+ **Never route mutation-fresh reads through SSR loader data.** Data that changes
155
+ when a user acts belongs in an action, read from the client with
156
+ `useActionQuery` / `useActionMutation` and kept live by `useDbSync()` polling —
157
+ that path never touches the SSR shell cache. A `useRevalidator()` after a
158
+ mutation re-fetches `.data` with a plain GET and can legitimately be served the
159
+ cached copy. SSR loaders render the public shell; the client resolves anything
160
+ that must be fresh.
161
+
162
+ The one supported knob is the deployment-wide `AGENT_NATIVE_SSR_CACHE` env var:
163
+ unset/`on` keeps the default, `off` sends `no-store`, and a duration such as
164
+ `30s` / `5m` shortens freshness. It is for deployments whose host does not purge
165
+ its CDN on deploy, or whose loaders genuinely serve mutable public data. It
166
+ changes cache duration only — cookies are still stripped before render, so
167
+ turning it off does not make SSR personalized. There is deliberately no
168
+ per-route or per-request override; that is how one visitor's payload lands in
169
+ another visitor's shared CDN entry.
170
+
154
171
  ## 7. Big payloads and long lists
155
172
 
156
173
  - **Paginate or window** unbounded lists (messages, responses, events, activity).
@@ -176,3 +193,5 @@ enforced contract.
176
193
  - [ ] Unbounded lists are paginated/windowed; large blobs aren't inlined on the hot path.
177
194
  - [ ] SSR HTML/`.data` path stays session-blind and cacheable — no `private`,
178
195
  `no-store`, `Vary: Cookie`, or auth branch added to it.
196
+ - [ ] Mutation-fresh reads go through actions + `useActionQuery`, not SSR loader
197
+ data.
@@ -56,7 +56,29 @@ install → refresh scaffold skills → verify, then fix **app** code only.
56
56
  - Runs `skills update scaffold --project`
57
57
  - Runs `typecheck` when the project has that script
58
58
 
59
- 3. **If upgrade or typecheck fails**
59
+ 3. **Pull upstream template changes (optional, separate from the bump)**
60
+
61
+ `agent-native upgrade` moves package versions. It never touches files that
62
+ were copied out of a template at scaffold time, so template fixes and
63
+ improvements do not arrive with a bump.
64
+
65
+ ```bash
66
+ agent-native template status # recorded ref vs latest, drift counts
67
+ agent-native template diff # what upstream changed, read-only
68
+ agent-native template sync # 3-way merge it into the app
69
+ ```
70
+
71
+ `sync` defaults to the ref matching the installed `@agent-native/core`, so
72
+ run it after `upgrade`. It merges per file against a pristine baseline
73
+ stored in `refs/agent-native/template-baseline/<app-path>`; files upstream
74
+ did not touch are left alone, and real collisions get conflict markers.
75
+ After resolving markers, run `agent-native template accept` — the baseline
76
+ deliberately does not advance past an unresolved merge.
77
+
78
+ Apps scaffolded before provenance existed have no baseline. Create one
79
+ with `agent-native template baseline` before the first sync.
80
+
81
+ 4. **If upgrade or typecheck fails**
60
82
 
61
83
  - Read the concrete error
62
84
  - Fix **app** source, actions, config, or env — not framework packages
@@ -68,7 +90,7 @@ install → refresh scaffold skills → verify, then fix **app** code only.
68
90
  copied component; do not use that path to reproduce framework runtime
69
91
  behavior or hide version skew.
70
92
 
71
- 4. **Dry-run / partial runs**
93
+ 5. **Dry-run / partial runs**
72
94
 
73
95
  ```bash
74
96
  agent-native upgrade --dry-run
@@ -3,6 +3,7 @@ name: visual-answer
3
3
  description: >-
4
4
  Answer code/product questions as visual Plan artifacts using repo, bridge, or
5
5
  GitHub context; use for API specs, UI look, schema models, and architecture.
6
+ scope: dev
6
7
  metadata:
7
8
  visibility: exported
8
9
  ---
@@ -1 +1 @@
1
- {"version":3,"file":"agents-bundle-plugin.d.ts","sourceRoot":"","sources":["../../src/vite/agents-bundle-plugin.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAyDnC,wBAAgB,kBAAkB,IAAI,MAAM,CA8G3C"}
1
+ {"version":3,"file":"agents-bundle-plugin.d.ts","sourceRoot":"","sources":["../../src/vite/agents-bundle-plugin.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAyDnC,wBAAgB,kBAAkB,IAAI,MAAM,CA+G3C"}