@agent-native/core 0.112.0 → 0.114.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 (1902) hide show
  1. package/agent-native.eject.json +164 -0
  2. package/corpus/README.md +4 -2
  3. package/corpus/core/CHANGELOG.md +33 -0
  4. package/corpus/core/README.md +61 -174
  5. package/corpus/core/agent-native.eject.json +164 -0
  6. package/corpus/core/docs/AGENTS.md +7 -0
  7. package/corpus/core/docs/content/agent-native-toolkit.mdx +38 -0
  8. package/corpus/core/docs/content/integrations.mdx +63 -2
  9. package/corpus/core/docs/content/package-lifecycle.mdx +54 -4
  10. package/corpus/core/docs/design/provider-integration-authority.md +117 -0
  11. package/corpus/core/package.json +20 -2
  12. package/corpus/core/scripts/materialize-source-corpus.mjs +9 -2
  13. package/corpus/core/src/cli/atomic-json-file.ts +324 -0
  14. package/corpus/core/src/cli/claude-code-participant.ts +515 -0
  15. package/corpus/core/src/cli/code-agent-executor.ts +18 -10
  16. package/corpus/core/src/cli/code-agent-runs.concurrent-worker.ts +33 -0
  17. package/corpus/core/src/cli/code-agent-runs.ts +55 -62
  18. package/corpus/core/src/cli/codex-cli-participant.ts +496 -0
  19. package/corpus/core/src/cli/eject.ts +1594 -0
  20. package/corpus/core/src/cli/index.ts +16 -0
  21. package/corpus/core/src/cli/multi-frontier-runs.ts +1246 -135
  22. package/corpus/core/src/client/chat/ChatHistoryList.tsx +7 -404
  23. package/corpus/core/src/client/index.ts +4 -0
  24. package/corpus/core/src/client/resources/McpConnectionSuggestion.tsx +8 -2
  25. package/corpus/core/src/client/resources/McpIntegrationDialog.tsx +7 -2
  26. package/corpus/core/src/client/resources/ResourcesPanel.tsx +17 -3
  27. package/corpus/core/src/client/resources/index.ts +19 -0
  28. package/corpus/core/src/client/resources/mcp-integration-catalog.ts +9 -1
  29. package/corpus/core/src/client/resources/runtime.ts +1 -0
  30. package/corpus/core/src/client/setup-connections/catalog.ts +6 -0
  31. package/corpus/core/src/client/setup-connections/index.ts +1 -0
  32. package/corpus/core/src/client/setup-connections/runtime.ts +1 -0
  33. package/corpus/core/src/connections/catalog.ts +41 -24
  34. package/corpus/core/src/connections/index.ts +1 -0
  35. package/corpus/core/src/connections/runtime.ts +1 -0
  36. package/corpus/core/src/eject/provider-api-definitions.ts +193 -0
  37. package/corpus/core/src/eject/remote-mcp-presets.ts +137 -0
  38. package/corpus/core/src/eject/setup-readiness-ui.tsx +29 -0
  39. package/corpus/core/src/eject/workspace-connections.ts +92 -0
  40. package/corpus/core/src/index.ts +1 -0
  41. package/corpus/core/src/integrations/adapter-overrides.ts +12 -0
  42. package/corpus/core/src/integrations/eject/messaging-adapters.ts +85 -0
  43. package/corpus/core/src/integrations/index.ts +15 -1
  44. package/corpus/core/src/integrations/plugin.ts +34 -12
  45. package/corpus/core/src/integrations/runtime.ts +1 -0
  46. package/corpus/core/src/integrations/slack-oauth.ts +1 -0
  47. package/corpus/core/src/integrations/types.ts +3 -1
  48. package/corpus/core/src/integrations/webhook-delivery.ts +55 -0
  49. package/corpus/core/src/notifications/channels.ts +4 -10
  50. package/corpus/core/src/package-lifecycle/eject-manifest.ts +345 -0
  51. package/corpus/core/src/package-lifecycle/index.ts +1 -0
  52. package/corpus/core/src/provider-api/actions/custom-provider-registration.ts +197 -0
  53. package/corpus/core/src/provider-api/actions/delete-staged-dataset.ts +3 -42
  54. package/corpus/core/src/provider-api/actions/list-staged-datasets.ts +3 -45
  55. package/corpus/core/src/provider-api/actions/provider-api-audit.ts +88 -0
  56. package/corpus/core/src/provider-api/actions/provider-api.ts +460 -0
  57. package/corpus/core/src/provider-api/actions/query-staged-dataset.ts +3 -140
  58. package/corpus/core/src/provider-api/actions/staged-datasets.ts +359 -0
  59. package/corpus/core/src/provider-api/gong.ts +108 -0
  60. package/corpus/core/src/provider-api/index.ts +46 -12
  61. package/corpus/core/src/provider-api/runtime.ts +1 -0
  62. package/corpus/core/src/scripts/docs/source-search.ts +2 -1
  63. package/corpus/core/src/server/google-oauth-credentials.ts +80 -3
  64. package/corpus/core/src/server/index.ts +6 -0
  65. package/corpus/core/src/setup-connections/index.ts +1 -0
  66. package/corpus/core/src/shared/merge-by-id.ts +14 -0
  67. package/corpus/core/src/styles/chat-history-list.css +1 -313
  68. package/corpus/core/src/templates/default/.agents/skills/actions/SKILL.md +32 -12
  69. package/corpus/core/src/templates/default/.agents/skills/agent-native-docs/SKILL.md +21 -9
  70. package/corpus/core/src/templates/default/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  71. package/corpus/core/src/templates/default/.agents/skills/integration-webhooks/SKILL.md +323 -0
  72. package/corpus/core/src/templates/default/.agents/skills/onboarding/SKILL.md +56 -0
  73. package/corpus/core/src/templates/default/.agents/skills/secrets/SKILL.md +273 -0
  74. package/corpus/core/src/templates/default/.agents/skills/self-modifying-code/SKILL.md +14 -2
  75. package/corpus/core/src/templates/default/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  76. package/corpus/core/src/templates/default/AGENTS.md +26 -18
  77. package/corpus/core/src/templates/headless/.agents/skills/actions/SKILL.md +512 -0
  78. package/corpus/core/src/templates/headless/.agents/skills/agent-native-docs/SKILL.md +21 -9
  79. package/corpus/core/src/templates/headless/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  80. package/corpus/core/src/templates/headless/.agents/skills/integration-webhooks/SKILL.md +323 -0
  81. package/corpus/core/src/templates/headless/.agents/skills/secrets/SKILL.md +273 -0
  82. package/corpus/core/src/templates/headless/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  83. package/corpus/core/src/templates/headless/AGENTS.md +8 -0
  84. package/corpus/core/src/templates/workspace-core/.agents/skills/actions/SKILL.md +32 -12
  85. package/corpus/core/src/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +21 -9
  86. package/corpus/core/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +7 -0
  87. package/corpus/core/src/templates/workspace-core/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  88. package/corpus/core/src/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +14 -2
  89. package/corpus/core/src/templates/workspace-core/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  90. package/corpus/core/src/templates/workspace-core/AGENTS.md +4 -0
  91. package/corpus/core/src/templates/workspace-root/AGENTS.md +4 -0
  92. package/corpus/core/src/vite/client.ts +25 -2
  93. package/corpus/templates/analytics/.agents/skills/actions/SKILL.md +32 -12
  94. package/corpus/templates/analytics/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  95. package/corpus/templates/analytics/.agents/skills/self-modifying-code/SKILL.md +14 -2
  96. package/corpus/templates/analytics/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  97. package/corpus/templates/analytics/actions/delete-staged-dataset.ts +3 -23
  98. package/corpus/templates/analytics/actions/list-staged-datasets.ts +3 -27
  99. package/corpus/templates/analytics/actions/provider-api-catalog.ts +16 -19
  100. package/corpus/templates/analytics/actions/provider-api-docs.ts +3 -5
  101. package/corpus/templates/analytics/actions/provider-api-request.ts +162 -185
  102. package/corpus/templates/analytics/actions/query-staged-dataset.ts +3 -47
  103. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +52 -161
  104. package/corpus/templates/assets/.agents/skills/actions/SKILL.md +32 -12
  105. package/corpus/templates/assets/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  106. package/corpus/templates/assets/.agents/skills/self-modifying-code/SKILL.md +14 -2
  107. package/corpus/templates/assets/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  108. package/corpus/templates/assets/app/components/layout/Sidebar.tsx +63 -160
  109. package/corpus/templates/brain/.agents/skills/actions/SKILL.md +32 -12
  110. package/corpus/templates/brain/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  111. package/corpus/templates/brain/.agents/skills/self-modifying-code/SKILL.md +14 -2
  112. package/corpus/templates/brain/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  113. package/corpus/templates/brain/actions/_schemas.ts +13 -7
  114. package/corpus/templates/brain/actions/delete-staged-dataset.ts +3 -24
  115. package/corpus/templates/brain/actions/list-staged-datasets.ts +3 -28
  116. package/corpus/templates/brain/actions/provider-api-catalog.ts +5 -11
  117. package/corpus/templates/brain/actions/provider-api-docs.ts +3 -5
  118. package/corpus/templates/brain/actions/provider-api-request.ts +3 -37
  119. package/corpus/templates/brain/actions/query-staged-dataset.ts +3 -48
  120. package/corpus/templates/brain/actions/remediate-legacy-capture-audiences.ts +167 -0
  121. package/corpus/templates/brain/actions/update-source.ts +5 -1
  122. package/corpus/templates/brain/app/components/layout/Sidebar.tsx +48 -154
  123. package/corpus/templates/brain/app/lib/brain-chat-readiness.ts +6 -0
  124. package/corpus/templates/brain/app/lib/brain.ts +55 -0
  125. package/corpus/templates/brain/app/lib/ingest-handoff.ts +35 -0
  126. package/corpus/templates/brain/app/routes/_index.tsx +8 -0
  127. package/corpus/templates/brain/app/routes.ts +1 -0
  128. package/corpus/templates/brain/changelog/2026-07-19-ask-starts-immediately-when-builder-s-managed-ai-connection-.md +6 -0
  129. package/corpus/templates/brain/changelog/2026-07-19-slack-and-granola-backfills-now-process-captures-concurrentl.md +6 -0
  130. package/corpus/templates/brain/changelog/2026-07-19-slack-backfills-can-now-join-configured-public-channels-befo.md +6 -0
  131. package/corpus/templates/brain/changelog/2026-07-19-slack-backfills-now-continue-across-the-configured-number-of.md +6 -0
  132. package/corpus/templates/brain/changelog/2026-07-19-slack-backfills-now-start-with-a-safe-four-week-window-and-r.md +6 -0
  133. package/corpus/templates/brain/changelog/2026-07-19-source-review-settings-now-control-knowledge-approval.md +6 -0
  134. package/corpus/templates/brain/changelog/2026-07-19-the-manage-agent-page-now-opens-correctly-from-brain-navigat.md +6 -0
  135. package/corpus/templates/brain/server/db/schema.ts +3 -0
  136. package/corpus/templates/brain/server/lib/brain.ts +41 -2
  137. package/corpus/templates/brain/server/lib/connectors.ts +432 -115
  138. package/corpus/templates/brain/server/lib/meeting-audience.ts +38 -0
  139. package/corpus/templates/brain/server/lib/slack-channel-membership.ts +44 -0
  140. package/corpus/templates/brain/server/plugins/db.ts +10 -0
  141. package/corpus/templates/brain/server/routes/api/_agent-native/brain/ingest.post.ts +6 -4
  142. package/corpus/templates/brain/shared/slack-source-config.ts +60 -0
  143. package/corpus/templates/calendar/.agents/skills/actions/SKILL.md +32 -12
  144. package/corpus/templates/calendar/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  145. package/corpus/templates/calendar/.agents/skills/self-modifying-code/SKILL.md +14 -2
  146. package/corpus/templates/calendar/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  147. package/corpus/templates/calendar/actions/delete-staged-dataset.ts +3 -24
  148. package/corpus/templates/calendar/actions/list-staged-datasets.ts +3 -28
  149. package/corpus/templates/calendar/actions/provider-api-catalog.ts +5 -11
  150. package/corpus/templates/calendar/actions/provider-api-docs.ts +3 -5
  151. package/corpus/templates/calendar/actions/provider-api-request.ts +3 -37
  152. package/corpus/templates/calendar/actions/query-staged-dataset.ts +3 -48
  153. package/corpus/templates/calendar/server/handlers/gong.ts +6 -61
  154. package/corpus/templates/calendar/server/handlers/google-auth.ts +10 -8
  155. package/corpus/templates/calendar/server/lib/google-calendar.ts +7 -45
  156. package/corpus/templates/chat/.agents/skills/actions/SKILL.md +32 -12
  157. package/corpus/templates/chat/.agents/skills/agent-native-docs/SKILL.md +21 -9
  158. package/corpus/templates/chat/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  159. package/corpus/templates/chat/.agents/skills/self-modifying-code/SKILL.md +14 -2
  160. package/corpus/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  161. package/corpus/templates/chat/AGENTS.md +6 -2
  162. package/corpus/templates/chat/app/components/layout/Sidebar.tsx +51 -157
  163. package/corpus/templates/clips/.agents/skills/actions/SKILL.md +32 -12
  164. package/corpus/templates/clips/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  165. package/corpus/templates/clips/.agents/skills/self-modifying-code/SKILL.md +14 -2
  166. package/corpus/templates/clips/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  167. package/corpus/templates/clips/AGENTS.md +11 -0
  168. package/corpus/templates/clips/actions/export-to-brain.ts +505 -171
  169. package/corpus/templates/clips/changelog/2026-07-19-ready-clips-transcripts-can-be-backfilled-to-brain-for-a-bou.md +6 -0
  170. package/corpus/templates/clips/server/lib/calendar-event-meetings.ts +1 -1
  171. package/corpus/templates/clips/server/lib/google-calendar-client.ts +12 -22
  172. package/corpus/templates/clips/server/lib/google-calendar-oauth.ts +9 -6
  173. package/corpus/templates/clips/server/lib/slack-oauth.ts +12 -47
  174. package/corpus/templates/clips/server/routes/_agent-native/google/auth-url.get.ts +2 -6
  175. package/corpus/templates/clips/server/routes/api/auth/google-calendar.get.ts +4 -4
  176. package/corpus/templates/content/.agents/skills/actions/SKILL.md +32 -12
  177. package/corpus/templates/content/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  178. package/corpus/templates/content/.agents/skills/self-modifying-code/SKILL.md +14 -2
  179. package/corpus/templates/content/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  180. package/corpus/templates/content/actions/delete-staged-dataset.ts +3 -24
  181. package/corpus/templates/content/actions/list-staged-datasets.ts +3 -28
  182. package/corpus/templates/content/actions/provider-api-catalog.ts +5 -11
  183. package/corpus/templates/content/actions/provider-api-docs.ts +3 -5
  184. package/corpus/templates/content/actions/provider-api-request.ts +3 -37
  185. package/corpus/templates/content/actions/query-staged-dataset.ts +3 -48
  186. package/corpus/templates/design/.agents/skills/actions/SKILL.md +32 -12
  187. package/corpus/templates/design/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  188. package/corpus/templates/design/.agents/skills/self-modifying-code/SKILL.md +14 -2
  189. package/corpus/templates/design/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  190. package/corpus/templates/design/actions/delete-staged-dataset.ts +4 -23
  191. package/corpus/templates/design/actions/list-staged-datasets.ts +4 -27
  192. package/corpus/templates/design/actions/provider-api-catalog.ts +15 -18
  193. package/corpus/templates/design/actions/provider-api-docs.ts +57 -48
  194. package/corpus/templates/design/actions/provider-api-request.ts +140 -164
  195. package/corpus/templates/design/actions/query-staged-dataset.ts +4 -47
  196. package/corpus/templates/dispatch/.agents/skills/actions/SKILL.md +32 -12
  197. package/corpus/templates/dispatch/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  198. package/corpus/templates/dispatch/.agents/skills/self-modifying-code/SKILL.md +14 -2
  199. package/corpus/templates/dispatch/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  200. package/corpus/templates/dispatch/actions/delete-staged-dataset.ts +4 -23
  201. package/corpus/templates/dispatch/actions/list-staged-datasets.ts +4 -30
  202. package/corpus/templates/dispatch/actions/provider-api-catalog.ts +15 -18
  203. package/corpus/templates/dispatch/actions/provider-api-docs.ts +57 -48
  204. package/corpus/templates/dispatch/actions/provider-api-request.ts +138 -163
  205. package/corpus/templates/dispatch/actions/query-staged-dataset.ts +4 -47
  206. package/corpus/templates/forms/.agents/skills/actions/SKILL.md +32 -12
  207. package/corpus/templates/forms/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  208. package/corpus/templates/forms/.agents/skills/self-modifying-code/SKILL.md +14 -2
  209. package/corpus/templates/forms/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  210. package/corpus/templates/forms/server/lib/integrations.ts +23 -22
  211. package/corpus/templates/macros/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  212. package/corpus/templates/macros/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  213. package/corpus/templates/mail/.agents/skills/actions/SKILL.md +32 -12
  214. package/corpus/templates/mail/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  215. package/corpus/templates/mail/.agents/skills/self-modifying-code/SKILL.md +14 -2
  216. package/corpus/templates/mail/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  217. package/corpus/templates/mail/actions/delete-staged-dataset.ts +4 -23
  218. package/corpus/templates/mail/actions/list-staged-datasets.ts +4 -27
  219. package/corpus/templates/mail/actions/provider-api-catalog.ts +15 -18
  220. package/corpus/templates/mail/actions/provider-api-docs.ts +57 -48
  221. package/corpus/templates/mail/actions/provider-api-request.ts +146 -173
  222. package/corpus/templates/mail/actions/query-staged-dataset.ts +4 -47
  223. package/corpus/templates/mail/server/handlers/gong.ts +6 -61
  224. package/corpus/templates/mail/server/lib/google-auth.ts +10 -13
  225. package/corpus/templates/plan/.agents/skills/actions/SKILL.md +32 -12
  226. package/corpus/templates/plan/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  227. package/corpus/templates/plan/.agents/skills/self-modifying-code/SKILL.md +14 -2
  228. package/corpus/templates/plan/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  229. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +47 -156
  230. package/corpus/templates/slides/.agents/skills/actions/SKILL.md +32 -12
  231. package/corpus/templates/slides/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  232. package/corpus/templates/slides/.agents/skills/self-modifying-code/SKILL.md +14 -2
  233. package/corpus/templates/slides/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  234. package/corpus/templates/slides/actions/delete-staged-dataset.ts +4 -23
  235. package/corpus/templates/slides/actions/list-staged-datasets.ts +4 -27
  236. package/corpus/templates/slides/actions/provider-api-catalog.ts +15 -18
  237. package/corpus/templates/slides/actions/provider-api-docs.ts +57 -48
  238. package/corpus/templates/slides/actions/provider-api-request.ts +145 -172
  239. package/corpus/templates/slides/actions/query-staged-dataset.ts +4 -47
  240. package/corpus/templates/slides/server/lib/google-docs-oauth.ts +11 -36
  241. package/corpus/templates/tasks/.agents/skills/actions/SKILL.md +32 -12
  242. package/corpus/templates/tasks/.agents/skills/agent-native-docs/SKILL.md +21 -9
  243. package/corpus/templates/tasks/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  244. package/corpus/templates/tasks/.agents/skills/self-modifying-code/SKILL.md +14 -2
  245. package/corpus/templates/tasks/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  246. package/corpus/toolkit/CHANGELOG.md +131 -0
  247. package/corpus/toolkit/README.md +60 -0
  248. package/corpus/toolkit/agent-native.eject.json +411 -0
  249. package/corpus/toolkit/export-snapshot.json +35 -0
  250. package/corpus/toolkit/migration-manifest.json +4 -0
  251. package/corpus/toolkit/package.json +284 -0
  252. package/corpus/toolkit/scripts/finalize-build.mjs +55 -0
  253. package/corpus/toolkit/src/app-shell/header-actions.tsx +84 -0
  254. package/corpus/toolkit/src/app-shell/index.ts +1 -0
  255. package/corpus/toolkit/src/chat-history/ChatHistoryList.tsx +469 -0
  256. package/corpus/toolkit/src/chat-history/index.ts +7 -0
  257. package/corpus/toolkit/src/chat-history.css +314 -0
  258. package/corpus/toolkit/src/collab-ui/AgentPresenceChip.tsx +69 -0
  259. package/corpus/toolkit/src/collab-ui/LiveCursorOverlay.tsx +241 -0
  260. package/corpus/toolkit/src/collab-ui/PresenceBar.tsx +346 -0
  261. package/corpus/toolkit/src/collab-ui/RecentEditHighlights.tsx +225 -0
  262. package/corpus/toolkit/src/collab-ui/RemoteSelectionRings.tsx +227 -0
  263. package/corpus/toolkit/src/collab-ui/agent-identity.ts +16 -0
  264. package/corpus/toolkit/src/collab-ui/index.ts +39 -0
  265. package/corpus/toolkit/src/collab-ui/lead-client.ts +32 -0
  266. package/corpus/toolkit/src/collab-ui/types.ts +96 -0
  267. package/corpus/toolkit/src/composer/AgentComposerFrame.tsx +59 -0
  268. package/corpus/toolkit/src/composer/ComposerPlusMenu.tsx +983 -0
  269. package/corpus/toolkit/src/composer/MentionPopover.tsx +412 -0
  270. package/corpus/toolkit/src/composer/PastedTextChip.tsx +150 -0
  271. package/corpus/toolkit/src/composer/PromptComposer.tsx +718 -0
  272. package/corpus/toolkit/src/composer/RealtimeVoiceMode.tsx +856 -0
  273. package/corpus/toolkit/src/composer/TiptapComposer.tsx +2936 -0
  274. package/corpus/toolkit/src/composer/VoiceButton.tsx +255 -0
  275. package/corpus/toolkit/src/composer/asset-picker-url.ts +80 -0
  276. package/corpus/toolkit/src/composer/attachment-accept.ts +71 -0
  277. package/corpus/toolkit/src/composer/draft-key.ts +7 -0
  278. package/corpus/toolkit/src/composer/extensions/FileReference.tsx +55 -0
  279. package/corpus/toolkit/src/composer/extensions/MentionReference.tsx +93 -0
  280. package/corpus/toolkit/src/composer/extensions/SkillReference.tsx +56 -0
  281. package/corpus/toolkit/src/composer/index.ts +79 -0
  282. package/corpus/toolkit/src/composer/pasted-text.ts +160 -0
  283. package/corpus/toolkit/src/composer/prompt-attachments.ts +93 -0
  284. package/corpus/toolkit/src/composer/realtime-voice-audio-level.ts +64 -0
  285. package/corpus/toolkit/src/composer/realtime-voice-transcript.ts +134 -0
  286. package/corpus/toolkit/src/composer/runtime-adapters.tsx +343 -0
  287. package/corpus/toolkit/src/composer/types.ts +66 -0
  288. package/corpus/toolkit/src/composer/use-file-search.ts +64 -0
  289. package/corpus/toolkit/src/composer/use-mention-search.ts +90 -0
  290. package/corpus/toolkit/src/composer/use-skills.ts +45 -0
  291. package/corpus/toolkit/src/composer/useRealtimeVoiceMode.tsx +2117 -0
  292. package/corpus/toolkit/src/composer/useVoiceDictation.ts +1191 -0
  293. package/corpus/toolkit/src/context-ui/ContextMeter.tsx +101 -0
  294. package/corpus/toolkit/src/context-ui/ContextSegmentRow.tsx +184 -0
  295. package/corpus/toolkit/src/context-ui/ContextTreemap.tsx +125 -0
  296. package/corpus/toolkit/src/context-ui/ContextXRayPanel.tsx +377 -0
  297. package/corpus/toolkit/src/context-ui/format.ts +42 -0
  298. package/corpus/toolkit/src/context-ui/index.ts +15 -0
  299. package/corpus/toolkit/src/context-ui/types.ts +43 -0
  300. package/corpus/toolkit/src/design-tweaks/index.ts +1 -0
  301. package/corpus/toolkit/src/design-tweaks/visual-style-controls.tsx +1084 -0
  302. package/corpus/toolkit/src/editor/BubbleToolbar.tsx +253 -0
  303. package/corpus/toolkit/src/editor/CodeBlockNode.tsx +254 -0
  304. package/corpus/toolkit/src/editor/DragHandle.ts +1437 -0
  305. package/corpus/toolkit/src/editor/ImageExtension.ts +306 -0
  306. package/corpus/toolkit/src/editor/RegistryBlockContext.tsx +107 -0
  307. package/corpus/toolkit/src/editor/RegistryBlockNode.tsx +652 -0
  308. package/corpus/toolkit/src/editor/RichMarkdownEditor.tsx +81 -0
  309. package/corpus/toolkit/src/editor/RunId.ts +61 -0
  310. package/corpus/toolkit/src/editor/SharedRichEditor.tsx +321 -0
  311. package/corpus/toolkit/src/editor/SlashCommandMenu.tsx +310 -0
  312. package/corpus/toolkit/src/editor/extensions.ts +402 -0
  313. package/corpus/toolkit/src/editor/gfmDoc.ts +92 -0
  314. package/corpus/toolkit/src/editor/index.ts +93 -0
  315. package/corpus/toolkit/src/editor/registrySlashCommands.ts +131 -0
  316. package/corpus/toolkit/src/editor/surgical-apply.ts +192 -0
  317. package/corpus/toolkit/src/editor/useCollabReconcile.ts +589 -0
  318. package/corpus/toolkit/src/editor.css +510 -0
  319. package/corpus/toolkit/src/hooks/index.ts +2 -0
  320. package/corpus/toolkit/src/hooks/use-mobile.tsx +21 -0
  321. package/corpus/toolkit/src/hooks/use-toast.ts +188 -0
  322. package/corpus/toolkit/src/index.ts +8 -0
  323. package/corpus/toolkit/src/onboarding/index.ts +1 -0
  324. package/corpus/toolkit/src/provider.tsx +47 -0
  325. package/corpus/toolkit/src/sharing/VisibilityBadge.tsx +37 -0
  326. package/corpus/toolkit/src/sharing/index.ts +4 -0
  327. package/corpus/toolkit/src/styles.css +21 -0
  328. package/corpus/toolkit/src/ui/accordion.tsx +56 -0
  329. package/corpus/toolkit/src/ui/alert-dialog.tsx +141 -0
  330. package/corpus/toolkit/src/ui/alert.tsx +59 -0
  331. package/corpus/toolkit/src/ui/aspect-ratio.tsx +5 -0
  332. package/corpus/toolkit/src/ui/avatar.tsx +48 -0
  333. package/corpus/toolkit/src/ui/badge.tsx +37 -0
  334. package/corpus/toolkit/src/ui/breadcrumb.tsx +115 -0
  335. package/corpus/toolkit/src/ui/button.tsx +78 -0
  336. package/corpus/toolkit/src/ui/calendar.tsx +214 -0
  337. package/corpus/toolkit/src/ui/card.tsx +86 -0
  338. package/corpus/toolkit/src/ui/carousel.tsx +260 -0
  339. package/corpus/toolkit/src/ui/chart.tsx +375 -0
  340. package/corpus/toolkit/src/ui/checkbox.tsx +28 -0
  341. package/corpus/toolkit/src/ui/collapsible.tsx +9 -0
  342. package/corpus/toolkit/src/ui/command.tsx +174 -0
  343. package/corpus/toolkit/src/ui/context-menu.tsx +202 -0
  344. package/corpus/toolkit/src/ui/date-picker.tsx +64 -0
  345. package/corpus/toolkit/src/ui/dialog.tsx +146 -0
  346. package/corpus/toolkit/src/ui/drawer.tsx +126 -0
  347. package/corpus/toolkit/src/ui/dropdown-menu.tsx +218 -0
  348. package/corpus/toolkit/src/ui/form.tsx +177 -0
  349. package/corpus/toolkit/src/ui/hover-card.tsx +27 -0
  350. package/corpus/toolkit/src/ui/index.ts +52 -0
  351. package/corpus/toolkit/src/ui/input-otp.tsx +69 -0
  352. package/corpus/toolkit/src/ui/input.tsx +22 -0
  353. package/corpus/toolkit/src/ui/label.tsx +24 -0
  354. package/corpus/toolkit/src/ui/logo.tsx +36 -0
  355. package/corpus/toolkit/src/ui/menubar.tsx +235 -0
  356. package/corpus/toolkit/src/ui/navigation-menu.tsx +128 -0
  357. package/corpus/toolkit/src/ui/pagination.tsx +121 -0
  358. package/corpus/toolkit/src/ui/popover.tsx +44 -0
  359. package/corpus/toolkit/src/ui/progress.tsx +26 -0
  360. package/corpus/toolkit/src/ui/radio-group.tsx +42 -0
  361. package/corpus/toolkit/src/ui/resizable.tsx +43 -0
  362. package/corpus/toolkit/src/ui/scroll-area.tsx +46 -0
  363. package/corpus/toolkit/src/ui/select.tsx +158 -0
  364. package/corpus/toolkit/src/ui/separator.tsx +29 -0
  365. package/corpus/toolkit/src/ui/sheet.tsx +160 -0
  366. package/corpus/toolkit/src/ui/sidebar.tsx +777 -0
  367. package/corpus/toolkit/src/ui/skeleton.tsx +18 -0
  368. package/corpus/toolkit/src/ui/slider.tsx +26 -0
  369. package/corpus/toolkit/src/ui/sonner.tsx +58 -0
  370. package/corpus/toolkit/src/ui/spinner.tsx +17 -0
  371. package/corpus/toolkit/src/ui/switch.tsx +27 -0
  372. package/corpus/toolkit/src/ui/table.tsx +117 -0
  373. package/corpus/toolkit/src/ui/tabs.tsx +53 -0
  374. package/corpus/toolkit/src/ui/textarea.tsx +23 -0
  375. package/corpus/toolkit/src/ui/toast.tsx +127 -0
  376. package/corpus/toolkit/src/ui/toaster.tsx +33 -0
  377. package/corpus/toolkit/src/ui/toggle-group.tsx +59 -0
  378. package/corpus/toolkit/src/ui/toggle.tsx +43 -0
  379. package/corpus/toolkit/src/ui/tooltip.tsx +53 -0
  380. package/corpus/toolkit/src/ui/use-toast.ts +3 -0
  381. package/corpus/toolkit/src/utils.ts +8 -0
  382. package/corpus/toolkit/tsconfig.json +23 -0
  383. package/dist/cli/atomic-json-file.d.ts +30 -0
  384. package/dist/cli/atomic-json-file.d.ts.map +1 -0
  385. package/dist/cli/atomic-json-file.js +240 -0
  386. package/dist/cli/atomic-json-file.js.map +1 -0
  387. package/dist/cli/claude-code-participant.d.ts +77 -0
  388. package/dist/cli/claude-code-participant.d.ts.map +1 -0
  389. package/dist/cli/claude-code-participant.js +355 -0
  390. package/dist/cli/claude-code-participant.js.map +1 -0
  391. package/dist/cli/code-agent-executor.d.ts.map +1 -1
  392. package/dist/cli/code-agent-executor.js +18 -10
  393. package/dist/cli/code-agent-executor.js.map +1 -1
  394. package/dist/cli/code-agent-runs.concurrent-worker.d.ts +2 -0
  395. package/dist/cli/code-agent-runs.concurrent-worker.d.ts.map +1 -0
  396. package/dist/cli/code-agent-runs.concurrent-worker.js +32 -0
  397. package/dist/cli/code-agent-runs.concurrent-worker.js.map +1 -0
  398. package/dist/cli/code-agent-runs.d.ts.map +1 -1
  399. package/dist/cli/code-agent-runs.js +43 -56
  400. package/dist/cli/code-agent-runs.js.map +1 -1
  401. package/dist/cli/codex-cli-participant.d.ts +77 -0
  402. package/dist/cli/codex-cli-participant.d.ts.map +1 -0
  403. package/dist/cli/codex-cli-participant.js +354 -0
  404. package/dist/cli/codex-cli-participant.js.map +1 -0
  405. package/dist/cli/eject.d.ts +21 -0
  406. package/dist/cli/eject.d.ts.map +1 -0
  407. package/dist/cli/eject.js +1145 -0
  408. package/dist/cli/eject.js.map +1 -0
  409. package/dist/cli/index.js +15 -0
  410. package/dist/cli/index.js.map +1 -1
  411. package/dist/cli/multi-frontier-runs.d.ts +115 -0
  412. package/dist/cli/multi-frontier-runs.d.ts.map +1 -1
  413. package/dist/cli/multi-frontier-runs.js +831 -113
  414. package/dist/cli/multi-frontier-runs.js.map +1 -1
  415. package/dist/client/chat/ChatHistoryList.d.ts +1 -87
  416. package/dist/client/chat/ChatHistoryList.d.ts.map +1 -1
  417. package/dist/client/chat/ChatHistoryList.js +1 -82
  418. package/dist/client/chat/ChatHistoryList.js.map +1 -1
  419. package/dist/client/index.d.ts +1 -1
  420. package/dist/client/index.d.ts.map +1 -1
  421. package/dist/client/index.js +1 -1
  422. package/dist/client/index.js.map +1 -1
  423. package/dist/client/resources/McpConnectionSuggestion.d.ts +4 -3
  424. package/dist/client/resources/McpConnectionSuggestion.d.ts.map +1 -1
  425. package/dist/client/resources/McpConnectionSuggestion.js +3 -3
  426. package/dist/client/resources/McpConnectionSuggestion.js.map +1 -1
  427. package/dist/client/resources/McpIntegrationDialog.d.ts +4 -3
  428. package/dist/client/resources/McpIntegrationDialog.d.ts.map +1 -1
  429. package/dist/client/resources/McpIntegrationDialog.js +2 -2
  430. package/dist/client/resources/McpIntegrationDialog.js.map +1 -1
  431. package/dist/client/resources/ResourcesPanel.d.ts +4 -1
  432. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  433. package/dist/client/resources/ResourcesPanel.js +9 -7
  434. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  435. package/dist/client/resources/index.d.ts +3 -0
  436. package/dist/client/resources/index.d.ts.map +1 -1
  437. package/dist/client/resources/index.js +3 -0
  438. package/dist/client/resources/index.js.map +1 -1
  439. package/dist/client/resources/mcp-integration-catalog.d.ts +2 -1
  440. package/dist/client/resources/mcp-integration-catalog.d.ts.map +1 -1
  441. package/dist/client/resources/mcp-integration-catalog.js +6 -2
  442. package/dist/client/resources/mcp-integration-catalog.js.map +1 -1
  443. package/dist/client/resources/runtime.d.ts +2 -0
  444. package/dist/client/resources/runtime.d.ts.map +1 -0
  445. package/dist/client/resources/runtime.js +2 -0
  446. package/dist/client/resources/runtime.js.map +1 -0
  447. package/dist/client/setup-connections/catalog.d.ts +2 -0
  448. package/dist/client/setup-connections/catalog.d.ts.map +1 -0
  449. package/dist/client/setup-connections/catalog.js +7 -0
  450. package/dist/client/setup-connections/catalog.js.map +1 -0
  451. package/dist/client/setup-connections/index.d.ts +1 -0
  452. package/dist/client/setup-connections/index.d.ts.map +1 -1
  453. package/dist/client/setup-connections/index.js +1 -0
  454. package/dist/client/setup-connections/index.js.map +1 -1
  455. package/dist/client/setup-connections/runtime.d.ts +2 -0
  456. package/dist/client/setup-connections/runtime.d.ts.map +1 -0
  457. package/dist/client/setup-connections/runtime.js +2 -0
  458. package/dist/client/setup-connections/runtime.js.map +1 -0
  459. package/dist/collab/awareness.d.ts +2 -2
  460. package/dist/collab/awareness.d.ts.map +1 -1
  461. package/dist/collab/routes.d.ts +1 -1
  462. package/dist/connections/catalog.d.ts +5 -3
  463. package/dist/connections/catalog.d.ts.map +1 -1
  464. package/dist/connections/catalog.js +16 -8
  465. package/dist/connections/catalog.js.map +1 -1
  466. package/dist/connections/index.d.ts +1 -1
  467. package/dist/connections/index.d.ts.map +1 -1
  468. package/dist/connections/index.js +1 -1
  469. package/dist/connections/index.js.map +1 -1
  470. package/dist/connections/runtime.d.ts +2 -0
  471. package/dist/connections/runtime.d.ts.map +1 -0
  472. package/dist/connections/runtime.js +2 -0
  473. package/dist/connections/runtime.js.map +1 -0
  474. package/dist/eject/provider-api-definitions.d.ts +34 -0
  475. package/dist/eject/provider-api-definitions.d.ts.map +1 -0
  476. package/dist/eject/provider-api-definitions.js +88 -0
  477. package/dist/eject/provider-api-definitions.js.map +1 -0
  478. package/dist/eject/remote-mcp-presets.d.ts +17 -0
  479. package/dist/eject/remote-mcp-presets.d.ts.map +1 -0
  480. package/dist/eject/remote-mcp-presets.js +81 -0
  481. package/dist/eject/remote-mcp-presets.js.map +1 -0
  482. package/dist/eject/setup-readiness-ui.d.ts +7 -0
  483. package/dist/eject/setup-readiness-ui.d.ts.map +1 -0
  484. package/dist/eject/setup-readiness-ui.js +13 -0
  485. package/dist/eject/setup-readiness-ui.js.map +1 -0
  486. package/dist/eject/workspace-connections.d.ts +11 -0
  487. package/dist/eject/workspace-connections.d.ts.map +1 -0
  488. package/dist/eject/workspace-connections.js +47 -0
  489. package/dist/eject/workspace-connections.js.map +1 -0
  490. package/dist/index.d.ts +1 -1
  491. package/dist/index.d.ts.map +1 -1
  492. package/dist/index.js +1 -1
  493. package/dist/index.js.map +1 -1
  494. package/dist/integrations/adapter-overrides.d.ts +3 -0
  495. package/dist/integrations/adapter-overrides.d.ts.map +1 -0
  496. package/dist/integrations/adapter-overrides.js +7 -0
  497. package/dist/integrations/adapter-overrides.js.map +1 -0
  498. package/dist/integrations/eject/messaging-adapters.d.ts +12 -0
  499. package/dist/integrations/eject/messaging-adapters.d.ts.map +1 -0
  500. package/dist/integrations/eject/messaging-adapters.js +49 -0
  501. package/dist/integrations/eject/messaging-adapters.js.map +1 -0
  502. package/dist/integrations/index.d.ts +5 -3
  503. package/dist/integrations/index.d.ts.map +1 -1
  504. package/dist/integrations/index.js +4 -2
  505. package/dist/integrations/index.js.map +1 -1
  506. package/dist/integrations/plugin.d.ts +32 -1
  507. package/dist/integrations/plugin.d.ts.map +1 -1
  508. package/dist/integrations/plugin.js +19 -12
  509. package/dist/integrations/plugin.js.map +1 -1
  510. package/dist/integrations/runtime.d.ts +2 -0
  511. package/dist/integrations/runtime.d.ts.map +1 -0
  512. package/dist/integrations/runtime.js +2 -0
  513. package/dist/integrations/runtime.js.map +1 -0
  514. package/dist/integrations/slack-manifest.d.ts +1 -1
  515. package/dist/integrations/slack-oauth.d.ts +1 -1
  516. package/dist/integrations/slack-oauth.d.ts.map +1 -1
  517. package/dist/integrations/slack-oauth.js +1 -0
  518. package/dist/integrations/slack-oauth.js.map +1 -1
  519. package/dist/integrations/types.d.ts +3 -1
  520. package/dist/integrations/types.d.ts.map +1 -1
  521. package/dist/integrations/types.js.map +1 -1
  522. package/dist/integrations/webhook-delivery.d.ts +23 -0
  523. package/dist/integrations/webhook-delivery.d.ts.map +1 -0
  524. package/dist/integrations/webhook-delivery.js +32 -0
  525. package/dist/integrations/webhook-delivery.js.map +1 -0
  526. package/dist/notifications/channels.d.ts.map +1 -1
  527. package/dist/notifications/channels.js +4 -9
  528. package/dist/notifications/channels.js.map +1 -1
  529. package/dist/notifications/routes.d.ts +3 -3
  530. package/dist/package-lifecycle/eject-manifest.d.ts +43 -0
  531. package/dist/package-lifecycle/eject-manifest.d.ts.map +1 -0
  532. package/dist/package-lifecycle/eject-manifest.js +219 -0
  533. package/dist/package-lifecycle/eject-manifest.js.map +1 -0
  534. package/dist/package-lifecycle/index.d.ts +1 -0
  535. package/dist/package-lifecycle/index.d.ts.map +1 -1
  536. package/dist/package-lifecycle/index.js +1 -0
  537. package/dist/package-lifecycle/index.js.map +1 -1
  538. package/dist/progress/routes.d.ts +1 -1
  539. package/dist/provider-api/actions/custom-provider-registration.d.ts +136 -0
  540. package/dist/provider-api/actions/custom-provider-registration.d.ts.map +1 -0
  541. package/dist/provider-api/actions/custom-provider-registration.js +154 -0
  542. package/dist/provider-api/actions/custom-provider-registration.js.map +1 -0
  543. package/dist/provider-api/actions/delete-staged-dataset.d.ts +1 -1
  544. package/dist/provider-api/actions/delete-staged-dataset.d.ts.map +1 -1
  545. package/dist/provider-api/actions/delete-staged-dataset.js +3 -34
  546. package/dist/provider-api/actions/delete-staged-dataset.js.map +1 -1
  547. package/dist/provider-api/actions/list-staged-datasets.d.ts +2 -3
  548. package/dist/provider-api/actions/list-staged-datasets.d.ts.map +1 -1
  549. package/dist/provider-api/actions/list-staged-datasets.js +3 -40
  550. package/dist/provider-api/actions/list-staged-datasets.js.map +1 -1
  551. package/dist/provider-api/actions/provider-api-audit.d.ts +7 -0
  552. package/dist/provider-api/actions/provider-api-audit.d.ts.map +1 -0
  553. package/dist/provider-api/actions/provider-api-audit.js +74 -0
  554. package/dist/provider-api/actions/provider-api-audit.js.map +1 -0
  555. package/dist/provider-api/actions/provider-api.d.ts +370 -0
  556. package/dist/provider-api/actions/provider-api.d.ts.map +1 -0
  557. package/dist/provider-api/actions/provider-api.js +280 -0
  558. package/dist/provider-api/actions/provider-api.js.map +1 -0
  559. package/dist/provider-api/actions/query-staged-dataset.d.ts +1 -1
  560. package/dist/provider-api/actions/query-staged-dataset.d.ts.map +1 -1
  561. package/dist/provider-api/actions/query-staged-dataset.js +3 -116
  562. package/dist/provider-api/actions/query-staged-dataset.js.map +1 -1
  563. package/dist/provider-api/actions/staged-datasets.d.ts +190 -0
  564. package/dist/provider-api/actions/staged-datasets.d.ts.map +1 -0
  565. package/dist/provider-api/actions/staged-datasets.js +210 -0
  566. package/dist/provider-api/actions/staged-datasets.js.map +1 -0
  567. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  568. package/dist/provider-api/gong.d.ts +44 -0
  569. package/dist/provider-api/gong.d.ts.map +1 -0
  570. package/dist/provider-api/gong.js +56 -0
  571. package/dist/provider-api/gong.js.map +1 -0
  572. package/dist/provider-api/index.d.ts +6 -2
  573. package/dist/provider-api/index.d.ts.map +1 -1
  574. package/dist/provider-api/index.js +25 -12
  575. package/dist/provider-api/index.js.map +1 -1
  576. package/dist/provider-api/runtime.d.ts +2 -0
  577. package/dist/provider-api/runtime.d.ts.map +1 -0
  578. package/dist/provider-api/runtime.js +2 -0
  579. package/dist/provider-api/runtime.js.map +1 -0
  580. package/dist/scripts/docs/source-search.d.ts +2 -1
  581. package/dist/scripts/docs/source-search.d.ts.map +1 -1
  582. package/dist/scripts/docs/source-search.js +2 -1
  583. package/dist/scripts/docs/source-search.js.map +1 -1
  584. package/dist/secrets/routes.d.ts +9 -9
  585. package/dist/server/google-oauth-credentials.d.ts +35 -0
  586. package/dist/server/google-oauth-credentials.d.ts.map +1 -1
  587. package/dist/server/google-oauth-credentials.js +48 -2
  588. package/dist/server/google-oauth-credentials.js.map +1 -1
  589. package/dist/server/index.d.ts +1 -1
  590. package/dist/server/index.d.ts.map +1 -1
  591. package/dist/server/index.js +1 -1
  592. package/dist/server/index.js.map +1 -1
  593. package/dist/server/transcribe-voice.d.ts +1 -1
  594. package/dist/setup-connections/index.d.ts +1 -1
  595. package/dist/setup-connections/index.d.ts.map +1 -1
  596. package/dist/setup-connections/index.js +1 -1
  597. package/dist/setup-connections/index.js.map +1 -1
  598. package/dist/shared/merge-by-id.d.ts +5 -0
  599. package/dist/shared/merge-by-id.d.ts.map +1 -0
  600. package/dist/shared/merge-by-id.js +7 -0
  601. package/dist/shared/merge-by-id.js.map +1 -0
  602. package/dist/styles/chat-history-list.css +1 -313
  603. package/dist/templates/chat/.agents/skills/actions/SKILL.md +32 -12
  604. package/dist/templates/chat/.agents/skills/agent-native-docs/SKILL.md +21 -9
  605. package/dist/templates/chat/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  606. package/dist/templates/chat/.agents/skills/self-modifying-code/SKILL.md +14 -2
  607. package/dist/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  608. package/dist/templates/chat/AGENTS.md +6 -2
  609. package/dist/templates/chat/app/components/layout/Sidebar.tsx +51 -157
  610. package/dist/templates/default/.agents/skills/actions/SKILL.md +32 -12
  611. package/dist/templates/default/.agents/skills/agent-native-docs/SKILL.md +21 -9
  612. package/dist/templates/default/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  613. package/dist/templates/default/.agents/skills/integration-webhooks/SKILL.md +323 -0
  614. package/dist/templates/default/.agents/skills/onboarding/SKILL.md +56 -0
  615. package/dist/templates/default/.agents/skills/secrets/SKILL.md +273 -0
  616. package/dist/templates/default/.agents/skills/self-modifying-code/SKILL.md +14 -2
  617. package/dist/templates/default/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  618. package/dist/templates/default/AGENTS.md +26 -18
  619. package/dist/templates/headless/.agents/skills/actions/SKILL.md +512 -0
  620. package/dist/templates/headless/.agents/skills/agent-native-docs/SKILL.md +21 -9
  621. package/dist/templates/headless/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  622. package/dist/templates/headless/.agents/skills/integration-webhooks/SKILL.md +323 -0
  623. package/dist/templates/headless/.agents/skills/secrets/SKILL.md +273 -0
  624. package/dist/templates/headless/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  625. package/dist/templates/headless/AGENTS.md +8 -0
  626. package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +32 -12
  627. package/dist/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +21 -9
  628. package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +7 -0
  629. package/dist/templates/workspace-core/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  630. package/dist/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +14 -2
  631. package/dist/templates/workspace-core/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  632. package/dist/templates/workspace-core/AGENTS.md +4 -0
  633. package/dist/templates/workspace-root/AGENTS.md +4 -0
  634. package/dist/vite/client.d.ts.map +1 -1
  635. package/dist/vite/client.js +22 -2
  636. package/dist/vite/client.js.map +1 -1
  637. package/docs/AGENTS.md +7 -0
  638. package/docs/content/agent-native-toolkit.mdx +38 -0
  639. package/docs/content/integrations.mdx +63 -2
  640. package/docs/content/package-lifecycle.mdx +54 -4
  641. package/docs/design/provider-integration-authority.md +117 -0
  642. package/package.json +20 -2
  643. package/src/a2a/agent-card.ts +83 -0
  644. package/src/a2a/artifact-response.ts +1648 -0
  645. package/src/a2a/auth-policy.ts +66 -0
  646. package/src/a2a/caller-auth.ts +102 -0
  647. package/src/a2a/client.ts +876 -0
  648. package/src/a2a/correlation.ts +50 -0
  649. package/src/a2a/handlers.ts +1285 -0
  650. package/src/a2a/index.ts +50 -0
  651. package/src/a2a/invoke.ts +348 -0
  652. package/src/a2a/response-text.ts +53 -0
  653. package/src/a2a/server.ts +586 -0
  654. package/src/a2a/task-store.ts +917 -0
  655. package/src/a2a/types.ts +221 -0
  656. package/src/a2a-claims.ts +52 -0
  657. package/src/action-change-marker.ts +74 -0
  658. package/src/action-ui.ts +38 -0
  659. package/src/action.ts +1406 -0
  660. package/src/adapters/cli/index.ts +6 -0
  661. package/src/adapters/cli/registry.ts +73 -0
  662. package/src/adapters/cli/shell-adapter.ts +92 -0
  663. package/src/adapters/cli/types.ts +27 -0
  664. package/src/agent/action-continuation-guidance.ts +38 -0
  665. package/src/agent/app-model-defaults.ts +201 -0
  666. package/src/agent/context-xray/actions/context-evict.ts +56 -0
  667. package/src/agent/context-xray/actions/context-manifest-get.ts +75 -0
  668. package/src/agent/context-xray/actions/context-pin.ts +56 -0
  669. package/src/agent/context-xray/actions/context-preview-get.ts +134 -0
  670. package/src/agent/context-xray/actions/context-report.ts +75 -0
  671. package/src/agent/context-xray/actions/context-restore.ts +51 -0
  672. package/src/agent/context-xray/actions/errors.ts +40 -0
  673. package/src/agent/context-xray/apply-directives.ts +137 -0
  674. package/src/agent/context-xray/directives-store.ts +178 -0
  675. package/src/agent/context-xray/identity.ts +37 -0
  676. package/src/agent/context-xray/manifest.ts +284 -0
  677. package/src/agent/context-xray/migrations.ts +32 -0
  678. package/src/agent/context-xray/plugin.ts +23 -0
  679. package/src/agent/context-xray/schema.ts +17 -0
  680. package/src/agent/context-xray/segments.ts +194 -0
  681. package/src/agent/context-xray/tokenize.ts +93 -0
  682. package/src/agent/default-model.ts +5 -0
  683. package/src/agent/durable-background.ts +547 -0
  684. package/src/agent/engine/ai-sdk-engine.ts +565 -0
  685. package/src/agent/engine/anthropic-engine.ts +320 -0
  686. package/src/agent/engine/builder-engine.ts +1110 -0
  687. package/src/agent/engine/builder-gateway-headers.ts +44 -0
  688. package/src/agent/engine/builtin.ts +122 -0
  689. package/src/agent/engine/context-directives-transform.ts +73 -0
  690. package/src/agent/engine/continuation-dispatch-retry.ts +168 -0
  691. package/src/agent/engine/credential-errors.ts +69 -0
  692. package/src/agent/engine/index.ts +54 -0
  693. package/src/agent/engine/openai-compatible-endpoint.ts +25 -0
  694. package/src/agent/engine/output-tokens.ts +181 -0
  695. package/src/agent/engine/provider-env-vars.ts +69 -0
  696. package/src/agent/engine/registry.ts +853 -0
  697. package/src/agent/engine/tool-call-journal-seed.ts +85 -0
  698. package/src/agent/engine/translate-ai-sdk.ts +407 -0
  699. package/src/agent/engine/translate-anthropic.ts +611 -0
  700. package/src/agent/engine/types.ts +310 -0
  701. package/src/agent/harness/acp-adapter.ts +893 -0
  702. package/src/agent/harness/acp-builtin.ts +70 -0
  703. package/src/agent/harness/ai-sdk-adapter.ts +509 -0
  704. package/src/agent/harness/background.ts +365 -0
  705. package/src/agent/harness/builtin.ts +50 -0
  706. package/src/agent/harness/index.ts +86 -0
  707. package/src/agent/harness/lifecycle.ts +498 -0
  708. package/src/agent/harness/registry.ts +97 -0
  709. package/src/agent/harness/runner.ts +182 -0
  710. package/src/agent/harness/store.ts +466 -0
  711. package/src/agent/harness/translate.ts +130 -0
  712. package/src/agent/harness/types.ts +129 -0
  713. package/src/agent/index.ts +32 -0
  714. package/src/agent/loop-settings.ts +186 -0
  715. package/src/agent/model-config.ts +363 -0
  716. package/src/agent/observational-memory/compactor.ts +78 -0
  717. package/src/agent/observational-memory/config.ts +78 -0
  718. package/src/agent/observational-memory/index.ts +79 -0
  719. package/src/agent/observational-memory/internal-run.ts +89 -0
  720. package/src/agent/observational-memory/message-text.ts +49 -0
  721. package/src/agent/observational-memory/migrations.ts +44 -0
  722. package/src/agent/observational-memory/observer.ts +128 -0
  723. package/src/agent/observational-memory/plugin.ts +35 -0
  724. package/src/agent/observational-memory/prompts.ts +53 -0
  725. package/src/agent/observational-memory/read.ts +131 -0
  726. package/src/agent/observational-memory/reflector.ts +119 -0
  727. package/src/agent/observational-memory/schema.ts +48 -0
  728. package/src/agent/observational-memory/store.ts +275 -0
  729. package/src/agent/observational-memory/types.ts +65 -0
  730. package/src/agent/processors.ts +209 -0
  731. package/src/agent/production-agent.ts +8254 -0
  732. package/src/agent/run-loop-with-resume.ts +394 -0
  733. package/src/agent/run-manager.ts +1825 -0
  734. package/src/agent/run-ownership.ts +75 -0
  735. package/src/agent/run-store.ts +2601 -0
  736. package/src/agent/runtime-context.ts +169 -0
  737. package/src/agent/thread-data-builder.ts +1584 -0
  738. package/src/agent/tool-call-journal.ts +368 -0
  739. package/src/agent/tool-error-redaction.ts +52 -0
  740. package/src/agent/tool-result-images.ts +178 -0
  741. package/src/agent/tool-search.ts +376 -0
  742. package/src/agent/types.ts +372 -0
  743. package/src/agent-native/index.ts +198 -0
  744. package/src/agent-web/config.ts +253 -0
  745. package/src/agent-web/generator.ts +382 -0
  746. package/src/agent-web/index.ts +36 -0
  747. package/src/appearance/actions/change-appearance.ts +35 -0
  748. package/src/application-state/emitter.ts +81 -0
  749. package/src/application-state/handlers.ts +121 -0
  750. package/src/application-state/index.ts +44 -0
  751. package/src/application-state/script-helpers.ts +155 -0
  752. package/src/application-state/store.ts +274 -0
  753. package/src/assets/branding/agent-native.icon/Assets/background.svg +3 -0
  754. package/src/assets/branding/agent-native.icon/Assets/foreground.svg +12 -0
  755. package/src/assets/branding/agent-native.icon/icon.json +49 -0
  756. package/src/assets/branding/favicon.png +0 -0
  757. package/src/assets/branding/favicon.svg +1 -0
  758. package/src/assets/branding/icon-on-dark.svg +10 -0
  759. package/src/assets/branding/icon-on-light.svg +10 -0
  760. package/src/assets/branding/mac-app-icon.svg +1 -0
  761. package/src/assets/branding/slack-bot/agent-native-1024.png +0 -0
  762. package/src/assets/branding/slack-bot/agent-native-512.png +0 -0
  763. package/src/assets/branding/tray-icon.svg +6 -0
  764. package/src/assets/branding/wordmark-on-dark.svg +21 -0
  765. package/src/assets/branding/wordmark-on-light.svg +21 -0
  766. package/src/assets/fonts/LICENSE_LIBERATION +96 -0
  767. package/src/assets/fonts/LICENSE_NOTO_NASKH_ARABIC +93 -0
  768. package/src/assets/fonts/LiberationSans-Bold.ttf +0 -0
  769. package/src/assets/fonts/LiberationSans-Regular.ttf +0 -0
  770. package/src/assets/fonts/NotoNaskhArabic-Variable.ttf +0 -0
  771. package/src/audit/actions/export-audit-events.ts +162 -0
  772. package/src/audit/actions/get-audit-event.ts +24 -0
  773. package/src/audit/actions/list-audit-events.ts +66 -0
  774. package/src/audit/cleanup-job.ts +100 -0
  775. package/src/audit/config.ts +90 -0
  776. package/src/audit/index.ts +43 -0
  777. package/src/audit/record.ts +180 -0
  778. package/src/audit/redact.ts +109 -0
  779. package/src/audit/store.ts +346 -0
  780. package/src/audit/types.ts +141 -0
  781. package/src/automation/index.ts +802 -0
  782. package/src/brand-kit/brand-signals.ts +124 -0
  783. package/src/brand-kit/fig/index.ts +64 -0
  784. package/src/brand-kit/index.ts +72 -0
  785. package/src/brand-kit/types.ts +113 -0
  786. package/src/browser-sessions/actions.ts +302 -0
  787. package/src/browser-sessions/routes.ts +234 -0
  788. package/src/browser-sessions/store.ts +679 -0
  789. package/src/browser-sessions/types.ts +84 -0
  790. package/src/changelog/parse.ts +328 -0
  791. package/src/chat-threads/emitter.ts +22 -0
  792. package/src/chat-threads/schema.ts +43 -0
  793. package/src/chat-threads/store.ts +1311 -0
  794. package/src/checkpoints/index.ts +15 -0
  795. package/src/checkpoints/service.ts +142 -0
  796. package/src/checkpoints/store.ts +153 -0
  797. package/src/cli/add.ts +425 -0
  798. package/src/cli/agent.ts +424 -0
  799. package/src/cli/agents.ts +122 -0
  800. package/src/cli/app-skill.ts +1455 -0
  801. package/src/cli/atomic-json-file.ts +324 -0
  802. package/src/cli/audit-agent-web.ts +324 -0
  803. package/src/cli/changelog.ts +199 -0
  804. package/src/cli/claude-code-participant.ts +515 -0
  805. package/src/cli/code-agent-commands.ts +270 -0
  806. package/src/cli/code-agent-connector.ts +1109 -0
  807. package/src/cli/code-agent-executor.ts +1970 -0
  808. package/src/cli/code-agent-output-smoother.ts +140 -0
  809. package/src/cli/code-agent-runs.concurrent-worker.ts +33 -0
  810. package/src/cli/code-agent-runs.ts +548 -0
  811. package/src/cli/code.ts +1805 -0
  812. package/src/cli/codex-cli-participant.ts +496 -0
  813. package/src/cli/connect.ts +2714 -0
  814. package/src/cli/content-local.ts +442 -0
  815. package/src/cli/context-xray-local.ts +2193 -0
  816. package/src/cli/create-workspace.ts +30 -0
  817. package/src/cli/create.ts +2247 -0
  818. package/src/cli/deploy-build.ts +50 -0
  819. package/src/cli/design-connect.ts +3187 -0
  820. package/src/cli/doctor.ts +472 -0
  821. package/src/cli/eject.ts +1594 -0
  822. package/src/cli/eval.ts +134 -0
  823. package/src/cli/gateway-helpers.ts +70 -0
  824. package/src/cli/index.ts +1217 -0
  825. package/src/cli/info.ts +105 -0
  826. package/src/cli/invoke.ts +288 -0
  827. package/src/cli/mcp-config-writers.ts +857 -0
  828. package/src/cli/mcp.ts +594 -0
  829. package/src/cli/migrate.ts +1813 -0
  830. package/src/cli/migration-codemod.ts +646 -0
  831. package/src/cli/multi-frontier-runs.ts +1952 -0
  832. package/src/cli/package-lifecycle.ts +823 -0
  833. package/src/cli/plan-blocks.ts +143 -0
  834. package/src/cli/plan-local.ts +3189 -0
  835. package/src/cli/plan-publish-store.ts +138 -0
  836. package/src/cli/pr-visual-recap-workflow.ts +2 -0
  837. package/src/cli/recap.ts +5 -0
  838. package/src/cli/setup-agents.ts +120 -0
  839. package/src/cli/skills-content/assets-skill.ts +83 -0
  840. package/src/cli/skills-content/canvas.ts +153 -0
  841. package/src/cli/skills-content/connection.ts +52 -0
  842. package/src/cli/skills-content/content-skill.ts +120 -0
  843. package/src/cli/skills-content/design-exploration-skill.ts +118 -0
  844. package/src/cli/skills-content/design-visual-edit-skill.ts +228 -0
  845. package/src/cli/skills-content/document-quality.ts +196 -0
  846. package/src/cli/skills-content/exemplar.ts +69 -0
  847. package/src/cli/skills-content/help.ts +77 -0
  848. package/src/cli/skills-content/index.ts +22 -0
  849. package/src/cli/skills-content/local-files.ts +100 -0
  850. package/src/cli/skills-content/plan-setup-auth.ts +80 -0
  851. package/src/cli/skills-content/visual-plan-skill.ts +493 -0
  852. package/src/cli/skills-content/visual-recap-skill.ts +553 -0
  853. package/src/cli/skills-content/visualize-repo-skill.ts +93 -0
  854. package/src/cli/skills-content/wireframe.ts +349 -0
  855. package/src/cli/skills.ts +4340 -0
  856. package/src/cli/sync-builder-starter-manifest.ts +631 -0
  857. package/src/cli/telemetry.ts +136 -0
  858. package/src/cli/templates-meta.ts +269 -0
  859. package/src/cli/upgrade.ts +956 -0
  860. package/src/cli/visualize-repo.ts +715 -0
  861. package/src/cli/workspace-dev.ts +1486 -0
  862. package/src/cli/workspacify.ts +258 -0
  863. package/src/client/AgentAskPopover.tsx +89 -0
  864. package/src/client/AgentChatHome.tsx +66 -0
  865. package/src/client/AgentNative.tsx +161 -0
  866. package/src/client/AgentNativeEmbedded.tsx +288 -0
  867. package/src/client/AgentNativeFrame.tsx +151 -0
  868. package/src/client/AgentPanel.tsx +3437 -0
  869. package/src/client/AgentTaskCard.tsx +273 -0
  870. package/src/client/AppearancePicker.tsx +79 -0
  871. package/src/client/AssistantChat.tsx +5793 -0
  872. package/src/client/ClientOnly.tsx +22 -0
  873. package/src/client/CommandMenu.tsx +726 -0
  874. package/src/client/ConnectBuilderCard.tsx +390 -0
  875. package/src/client/DefaultSpinner.tsx +47 -0
  876. package/src/client/ErrorBoundary.tsx +359 -0
  877. package/src/client/ErrorReportActions.tsx +69 -0
  878. package/src/client/FeedbackButton.tsx +553 -0
  879. package/src/client/HighlightedCodeBlock.tsx +173 -0
  880. package/src/client/IframeEmbed.tsx +151 -0
  881. package/src/client/KeepTabOpenNotice.tsx +181 -0
  882. package/src/client/MultiTabAssistantChat.tsx +2576 -0
  883. package/src/client/NewWorkspaceAppFlow.tsx +525 -0
  884. package/src/client/PoweredByBadge.tsx +284 -0
  885. package/src/client/RunStuckBanner.tsx +431 -0
  886. package/src/client/StarfieldBackground.tsx +466 -0
  887. package/src/client/Turnstile.tsx +125 -0
  888. package/src/client/active-run-state.ts +139 -0
  889. package/src/client/agent-chat/index.ts +279 -0
  890. package/src/client/agent-chat-adapter.ts +3692 -0
  891. package/src/client/agent-chat.ts +1233 -0
  892. package/src/client/agent-engine-key.ts +122 -0
  893. package/src/client/agent-page/AgentContextTab.tsx +487 -0
  894. package/src/client/agent-page/AgentEmptyState.tsx +44 -0
  895. package/src/client/agent-page/AgentJobsTab.tsx +441 -0
  896. package/src/client/agent-page/AgentTabFrame.tsx +39 -0
  897. package/src/client/agent-page/AgentTabsPage.tsx +1096 -0
  898. package/src/client/agent-page/types.ts +18 -0
  899. package/src/client/agent-page/use-jobs.ts +150 -0
  900. package/src/client/agent-sidebar-state.ts +166 -0
  901. package/src/client/analytics/index.ts +40 -0
  902. package/src/client/analytics-session.ts +70 -0
  903. package/src/client/analytics.ts +1757 -0
  904. package/src/client/api-path.ts +124 -0
  905. package/src/client/app-providers.tsx +230 -0
  906. package/src/client/appearance.ts +130 -0
  907. package/src/client/application-state.ts +154 -0
  908. package/src/client/assistant-ui-recovery.tsx +205 -0
  909. package/src/client/automation/index.ts +4 -0
  910. package/src/client/automation.ts +22 -0
  911. package/src/client/blocks/AiEditableField.tsx +30 -0
  912. package/src/client/blocks/BlockView.tsx +145 -0
  913. package/src/client/blocks/RegistryBlockDataProvider.tsx +121 -0
  914. package/src/client/blocks/SchemaBlockEditor.tsx +457 -0
  915. package/src/client/blocks/agent.ts +95 -0
  916. package/src/client/blocks/code-block-direction.ts +21 -0
  917. package/src/client/blocks/index.ts +308 -0
  918. package/src/client/blocks/library/AnnotatedCodeBlock.tsx +710 -0
  919. package/src/client/blocks/library/ApiEndpointBlock.tsx +1120 -0
  920. package/src/client/blocks/library/DataModelBlock.tsx +775 -0
  921. package/src/client/blocks/library/DiffBlock.tsx +1854 -0
  922. package/src/client/blocks/library/FileTreeBlock.tsx +868 -0
  923. package/src/client/blocks/library/HighlightedCode.tsx +260 -0
  924. package/src/client/blocks/library/JsonExplorerBlock.tsx +608 -0
  925. package/src/client/blocks/library/MermaidBlock.tsx +362 -0
  926. package/src/client/blocks/library/OpenApiSpecBlock.tsx +998 -0
  927. package/src/client/blocks/library/annotated-code.config.ts +101 -0
  928. package/src/client/blocks/library/annotation-rail.tsx +1020 -0
  929. package/src/client/blocks/library/api-endpoint.config.ts +207 -0
  930. package/src/client/blocks/library/block-copy.ts +399 -0
  931. package/src/client/blocks/library/callout.config.ts +57 -0
  932. package/src/client/blocks/library/callout.tsx +149 -0
  933. package/src/client/blocks/library/checklist.config.ts +56 -0
  934. package/src/client/blocks/library/checklist.tsx +208 -0
  935. package/src/client/blocks/library/code-filename-label.tsx +59 -0
  936. package/src/client/blocks/library/code-highlight.tsx +178 -0
  937. package/src/client/blocks/library/code-tabs.config.ts +70 -0
  938. package/src/client/blocks/library/code-tabs.tsx +606 -0
  939. package/src/client/blocks/library/code.config.ts +69 -0
  940. package/src/client/blocks/library/code.tsx +440 -0
  941. package/src/client/blocks/library/columns.config.ts +85 -0
  942. package/src/client/blocks/library/columns.tsx +334 -0
  943. package/src/client/blocks/library/data-model.config.ts +152 -0
  944. package/src/client/blocks/library/dev-doc-ui.tsx +191 -0
  945. package/src/client/blocks/library/diagram.config.ts +222 -0
  946. package/src/client/blocks/library/diagram.tsx +958 -0
  947. package/src/client/blocks/library/diff.config.ts +115 -0
  948. package/src/client/blocks/library/file-tree.config.ts +92 -0
  949. package/src/client/blocks/library/html.config.ts +79 -0
  950. package/src/client/blocks/library/html.tsx +258 -0
  951. package/src/client/blocks/library/json-explorer.config.ts +74 -0
  952. package/src/client/blocks/library/mermaid.config.ts +49 -0
  953. package/src/client/blocks/library/narrow-container.tsx +37 -0
  954. package/src/client/blocks/library/openapi-spec.config.ts +66 -0
  955. package/src/client/blocks/library/question-form.config.ts +127 -0
  956. package/src/client/blocks/library/question-form.tsx +944 -0
  957. package/src/client/blocks/library/sanitize-html.ts +343 -0
  958. package/src/client/blocks/library/server-specs.ts +338 -0
  959. package/src/client/blocks/library/specs.tsx +308 -0
  960. package/src/client/blocks/library/table.config.ts +61 -0
  961. package/src/client/blocks/library/table.tsx +449 -0
  962. package/src/client/blocks/library/tabs.config.ts +96 -0
  963. package/src/client/blocks/library/tabs.tsx +665 -0
  964. package/src/client/blocks/library/wireframe-icons.ts +210 -0
  965. package/src/client/blocks/library/wireframe-kit.tsx +1850 -0
  966. package/src/client/blocks/library/wireframe.config.ts +539 -0
  967. package/src/client/blocks/library/wireframe.tsx +535 -0
  968. package/src/client/blocks/mdx.ts +364 -0
  969. package/src/client/blocks/provider.tsx +51 -0
  970. package/src/client/blocks/registry.ts +83 -0
  971. package/src/client/blocks/schema-form/introspect.ts +201 -0
  972. package/src/client/blocks/server.ts +170 -0
  973. package/src/client/blocks/types.ts +415 -0
  974. package/src/client/browser-session-bridge.ts +548 -0
  975. package/src/client/browser-tab-id.ts +36 -0
  976. package/src/client/builder-frame.ts +194 -0
  977. package/src/client/builder-mark.tsx +21 -0
  978. package/src/client/changelog/Changelog.tsx +333 -0
  979. package/src/client/changelog/index.ts +1 -0
  980. package/src/client/chat/ChatHistoryList.tsx +7 -0
  981. package/src/client/chat/attachment-adapters.ts +426 -0
  982. package/src/client/chat/connectors.ts +1579 -0
  983. package/src/client/chat/index.ts +160 -0
  984. package/src/client/chat/markdown-renderer.tsx +693 -0
  985. package/src/client/chat/message-components.tsx +1326 -0
  986. package/src/client/chat/repo-helpers.ts +281 -0
  987. package/src/client/chat/run-recovery.tsx +994 -0
  988. package/src/client/chat/runtime.ts +1810 -0
  989. package/src/client/chat/tool-call-display.tsx +1270 -0
  990. package/src/client/chat/tool-render-registry.tsx +144 -0
  991. package/src/client/chat/use-agent-chat-lifecycle-tracking.ts +74 -0
  992. package/src/client/chat/use-reconnect-reader-owner.ts +28 -0
  993. package/src/client/chat/widgets/DataChartRenderer.tsx +242 -0
  994. package/src/client/chat/widgets/DataChartWidget.tsx +51 -0
  995. package/src/client/chat/widgets/DataInsightsWidget.tsx +59 -0
  996. package/src/client/chat/widgets/DataTableWidget.tsx +240 -0
  997. package/src/client/chat/widgets/InlineExtensionWidget.tsx +60 -0
  998. package/src/client/chat/widgets/builtin-tool-renderers.tsx +213 -0
  999. package/src/client/chat/widgets/data-widget-types.ts +1 -0
  1000. package/src/client/chat/widgets/inline-extension-result.ts +86 -0
  1001. package/src/client/chat-model-groups.ts +171 -0
  1002. package/src/client/chat-thread-url.ts +11 -0
  1003. package/src/client/chat-view-transition.ts +213 -0
  1004. package/src/client/client-action.ts +21 -0
  1005. package/src/client/client-bootstrap.ts +7 -0
  1006. package/src/client/client-surface.ts +41 -0
  1007. package/src/client/clipboard.ts +89 -0
  1008. package/src/client/code-agent-chat-adapter.ts +537 -0
  1009. package/src/client/collab/index.ts +60 -0
  1010. package/src/client/command-navigation/index.ts +15 -0
  1011. package/src/client/comments-review/index.ts +1 -0
  1012. package/src/client/components/AgentPresenceChip.tsx +4 -0
  1013. package/src/client/components/ApiKeySettings.tsx +309 -0
  1014. package/src/client/components/CodeAgentIndicator.tsx +59 -0
  1015. package/src/client/components/CodeRequiredDialog.tsx +470 -0
  1016. package/src/client/components/LiveCursorOverlay.tsx +5 -0
  1017. package/src/client/components/MissingKeyCard.tsx +61 -0
  1018. package/src/client/components/PresenceBar.tsx +4 -0
  1019. package/src/client/components/RecentEditHighlights.tsx +4 -0
  1020. package/src/client/components/RemoteSelectionRings.tsx +5 -0
  1021. package/src/client/components/icons/AgentNativeIcon.tsx +46 -0
  1022. package/src/client/components/ui/dialog.tsx +1 -0
  1023. package/src/client/components/ui/dropdown-menu.tsx +1 -0
  1024. package/src/client/components/ui/hover-card.tsx +1 -0
  1025. package/src/client/components/ui/message-scroller.tsx +131 -0
  1026. package/src/client/components/ui/popover.tsx +1 -0
  1027. package/src/client/components/ui/sheet.tsx +1 -0
  1028. package/src/client/components/ui/tooltip.tsx +1 -0
  1029. package/src/client/composer/index.ts +11 -0
  1030. package/src/client/composer/runtime-adapters.tsx +123 -0
  1031. package/src/client/composer/use-mention-search.ts +7 -0
  1032. package/src/client/composer/wired-components.tsx +53 -0
  1033. package/src/client/context-xray/ContextMeter.tsx +124 -0
  1034. package/src/client/context-xray/ContextSegmentRow.tsx +27 -0
  1035. package/src/client/context-xray/ContextTreemap.tsx +24 -0
  1036. package/src/client/context-xray/ContextXRayPanel.tsx +59 -0
  1037. package/src/client/context-xray/SegmentProvenancePopover.tsx +18 -0
  1038. package/src/client/context-xray/format.ts +27 -0
  1039. package/src/client/conversation/AgentConversation.tsx +555 -0
  1040. package/src/client/conversation/code-agent-transcript.ts +283 -0
  1041. package/src/client/conversation/index.ts +22 -0
  1042. package/src/client/conversation/types.ts +85 -0
  1043. package/src/client/conversation/use-near-bottom-autoscroll.ts +278 -0
  1044. package/src/client/create-query-client.ts +86 -0
  1045. package/src/client/db-admin/DataGrid.tsx +551 -0
  1046. package/src/client/db-admin/DbAdminPage.tsx +218 -0
  1047. package/src/client/db-admin/DevDatabaseLink.tsx +16 -0
  1048. package/src/client/db-admin/EditableCell.tsx +451 -0
  1049. package/src/client/db-admin/FilterBar.tsx +203 -0
  1050. package/src/client/db-admin/ResultsGrid.tsx +114 -0
  1051. package/src/client/db-admin/RowSidePanel.tsx +337 -0
  1052. package/src/client/db-admin/SqlEditor.tsx +840 -0
  1053. package/src/client/db-admin/TableBrowser.tsx +212 -0
  1054. package/src/client/db-admin/TableEditor.tsx +760 -0
  1055. package/src/client/db-admin/cell-format.ts +246 -0
  1056. package/src/client/db-admin/changeset.ts +296 -0
  1057. package/src/client/db-admin/export-utils.ts +78 -0
  1058. package/src/client/db-admin/index.ts +33 -0
  1059. package/src/client/db-admin/sql-storage.ts +134 -0
  1060. package/src/client/db-admin/storage.ts +68 -0
  1061. package/src/client/db-admin/useAgentSync.ts +226 -0
  1062. package/src/client/db-admin/useDbAdmin.ts +294 -0
  1063. package/src/client/dev-overlay/DevOverlay.tsx +576 -0
  1064. package/src/client/dev-overlay/builtins.ts +40 -0
  1065. package/src/client/dev-overlay/index.ts +23 -0
  1066. package/src/client/dev-overlay/registry.ts +67 -0
  1067. package/src/client/dev-overlay/types.ts +64 -0
  1068. package/src/client/dev-overlay/use-dev-option.ts +78 -0
  1069. package/src/client/dev-overlay/use-dev-overlay-shortcut.ts +31 -0
  1070. package/src/client/dynamic-suggestions.ts +455 -0
  1071. package/src/client/embed-auth.ts +544 -0
  1072. package/src/client/embed.ts +54 -0
  1073. package/src/client/error-capture.ts +690 -0
  1074. package/src/client/error-format.ts +211 -0
  1075. package/src/client/error-reporting.ts +100 -0
  1076. package/src/client/extensions/AgentNativeExtensionFrame.e2e-host.tsx +136 -0
  1077. package/src/client/extensions/AgentNativeExtensionFrame.tsx +708 -0
  1078. package/src/client/extensions/EmbeddedExtension.tsx +604 -0
  1079. package/src/client/extensions/ExtensionEditor.tsx +450 -0
  1080. package/src/client/extensions/ExtensionQueryErrorState.tsx +47 -0
  1081. package/src/client/extensions/ExtensionSlot.tsx +345 -0
  1082. package/src/client/extensions/ExtensionViewer.tsx +1502 -0
  1083. package/src/client/extensions/ExtensionViewerPage.tsx +32 -0
  1084. package/src/client/extensions/ExtensionsListPage.tsx +432 -0
  1085. package/src/client/extensions/ExtensionsSidebarSection.tsx +1259 -0
  1086. package/src/client/extensions/InlineExtensionFrame.tsx +660 -0
  1087. package/src/client/extensions/agent-native-extension-runtime.ts +495 -0
  1088. package/src/client/extensions/delete-extension.ts +76 -0
  1089. package/src/client/extensions/extension-load-error.ts +26 -0
  1090. package/src/client/extensions/extension-order.ts +49 -0
  1091. package/src/client/extensions/extension-popularity.ts +61 -0
  1092. package/src/client/extensions/iframe-bridge.ts +377 -0
  1093. package/src/client/extensions/index.ts +84 -0
  1094. package/src/client/extensions/portable-extension.ts +712 -0
  1095. package/src/client/feature-flags/FeatureFlagsPanel.tsx +519 -0
  1096. package/src/client/feature-flags/helpers.ts +77 -0
  1097. package/src/client/feature-flags/index.ts +13 -0
  1098. package/src/client/feature-flags/types.ts +29 -0
  1099. package/src/client/feature-flags/use-feature-flag.ts +26 -0
  1100. package/src/client/feedback-context.ts +90 -0
  1101. package/src/client/frame-protocol.ts +168 -0
  1102. package/src/client/frame.ts +329 -0
  1103. package/src/client/guided-questions.tsx +1152 -0
  1104. package/src/client/history/VersionHistoryPanel.tsx +175 -0
  1105. package/src/client/history/index.ts +21 -0
  1106. package/src/client/history/use-history.ts +114 -0
  1107. package/src/client/hooks/index.ts +46 -0
  1108. package/src/client/host/index.ts +170 -0
  1109. package/src/client/host-bridge.ts +1272 -0
  1110. package/src/client/host-tools.ts +190 -0
  1111. package/src/client/i18n.tsx +798 -0
  1112. package/src/client/index.ts +370 -0
  1113. package/src/client/integrations/IntegrationCard.tsx +186 -0
  1114. package/src/client/integrations/IntegrationsPanel.tsx +633 -0
  1115. package/src/client/integrations/api.ts +295 -0
  1116. package/src/client/integrations/index.ts +29 -0
  1117. package/src/client/integrations/useIntegrationStatus.ts +52 -0
  1118. package/src/client/mcp-app-host.ts +720 -0
  1119. package/src/client/mcp-apps/McpAppRenderer.tsx +760 -0
  1120. package/src/client/navigation/index.ts +54 -0
  1121. package/src/client/notifications/NotificationsBell.tsx +383 -0
  1122. package/src/client/notifications/index.ts +1 -0
  1123. package/src/client/observability/ObservabilityDashboard.tsx +890 -0
  1124. package/src/client/observability/ThumbsFeedback.tsx +160 -0
  1125. package/src/client/observability/index.ts +20 -0
  1126. package/src/client/observability/useObservability.ts +266 -0
  1127. package/src/client/onboarding/OnboardingBanner.tsx +73 -0
  1128. package/src/client/onboarding/OnboardingPanel.tsx +1036 -0
  1129. package/src/client/onboarding/SetupButton.tsx +64 -0
  1130. package/src/client/onboarding/index.ts +25 -0
  1131. package/src/client/onboarding/use-onboarding.ts +164 -0
  1132. package/src/client/onboarding/use-preview-mode.ts +40 -0
  1133. package/src/client/org/InvitationBanner.tsx +148 -0
  1134. package/src/client/org/OrgSwitcher.tsx +754 -0
  1135. package/src/client/org/RequireActiveOrg.tsx +337 -0
  1136. package/src/client/org/TeamPage.tsx +1432 -0
  1137. package/src/client/org/hooks.ts +359 -0
  1138. package/src/client/org/index.ts +70 -0
  1139. package/src/client/org/workspace-app-links.ts +367 -0
  1140. package/src/client/org-team/index.ts +1 -0
  1141. package/src/client/progress/RunsTray.tsx +680 -0
  1142. package/src/client/progress/index.ts +1 -0
  1143. package/src/client/require-session.tsx +142 -0
  1144. package/src/client/resources/BuiltinCapabilityDetail.tsx +258 -0
  1145. package/src/client/resources/McpConnectionSuggestion.tsx +276 -0
  1146. package/src/client/resources/McpIntegrationDialog.tsx +808 -0
  1147. package/src/client/resources/McpServerDetail.tsx +230 -0
  1148. package/src/client/resources/ResourceEditor.tsx +872 -0
  1149. package/src/client/resources/ResourceTree.tsx +860 -0
  1150. package/src/client/resources/ResourcesPanel.tsx +1960 -0
  1151. package/src/client/resources/index.ts +25 -0
  1152. package/src/client/resources/mcp-integration-catalog.ts +771 -0
  1153. package/src/client/resources/mcp-integration-logos.ts +108 -0
  1154. package/src/client/resources/runtime.ts +1 -0
  1155. package/src/client/resources/use-builtin-capabilities.ts +113 -0
  1156. package/src/client/resources/use-mcp-servers.ts +217 -0
  1157. package/src/client/resources/use-resources.ts +402 -0
  1158. package/src/client/review/ReviewCommentComposer.tsx +123 -0
  1159. package/src/client/review/ReviewStatusBadge.tsx +39 -0
  1160. package/src/client/review/ReviewThreadPanel.tsx +625 -0
  1161. package/src/client/review/index.ts +38 -0
  1162. package/src/client/review/use-review.ts +186 -0
  1163. package/src/client/route-chunk-recovery/index.ts +1 -0
  1164. package/src/client/route-chunk-recovery.ts +331 -0
  1165. package/src/client/route-state.ts +455 -0
  1166. package/src/client/route-warmup.tsx +543 -0
  1167. package/src/client/session-replay-iframe.e2e-host.tsx +100 -0
  1168. package/src/client/session-replay.ts +3417 -0
  1169. package/src/client/settings/AgentsSection.tsx +441 -0
  1170. package/src/client/settings/AutomationsSection.tsx +516 -0
  1171. package/src/client/settings/BackgroundAgentSection.tsx +189 -0
  1172. package/src/client/settings/BrowserSection.tsx +110 -0
  1173. package/src/client/settings/DemoModeSection.tsx +48 -0
  1174. package/src/client/settings/SecretsSection.tsx +875 -0
  1175. package/src/client/settings/SettingsPanel.tsx +3162 -0
  1176. package/src/client/settings/SettingsSection.tsx +283 -0
  1177. package/src/client/settings/SettingsTabsPage.tsx +592 -0
  1178. package/src/client/settings/UsageSection.tsx +401 -0
  1179. package/src/client/settings/VoiceTranscriptionSection.tsx +960 -0
  1180. package/src/client/settings/agent-settings-search.ts +220 -0
  1181. package/src/client/settings/index.ts +27 -0
  1182. package/src/client/settings/useBuilderStatus.ts +1055 -0
  1183. package/src/client/setup-connections/BuilderConnectCard.tsx +89 -0
  1184. package/src/client/setup-connections/ProviderReadinessBadge.tsx +73 -0
  1185. package/src/client/setup-connections/SetupConnectionsPage.tsx +94 -0
  1186. package/src/client/setup-connections/catalog.ts +6 -0
  1187. package/src/client/setup-connections/index.ts +47 -0
  1188. package/src/client/setup-connections/runtime.ts +1 -0
  1189. package/src/client/sharing/ShareButton.tsx +1748 -0
  1190. package/src/client/sharing/ShareDialog.tsx +846 -0
  1191. package/src/client/sharing/VisibilityBadge.tsx +4 -0
  1192. package/src/client/sharing/index.ts +2 -0
  1193. package/src/client/sse-event-processor.ts +2002 -0
  1194. package/src/client/terminal/AgentTerminal.tsx +488 -0
  1195. package/src/client/terminal/index.ts +7 -0
  1196. package/src/client/theme.ts +27 -0
  1197. package/src/client/tombstone/agent-presence-chip.ts +17 -0
  1198. package/src/client/tombstone/editor.ts +265 -0
  1199. package/src/client/tombstone/live-cursor-overlay.ts +21 -0
  1200. package/src/client/tombstone/presence-bar.ts +17 -0
  1201. package/src/client/tombstone/recent-edit-highlights.ts +17 -0
  1202. package/src/client/tombstone/remote-selection-rings.ts +21 -0
  1203. package/src/client/tombstone/rich-markdown-editor.ts +265 -0
  1204. package/src/client/tombstone/ui-dialog.ts +49 -0
  1205. package/src/client/tombstone/ui-dropdown-menu.ts +69 -0
  1206. package/src/client/tombstone/ui-hover-card.ts +21 -0
  1207. package/src/client/tombstone/ui-popover.ts +25 -0
  1208. package/src/client/tombstone/ui-sheet.ts +49 -0
  1209. package/src/client/tombstone/ui-tooltip.ts +29 -0
  1210. package/src/client/tombstone/visual-style-controls.ts +61 -0
  1211. package/src/client/tool-cells/BashCell.tsx +164 -0
  1212. package/src/client/tool-cells/EditCell.tsx +303 -0
  1213. package/src/client/tool-cells/FilesChangedSummary.tsx +208 -0
  1214. package/src/client/tool-cells/WriteCell.tsx +145 -0
  1215. package/src/client/tool-cells/index.ts +7 -0
  1216. package/src/client/tool-display.ts +41 -0
  1217. package/src/client/track.ts +57 -0
  1218. package/src/client/transcription/BuilderTranscriptionCta.tsx +120 -0
  1219. package/src/client/transcription/use-live-transcription.ts +292 -0
  1220. package/src/client/ui/index.ts +55 -0
  1221. package/src/client/uploads/index.ts +6 -0
  1222. package/src/client/uploads/upload-editor-image.ts +79 -0
  1223. package/src/client/uploads/use-upload-resource.ts +24 -0
  1224. package/src/client/url-scrub.ts +51 -0
  1225. package/src/client/use-action.ts +766 -0
  1226. package/src/client/use-agent-chat-context.ts +63 -0
  1227. package/src/client/use-agent-chat-home-handoff.ts +207 -0
  1228. package/src/client/use-agent-chat.ts +53 -0
  1229. package/src/client/use-agent-engine-configured.ts +211 -0
  1230. package/src/client/use-avatar.ts +127 -0
  1231. package/src/client/use-change-version.ts +150 -0
  1232. package/src/client/use-chat-models.ts +252 -0
  1233. package/src/client/use-chat-threads.ts +1262 -0
  1234. package/src/client/use-db-sync.ts +1112 -0
  1235. package/src/client/use-demo-mode-status.ts +30 -0
  1236. package/src/client/use-dev-mode.ts +177 -0
  1237. package/src/client/use-external-value.ts +40 -0
  1238. package/src/client/use-pausing-interval.ts +65 -0
  1239. package/src/client/use-pinch-zoom.ts +202 -0
  1240. package/src/client/use-run-stuck-detection.ts +427 -0
  1241. package/src/client/use-send-to-agent-chat.ts +85 -0
  1242. package/src/client/use-session.ts +114 -0
  1243. package/src/client/utils.ts +7 -0
  1244. package/src/client/visual-style-controls.tsx +1 -0
  1245. package/src/client/vite-dev-recovery-script.ts +226 -0
  1246. package/src/client/voice-provider-status.ts +44 -0
  1247. package/src/client/widgets/index.ts +41 -0
  1248. package/src/code-agents/background-controller.ts +398 -0
  1249. package/src/code-agents/background-run.ts +156 -0
  1250. package/src/code-agents/index.ts +95 -0
  1251. package/src/code-agents/prompt-attachments.ts +39 -0
  1252. package/src/code-agents/transcript-normalizer.ts +750 -0
  1253. package/src/code-agents/transcript-order.ts +73 -0
  1254. package/src/coding-tools/index.ts +742 -0
  1255. package/src/coding-tools/run-code.ts +1662 -0
  1256. package/src/coding-tools/sandbox/adapter.ts +82 -0
  1257. package/src/coding-tools/sandbox/background.ts +406 -0
  1258. package/src/coding-tools/sandbox/executions-store.ts +517 -0
  1259. package/src/coding-tools/sandbox/index.ts +132 -0
  1260. package/src/coding-tools/sandbox/local-child-process-adapter.ts +217 -0
  1261. package/src/collab/agent-identity.ts +5 -0
  1262. package/src/collab/agent-presence.ts +341 -0
  1263. package/src/collab/awareness-store.ts +196 -0
  1264. package/src/collab/awareness.ts +317 -0
  1265. package/src/collab/client-struct.ts +366 -0
  1266. package/src/collab/client.ts +1205 -0
  1267. package/src/collab/emitter.ts +31 -0
  1268. package/src/collab/follow-mode.ts +107 -0
  1269. package/src/collab/index.ts +151 -0
  1270. package/src/collab/json-to-yjs.ts +504 -0
  1271. package/src/collab/presence.ts +207 -0
  1272. package/src/collab/recent-edits.ts +215 -0
  1273. package/src/collab/routes.ts +191 -0
  1274. package/src/collab/storage.ts +228 -0
  1275. package/src/collab/struct-routes.ts +133 -0
  1276. package/src/collab/text-to-yjs.ts +79 -0
  1277. package/src/collab/undo.ts +432 -0
  1278. package/src/collab/xml-ops.ts +68 -0
  1279. package/src/collab/ydoc-manager.ts +544 -0
  1280. package/src/command-navigation/actions.ts +100 -0
  1281. package/src/command-navigation/index.ts +12 -0
  1282. package/src/comments-review/index.ts +1 -0
  1283. package/src/connections/catalog.ts +451 -0
  1284. package/src/connections/index.ts +48 -0
  1285. package/src/connections/reader.ts +911 -0
  1286. package/src/connections/runtime.ts +1 -0
  1287. package/src/credentials/index.ts +187 -0
  1288. package/src/data-programs/actions.ts +335 -0
  1289. package/src/data-programs/contract.ts +284 -0
  1290. package/src/data-programs/execute.ts +693 -0
  1291. package/src/data-programs/index.ts +72 -0
  1292. package/src/data-programs/schema.ts +148 -0
  1293. package/src/data-programs/store.ts +755 -0
  1294. package/src/data-widgets/index.ts +376 -0
  1295. package/src/db/client.ts +1627 -0
  1296. package/src/db/create-get-db.ts +579 -0
  1297. package/src/db/ddl-guard.ts +302 -0
  1298. package/src/db/drizzle-config.ts +190 -0
  1299. package/src/db/ensure-additive-columns.ts +430 -0
  1300. package/src/db/index.ts +57 -0
  1301. package/src/db/migrations.ts +691 -0
  1302. package/src/db/request-telemetry.ts +154 -0
  1303. package/src/db/runtime-diagnostics.ts +331 -0
  1304. package/src/db/schema.ts +121 -0
  1305. package/src/db/widen-columns.ts +75 -0
  1306. package/src/db-admin/agent-tools.ts +202 -0
  1307. package/src/db-admin/index.ts +26 -0
  1308. package/src/db-admin/operations.ts +803 -0
  1309. package/src/db-admin/routes.ts +174 -0
  1310. package/src/db-admin/types.ts +110 -0
  1311. package/src/demo/browser-state.ts +47 -0
  1312. package/src/demo/fetch-interceptor.ts +175 -0
  1313. package/src/demo/redact.ts +575 -0
  1314. package/src/deploy/build.ts +3935 -0
  1315. package/src/deploy/immutable-assets.ts +65 -0
  1316. package/src/deploy/route-discovery.ts +458 -0
  1317. package/src/deploy/workspace-core.ts +282 -0
  1318. package/src/deploy/workspace-deploy.ts +1488 -0
  1319. package/src/eject/provider-api-definitions.ts +193 -0
  1320. package/src/eject/remote-mcp-presets.ts +137 -0
  1321. package/src/eject/setup-readiness-ui.tsx +29 -0
  1322. package/src/eject/workspace-connections.ts +92 -0
  1323. package/src/embedding/agent.ts +159 -0
  1324. package/src/embedding/bridge.ts +297 -0
  1325. package/src/embedding/index.ts +43 -0
  1326. package/src/embedding/protocol.ts +185 -0
  1327. package/src/embedding/react.tsx +319 -0
  1328. package/src/embeddings/index.ts +233 -0
  1329. package/src/eval/agent-runner.ts +210 -0
  1330. package/src/eval/define-eval.ts +55 -0
  1331. package/src/eval/index.ts +49 -0
  1332. package/src/eval/report.ts +75 -0
  1333. package/src/eval/runner.ts +369 -0
  1334. package/src/eval/scorer.ts +244 -0
  1335. package/src/eval/types.ts +188 -0
  1336. package/src/event-bus/bus.ts +140 -0
  1337. package/src/event-bus/index.ts +3 -0
  1338. package/src/event-bus/registry.ts +79 -0
  1339. package/src/event-bus/types.ts +29 -0
  1340. package/src/extensions/actions.ts +1636 -0
  1341. package/src/extensions/change-marker.ts +54 -0
  1342. package/src/extensions/content-patch.ts +468 -0
  1343. package/src/extensions/fetch-tool.ts +461 -0
  1344. package/src/extensions/html-shell.ts +803 -0
  1345. package/src/extensions/local.ts +462 -0
  1346. package/src/extensions/path.ts +40 -0
  1347. package/src/extensions/proxy-security.ts +171 -0
  1348. package/src/extensions/routes.ts +1080 -0
  1349. package/src/extensions/schema.ts +269 -0
  1350. package/src/extensions/session-replay-iframe.ts +131 -0
  1351. package/src/extensions/slots/routes.ts +126 -0
  1352. package/src/extensions/slots/schema.ts +87 -0
  1353. package/src/extensions/slots/store.ts +450 -0
  1354. package/src/extensions/store.ts +1347 -0
  1355. package/src/extensions/theme.ts +114 -0
  1356. package/src/extensions/url-safety.ts +316 -0
  1357. package/src/extensions/web-content.ts +663 -0
  1358. package/src/extensions/web-search-tool.ts +437 -0
  1359. package/src/feature-flags/a2a-action-route.ts +56 -0
  1360. package/src/feature-flags/actions/get-feature-flags.ts +24 -0
  1361. package/src/feature-flags/actions/list-feature-flags.ts +69 -0
  1362. package/src/feature-flags/actions/set-feature-flag.ts +89 -0
  1363. package/src/feature-flags/index.ts +21 -0
  1364. package/src/feature-flags/permissions.ts +53 -0
  1365. package/src/feature-flags/plugin.ts +44 -0
  1366. package/src/feature-flags/registry.ts +96 -0
  1367. package/src/feature-flags/store.ts +176 -0
  1368. package/src/file-upload/actions/upload-image.ts +213 -0
  1369. package/src/file-upload/builder.ts +431 -0
  1370. package/src/file-upload/index.ts +24 -0
  1371. package/src/file-upload/pre-upload-attachments.ts +305 -0
  1372. package/src/file-upload/registry.ts +125 -0
  1373. package/src/file-upload/types.ts +89 -0
  1374. package/src/guards/db-tool-scoping.ts +129 -0
  1375. package/src/guards/index.ts +23 -0
  1376. package/src/guards/no-drizzle-push.ts +116 -0
  1377. package/src/guards/no-env-credentials.ts +229 -0
  1378. package/src/guards/no-env-mutation.ts +114 -0
  1379. package/src/guards/no-localhost-fallback.ts +124 -0
  1380. package/src/guards/no-unscoped-credentials.ts +227 -0
  1381. package/src/guards/no-unscoped-queries.ts +834 -0
  1382. package/src/guards/scan-utils.ts +105 -0
  1383. package/src/guards/types.ts +30 -0
  1384. package/src/history/actions/create-resource-version.ts +92 -0
  1385. package/src/history/actions/get-resource-version.ts +60 -0
  1386. package/src/history/actions/list-resource-history.ts +53 -0
  1387. package/src/history/actions/list-resource-versions.ts +43 -0
  1388. package/src/history/actions/restore-resource-version.ts +96 -0
  1389. package/src/history/index.ts +26 -0
  1390. package/src/history/registry.ts +111 -0
  1391. package/src/history/store.ts +379 -0
  1392. package/src/history/types.ts +69 -0
  1393. package/src/index.browser.ts +155 -0
  1394. package/src/index.ts +408 -0
  1395. package/src/ingestion/docx.ts +158 -0
  1396. package/src/ingestion/figma-node-to-html.ts +1860 -0
  1397. package/src/ingestion/figma.ts +548 -0
  1398. package/src/ingestion/index.ts +107 -0
  1399. package/src/ingestion/media.ts +264 -0
  1400. package/src/ingestion/notion.ts +121 -0
  1401. package/src/ingestion/office.ts +213 -0
  1402. package/src/ingestion/orchestration.ts +160 -0
  1403. package/src/ingestion/pptx.ts +331 -0
  1404. package/src/ingestion/selection.ts +81 -0
  1405. package/src/ingestion/website.ts +151 -0
  1406. package/src/integrations/a2a-continuation-marker.ts +2 -0
  1407. package/src/integrations/a2a-continuation-processor.ts +888 -0
  1408. package/src/integrations/a2a-continuations-store.ts +643 -0
  1409. package/src/integrations/adapter-overrides.ts +12 -0
  1410. package/src/integrations/adapters/discord.ts +364 -0
  1411. package/src/integrations/adapters/email.ts +1164 -0
  1412. package/src/integrations/adapters/google-docs.ts +371 -0
  1413. package/src/integrations/adapters/index.ts +29 -0
  1414. package/src/integrations/adapters/microsoft-teams.ts +413 -0
  1415. package/src/integrations/adapters/slack.ts +1914 -0
  1416. package/src/integrations/adapters/telegram.ts +386 -0
  1417. package/src/integrations/adapters/whatsapp.ts +358 -0
  1418. package/src/integrations/awaiting-input-store.ts +130 -0
  1419. package/src/integrations/catalog.ts +571 -0
  1420. package/src/integrations/computer-supervision-store.ts +423 -0
  1421. package/src/integrations/computer-supervision.ts +213 -0
  1422. package/src/integrations/config-store.ts +131 -0
  1423. package/src/integrations/controls-store.ts +187 -0
  1424. package/src/integrations/eject/messaging-adapters.ts +85 -0
  1425. package/src/integrations/google-docs-poller.ts +671 -0
  1426. package/src/integrations/identity-links-store.ts +210 -0
  1427. package/src/integrations/identity.ts +196 -0
  1428. package/src/integrations/index.ts +220 -0
  1429. package/src/integrations/installations-store.ts +677 -0
  1430. package/src/integrations/integration-memory.ts +187 -0
  1431. package/src/integrations/internal-token.ts +106 -0
  1432. package/src/integrations/pending-tasks-retry-job.ts +286 -0
  1433. package/src/integrations/pending-tasks-store.ts +468 -0
  1434. package/src/integrations/plugin.ts +3048 -0
  1435. package/src/integrations/remote-commands-store.ts +690 -0
  1436. package/src/integrations/remote-devices-store.ts +492 -0
  1437. package/src/integrations/remote-json-safety.ts +127 -0
  1438. package/src/integrations/remote-push-delivery-job.ts +48 -0
  1439. package/src/integrations/remote-push-delivery.ts +370 -0
  1440. package/src/integrations/remote-push-store.ts +664 -0
  1441. package/src/integrations/remote-retry-job.ts +55 -0
  1442. package/src/integrations/remote-run-events-store.ts +222 -0
  1443. package/src/integrations/remote-types.ts +186 -0
  1444. package/src/integrations/runtime.ts +1 -0
  1445. package/src/integrations/scope-store.ts +498 -0
  1446. package/src/integrations/slack-manifest.ts +78 -0
  1447. package/src/integrations/slack-oauth.ts +344 -0
  1448. package/src/integrations/task-queue-stats.ts +144 -0
  1449. package/src/integrations/thread-mapping-store.ts +134 -0
  1450. package/src/integrations/types.ts +485 -0
  1451. package/src/integrations/usage-budget-store.ts +906 -0
  1452. package/src/integrations/webhook-delivery.ts +55 -0
  1453. package/src/integrations/webhook-handler.ts +1939 -0
  1454. package/src/jobs/actions/list-recurring-jobs.ts +105 -0
  1455. package/src/jobs/actions/manage-recurring-job.ts +85 -0
  1456. package/src/jobs/cron.ts +126 -0
  1457. package/src/jobs/index.ts +9 -0
  1458. package/src/jobs/scheduler.ts +703 -0
  1459. package/src/jobs/tools.ts +367 -0
  1460. package/src/local-artifacts/index.ts +1372 -0
  1461. package/src/localization/actions/get-localization-preference.ts +24 -0
  1462. package/src/localization/actions/set-localization-preference.ts +32 -0
  1463. package/src/localization/default-messages.ts +1009 -0
  1464. package/src/localization/index.ts +2 -0
  1465. package/src/localization/server.ts +131 -0
  1466. package/src/localization/shared.ts +208 -0
  1467. package/src/mcp/actions/call-mcp-tool.ts +19 -0
  1468. package/src/mcp/actions/create-org-service-token.ts +87 -0
  1469. package/src/mcp/actions/list-mcp-tools.ts +18 -0
  1470. package/src/mcp/actions/list-org-service-tokens.ts +44 -0
  1471. package/src/mcp/actions/revoke-org-service-token.ts +30 -0
  1472. package/src/mcp/actions/service-token-access.ts +121 -0
  1473. package/src/mcp/ask-app-inline-tasks.ts +125 -0
  1474. package/src/mcp/build-server.ts +2356 -0
  1475. package/src/mcp/builtin-tools.ts +1506 -0
  1476. package/src/mcp/connect-route.ts +1460 -0
  1477. package/src/mcp/connect-store.ts +680 -0
  1478. package/src/mcp/embed-app.ts +2051 -0
  1479. package/src/mcp/embed-route.ts +84 -0
  1480. package/src/mcp/external-agent-policy.ts +18 -0
  1481. package/src/mcp/index.ts +47 -0
  1482. package/src/mcp/oauth-route.ts +1016 -0
  1483. package/src/mcp/oauth-store.ts +581 -0
  1484. package/src/mcp/oauth-token.ts +227 -0
  1485. package/src/mcp/org-directory.ts +343 -0
  1486. package/src/mcp/route-paths.ts +34 -0
  1487. package/src/mcp/screen-memory-stdio.ts +290 -0
  1488. package/src/mcp/server.ts +507 -0
  1489. package/src/mcp/stdio.ts +328 -0
  1490. package/src/mcp/workspace-resolve.ts +261 -0
  1491. package/src/mcp-client/app-api.ts +136 -0
  1492. package/src/mcp-client/app-result.ts +64 -0
  1493. package/src/mcp-client/builtin-capabilities.ts +146 -0
  1494. package/src/mcp-client/builtin-store.ts +93 -0
  1495. package/src/mcp-client/config.ts +281 -0
  1496. package/src/mcp-client/errors.ts +54 -0
  1497. package/src/mcp-client/hub-client.ts +172 -0
  1498. package/src/mcp-client/hub-routes.ts +198 -0
  1499. package/src/mcp-client/index.ts +504 -0
  1500. package/src/mcp-client/manager.ts +968 -0
  1501. package/src/mcp-client/oauth-client.ts +462 -0
  1502. package/src/mcp-client/oauth-routes.ts +307 -0
  1503. package/src/mcp-client/remote-store.ts +674 -0
  1504. package/src/mcp-client/remote-url.ts +97 -0
  1505. package/src/mcp-client/routes.ts +1093 -0
  1506. package/src/mcp-client/screen-memory-local.ts +461 -0
  1507. package/src/mcp-client/tool-policy.ts +182 -0
  1508. package/src/mcp-client/visibility.ts +56 -0
  1509. package/src/mcp-client/workspace-servers.ts +379 -0
  1510. package/src/navigation/index.ts +170 -0
  1511. package/src/notifications/actions.ts +151 -0
  1512. package/src/notifications/channels.ts +410 -0
  1513. package/src/notifications/index.ts +22 -0
  1514. package/src/notifications/registry.ts +216 -0
  1515. package/src/notifications/routes.ts +106 -0
  1516. package/src/notifications/store.ts +236 -0
  1517. package/src/notifications/types.ts +52 -0
  1518. package/src/oauth-tokens/google-refresh.ts +175 -0
  1519. package/src/oauth-tokens/index.ts +15 -0
  1520. package/src/oauth-tokens/store.ts +384 -0
  1521. package/src/observability/cleanup-job.ts +124 -0
  1522. package/src/observability/evals.ts +507 -0
  1523. package/src/observability/experiments.ts +359 -0
  1524. package/src/observability/feedback.ts +332 -0
  1525. package/src/observability/hosted-model-experiment.ts +118 -0
  1526. package/src/observability/index.ts +62 -0
  1527. package/src/observability/plugin.ts +31 -0
  1528. package/src/observability/routes.ts +431 -0
  1529. package/src/observability/sentiment.ts +261 -0
  1530. package/src/observability/store.ts +1347 -0
  1531. package/src/observability/traces.ts +789 -0
  1532. package/src/observability/tracing.ts +157 -0
  1533. package/src/observability/tracking-identity.ts +55 -0
  1534. package/src/observability/types.ts +211 -0
  1535. package/src/onboarding/default-steps.ts +428 -0
  1536. package/src/onboarding/index.ts +22 -0
  1537. package/src/onboarding/plugin.ts +262 -0
  1538. package/src/onboarding/registry.ts +47 -0
  1539. package/src/onboarding/types.ts +96 -0
  1540. package/src/org/accept-pending.ts +98 -0
  1541. package/src/org/auto-join-domain.ts +113 -0
  1542. package/src/org/context.ts +614 -0
  1543. package/src/org/free-email-providers.ts +124 -0
  1544. package/src/org/handlers.ts +1153 -0
  1545. package/src/org/index.ts +63 -0
  1546. package/src/org/migrations.ts +105 -0
  1547. package/src/org/permissions.ts +30 -0
  1548. package/src/org/plugin.ts +255 -0
  1549. package/src/org/schema.ts +28 -0
  1550. package/src/org/types.ts +57 -0
  1551. package/src/org-team/index.ts +1 -0
  1552. package/src/package-lifecycle/deprecated-imports.ts +179 -0
  1553. package/src/package-lifecycle/eject-manifest.ts +345 -0
  1554. package/src/package-lifecycle/index.ts +7 -0
  1555. package/src/package-lifecycle/manifest.ts +120 -0
  1556. package/src/package-lifecycle/migration-manifest.ts +159 -0
  1557. package/src/package-lifecycle/migration-message.ts +6 -0
  1558. package/src/package-lifecycle/tombstone.ts +58 -0
  1559. package/src/package-lifecycle/upgrade-error.ts +37 -0
  1560. package/src/private-blob/index.ts +18 -0
  1561. package/src/private-blob/registry.ts +242 -0
  1562. package/src/private-blob/types.ts +55 -0
  1563. package/src/progress/actions.ts +179 -0
  1564. package/src/progress/index.ts +16 -0
  1565. package/src/progress/registry.ts +127 -0
  1566. package/src/progress/routes.ts +89 -0
  1567. package/src/progress/store.ts +353 -0
  1568. package/src/progress/types.ts +59 -0
  1569. package/src/provider-api/actions/custom-provider-registration.ts +197 -0
  1570. package/src/provider-api/actions/delete-staged-dataset.ts +5 -0
  1571. package/src/provider-api/actions/github-repo-files.ts +266 -0
  1572. package/src/provider-api/actions/list-staged-datasets.ts +5 -0
  1573. package/src/provider-api/actions/provider-api-audit.ts +88 -0
  1574. package/src/provider-api/actions/provider-api.ts +460 -0
  1575. package/src/provider-api/actions/query-staged-dataset.ts +5 -0
  1576. package/src/provider-api/actions/staged-datasets.ts +359 -0
  1577. package/src/provider-api/corpus-jobs-store.ts +522 -0
  1578. package/src/provider-api/corpus-jobs.ts +1817 -0
  1579. package/src/provider-api/custom-registry.ts +456 -0
  1580. package/src/provider-api/github-repo.ts +675 -0
  1581. package/src/provider-api/gong.ts +108 -0
  1582. package/src/provider-api/index.ts +5444 -0
  1583. package/src/provider-api/quota-governor.ts +562 -0
  1584. package/src/provider-api/runtime.ts +1 -0
  1585. package/src/provider-api/staged-datasets-aggregate.ts +304 -0
  1586. package/src/provider-api/staged-datasets-store.ts +441 -0
  1587. package/src/provider-api/staging.ts +483 -0
  1588. package/src/resources/agents.ts +65 -0
  1589. package/src/resources/emitter.ts +54 -0
  1590. package/src/resources/handlers.ts +728 -0
  1591. package/src/resources/index.ts +4 -0
  1592. package/src/resources/metadata.ts +252 -0
  1593. package/src/resources/script-helpers.ts +160 -0
  1594. package/src/resources/store.ts +1618 -0
  1595. package/src/review/actions/consume-review-feedback.ts +48 -0
  1596. package/src/review/actions/create-review-comment.ts +108 -0
  1597. package/src/review/actions/delete-review-comment.ts +67 -0
  1598. package/src/review/actions/get-review-feedback.ts +49 -0
  1599. package/src/review/actions/list-review-comments.ts +87 -0
  1600. package/src/review/actions/reply-review-comment.ts +118 -0
  1601. package/src/review/actions/resolve-review-thread.ts +94 -0
  1602. package/src/review/actions/send-review-thread-to-agent.ts +62 -0
  1603. package/src/review/actions/set-review-status.ts +58 -0
  1604. package/src/review/identity.ts +101 -0
  1605. package/src/review/index.ts +45 -0
  1606. package/src/review/mentions.ts +44 -0
  1607. package/src/review/registry.ts +111 -0
  1608. package/src/review/store.ts +997 -0
  1609. package/src/review/types.ts +101 -0
  1610. package/src/router/index.ts +24 -0
  1611. package/src/scripts/agent-engines/list-agent-engines.ts +130 -0
  1612. package/src/scripts/agent-engines/manage-agent-engine.ts +197 -0
  1613. package/src/scripts/agent-engines/set-agent-engine.ts +84 -0
  1614. package/src/scripts/agent-engines/test-agent-engine.ts +174 -0
  1615. package/src/scripts/call-agent.ts +792 -0
  1616. package/src/scripts/chat/index.ts +8 -0
  1617. package/src/scripts/chat/open-chat.ts +56 -0
  1618. package/src/scripts/chat/search-chats.ts +121 -0
  1619. package/src/scripts/core-scripts.ts +22 -0
  1620. package/src/scripts/db/check-scoping.ts +212 -0
  1621. package/src/scripts/db/exec.ts +791 -0
  1622. package/src/scripts/db/index.ts +19 -0
  1623. package/src/scripts/db/migrate-encrypt-credentials.ts +223 -0
  1624. package/src/scripts/db/migrate-encrypt-oauth-tokens.ts +213 -0
  1625. package/src/scripts/db/migrate-user-api-keys.ts +257 -0
  1626. package/src/scripts/db/patch.ts +820 -0
  1627. package/src/scripts/db/query.ts +299 -0
  1628. package/src/scripts/db/reset-dev-owner.ts +285 -0
  1629. package/src/scripts/db/safety.ts +286 -0
  1630. package/src/scripts/db/schema.ts +364 -0
  1631. package/src/scripts/db/scoping.ts +341 -0
  1632. package/src/scripts/db/sqlite-client.ts +78 -0
  1633. package/src/scripts/db/tool-mode.ts +23 -0
  1634. package/src/scripts/db/tool-schemas.ts +31 -0
  1635. package/src/scripts/db/wipe-leaked-builder-keys.ts +201 -0
  1636. package/src/scripts/dev/index.ts +296 -0
  1637. package/src/scripts/dev/list-files.ts +119 -0
  1638. package/src/scripts/dev/read-file.ts +77 -0
  1639. package/src/scripts/dev/search-files.ts +151 -0
  1640. package/src/scripts/dev/shell.ts +111 -0
  1641. package/src/scripts/dev/write-file.ts +56 -0
  1642. package/src/scripts/dev-session.ts +96 -0
  1643. package/src/scripts/docs/index.ts +8 -0
  1644. package/src/scripts/docs/search.ts +274 -0
  1645. package/src/scripts/docs/source-search.ts +363 -0
  1646. package/src/scripts/index.ts +15 -0
  1647. package/src/scripts/manage-agent-loop-settings.ts +84 -0
  1648. package/src/scripts/parse-args.ts +46 -0
  1649. package/src/scripts/resources/delete-memory.ts +67 -0
  1650. package/src/scripts/resources/delete.ts +69 -0
  1651. package/src/scripts/resources/effective.ts +71 -0
  1652. package/src/scripts/resources/index.ts +18 -0
  1653. package/src/scripts/resources/list.ts +103 -0
  1654. package/src/scripts/resources/migrate-learnings.ts +40 -0
  1655. package/src/scripts/resources/read.ts +107 -0
  1656. package/src/scripts/resources/save-memory.ts +99 -0
  1657. package/src/scripts/resources/write.ts +158 -0
  1658. package/src/scripts/runner.ts +339 -0
  1659. package/src/scripts/utils.ts +130 -0
  1660. package/src/search/index.ts +413 -0
  1661. package/src/search-utils/index.ts +112 -0
  1662. package/src/secrets/crypto.ts +228 -0
  1663. package/src/secrets/index.ts +65 -0
  1664. package/src/secrets/onboarding.ts +101 -0
  1665. package/src/secrets/register-framework-secrets.ts +228 -0
  1666. package/src/secrets/register.ts +129 -0
  1667. package/src/secrets/routes.ts +697 -0
  1668. package/src/secrets/schema.ts +52 -0
  1669. package/src/secrets/storage.ts +561 -0
  1670. package/src/secrets/substitution.ts +305 -0
  1671. package/src/server/__snapshots__/agent-chat-plugin.surface.spec.ts.snap +150 -0
  1672. package/src/server/action-change.ts +66 -0
  1673. package/src/server/action-discovery.ts +774 -0
  1674. package/src/server/action-routes.ts +608 -0
  1675. package/src/server/agent-access.ts +72 -0
  1676. package/src/server/agent-chat/action-filters-a2a.ts +339 -0
  1677. package/src/server/agent-chat/browser-team-tools.ts +510 -0
  1678. package/src/server/agent-chat/context-tools.ts +599 -0
  1679. package/src/server/agent-chat/framework-prompts.ts +467 -0
  1680. package/src/server/agent-chat/lazy-fs.ts +11 -0
  1681. package/src/server/agent-chat/mcp-glue.ts +91 -0
  1682. package/src/server/agent-chat/plugin-options.ts +379 -0
  1683. package/src/server/agent-chat/process-run-failure.ts +62 -0
  1684. package/src/server/agent-chat/prompt-resources.ts +1004 -0
  1685. package/src/server/agent-chat/recurring-jobs-runtime.ts +80 -0
  1686. package/src/server/agent-chat/request-surface.ts +71 -0
  1687. package/src/server/agent-chat/run-code-tools.ts +67 -0
  1688. package/src/server/agent-chat/script-entries.ts +796 -0
  1689. package/src/server/agent-chat/shared-thread.ts +301 -0
  1690. package/src/server/agent-chat/skill-frontmatter.ts +41 -0
  1691. package/src/server/agent-chat-plugin.ts +5930 -0
  1692. package/src/server/agent-discovery.ts +706 -0
  1693. package/src/server/agent-engine-api-key-route.ts +236 -0
  1694. package/src/server/agent-run-context.ts +204 -0
  1695. package/src/server/agent-teams-run-queue.ts +344 -0
  1696. package/src/server/agent-teams.ts +2257 -0
  1697. package/src/server/agents-bundle.ts +464 -0
  1698. package/src/server/analytics.ts +105 -0
  1699. package/src/server/app-base-path.ts +79 -0
  1700. package/src/server/app-name.ts +53 -0
  1701. package/src/server/app-url.ts +184 -0
  1702. package/src/server/attachment-actions.ts +276 -0
  1703. package/src/server/attribution.ts +214 -0
  1704. package/src/server/auth-marketing.ts +260 -0
  1705. package/src/server/auth-plugin.ts +27 -0
  1706. package/src/server/auth.ts +3803 -0
  1707. package/src/server/better-auth-instance.ts +1197 -0
  1708. package/src/server/builder-browser.ts +1701 -0
  1709. package/src/server/builder-design-systems.ts +668 -0
  1710. package/src/server/builder-space.ts +176 -0
  1711. package/src/server/captcha.ts +63 -0
  1712. package/src/server/capture-error.ts +64 -0
  1713. package/src/server/cli-capture.ts +141 -0
  1714. package/src/server/collab-plugin.ts +391 -0
  1715. package/src/server/complete-text.ts +231 -0
  1716. package/src/server/cookie-namespace.ts +159 -0
  1717. package/src/server/core-routes-plugin.ts +4122 -0
  1718. package/src/server/cors-origins.ts +60 -0
  1719. package/src/server/create-server.ts +268 -0
  1720. package/src/server/credential-provider.ts +1202 -0
  1721. package/src/server/csrf.ts +229 -0
  1722. package/src/server/date-utils.ts +42 -0
  1723. package/src/server/deep-link.ts +119 -0
  1724. package/src/server/derived-secret.ts +32 -0
  1725. package/src/server/design-token-utils.ts +1032 -0
  1726. package/src/server/desktop-sso.ts +83 -0
  1727. package/src/server/edge.ts +69 -0
  1728. package/src/server/email-actions.ts +218 -0
  1729. package/src/server/email-template.ts +192 -0
  1730. package/src/server/email-templates.ts +148 -0
  1731. package/src/server/email.ts +219 -0
  1732. package/src/server/embed-route.ts +283 -0
  1733. package/src/server/embed-session.ts +805 -0
  1734. package/src/server/embedded.ts +252 -0
  1735. package/src/server/entry-server.tsx +154 -0
  1736. package/src/server/framework-request-handler.ts +848 -0
  1737. package/src/server/fusion-app.ts +447 -0
  1738. package/src/server/google-auth-mode.ts +34 -0
  1739. package/src/server/google-auth-plugin.ts +496 -0
  1740. package/src/server/google-oauth-credentials.ts +128 -0
  1741. package/src/server/google-oauth.ts +972 -0
  1742. package/src/server/google-realtime-session.ts +182 -0
  1743. package/src/server/h3-helpers.ts +174 -0
  1744. package/src/server/http-response-telemetry.ts +396 -0
  1745. package/src/server/identity-sso-store.ts +304 -0
  1746. package/src/server/identity-sso.ts +514 -0
  1747. package/src/server/index.ts +593 -0
  1748. package/src/server/missing-key.ts +36 -0
  1749. package/src/server/oauth-helpers.ts +44 -0
  1750. package/src/server/oauth-public-origin.ts +44 -0
  1751. package/src/server/oauth-return-url.ts +120 -0
  1752. package/src/server/og-fonts-data.ts +15 -0
  1753. package/src/server/og-fonts.ts +75 -0
  1754. package/src/server/onboarding-html.ts +4040 -0
  1755. package/src/server/open-route.ts +311 -0
  1756. package/src/server/org-admin.ts +28 -0
  1757. package/src/server/poll-events.ts +88 -0
  1758. package/src/server/poll.ts +1224 -0
  1759. package/src/server/prompts/framework-core-compact.ts +107 -0
  1760. package/src/server/prompts/framework-core.ts +143 -0
  1761. package/src/server/prompts/index.ts +16 -0
  1762. package/src/server/prompts/model-overlays.ts +54 -0
  1763. package/src/server/prompts/shared-rules.ts +104 -0
  1764. package/src/server/realtime-voice.ts +967 -0
  1765. package/src/server/recap-image-route.ts +242 -0
  1766. package/src/server/recap-image-store.ts +185 -0
  1767. package/src/server/request-context.ts +416 -0
  1768. package/src/server/request-origin.ts +67 -0
  1769. package/src/server/resources-plugin.ts +119 -0
  1770. package/src/server/schema-prompt.ts +429 -0
  1771. package/src/server/scoped-key-storage.ts +223 -0
  1772. package/src/server/security-headers.ts +170 -0
  1773. package/src/server/self-dispatch.ts +224 -0
  1774. package/src/server/sentry-config.ts +73 -0
  1775. package/src/server/sentry-plugin.ts +138 -0
  1776. package/src/server/sentry.ts +444 -0
  1777. package/src/server/short-lived-token.ts +170 -0
  1778. package/src/server/social-og-image.ts +454 -0
  1779. package/src/server/sse.ts +102 -0
  1780. package/src/server/ssr-handler.ts +466 -0
  1781. package/src/server/transcribe-voice.ts +1076 -0
  1782. package/src/server/voice-providers-status.ts +118 -0
  1783. package/src/server/workspace-oauth.ts +31 -0
  1784. package/src/server/workspace-provider-oauth.ts +970 -0
  1785. package/src/session-replay-iframe-protocol.ts +58 -0
  1786. package/src/settings/handlers.ts +44 -0
  1787. package/src/settings/index.ts +34 -0
  1788. package/src/settings/org-settings.ts +83 -0
  1789. package/src/settings/script-helpers.ts +24 -0
  1790. package/src/settings/store.ts +247 -0
  1791. package/src/settings/user-settings.ts +47 -0
  1792. package/src/setup-connections/index.ts +90 -0
  1793. package/src/setup-connections/onboarding.ts +47 -0
  1794. package/src/shared/agent-access.ts +112 -0
  1795. package/src/shared/agent-chat.ts +124 -0
  1796. package/src/shared/agent-env.ts +46 -0
  1797. package/src/shared/agent-readable-resource.ts +111 -0
  1798. package/src/shared/agent-sidebar-url.ts +39 -0
  1799. package/src/shared/cache-control.ts +25 -0
  1800. package/src/shared/cloudflare-globals.d.ts +34 -0
  1801. package/src/shared/context-xray.ts +172 -0
  1802. package/src/shared/embed-auth.ts +6 -0
  1803. package/src/shared/index.ts +83 -0
  1804. package/src/shared/llm-connection.ts +42 -0
  1805. package/src/shared/markdown-block-split.ts +129 -0
  1806. package/src/shared/mcp-connect-content.ts +130 -0
  1807. package/src/shared/mcp-embed-headers.ts +175 -0
  1808. package/src/shared/mcp-integration-config.ts +101 -0
  1809. package/src/shared/merge-by-id.ts +14 -0
  1810. package/src/shared/oauth-state.ts +39 -0
  1811. package/src/shared/reasoning-effort.ts +228 -0
  1812. package/src/shared/route-warmup-config.ts +128 -0
  1813. package/src/shared/runtime.ts +31 -0
  1814. package/src/shared/social-meta.ts +82 -0
  1815. package/src/shared/streaming-text-smoothing.ts +184 -0
  1816. package/src/shared/truncate.ts +13 -0
  1817. package/src/shared/workspace-app-audience.ts +177 -0
  1818. package/src/shared/workspace-app-id.ts +54 -0
  1819. package/src/sharing/access.ts +585 -0
  1820. package/src/sharing/actions/create-agent-resource-link.ts +91 -0
  1821. package/src/sharing/actions/extension-change.ts +22 -0
  1822. package/src/sharing/actions/list-resource-shares.ts +93 -0
  1823. package/src/sharing/actions/set-resource-visibility.ts +91 -0
  1824. package/src/sharing/actions/share-resource.ts +322 -0
  1825. package/src/sharing/actions/unshare-resource.ts +72 -0
  1826. package/src/sharing/index.ts +35 -0
  1827. package/src/sharing/registry.ts +201 -0
  1828. package/src/sharing/schema.ts +99 -0
  1829. package/src/styles/agent-conversation.css +766 -0
  1830. package/src/styles/agent-native.css +938 -0
  1831. package/src/styles/blocks.css +1717 -0
  1832. package/src/styles/chat-history-list.css +1 -0
  1833. package/src/styles/rich-markdown-editor.css +1 -0
  1834. package/src/tailwind.preset.ts +140 -0
  1835. package/src/templates/chat/.agents/skills/actions/SKILL.md +32 -12
  1836. package/src/templates/chat/.agents/skills/agent-native-docs/SKILL.md +21 -9
  1837. package/src/templates/chat/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  1838. package/src/templates/chat/.agents/skills/self-modifying-code/SKILL.md +14 -2
  1839. package/src/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  1840. package/src/templates/chat/AGENTS.md +6 -2
  1841. package/src/templates/chat/app/components/layout/Sidebar.tsx +51 -157
  1842. package/src/templates/default/.agents/skills/actions/SKILL.md +32 -12
  1843. package/src/templates/default/.agents/skills/agent-native-docs/SKILL.md +21 -9
  1844. package/src/templates/default/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  1845. package/src/templates/default/.agents/skills/integration-webhooks/SKILL.md +323 -0
  1846. package/src/templates/default/.agents/skills/onboarding/SKILL.md +56 -0
  1847. package/src/templates/default/.agents/skills/secrets/SKILL.md +273 -0
  1848. package/src/templates/default/.agents/skills/self-modifying-code/SKILL.md +14 -2
  1849. package/src/templates/default/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  1850. package/src/templates/default/AGENTS.md +26 -18
  1851. package/src/templates/headless/.agents/skills/actions/SKILL.md +512 -0
  1852. package/src/templates/headless/.agents/skills/agent-native-docs/SKILL.md +21 -9
  1853. package/src/templates/headless/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  1854. package/src/templates/headless/.agents/skills/integration-webhooks/SKILL.md +323 -0
  1855. package/src/templates/headless/.agents/skills/secrets/SKILL.md +273 -0
  1856. package/src/templates/headless/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  1857. package/src/templates/headless/AGENTS.md +8 -0
  1858. package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +32 -12
  1859. package/src/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +21 -9
  1860. package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +7 -0
  1861. package/src/templates/workspace-core/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  1862. package/src/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +14 -2
  1863. package/src/templates/workspace-core/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  1864. package/src/templates/workspace-core/AGENTS.md +4 -0
  1865. package/src/templates/workspace-root/AGENTS.md +4 -0
  1866. package/src/terminal/cli-registry.ts +57 -0
  1867. package/src/terminal/index.ts +22 -0
  1868. package/src/terminal/pty-server.ts +389 -0
  1869. package/src/terminal/terminal-plugin.ts +265 -0
  1870. package/src/testing.ts +23 -0
  1871. package/src/tracking/index.ts +10 -0
  1872. package/src/tracking/providers.ts +422 -0
  1873. package/src/tracking/registry.ts +102 -0
  1874. package/src/tracking/route.ts +108 -0
  1875. package/src/tracking/types.ts +16 -0
  1876. package/src/transcription/builder-transcription.ts +118 -0
  1877. package/src/triggers/actions/list-automations.ts +99 -0
  1878. package/src/triggers/actions/manage-automation.ts +78 -0
  1879. package/src/triggers/actions.ts +333 -0
  1880. package/src/triggers/condition-evaluator.ts +163 -0
  1881. package/src/triggers/dispatcher.ts +536 -0
  1882. package/src/triggers/index.ts +13 -0
  1883. package/src/triggers/routes.ts +322 -0
  1884. package/src/triggers/types.ts +42 -0
  1885. package/src/types/pglite.d.ts +26 -0
  1886. package/src/usage/store.ts +698 -0
  1887. package/src/vite/action-types-plugin.ts +481 -0
  1888. package/src/vite/agent-web-plugin.ts +78 -0
  1889. package/src/vite/agents-bundle-plugin.ts +185 -0
  1890. package/src/vite/client.ts +3039 -0
  1891. package/src/vite/index.ts +21 -0
  1892. package/src/voice/index.ts +18 -0
  1893. package/src/voice/voice-cleanup-prompt.ts +38 -0
  1894. package/src/voice/voice-context.ts +217 -0
  1895. package/src/voice/voice-replacements.ts +75 -0
  1896. package/src/workspace-connections/credentials.ts +603 -0
  1897. package/src/workspace-connections/index.ts +72 -0
  1898. package/src/workspace-connections/lifecycle.ts +43 -0
  1899. package/src/workspace-connections/store.ts +1943 -0
  1900. package/src/workspace-files/index.ts +18 -0
  1901. package/src/workspace-files/store.ts +339 -0
  1902. package/src/workspace-files/tool.ts +266 -0
@@ -0,0 +1,3935 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Post-build step for deploying agent-native apps to edge/serverless targets.
5
+ *
6
+ * When NITRO_PRESET is set, this script:
7
+ * 1. Takes the React Router build output (build/client/ + build/server/)
8
+ * 2. Generates a platform-specific server entry point
9
+ * 3. Bundles everything with esbuild into the target format
10
+ *
11
+ * Supported presets:
12
+ * - cloudflare_pages: Outputs dist/ with _worker.js for Cloudflare Pages
13
+ *
14
+ * Usage: node deploy/build.js (called automatically by `agent-native build`)
15
+ */
16
+
17
+ import { execFileSync } from "child_process";
18
+ import fs from "fs";
19
+ import { createRequire } from "module";
20
+ import path from "path";
21
+ import { fileURLToPath } from "url";
22
+
23
+ import {
24
+ AGENT_BACKGROUND_FUNCTION_NAME,
25
+ AGENT_BACKGROUND_PROCESSOR_A2A,
26
+ AGENT_BACKGROUND_PROCESSOR_FIELD,
27
+ AGENT_BACKGROUND_PROCESSOR_ROUTE,
28
+ AGENT_BACKGROUND_PROCESSOR_ROUTE_FIELD,
29
+ AGENT_CHAT_PROCESS_RUN_PATH,
30
+ } from "../agent/durable-background.js";
31
+ import { normalizeAppBasePath } from "../server/app-base-path.js";
32
+ import {
33
+ DEFAULT_SSR_CDN_CACHE_CONTROL,
34
+ DEFAULT_SSR_NETLIFY_CDN_CACHE_CONTROL,
35
+ DEFAULT_SPECULATION_RULES_PATH,
36
+ DEFAULT_SSR_CACHE_CONTROL,
37
+ } from "../shared/cache-control.js";
38
+ import { mcpEmbedStaticAssetRouteRules } from "../shared/mcp-embed-headers.js";
39
+ import {
40
+ AGENT_NATIVE_SOCIAL_IMAGE_ALT,
41
+ AGENT_NATIVE_SOCIAL_IMAGE_CACHE_BUSTER,
42
+ AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT,
43
+ AGENT_NATIVE_SOCIAL_IMAGE_PATH,
44
+ AGENT_NATIVE_SOCIAL_IMAGE_TYPE,
45
+ AGENT_NATIVE_SOCIAL_IMAGE_WIDTH,
46
+ } from "../shared/social-meta.js";
47
+ import { generateActionRegistryForProject } from "../vite/action-types-plugin.js";
48
+ import {
49
+ collectImmutableAssetPaths,
50
+ IMMUTABLE_ASSET_CACHE_CONTROL,
51
+ IMMUTABLE_ASSET_CACHE_HEADERS,
52
+ prefixAssetPath,
53
+ } from "./immutable-assets.js";
54
+ import {
55
+ discoverApiRoutes,
56
+ discoverPlugins,
57
+ discoverActionFiles,
58
+ getMissingDefaultPlugins,
59
+ DEFAULT_PLUGIN_REGISTRY,
60
+ type DiscoveredRoute,
61
+ type DiscoveredAction,
62
+ } from "./route-discovery.js";
63
+ import {
64
+ getWorkspaceCoreExports,
65
+ type WorkspaceCoreExports,
66
+ } from "./workspace-core.js";
67
+
68
+ const cwd = process.cwd();
69
+ const preset = process.env.NITRO_PRESET || "node";
70
+ export const NITRO_RUNTIME_IGNORE_PATTERNS = [
71
+ "**/*.spec.ts",
72
+ "**/*.spec.tsx",
73
+ "**/*.spec.mts",
74
+ "**/*.spec.cts",
75
+ "**/*.spec.js",
76
+ "**/*.spec.jsx",
77
+ "**/*.spec.mjs",
78
+ "**/*.spec.cjs",
79
+ "**/*.test.ts",
80
+ "**/*.test.tsx",
81
+ "**/*.test.mts",
82
+ "**/*.test.cts",
83
+ "**/*.test.js",
84
+ "**/*.test.jsx",
85
+ "**/*.test.mjs",
86
+ "**/*.test.cjs",
87
+ ];
88
+
89
+ export const CLOUDFLARE_WORKER_ESBUILD_EXTERNALS = [
90
+ "mermaid",
91
+ "@excalidraw/excalidraw",
92
+ "@excalidraw/mermaid-to-excalidraw",
93
+ "pdf-parse",
94
+ "pdfjs-dist",
95
+ "@google/genai",
96
+ "chartjs-node-canvas",
97
+ "@napi-rs/canvas",
98
+ "@anthropic-ai/tokenizer",
99
+ "@resvg/resvg-js",
100
+ "playwright",
101
+ "playwright-core",
102
+ "chromium-bidi",
103
+ "chromium-bidi/*",
104
+ "@sparticuz/chromium-min",
105
+ "fsevents",
106
+ ];
107
+ export const CLOUDFLARE_WORKER_STUB_MODULES: Record<string, string> = {
108
+ "better-sqlite3":
109
+ "export default {}; export const Database = class {}; export const watch = () => ({ close() {} });\n",
110
+ "node-pty":
111
+ "export default {}; export const watch = () => ({ close() {} });\n",
112
+ chokidar: "export default {}; export const watch = () => ({ close() {} });\n",
113
+ fsevents: "export default {}; export const watch = () => ({ close() {} });\n",
114
+ dotenv: "export default {}; export const config = () => ({ parsed: {} });\n",
115
+ "@anthropic-ai/sdk": "export default class Anthropic {}\n",
116
+ "@anthropic-ai/tokenizer":
117
+ "export default {}; export const countTokens = undefined;\n",
118
+ "@sentry/node": [
119
+ "export const init = () => {};",
120
+ "const scope = {",
121
+ " setUser() {},",
122
+ " setTag() {},",
123
+ " setExtra() {},",
124
+ " setContext() {},",
125
+ " setLevel() {},",
126
+ " getScopeData() { return {}; },",
127
+ "};",
128
+ "export const getIsolationScope = () => scope;",
129
+ "export const withScope = (fn) => fn(scope);",
130
+ "export const captureException = () => undefined;",
131
+ "export default { init, getIsolationScope, withScope, captureException };",
132
+ "",
133
+ ].join("\n"),
134
+ "@resvg/resvg-js": [
135
+ "export class Resvg {",
136
+ ' constructor() { throw new Error("@resvg/resvg-js unavailable in Cloudflare Pages worker"); }',
137
+ "}",
138
+ "export default { Resvg };",
139
+ "",
140
+ ].join("\n"),
141
+ playwright: [
142
+ "const unavailable = async () => { throw new Error('playwright unavailable in Cloudflare Pages worker'); };",
143
+ "export const chromium = { launch: unavailable, connect: unavailable, connectOverCDP: unavailable };",
144
+ "export const firefox = { launch: unavailable, connect: unavailable };",
145
+ "export const webkit = { launch: unavailable, connect: unavailable };",
146
+ "export default { chromium, firefox, webkit };",
147
+ "",
148
+ ].join("\n"),
149
+ "playwright-core": [
150
+ "const unavailable = async () => { throw new Error('playwright-core unavailable in Cloudflare Pages worker'); };",
151
+ "export const chromium = { launch: unavailable };",
152
+ "export const firefox = { launch: unavailable };",
153
+ "export const webkit = { launch: unavailable };",
154
+ "export default { chromium, firefox, webkit };",
155
+ "",
156
+ ].join("\n"),
157
+ "@sparticuz/chromium-min": [
158
+ "const chromium = {",
159
+ " args: [],",
160
+ " setGraphicsMode: false,",
161
+ " executablePath: async () => { throw new Error('@sparticuz/chromium-min unavailable in Cloudflare Pages worker'); },",
162
+ "};",
163
+ "export default chromium;",
164
+ "",
165
+ ].join("\n"),
166
+ "@google/genai": [
167
+ "export class GoogleGenAI {",
168
+ " constructor() { throw new Error('@google/genai unavailable in Cloudflare Pages worker'); }",
169
+ "}",
170
+ "export default { GoogleGenAI };",
171
+ "",
172
+ ].join("\n"),
173
+ "pdf-parse": [
174
+ "export class PDFParse {",
175
+ " constructor() { throw new Error('pdf-parse unavailable in Cloudflare Pages worker'); }",
176
+ "}",
177
+ "export default { PDFParse };",
178
+ "",
179
+ ].join("\n"),
180
+ "pdfjs-dist":
181
+ "export default {}; export const getDocument = () => { throw new Error('pdfjs-dist unavailable in Cloudflare Pages worker'); };\n",
182
+ "chartjs-node-canvas": [
183
+ "export class ChartJSNodeCanvas {",
184
+ " constructor() { throw new Error('chartjs-node-canvas unavailable in Cloudflare Pages worker'); }",
185
+ "}",
186
+ "export default { ChartJSNodeCanvas };",
187
+ "",
188
+ ].join("\n"),
189
+ "@napi-rs/canvas":
190
+ "export default {}; export const createCanvas = () => { throw new Error('@napi-rs/canvas unavailable in Cloudflare Pages worker'); };\n",
191
+ mermaid: "export default {}; export const mermaidAPI = {};\n",
192
+ "@excalidraw/excalidraw":
193
+ "export default {}; export const MainMenu = {}; export const WelcomeScreen = {};\n",
194
+ "@excalidraw/mermaid-to-excalidraw":
195
+ "export default async () => ({ elements: [], files: {} });\n",
196
+ };
197
+
198
+ export const CLOUDFLARE_WORKER_STUB_SUBPATH_MODULES: Record<string, string> = {
199
+ "pdf-parse/worker": [
200
+ "const unavailable = async () => { throw new Error('pdf-parse/worker unavailable in Cloudflare Pages worker'); };",
201
+ "export class CanvasFactory {}",
202
+ "export const getData = unavailable;",
203
+ "export default { CanvasFactory, getData };",
204
+ "",
205
+ ].join("\n"),
206
+ };
207
+
208
+ export function cloudflareWorkerStubAliasArgs(stubDir: string): string[] {
209
+ const subpathAliases = Object.keys(CLOUDFLARE_WORKER_STUB_SUBPATH_MODULES)
210
+ .sort((a, b) => b.length - a.length)
211
+ .map(
212
+ (mod) =>
213
+ `--alias:${mod}=${path.join(stubDir, `${mod.replace(/\//g, "__")}.js`)}`,
214
+ );
215
+ const packageAliases = Object.keys(CLOUDFLARE_WORKER_STUB_MODULES)
216
+ .sort((a, b) => b.length - a.length)
217
+ .map((mod) => `--alias:${mod}=${path.join(stubDir, mod, "index.js")}`);
218
+ return [...subpathAliases, ...packageAliases];
219
+ }
220
+
221
+ export function assertNoCloudflareWorkerStubDynamicImports(
222
+ code: string,
223
+ sourceName: string,
224
+ ): void {
225
+ const stubbedModules = [
226
+ ...Object.keys(CLOUDFLARE_WORKER_STUB_SUBPATH_MODULES),
227
+ ...Object.keys(CLOUDFLARE_WORKER_STUB_MODULES),
228
+ ];
229
+ const pattern = stubbedModules
230
+ .sort((a, b) => b.length - a.length)
231
+ .map((moduleName) => moduleName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))
232
+ .join("|");
233
+ const unresolvedImport = code.match(
234
+ new RegExp(`\\bimport\\s*\\(\\s*(["'])(${pattern})\\1\\s*\\)`),
235
+ );
236
+ if (!unresolvedImport) return;
237
+ throw new Error(
238
+ `Cloudflare worker output ${sourceName} retained a dynamic import for stubbed module "${unresolvedImport[2]}". Use a literal import so the worker bundler can apply its fail-closed stub.`,
239
+ );
240
+ }
241
+
242
+ function cloudflareNodeBuiltinStubSource(
243
+ moduleName: string,
244
+ namedExports: string[],
245
+ overrides: string[] = [],
246
+ ): string {
247
+ const overridden = new Set(
248
+ overrides.flatMap((source) =>
249
+ Array.from(source.matchAll(/\bexport const ([A-Za-z_$][\w$]*)/g)).map(
250
+ (match) => match[1],
251
+ ),
252
+ ),
253
+ );
254
+ const exports = Array.from(new Set(namedExports))
255
+ .filter((name) => !overridden.has(name))
256
+ .sort();
257
+ return [
258
+ `const unavailable = (name) => (..._args) => { throw new Error(name + " is unavailable in Cloudflare Pages workers"); };`,
259
+ `const proxy = new Proxy({}, { get(_target, prop) { return unavailable("${moduleName}." + String(prop)); } });`,
260
+ ...overrides,
261
+ ...exports.map(
262
+ (name) => `export const ${name} = unavailable("${moduleName}.${name}");`,
263
+ ),
264
+ "export default proxy;",
265
+ "",
266
+ ].join("\n");
267
+ }
268
+
269
+ export const CLOUDFLARE_WORKER_NODE_BUILTIN_STUB_MODULES: Record<
270
+ string,
271
+ string
272
+ > = {
273
+ child_process: cloudflareNodeBuiltinStubSource("child_process", [
274
+ "exec",
275
+ "execFile",
276
+ "execFileSync",
277
+ "execSync",
278
+ "fork",
279
+ "spawn",
280
+ "spawnSync",
281
+ ]),
282
+ cluster: cloudflareNodeBuiltinStubSource("cluster", [
283
+ "disconnect",
284
+ "fork",
285
+ "isMaster",
286
+ "isPrimary",
287
+ "isWorker",
288
+ "setupMaster",
289
+ "setupPrimary",
290
+ "worker",
291
+ "workers",
292
+ ]),
293
+ console: [
294
+ "const globalConsole = globalThis.console;",
295
+ "const bind = (name) => typeof globalConsole?.[name] === 'function' ? globalConsole[name].bind(globalConsole) : () => undefined;",
296
+ "export class Console {",
297
+ " constructor() { return globalConsole; }",
298
+ "}",
299
+ "export const assert = bind('assert');",
300
+ "export const clear = bind('clear');",
301
+ "export const count = bind('count');",
302
+ "export const countReset = bind('countReset');",
303
+ "export const debug = bind('debug');",
304
+ "export const dir = bind('dir');",
305
+ "export const dirxml = bind('dirxml');",
306
+ "export const error = bind('error');",
307
+ "export const group = bind('group');",
308
+ "export const groupCollapsed = bind('groupCollapsed');",
309
+ "export const groupEnd = bind('groupEnd');",
310
+ "export const info = bind('info');",
311
+ "export const log = bind('log');",
312
+ "export const profile = bind('profile');",
313
+ "export const profileEnd = bind('profileEnd');",
314
+ "export const table = bind('table');",
315
+ "export const time = bind('time');",
316
+ "export const timeEnd = bind('timeEnd');",
317
+ "export const timeLog = bind('timeLog');",
318
+ "export const timeStamp = bind('timeStamp');",
319
+ "export const trace = bind('trace');",
320
+ "export const warn = bind('warn');",
321
+ "export { globalConsole as console };",
322
+ "export default globalConsole;",
323
+ "",
324
+ ].join("\n"),
325
+ dgram: cloudflareNodeBuiltinStubSource("dgram", ["createSocket"]),
326
+ dns: cloudflareNodeBuiltinStubSource("dns", [
327
+ "lookup",
328
+ "promises",
329
+ "resolve",
330
+ "resolve4",
331
+ "resolve6",
332
+ ]),
333
+ "dns/promises": cloudflareNodeBuiltinStubSource("dns/promises", [
334
+ "lookup",
335
+ "resolve",
336
+ "resolve4",
337
+ "resolve6",
338
+ ]),
339
+ domain: cloudflareNodeBuiltinStubSource("domain", ["create"]),
340
+ fs: cloudflareNodeBuiltinStubSource(
341
+ "fs",
342
+ [
343
+ "access",
344
+ "accessSync",
345
+ "appendFile",
346
+ "appendFileSync",
347
+ "chmod",
348
+ "chmodSync",
349
+ "close",
350
+ "closeSync",
351
+ "copyFile",
352
+ "copyFileSync",
353
+ "cp",
354
+ "cpSync",
355
+ "createReadStream",
356
+ "createWriteStream",
357
+ "existsSync",
358
+ "lstat",
359
+ "lstatSync",
360
+ "mkdir",
361
+ "mkdirSync",
362
+ "open",
363
+ "openSync",
364
+ "readFile",
365
+ "readFileSync",
366
+ "readdir",
367
+ "readdirSync",
368
+ "readlink",
369
+ "readlinkSync",
370
+ "realpath",
371
+ "realpathSync",
372
+ "rename",
373
+ "renameSync",
374
+ "rm",
375
+ "rmSync",
376
+ "stat",
377
+ "statSync",
378
+ "symlink",
379
+ "symlinkSync",
380
+ "unlink",
381
+ "unlinkSync",
382
+ "watch",
383
+ "writeFile",
384
+ "writeFileSync",
385
+ ],
386
+ [
387
+ "export const constants = {};",
388
+ "export const promises = {};",
389
+ "export const existsSync = () => false;",
390
+ "export const readdirSync = () => [];",
391
+ "export const realpathSync = (value) => value;",
392
+ "export const mkdirSync = () => undefined;",
393
+ "export const rmSync = () => undefined;",
394
+ ],
395
+ ),
396
+ "fs/promises": cloudflareNodeBuiltinStubSource("fs/promises", [
397
+ "access",
398
+ "appendFile",
399
+ "chmod",
400
+ "copyFile",
401
+ "cp",
402
+ "lstat",
403
+ "mkdtemp",
404
+ "mkdir",
405
+ "readFile",
406
+ "readdir",
407
+ "readlink",
408
+ "realpath",
409
+ "rename",
410
+ "rm",
411
+ "stat",
412
+ "symlink",
413
+ "unlink",
414
+ "writeFile",
415
+ ]),
416
+ http: cloudflareNodeBuiltinStubSource("http", [
417
+ "Agent",
418
+ "ClientRequest",
419
+ "IncomingMessage",
420
+ "ServerResponse",
421
+ "createServer",
422
+ "get",
423
+ "request",
424
+ ]),
425
+ http2: cloudflareNodeBuiltinStubSource("http2", [
426
+ "Http2ServerRequest",
427
+ "Http2ServerResponse",
428
+ "constants",
429
+ "connect",
430
+ "createSecureServer",
431
+ "createServer",
432
+ ]),
433
+ https: cloudflareNodeBuiltinStubSource("https", [
434
+ "Agent",
435
+ "createServer",
436
+ "get",
437
+ "request",
438
+ ]),
439
+ inspector: cloudflareNodeBuiltinStubSource("inspector", [
440
+ "Session",
441
+ "close",
442
+ "open",
443
+ "url",
444
+ "waitForDebugger",
445
+ ]),
446
+ module: cloudflareNodeBuiltinStubSource(
447
+ "module",
448
+ ["Module", "builtinModules", "createRequire", "syncBuiltinESMExports"],
449
+ [
450
+ "export const builtinModules = [];",
451
+ "export const createRequire = () => globalThis.require ?? ((specifier) => { throw new Error('Cannot require: ' + specifier); });",
452
+ ],
453
+ ),
454
+ net: cloudflareNodeBuiltinStubSource(
455
+ "net",
456
+ ["Socket", "connect", "createConnection", "createServer", "isIP"],
457
+ [
458
+ `export const isIP = (value) => {
459
+ const input = String(value ?? "");
460
+ const ipv4Parts = input.split(".");
461
+ if (
462
+ ipv4Parts.length === 4 &&
463
+ ipv4Parts.every((part) => /^\\d{1,3}$/.test(part) && Number(part) >= 0 && Number(part) <= 255)
464
+ ) {
465
+ return 4;
466
+ }
467
+ if (input.includes(":") && /^[0-9A-Fa-f:.]+$/.test(input)) {
468
+ return 6;
469
+ }
470
+ return 0;
471
+ };`,
472
+ ],
473
+ ),
474
+ os: cloudflareNodeBuiltinStubSource(
475
+ "os",
476
+ [
477
+ "arch",
478
+ "cpus",
479
+ "endianness",
480
+ "freemem",
481
+ "homedir",
482
+ "hostname",
483
+ "networkInterfaces",
484
+ "platform",
485
+ "release",
486
+ "tmpdir",
487
+ "totalmem",
488
+ "type",
489
+ "userInfo",
490
+ ],
491
+ [
492
+ 'export const EOL = "\\n";',
493
+ 'export const arch = () => "x64";',
494
+ "export const cpus = () => [];",
495
+ 'export const endianness = () => "LE";',
496
+ "export const freemem = () => 0;",
497
+ 'export const homedir = () => "/tmp";',
498
+ 'export const hostname = () => "cloudflare-worker";',
499
+ "export const networkInterfaces = () => ({});",
500
+ 'export const platform = () => "linux";',
501
+ 'export const release = () => "";',
502
+ 'export const tmpdir = () => "/tmp";',
503
+ "export const totalmem = () => 0;",
504
+ 'export const type = () => "Worker";',
505
+ "export const userInfo = () => ({ username: 'worker', homedir: '/tmp' });",
506
+ ],
507
+ ),
508
+ readline: cloudflareNodeBuiltinStubSource("readline", [
509
+ "Interface",
510
+ "clearLine",
511
+ "clearScreenDown",
512
+ "createInterface",
513
+ "cursorTo",
514
+ "emitKeypressEvents",
515
+ "moveCursor",
516
+ ]),
517
+ repl: cloudflareNodeBuiltinStubSource("repl", ["start"]),
518
+ sqlite: cloudflareNodeBuiltinStubSource("sqlite", ["DatabaseSync"]),
519
+ sys: cloudflareNodeBuiltinStubSource("sys", [
520
+ "debug",
521
+ "deprecate",
522
+ "error",
523
+ "inspect",
524
+ "log",
525
+ "print",
526
+ "puts",
527
+ ]),
528
+ tls: cloudflareNodeBuiltinStubSource("tls", [
529
+ "TLSSocket",
530
+ "connect",
531
+ "createSecureContext",
532
+ "createServer",
533
+ ]),
534
+ trace_events: cloudflareNodeBuiltinStubSource("trace_events", [
535
+ "createTracing",
536
+ "getEnabledCategories",
537
+ ]),
538
+ tty: cloudflareNodeBuiltinStubSource("tty", [
539
+ "ReadStream",
540
+ "WriteStream",
541
+ "isatty",
542
+ ]),
543
+ v8: cloudflareNodeBuiltinStubSource("v8", [
544
+ "deserialize",
545
+ "getHeapStatistics",
546
+ "serialize",
547
+ ]),
548
+ vm: cloudflareNodeBuiltinStubSource("vm", [
549
+ "Script",
550
+ "compileFunction",
551
+ "createContext",
552
+ "runInContext",
553
+ "runInNewContext",
554
+ "runInThisContext",
555
+ ]),
556
+ wasi: cloudflareNodeBuiltinStubSource("wasi", ["WASI"]),
557
+ worker_threads: cloudflareNodeBuiltinStubSource(
558
+ "worker_threads",
559
+ ["MessageChannel", "MessagePort", "Worker", "isMainThread", "parentPort"],
560
+ ["export const isMainThread = true;", "export const parentPort = null;"],
561
+ ),
562
+ };
563
+
564
+ export interface GenerateWorkerEntryOptions {
565
+ includeReactRouterSsr?: boolean;
566
+ }
567
+
568
+ interface ReactRouterAssetManifest {
569
+ entry: ReactRouterAssetManifestEntry;
570
+ routes: Record<string, ReactRouterAssetManifestRoute>;
571
+ url: string;
572
+ }
573
+
574
+ interface ReactRouterAssetManifestEntry {
575
+ module: string;
576
+ imports?: string[];
577
+ css?: string[];
578
+ }
579
+
580
+ interface ReactRouterAssetManifestRoute {
581
+ id: string;
582
+ module: string;
583
+ imports?: string[];
584
+ css?: string[];
585
+ hasLoader?: boolean;
586
+ clientActionModule?: string;
587
+ clientLoaderModule?: string;
588
+ clientMiddlewareModule?: string;
589
+ hydrateFallbackModule?: string;
590
+ }
591
+
592
+ function normalizeConfiguredAppBasePath(): string {
593
+ return normalizeAppBasePath(
594
+ process.env.VITE_APP_BASE_PATH || process.env.APP_BASE_PATH,
595
+ );
596
+ }
597
+
598
+ /** Plugins that require Node.js runtime and cannot run on edge/serverless */
599
+ const NODE_ONLY_PLUGINS = new Set([
600
+ "terminal", // PTY requires child_process
601
+ // @sentry/node ships node:fs / node:async_hooks bindings that don't load
602
+ // on workerd / Cloudflare Workers. Templates running on edge presets can
603
+ // mount their own edge-compatible Sentry wrapper if they want server
604
+ // observability there; the framework default is the Node SDK.
605
+ "sentry",
606
+ ]);
607
+ const EDGE_SERVER_ENTRYPOINT = "@agent-native/core/server/edge";
608
+
609
+ function isNodeOnlyPlugin(filePath: string): boolean {
610
+ const basename = path.basename(filePath, path.extname(filePath));
611
+ return NODE_ONLY_PLUGINS.has(basename);
612
+ }
613
+
614
+ export function generateProvidedPluginsNitroPluginSource(
615
+ pluginStems: string[],
616
+ ): string {
617
+ const stems = [...new Set(pluginStems.filter(Boolean))].sort();
618
+ return `// AUTO-GENERATED by @agent-native/core deploy build
619
+ import { markDefaultPluginProvided } from "${EDGE_SERVER_ENTRYPOINT}";
620
+
621
+ const pluginStems = ${JSON.stringify(stems)};
622
+
623
+ export default function markBuildDiscoveredPlugins(nitroApp) {
624
+ for (const stem of pluginStems) {
625
+ markDefaultPluginProvided(nitroApp, stem);
626
+ }
627
+ }
628
+ `;
629
+ }
630
+
631
+ async function writeProvidedPluginsNitroPlugin(): Promise<string | null> {
632
+ const plugins = await discoverPlugins(cwd);
633
+ const stems = plugins.map((plugin) =>
634
+ path.basename(plugin, path.extname(plugin)),
635
+ );
636
+ if (stems.length === 0) return null;
637
+
638
+ const tmpDir = path.join(cwd, ".deploy-tmp");
639
+ fs.mkdirSync(tmpDir, { recursive: true });
640
+ const pluginPath = path.join(tmpDir, "agent-native-provided-plugins.mjs");
641
+ fs.writeFileSync(pluginPath, generateProvidedPluginsNitroPluginSource(stems));
642
+ return pluginPath;
643
+ }
644
+
645
+ type RouteRules = Record<string, { headers?: Record<string, string> }>;
646
+
647
+ function addImmutableAssetRouteRule(
648
+ routeRules: RouteRules,
649
+ pathname: string,
650
+ ): void {
651
+ const existing = routeRules[pathname] ?? {};
652
+ routeRules[pathname] = {
653
+ ...existing,
654
+ headers: {
655
+ ...(existing.headers ?? {}),
656
+ ...IMMUTABLE_ASSET_CACHE_HEADERS,
657
+ },
658
+ };
659
+ }
660
+
661
+ export function addImmutableAssetRouteRulesForClientBuild(
662
+ routeRules: RouteRules,
663
+ clientDir: string,
664
+ appBasePath = "",
665
+ ): void {
666
+ for (const assetPath of collectImmutableAssetPaths(clientDir)) {
667
+ addImmutableAssetRouteRule(routeRules, assetPath);
668
+ const mountedPath = prefixAssetPath(assetPath, appBasePath);
669
+ if (mountedPath !== assetPath) {
670
+ addImmutableAssetRouteRule(routeRules, mountedPath);
671
+ }
672
+ }
673
+ }
674
+
675
+ /**
676
+ * Generate the worker entry source code that wires up H3 + React Router SSR.
677
+ *
678
+ * If a workspace core is present (monorepo with `agent-native.workspaceCore`
679
+ * configured and the named package resolves), any plugin slot that the
680
+ * workspace core exports is imported from there instead of from
681
+ * `@agent-native/core/server/edge`. This is the middle layer of the three-layer
682
+ * inheritance model: app local > workspace core > framework default.
683
+ */
684
+ export function generateWorkerEntry(
685
+ routes: DiscoveredRoute[],
686
+ pluginPaths: string[],
687
+ defaultPluginStems: string[] = [],
688
+ actions: DiscoveredAction[] = [],
689
+ workspaceCore: WorkspaceCoreExports | null = null,
690
+ immutableAssetPaths: string[] = [],
691
+ builtAppBasePath = normalizeConfiguredAppBasePath(),
692
+ options: GenerateWorkerEntryOptions = {},
693
+ ): string {
694
+ const includeReactRouterSsr = options.includeReactRouterSsr ?? true;
695
+ const routeImports: string[] = [];
696
+ const routeRegistrations: string[] = [];
697
+
698
+ for (let i = 0; i < routes.length; i++) {
699
+ const r = routes[i];
700
+ const varName = `route_${i}`;
701
+ routeImports.push(`import ${varName} from ${JSON.stringify(r.absPath)};`);
702
+ routeRegistrations.push(
703
+ ` app.on(${JSON.stringify(r.method.toUpperCase())}, ${JSON.stringify(r.route)}, ${varName});`,
704
+ );
705
+ if (r.method.toLowerCase() === "get") {
706
+ routeRegistrations.push(
707
+ ` app.on("HEAD", ${JSON.stringify(r.route)}, defineEventHandler(async (event) => {
708
+ const originalReq = event.req;
709
+ event.req = requestWithMethod(event.req, "GET");
710
+ try {
711
+ const result = await ${varName}(event);
712
+ const response = result instanceof Response ? result : toResponse(result, event);
713
+ return new Response(null, {
714
+ status: response.status,
715
+ statusText: response.statusText,
716
+ headers: response.headers,
717
+ });
718
+ } finally {
719
+ event.req = originalReq;
720
+ }
721
+ }));`,
722
+ );
723
+ }
724
+ }
725
+
726
+ // Action route imports and registrations
727
+ const actionImports: string[] = [];
728
+ const actionRegistrations: string[] = [];
729
+ for (let i = 0; i < actions.length; i++) {
730
+ const a = actions[i];
731
+ const varName = `action_${i}`;
732
+ actionImports.push(`import ${varName} from ${JSON.stringify(a.absPath)};`);
733
+ // Mirror the runtime mount (action-routes.ts): `path = http?.path ?? name`.
734
+ const routePath = `/_agent-native/actions/${a.path ?? a.name}`;
735
+ actionRegistrations.push(
736
+ ` app.on(${JSON.stringify(a.method.toUpperCase())}, ${JSON.stringify(routePath)}, defineEventHandler(async (event) => {
737
+ const params = ${a.method === "get" ? "parseActionSearchParams(event.url.searchParams)" : "(await readBody(event)) ?? {}"};
738
+ try {
739
+ const result = await ${varName}.run(params, { caller: "http" });
740
+ if (typeof result === "string") { try { return JSON.parse(result); } catch { return result; } }
741
+ return result;
742
+ } catch (err) {
743
+ return new Response(JSON.stringify({ error: err?.message || "Action failed" }), { status: err?.message?.startsWith("Invalid action parameters") ? 400 : 500, headers: { "Content-Type": "application/json" } });
744
+ }
745
+ }));`,
746
+ );
747
+ }
748
+
749
+ // Filter out Node-only plugins
750
+ const edgePlugins = pluginPaths.filter((p) => !isNodeOnlyPlugin(p));
751
+ const pluginImports: string[] = [];
752
+ const pluginCalls: string[] = [];
753
+ const providedPluginStems = new Set<string>();
754
+
755
+ for (let i = 0; i < edgePlugins.length; i++) {
756
+ const varName = `plugin_${i}`;
757
+ providedPluginStems.add(
758
+ path.basename(edgePlugins[i], path.extname(edgePlugins[i])),
759
+ );
760
+ pluginImports.push(
761
+ `import ${varName} from ${JSON.stringify(edgePlugins[i])};`,
762
+ );
763
+ pluginCalls.push(` if (typeof ${varName} === "function") {
764
+ await ${varName}(nitroApp);
765
+ }`);
766
+ }
767
+ // Auto-mounted default plugins (for slots the template doesn't override
768
+ // locally). For each slot, prefer a workspace-core export over the
769
+ // @agent-native/core default, if the workspace core provides one.
770
+ const edgeDefaultStems = defaultPluginStems.filter(
771
+ (stem) => !NODE_ONLY_PLUGINS.has(stem),
772
+ );
773
+ for (let i = 0; i < edgeDefaultStems.length; i++) {
774
+ const stem = edgeDefaultStems[i];
775
+ providedPluginStems.add(stem);
776
+ const varName = `defaultPlugin_${i}`;
777
+
778
+ const workspaceExportName = workspaceCore?.plugins?.[stem as never];
779
+ if (workspaceCore && workspaceExportName) {
780
+ // Workspace-core layer wins over the framework default.
781
+ pluginImports.push(
782
+ `import { ${workspaceExportName} as ${varName} } from ${JSON.stringify(
783
+ `${workspaceCore.packageName}/server`,
784
+ )};`,
785
+ );
786
+ } else {
787
+ // Fall back to the framework default from the edge-safe core entrypoint.
788
+ const defaultExportName = DEFAULT_PLUGIN_REGISTRY[stem];
789
+ if (!defaultExportName) continue;
790
+ pluginImports.push(
791
+ `import { ${defaultExportName} as ${varName} } from "${EDGE_SERVER_ENTRYPOINT}";`,
792
+ );
793
+ }
794
+ pluginCalls.push(` if (typeof ${varName} === "function") {
795
+ await ${varName}(nitroApp);
796
+ }`);
797
+ }
798
+ const generatedPluginMarks =
799
+ providedPluginStems.size > 0
800
+ ? [
801
+ ...new Set([
802
+ ...Object.keys(DEFAULT_PLUGIN_REGISTRY),
803
+ ...providedPluginStems,
804
+ ]),
805
+ ]
806
+ : [];
807
+ if (generatedPluginMarks.length > 0) {
808
+ pluginImports.unshift(
809
+ `import { markDefaultPluginProvided as markGeneratedPluginProvided } from "${EDGE_SERVER_ENTRYPOINT}";`,
810
+ );
811
+ }
812
+
813
+ return `
814
+ // Auto-generated worker entry point for ${preset}
815
+ import { H3, defineEventHandler, readBody, toResponse } from "h3";
816
+ ${includeReactRouterSsr ? 'import { createRequestHandler } from "react-router";' : ""}
817
+ ${includeReactRouterSsr ? 'import * as serverBuild from "./server-build.js";' : ""}
818
+ ${includeReactRouterSsr ? `import { runWithRequestContext } from "${EDGE_SERVER_ENTRYPOINT}";` : ""}
819
+
820
+ function normalizeAppBasePath(value) {
821
+ if (!value || value === "/") return "";
822
+ const trimmed = String(value).trim();
823
+ if (!trimmed || trimmed === "/") return "";
824
+ return "/" + trimmed.replace(/^\\/+/, "").replace(/\\/+$/, "");
825
+ }
826
+
827
+ function getAppBasePath() {
828
+ const builtAppBasePath = ${JSON.stringify(builtAppBasePath)};
829
+ return normalizeAppBasePath(
830
+ globalThis.process?.env?.VITE_APP_BASE_PATH ||
831
+ globalThis.process?.env?.APP_BASE_PATH ||
832
+ builtAppBasePath,
833
+ );
834
+ }
835
+
836
+ function stripAppBasePath(pathname) {
837
+ const basePath = getAppBasePath();
838
+ if (!basePath) return pathname;
839
+ if (pathname === basePath) return "/";
840
+ if (pathname.startsWith(basePath + "/")) {
841
+ return pathname.slice(basePath.length) || "/";
842
+ }
843
+ return pathname;
844
+ }
845
+
846
+ function parseActionSearchParams(searchParams) {
847
+ const params = {};
848
+ for (const [rawKey, value] of searchParams.entries()) {
849
+ const isArrayKey = rawKey.endsWith("[]");
850
+ // The core client serializes arrays as key[]=value so one-item arrays
851
+ // survive GET action parsing in generated worker deployments.
852
+ const key = isArrayKey ? rawKey.slice(0, -2) : rawKey;
853
+ const current = params[key];
854
+ if (current === undefined) {
855
+ params[key] = isArrayKey ? [value] : value;
856
+ } else if (Array.isArray(current)) {
857
+ current.push(value);
858
+ } else {
859
+ params[key] = [current, value];
860
+ }
861
+ }
862
+ return params;
863
+ }
864
+
865
+ function isApiPath(pathname) {
866
+ return pathname === "/api" || pathname.startsWith("/api/");
867
+ }
868
+
869
+ function isFrameworkPath(pathname) {
870
+ return (
871
+ pathname === "/_agent-native" || pathname.startsWith("/_agent-native/")
872
+ );
873
+ }
874
+
875
+ function requestWithMountedApiPrefixStripped(request) {
876
+ const basePath = getAppBasePath();
877
+ if (!basePath) return request;
878
+ const url = new URL(request.url);
879
+ const strippedPathname = stripAppBasePath(url.pathname);
880
+ if (strippedPathname === url.pathname) {
881
+ return request;
882
+ }
883
+ if (!isApiPath(strippedPathname) && !isFrameworkPath(strippedPathname)) {
884
+ return request;
885
+ }
886
+ url.pathname = strippedPathname;
887
+ return new Request(url, request);
888
+ }
889
+
890
+ function prefixMountedPath(path, basePath) {
891
+ if (!basePath || !path.startsWith("/") || path.startsWith("//")) return path;
892
+ if (path === basePath || path.startsWith(basePath + "/")) return path;
893
+ return basePath + path;
894
+ }
895
+
896
+ function prefixMountedHtml(html, basePath) {
897
+ if (!basePath) return html;
898
+ return html
899
+ .replace(
900
+ /\\b(href|src|action|formaction|poster)=(["'])(\\/(?!\\/)[^"']*)\\2/g,
901
+ (_match, attr, quote, path) =>
902
+ attr + "=" + quote + prefixMountedPath(path, basePath) + quote,
903
+ )
904
+ .replace(/url\\((["']?)(\\/(?!\\/)[^)'" ]+)\\1\\)/g, (_match, quote, path) => {
905
+ const q = quote || "";
906
+ return "url(" + q + prefixMountedPath(path, basePath) + q + ")";
907
+ });
908
+ }
909
+
910
+ function firstNonEmpty() {
911
+ for (const value of arguments) {
912
+ const trimmed = typeof value === "string" ? value.trim() : "";
913
+ if (trimmed) return trimmed;
914
+ }
915
+ }
916
+
917
+ function getSentryClientConfigScript() {
918
+ const env = globalThis.process?.env || {};
919
+ const key = firstNonEmpty(env.SENTRY_CLIENT_KEY, env.VITE_SENTRY_CLIENT_KEY);
920
+ const projectId = firstNonEmpty(
921
+ env.SENTRY_PROJECT_ID,
922
+ env.VITE_SENTRY_PROJECT_ID,
923
+ );
924
+ const host = firstNonEmpty(
925
+ env.SENTRY_INGEST_HOST,
926
+ env.VITE_SENTRY_INGEST_HOST,
927
+ );
928
+ const dsn =
929
+ firstNonEmpty(
930
+ env.SENTRY_CLIENT_DSN,
931
+ env.VITE_SENTRY_CLIENT_DSN,
932
+ env.VITE_SENTRY_DSN,
933
+ env.SENTRY_DSN,
934
+ ) || (key && projectId && host ? "https://" + key + "@" + host + "/" + projectId : undefined);
935
+ if (!dsn) return null;
936
+ const config = {
937
+ sentryDsn: dsn,
938
+ sentryEnvironment:
939
+ firstNonEmpty(
940
+ env.SENTRY_ENVIRONMENT,
941
+ env.NETLIFY_CONTEXT,
942
+ env.VERCEL_ENV,
943
+ env.NODE_ENV,
944
+ ) || "production",
945
+ };
946
+ return (
947
+ '<script data-agent-native-sentry-config>' +
948
+ 'window.__AGENT_NATIVE_CONFIG__=Object.assign({},window.__AGENT_NATIVE_CONFIG__,' +
949
+ JSON.stringify(config) +
950
+ ");</script>"
951
+ );
952
+ }
953
+
954
+ function injectHeadScript(html, script) {
955
+ if (!script) return html;
956
+ const headCloseIdx = html.indexOf("</head>");
957
+ if (headCloseIdx === -1) return html;
958
+ return html.slice(0, headCloseIdx) + script + html.slice(headCloseIdx);
959
+ }
960
+
961
+ const DEFAULT_SSR_CACHE_CONTROL = ${JSON.stringify(DEFAULT_SSR_CACHE_CONTROL)};
962
+ const DEFAULT_SSR_CDN_CACHE_CONTROL = ${JSON.stringify(DEFAULT_SSR_CDN_CACHE_CONTROL)};
963
+ const DEFAULT_SSR_NETLIFY_CDN_CACHE_CONTROL = ${JSON.stringify(DEFAULT_SSR_NETLIFY_CDN_CACHE_CONTROL)};
964
+ const DEFAULT_SPECULATION_RULES_PATH = ${JSON.stringify(DEFAULT_SPECULATION_RULES_PATH)};
965
+ const IMMUTABLE_ASSET_CACHE_CONTROL = ${JSON.stringify(IMMUTABLE_ASSET_CACHE_CONTROL)};
966
+ const IMMUTABLE_ASSET_PATHS = new Set(${JSON.stringify(
967
+ [...new Set(immutableAssetPaths)].sort(),
968
+ )});
969
+ const AGENT_NATIVE_SOCIAL_IMAGE_PATH = ${JSON.stringify(
970
+ AGENT_NATIVE_SOCIAL_IMAGE_PATH,
971
+ )};
972
+ const AGENT_NATIVE_SOCIAL_IMAGE_CACHE_BUSTER = ${JSON.stringify(
973
+ AGENT_NATIVE_SOCIAL_IMAGE_CACHE_BUSTER,
974
+ )};
975
+ const AGENT_NATIVE_SOCIAL_IMAGE_ALT = ${JSON.stringify(
976
+ AGENT_NATIVE_SOCIAL_IMAGE_ALT,
977
+ )};
978
+ const AGENT_NATIVE_SOCIAL_IMAGE_TYPE = ${JSON.stringify(
979
+ AGENT_NATIVE_SOCIAL_IMAGE_TYPE,
980
+ )};
981
+ const AGENT_NATIVE_SOCIAL_IMAGE_WIDTH = ${JSON.stringify(
982
+ AGENT_NATIVE_SOCIAL_IMAGE_WIDTH,
983
+ )};
984
+ const AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT = ${JSON.stringify(
985
+ AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT,
986
+ )};
987
+ const OG_IMAGE_META_RE = /<meta\\b(?=[^>]*\\bproperty=(["'])og:image\\1)[^>]*>/i;
988
+ const TWITTER_CARD_META_RE = /<meta\\b(?=[^>]*\\bname=(["'])twitter:card\\1)[^>]*>/i;
989
+ const TWITTER_IMAGE_META_RE = /<meta\\b(?=[^>]*\\bname=(["'])twitter:image\\1)[^>]*>/i;
990
+
991
+ function withAgentNativeSocialImageCacheBuster(image) {
992
+ const separator = image.includes("?") ? "&" : "?";
993
+ return image + separator + "v=" + encodeURIComponent(AGENT_NATIVE_SOCIAL_IMAGE_CACHE_BUSTER);
994
+ }
995
+
996
+ function defaultSocialImageUrl(request, basePath) {
997
+ return withAgentNativeSocialImageCacheBuster(
998
+ new URL(prefixMountedPath(AGENT_NATIVE_SOCIAL_IMAGE_PATH, basePath), request.url).toString()
999
+ );
1000
+ }
1001
+
1002
+ function injectDefaultSocialImageMeta(html, imageUrl) {
1003
+ const headCloseIdx = html.indexOf("</head>");
1004
+ if (headCloseIdx === -1) return html;
1005
+
1006
+ const hasAnySocialImage =
1007
+ OG_IMAGE_META_RE.test(html) || TWITTER_IMAGE_META_RE.test(html);
1008
+ const tags = [];
1009
+
1010
+ if (!hasAnySocialImage) {
1011
+ tags.push('<meta property="og:image" content="' + imageUrl + '">');
1012
+ tags.push('<meta property="og:image:secure_url" content="' + imageUrl + '">');
1013
+ tags.push('<meta property="og:image:type" content="' + AGENT_NATIVE_SOCIAL_IMAGE_TYPE + '">');
1014
+ tags.push('<meta property="og:image:width" content="' + AGENT_NATIVE_SOCIAL_IMAGE_WIDTH + '">');
1015
+ tags.push('<meta property="og:image:height" content="' + AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT + '">');
1016
+ tags.push('<meta property="og:image:alt" content="' + AGENT_NATIVE_SOCIAL_IMAGE_ALT + '">');
1017
+ }
1018
+ if (!TWITTER_CARD_META_RE.test(html)) {
1019
+ tags.push('<meta name="twitter:card" content="summary_large_image">');
1020
+ }
1021
+ if (!hasAnySocialImage) {
1022
+ tags.push('<meta name="twitter:image" content="' + imageUrl + '">');
1023
+ tags.push('<meta name="twitter:image:alt" content="' + AGENT_NATIVE_SOCIAL_IMAGE_ALT + '">');
1024
+ }
1025
+
1026
+ if (tags.length === 0) return html;
1027
+ return html.slice(0, headCloseIdx) + tags.join("") + html.slice(headCloseIdx);
1028
+ }
1029
+
1030
+ function isSsrHtmlOrDataResponse(headers, status, pathname) {
1031
+ if (status < 200 || status >= 400) return false;
1032
+ const contentType = (headers.get("content-type") || "").toLowerCase();
1033
+ if (contentType.includes("text/html")) return true;
1034
+ return pathname.endsWith(".data") && contentType.includes("text/x-script");
1035
+ }
1036
+
1037
+ /**
1038
+ * Apply the SSR cache policy to the response headers.
1039
+ *
1040
+ * SSR HTML and React Router .data responses are one impersonal public shell.
1041
+ * Always overwrite route cache hints so generated edge workers cannot drift
1042
+ * from the canonical Nitro/Netlify handler or send normal pages to origin.
1043
+ */
1044
+ function applyDefaultSsrCacheHeader(headers, status, pathname) {
1045
+ if (!isSsrHtmlOrDataResponse(headers, status, pathname)) return;
1046
+
1047
+ headers.delete("set-cookie");
1048
+ const vary = headers.get("vary");
1049
+ if (vary) {
1050
+ const publicVary = vary
1051
+ .split(",")
1052
+ .map((value) => value.trim())
1053
+ .filter((value) => {
1054
+ const normalized = value.toLowerCase();
1055
+ return normalized && normalized !== "*" && normalized !== "cookie" && normalized !== "authorization";
1056
+ });
1057
+ if (publicVary.length > 0) headers.set("vary", publicVary.join(", "));
1058
+ else headers.delete("vary");
1059
+ }
1060
+
1061
+ headers.set("cache-control", DEFAULT_SSR_CACHE_CONTROL);
1062
+ headers.set("cdn-cache-control", DEFAULT_SSR_CDN_CACHE_CONTROL);
1063
+ // Netlify function responses are dynamic by default and can otherwise show
1064
+ // Cache-Status fwd=bypass even with Cache-Control: public. Keep this
1065
+ // Netlify-specific header so SSR HTML/.data are served from the shared
1066
+ // durable CDN cache instead of stampeding origin — for every visitor.
1067
+ headers.set("netlify-cdn-cache-control", DEFAULT_SSR_NETLIFY_CDN_CACHE_CONTROL);
1068
+ }
1069
+
1070
+ function applyDefaultSpeculationRulesHeader(headers, status, basePath) {
1071
+ if (status < 200 || status >= 400) return;
1072
+ if (headers.has("speculation-rules")) return;
1073
+
1074
+ const contentType = (headers.get("content-type") || "").toLowerCase();
1075
+ if (!contentType.includes("text/html")) return;
1076
+
1077
+ // Cloudflare Speed Brain injects Speculation-Rules when origin omits this
1078
+ // header. Those browser prefetches carry Sec-Purpose: prefetch and
1079
+ // Cloudflare can return 503 before the request reaches origin. Publish an
1080
+ // explicit no-op ruleset by default; apps can still provide their own header.
1081
+ headers.set("speculation-rules", '"' + prefixMountedPath(DEFAULT_SPECULATION_RULES_PATH, basePath) + '"');
1082
+ }
1083
+ function isImmutableAssetRequest(request) {
1084
+ const pathname = stripAppBasePath(new URL(request.url).pathname);
1085
+ return IMMUTABLE_ASSET_PATHS.has(pathname);
1086
+ }
1087
+
1088
+ function applyImmutableAssetCacheHeaders(response, request) {
1089
+ if (!isImmutableAssetRequest(request)) return response;
1090
+ if (!((response.status >= 200 && response.status < 300) || response.status === 304)) {
1091
+ return response;
1092
+ }
1093
+ const headers = new Headers(response.headers);
1094
+ headers.set("Cache-Control", IMMUTABLE_ASSET_CACHE_CONTROL);
1095
+ headers.set("CDN-Cache-Control", IMMUTABLE_ASSET_CACHE_CONTROL);
1096
+ headers.set("Netlify-CDN-Cache-Control", IMMUTABLE_ASSET_CACHE_CONTROL);
1097
+ return new Response(response.body, {
1098
+ status: response.status,
1099
+ statusText: response.statusText,
1100
+ headers,
1101
+ });
1102
+ }
1103
+
1104
+ async function rewriteMountedResponse(response, basePath, pathname, request) {
1105
+ const sentryClientConfigScript = getSentryClientConfigScript();
1106
+ const headers = new Headers(response.headers);
1107
+ applyDefaultSsrCacheHeader(headers, response.status, pathname);
1108
+ applyDefaultSpeculationRulesHeader(headers, response.status, basePath);
1109
+
1110
+ const location = headers.get("location");
1111
+ if (location?.startsWith("/") && !location.startsWith("//")) {
1112
+ headers.set("location", prefixMountedPath(location, basePath));
1113
+ }
1114
+
1115
+ const contentType = headers.get("content-type") || "";
1116
+ if (!contentType.toLowerCase().includes("text/html") || !response.body) {
1117
+ return new Response(response.body, {
1118
+ status: response.status,
1119
+ statusText: response.statusText,
1120
+ headers,
1121
+ });
1122
+ }
1123
+
1124
+ const html = await response.text();
1125
+ headers.delete("content-length");
1126
+ return new Response(
1127
+ injectHeadScript(
1128
+ injectDefaultSocialImageMeta(
1129
+ prefixMountedHtml(html, basePath),
1130
+ defaultSocialImageUrl(request, basePath),
1131
+ ),
1132
+ sentryClientConfigScript,
1133
+ ),
1134
+ {
1135
+ status: response.status,
1136
+ statusText: response.statusText,
1137
+ headers,
1138
+ },
1139
+ );
1140
+ }
1141
+
1142
+ function requestWithMethod(request, method) {
1143
+ return new Request(request.url, {
1144
+ method,
1145
+ headers: request.headers,
1146
+ signal: request.signal,
1147
+ });
1148
+ }
1149
+
1150
+ function requestWithPathname(request, pathname) {
1151
+ const url = new URL(request.url);
1152
+ if (url.pathname === pathname) return request;
1153
+ url.pathname = pathname;
1154
+ return new Request(url, request);
1155
+ }
1156
+
1157
+ function requestForAnonymousSsr(request) {
1158
+ const headers = new Headers(request.headers);
1159
+ headers.delete("cookie");
1160
+ headers.delete("authorization");
1161
+ return new Request(request, { headers });
1162
+ }
1163
+
1164
+ function isStaticAppShellRequest(request) {
1165
+ if (request.method !== "GET" && request.method !== "HEAD") return false;
1166
+ const p = stripAppBasePath(new URL(request.url).pathname);
1167
+ if (
1168
+ p.startsWith("/.well-known/") ||
1169
+ p.startsWith("/_agent-native/") ||
1170
+ isApiPath(p) ||
1171
+ p === "/favicon.ico" ||
1172
+ p === "/favicon.png" ||
1173
+ /\\.\\w+$/.test(p)
1174
+ ) {
1175
+ return false;
1176
+ }
1177
+ return true;
1178
+ }
1179
+
1180
+ async function fetchStaticAppShell(request, env) {
1181
+ if (!env?.ASSETS || !isStaticAppShellRequest(request)) return null;
1182
+ const basePath = getAppBasePath();
1183
+ const p = stripAppBasePath(new URL(request.url).pathname);
1184
+ const shellRequest = requestWithPathname(
1185
+ requestWithMethod(request, "GET"),
1186
+ "/index.html",
1187
+ );
1188
+ let response;
1189
+ try {
1190
+ response = await env.ASSETS.fetch(shellRequest);
1191
+ } catch {
1192
+ return null;
1193
+ }
1194
+ if (response.status === 404) return null;
1195
+ if (request.method === "HEAD") {
1196
+ return rewriteMountedResponse(
1197
+ new Response(null, {
1198
+ status: response.status,
1199
+ statusText: response.statusText,
1200
+ headers: response.headers,
1201
+ }),
1202
+ basePath,
1203
+ p,
1204
+ request,
1205
+ );
1206
+ }
1207
+ return rewriteMountedResponse(response, basePath, p, request);
1208
+ }
1209
+
1210
+ // API route handlers
1211
+ ${routeImports.join("\n")}
1212
+
1213
+ // Action handlers (auto-discovered from actions/)
1214
+ ${actionImports.join("\n")}
1215
+
1216
+ // Server plugins
1217
+ ${pluginImports.join("\n")}
1218
+
1219
+ let _handler;
1220
+
1221
+ async function getHandler() {
1222
+ if (_handler) return _handler;
1223
+
1224
+ const app = new H3();
1225
+
1226
+ // Build a fake nitroApp surface so framework plugins (which expect
1227
+ // \`nitroApp.h3["~middleware"]\`) can register routes via getH3App().
1228
+ const noop = () => {};
1229
+ const nitroApp = {
1230
+ h3: app,
1231
+ hooks: { hook: noop, callHook: noop, hookOnce: noop },
1232
+ captureError: noop,
1233
+ };
1234
+
1235
+ // CORS — applied as global middleware via .use(handler)
1236
+ app.use(defineEventHandler((event) => {
1237
+ if (event.req.method === "OPTIONS") {
1238
+ return new Response(null, {
1239
+ status: 204,
1240
+ headers: {
1241
+ "Access-Control-Allow-Origin": "*",
1242
+ "Access-Control-Allow-Methods": "GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS",
1243
+ "Access-Control-Allow-Headers": "Content-Type,Authorization,X-Requested-With,X-Request-Source,X-Agent-Native-CSRF,X-User-Timezone,X-Agent-Native-Tool-Bridge,X-Agent-Native-Tool-Id,X-Agent-Native-Frontend,X-Agent-Native-Embed-Target",
1244
+ },
1245
+ });
1246
+ }
1247
+ }));
1248
+
1249
+ // Run plugins — they call getH3App(nitroApp).use(path, handler) which
1250
+ // pushes path-prefix middleware onto app["~middleware"].
1251
+ // Pre-mark every build-time plugin slot before any plugin awaits the runtime
1252
+ // default bootstrap. Bundled serverless workers often lack server/plugins/
1253
+ // on disk, so runtime discovery would otherwise auto-mount duplicate
1254
+ // framework defaults before later custom plugins get a chance to mark
1255
+ // themselves as provided.
1256
+ ${generatedPluginMarks.map((stem) => ` markGeneratedPluginProvided(nitroApp, ${JSON.stringify(stem)});`).join("\n")}
1257
+ ${pluginCalls.join("\n")}
1258
+
1259
+ // Register API routes
1260
+ ${routeRegistrations.join("\n")}
1261
+
1262
+ // Register action routes (/_agent-native/actions/*)
1263
+ ${actionRegistrations.join("\n")}
1264
+
1265
+ ${
1266
+ includeReactRouterSsr
1267
+ ? ` // SSR catch-all for React Router
1268
+ const rrHandler = createRequestHandler(() => serverBuild);
1269
+ app.all("/**", defineEventHandler(async (event) => {
1270
+ const basePath = getAppBasePath();
1271
+ const p = stripAppBasePath(new URL(event.req.url).pathname);
1272
+ if (
1273
+ p.startsWith("/.well-known/") ||
1274
+ p.startsWith("/_agent-native/") ||
1275
+ isApiPath(p) ||
1276
+ p === "/favicon.ico" ||
1277
+ p === "/favicon.png" ||
1278
+ (/\\.\\w+$/.test(p) && !p.endsWith(".data"))
1279
+ ) {
1280
+ return new Response(null, { status: 404 });
1281
+ }
1282
+ const request = requestForAnonymousSsr(requestWithPathname(event.req, p));
1283
+ const anonymousContext = { userEmail: undefined, orgId: undefined };
1284
+ if (event.req.method === "HEAD") {
1285
+ const getRequest = requestWithMethod(request, "GET");
1286
+ const response = await runWithRequestContext(
1287
+ anonymousContext,
1288
+ () => rrHandler(getRequest)
1289
+ );
1290
+ return rewriteMountedResponse(
1291
+ new Response(null, {
1292
+ status: response.status,
1293
+ statusText: response.statusText,
1294
+ headers: response.headers,
1295
+ }),
1296
+ basePath,
1297
+ p,
1298
+ getRequest
1299
+ );
1300
+ }
1301
+ return rewriteMountedResponse(
1302
+ await runWithRequestContext(anonymousContext, () => rrHandler(request)),
1303
+ basePath,
1304
+ p,
1305
+ request
1306
+ );
1307
+ }));`
1308
+ : ""
1309
+ }
1310
+
1311
+ _handler = app.fetch.bind(app);
1312
+ return _handler;
1313
+ }
1314
+
1315
+ export default {
1316
+ async fetch(request, env, ctx) {
1317
+ // Expose env and ctx bindings globally for compatibility
1318
+ if (ctx) globalThis.__cf_ctx = ctx;
1319
+ if (env) {
1320
+ globalThis.process = globalThis.process || { env: {} };
1321
+ globalThis.process.env = globalThis.process.env || {};
1322
+ // Expose D1/KV/R2 bindings on globalThis.__cf_env for the db layer
1323
+ globalThis.__cf_env = env;
1324
+ for (const [key, value] of Object.entries(env)) {
1325
+ if (typeof value === "string") {
1326
+ globalThis.process.env[key] = value;
1327
+ }
1328
+ }
1329
+ }
1330
+
1331
+ // Try serving static assets first (CF Pages advanced mode).
1332
+ // Only attempt this for GET/HEAD — the ASSETS binding is a static file
1333
+ // server and returns 405 for any other method, which would short-circuit
1334
+ // API calls (PUT/POST/DELETE to /_agent-native/*) before they reach our
1335
+ // h3 middleware.
1336
+ if (env?.ASSETS && (request.method === "GET" || request.method === "HEAD")) {
1337
+ try {
1338
+ const assetResponse = await env.ASSETS.fetch(request);
1339
+ if (assetResponse.status !== 404) {
1340
+ return applyImmutableAssetCacheHeaders(assetResponse, request);
1341
+ }
1342
+ } catch {
1343
+ // Asset fetch failed — fall through to SSR
1344
+ }
1345
+ }
1346
+
1347
+ const handler = await getHandler();
1348
+ const response = await handler(requestWithMountedApiPrefixStripped(request));
1349
+ ${
1350
+ includeReactRouterSsr
1351
+ ? " return response;"
1352
+ : ` if (response.status === 404) {
1353
+ const shellResponse = await fetchStaticAppShell(request, env);
1354
+ if (shellResponse) return shellResponse;
1355
+ }
1356
+ return response;`
1357
+ }
1358
+ }
1359
+ };
1360
+ `;
1361
+ }
1362
+
1363
+ function escapeHtmlAttribute(value: string): string {
1364
+ return value
1365
+ .replaceAll("&", "&amp;")
1366
+ .replaceAll('"', "&quot;")
1367
+ .replaceAll("<", "&lt;")
1368
+ .replaceAll(">", "&gt;");
1369
+ }
1370
+
1371
+ function findReactRouterManifest(distDir: string): ReactRouterAssetManifest {
1372
+ const assetsDir = path.join(distDir, "assets");
1373
+ const manifestFile = fs
1374
+ .readdirSync(assetsDir)
1375
+ .find((file) => /^manifest-[\w-]+\.js$/.test(file));
1376
+ if (!manifestFile) {
1377
+ throw new Error(`React Router client manifest not found in ${assetsDir}`);
1378
+ }
1379
+
1380
+ const source = fs.readFileSync(path.join(assetsDir, manifestFile), "utf8");
1381
+ const match = source.match(/^window\.__reactRouterManifest=(.*);?\s*$/);
1382
+ if (!match) {
1383
+ throw new Error(`Could not parse React Router manifest ${manifestFile}`);
1384
+ }
1385
+
1386
+ return JSON.parse(match[1].replace(/;$/, "")) as ReactRouterAssetManifest;
1387
+ }
1388
+
1389
+ function collectModulePreloads(
1390
+ manifest: ReactRouterAssetManifest,
1391
+ route: ReactRouterAssetManifestRoute,
1392
+ ): string[] {
1393
+ const paths = new Set<string>();
1394
+ const add = (value: string | undefined) => {
1395
+ if (value) paths.add(value);
1396
+ };
1397
+ add(manifest.url);
1398
+ add(manifest.entry.module);
1399
+ manifest.entry.imports?.forEach(add);
1400
+ add(route.module);
1401
+ route.imports?.forEach(add);
1402
+ add(route.clientActionModule);
1403
+ add(route.clientLoaderModule);
1404
+ add(route.clientMiddlewareModule);
1405
+ add(route.hydrateFallbackModule);
1406
+ return [...paths];
1407
+ }
1408
+
1409
+ function collectStylesheetLinks(
1410
+ manifest: ReactRouterAssetManifest,
1411
+ route: ReactRouterAssetManifestRoute,
1412
+ ): string[] {
1413
+ return [...new Set([...(manifest.entry.css ?? []), ...(route.css ?? [])])];
1414
+ }
1415
+
1416
+ function generateRouteModuleImportScript(
1417
+ manifest: ReactRouterAssetManifest,
1418
+ route: ReactRouterAssetManifestRoute,
1419
+ ): string {
1420
+ const modules = [
1421
+ ["route0", route.module],
1422
+ ["route0_clientAction", route.clientActionModule],
1423
+ ["route0_clientLoader", route.clientLoaderModule],
1424
+ ["route0_clientMiddleware", route.clientMiddlewareModule],
1425
+ ["route0_hydrateFallback", route.hydrateFallbackModule],
1426
+ ] as const;
1427
+ const imports = modules
1428
+ .filter(([, modulePath]) => modulePath)
1429
+ .map(
1430
+ ([name, modulePath]) =>
1431
+ `import * as ${name} from ${JSON.stringify(modulePath)};`,
1432
+ );
1433
+ const parts = modules
1434
+ .filter(([, modulePath]) => modulePath)
1435
+ .map(([name]) => `...${name}`);
1436
+
1437
+ return [
1438
+ `import ${JSON.stringify(manifest.url)};`,
1439
+ ...imports,
1440
+ `window.__reactRouterRouteModules = {${JSON.stringify(route.id)}:{${parts.join(",")}}};`,
1441
+ `import(${JSON.stringify(manifest.entry.module)});`,
1442
+ ].join("\n");
1443
+ }
1444
+
1445
+ const EMPTY_REACT_ROUTER_TURBO_STREAM =
1446
+ '[{"_1":2,"_3":-5,"_4":-5},"loaderData",{},"actionData","errors"]\n';
1447
+
1448
+ // Manifest fallbacks cannot execute server loaders, so root loaders get the
1449
+ // framework's default locale shape to keep hydration from reading undefined.
1450
+ const DEFAULT_ROOT_LOADER_REACT_ROUTER_TURBO_STREAM =
1451
+ '[{"_1":2,"_3":-5,"_4":-5},"loaderData",{"_5":6},"actionData","errors","root",{"_7":8,"_9":10,"_11":12,"_13":14},"locale","en-US","preference",{"_7":15},"dir","ltr","messages",{},"system"]\n';
1452
+
1453
+ export function generateCloudflarePagesStaticShellFromManifest(
1454
+ manifest: ReactRouterAssetManifest,
1455
+ basePath = normalizeConfiguredAppBasePath(),
1456
+ ): string {
1457
+ const rootRoute = manifest.routes.root;
1458
+ if (!rootRoute) {
1459
+ throw new Error("React Router manifest is missing the root route");
1460
+ }
1461
+
1462
+ const modulePreloads = collectModulePreloads(manifest, rootRoute)
1463
+ .map(
1464
+ (href) =>
1465
+ `<link rel="modulepreload" href="${escapeHtmlAttribute(href)}"/>`,
1466
+ )
1467
+ .join("");
1468
+ const stylesheets = collectStylesheetLinks(manifest, rootRoute)
1469
+ .map(
1470
+ (href) => `<link rel="stylesheet" href="${escapeHtmlAttribute(href)}"/>`,
1471
+ )
1472
+ .join("");
1473
+ const routeModuleScript = generateRouteModuleImportScript(
1474
+ manifest,
1475
+ rootRoute,
1476
+ );
1477
+ const context = {
1478
+ basename: basePath || "/",
1479
+ future: { unstable_optimizeDeps: false },
1480
+ routeDiscovery: { mode: "initial" },
1481
+ ssr: true,
1482
+ isSpaMode: true,
1483
+ };
1484
+ const encodedInitialState = rootRoute.hasLoader
1485
+ ? DEFAULT_ROOT_LOADER_REACT_ROUTER_TURBO_STREAM
1486
+ : EMPTY_REACT_ROUTER_TURBO_STREAM;
1487
+
1488
+ return `<!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/><link rel="manifest" href="/manifest.json"/><link rel="icon" type="image/svg+xml" href="/favicon.svg"/>${modulePreloads}${stylesheets}</head><body><div style="display:flex;align-items:center;justify-content:center;height:100vh;width:100%"><svg role="status" aria-label="Loading" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="animation:an-spin 1s linear infinite;opacity:0.7"><path d="M21 12a9 9 0 1 1-6.219-8.56"></path></svg><style>@keyframes an-spin { to { transform: rotate(360deg) } } @media (prefers-color-scheme: dark) { html { background: #09090b; color: #fafafa } }</style></div><script>window.__reactRouterContext = ${JSON.stringify(context)};window.__reactRouterContext.stream = new ReadableStream({start(controller){window.__reactRouterContext.streamController = controller;}}).pipeThrough(new TextEncoderStream());</script><script type="module" async="">${routeModuleScript}</script><!--$--><script>window.__reactRouterContext.streamController.enqueue(${JSON.stringify(encodedInitialState)});</script><!--$--><script>window.__reactRouterContext.streamController.close();</script><!--/$--><!--/$--></body></html>`;
1489
+ }
1490
+
1491
+ function writeCloudflarePagesStaticShell({
1492
+ serverDir,
1493
+ distDir,
1494
+ tmpDir,
1495
+ }: {
1496
+ serverDir: string;
1497
+ distDir: string;
1498
+ tmpDir: string;
1499
+ }): void {
1500
+ const serverEntry = path.join(serverDir, "index.js");
1501
+ if (!fs.existsSync(serverEntry)) {
1502
+ throw new Error(`React Router server build not found at ${serverEntry}`);
1503
+ }
1504
+
1505
+ const outFile = path.join(distDir, "index.html");
1506
+ const renderScript = path.join(tmpDir, "render-cloudflare-static-shell.mjs");
1507
+ const basePath = normalizeConfiguredAppBasePath();
1508
+ fs.writeFileSync(
1509
+ renderScript,
1510
+ `
1511
+ import fs from "node:fs";
1512
+ import { createRequire } from "node:module";
1513
+ import { pathToFileURL } from "node:url";
1514
+
1515
+ const cwd = ${JSON.stringify(cwd)};
1516
+ const serverEntry = ${JSON.stringify(serverEntry)};
1517
+ const outFile = ${JSON.stringify(outFile)};
1518
+ const basePath = ${JSON.stringify(basePath)};
1519
+
1520
+ const requireFromApp = createRequire(cwd + "/package.json");
1521
+ const reactRouterEntry = requireFromApp.resolve("react-router");
1522
+ const { createRequestHandler } = await import(pathToFileURL(reactRouterEntry).href);
1523
+ const serverBuild = await import(pathToFileURL(serverEntry).href);
1524
+ const handler = createRequestHandler(serverBuild, "production");
1525
+ const pathname = basePath ? basePath + "/" : "/";
1526
+ const response = await handler(
1527
+ new Request(new URL(pathname, "https://agent-native.local"), {
1528
+ headers: { "X-React-Router-SPA-Mode": "yes" },
1529
+ }),
1530
+ );
1531
+ const html = await response.text();
1532
+
1533
+ if (!html || !html.includes("__reactRouterContext") || !html.includes("entry.client")) {
1534
+ throw new Error("React Router did not render a usable Cloudflare Pages static shell");
1535
+ }
1536
+
1537
+ fs.writeFileSync(outFile, html);
1538
+ process.exit(0);
1539
+ `,
1540
+ );
1541
+
1542
+ try {
1543
+ execFileSync(process.execPath, [renderScript], {
1544
+ cwd,
1545
+ env: {
1546
+ ...process.env,
1547
+ NODE_ENV: process.env.NODE_ENV || "production",
1548
+ IS_RR_BUILD_REQUEST: "yes",
1549
+ },
1550
+ stdio: "inherit",
1551
+ });
1552
+ console.log("[deploy] Wrote Cloudflare Pages static app shell.");
1553
+ } catch (error) {
1554
+ const message = error instanceof Error ? error.message : String(error);
1555
+ console.warn(
1556
+ `[deploy] React Router static shell render failed; using manifest fallback. ${message}`,
1557
+ );
1558
+ fs.writeFileSync(
1559
+ outFile,
1560
+ generateCloudflarePagesStaticShellFromManifest(
1561
+ findReactRouterManifest(distDir),
1562
+ basePath,
1563
+ ),
1564
+ );
1565
+ console.log("[deploy] Wrote Cloudflare Pages static app shell fallback.");
1566
+ }
1567
+ }
1568
+
1569
+ /**
1570
+ * Build for Cloudflare Pages.
1571
+ * Output structure:
1572
+ * dist/
1573
+ * _worker.js (bundled worker entry)
1574
+ * assets/ (static client assets)
1575
+ */
1576
+ async function buildCloudflarePages() {
1577
+ generateActionRegistryForProject(cwd);
1578
+
1579
+ const buildDir = path.join(cwd, "build");
1580
+ const clientDir = path.join(buildDir, "client");
1581
+ const serverDir = path.join(buildDir, "server");
1582
+ const distDir = path.join(cwd, "dist");
1583
+
1584
+ // Verify build output exists
1585
+ if (!fs.existsSync(clientDir) || !fs.existsSync(serverDir)) {
1586
+ console.error(
1587
+ "Build output not found at build/client/ and build/server/. Run react-router build first.",
1588
+ );
1589
+ process.exit(1);
1590
+ }
1591
+
1592
+ // Clean dist
1593
+ if (fs.existsSync(distDir)) {
1594
+ fs.rmSync(distDir, { recursive: true });
1595
+ }
1596
+ fs.mkdirSync(distDir, { recursive: true });
1597
+
1598
+ // Copy client assets to dist/
1599
+ copyDir(clientDir, distDir);
1600
+
1601
+ const tmpDir = path.join(cwd, ".deploy-tmp");
1602
+ fs.mkdirSync(tmpDir, { recursive: true });
1603
+ writeCloudflarePagesStaticShell({ serverDir, distDir, tmpDir });
1604
+
1605
+ // Exclude _worker.js from being served as a public asset
1606
+ fs.writeFileSync(path.join(distDir, ".assetsignore"), "_worker.js\n");
1607
+
1608
+ // Write package metadata inside _worker.js/ for the ES module worker that
1609
+ // Wrangler compiles and uploads for Cloudflare Pages.
1610
+ fs.mkdirSync(path.join(distDir, "_worker.js"), { recursive: true });
1611
+ fs.writeFileSync(
1612
+ path.join(distDir, "_worker.js", "package.json"),
1613
+ JSON.stringify({ main: "index.js", type: "module" }),
1614
+ );
1615
+
1616
+ // Create empty stub for native modules that wrangler's bundler needs to resolve
1617
+ const stubsDir = path.join(distDir, "_worker.js", "stubs");
1618
+ fs.mkdirSync(stubsDir, { recursive: true });
1619
+ fs.writeFileSync(
1620
+ path.join(stubsDir, "empty.js"),
1621
+ "export default {}; export const watch = () => ({ close() {} }); export const Database = class {};\n",
1622
+ );
1623
+
1624
+ // Discover routes, plugins, actions, and the workspace core (if any).
1625
+ const routes = await discoverApiRoutes(cwd);
1626
+ const plugins = await discoverPlugins(cwd);
1627
+ const actions = await discoverActionFiles(cwd);
1628
+ const missingDefaults = await getMissingDefaultPlugins(cwd);
1629
+ const workspaceCore = await getWorkspaceCoreExports(cwd);
1630
+ const includeReactRouterSsr = false;
1631
+
1632
+ const workspaceSlotCount = workspaceCore
1633
+ ? Object.keys(workspaceCore.plugins).length
1634
+ : 0;
1635
+ console.log(
1636
+ `[deploy] ${routes.length} API routes, ${actions.length} actions, ${plugins.length} plugins (${plugins.filter((p) => isNodeOnlyPlugin(p)).length} skipped as Node-only), ${missingDefaults.length} auto-mounted defaults${workspaceCore ? `, workspace-core ${workspaceCore.packageName} (${workspaceSlotCount} plugin slots)` : ""}`,
1637
+ );
1638
+
1639
+ // Generate the worker entry
1640
+ const immutableAssetPaths = collectImmutableAssetPaths(clientDir);
1641
+ const entrySource = generateWorkerEntry(
1642
+ routes,
1643
+ plugins,
1644
+ missingDefaults,
1645
+ actions,
1646
+ workspaceCore,
1647
+ immutableAssetPaths,
1648
+ normalizeConfiguredAppBasePath(),
1649
+ { includeReactRouterSsr },
1650
+ );
1651
+
1652
+ // Create _worker.js output directory
1653
+ const workerOutDir = path.join(distDir, "_worker.js");
1654
+ fs.mkdirSync(workerOutDir, { recursive: true });
1655
+
1656
+ // Write the worker entry
1657
+ const entryFile = path.join(workerOutDir, "index.js");
1658
+
1659
+ // Rewrite the server-build import to point at the copied files when this
1660
+ // worker intentionally includes React Router SSR.
1661
+ const adjustedEntry = includeReactRouterSsr
1662
+ ? entrySource.replace(
1663
+ `import * as serverBuild from "./server-build.js";`,
1664
+ `import * as serverBuild from "./server/index.js";`,
1665
+ )
1666
+ : entrySource;
1667
+
1668
+ // Write a temp file for esbuild to bundle everything into a single worker entry.
1669
+ // When React Router SSR is enabled, the server build is copied to tmp so
1670
+ // esbuild can resolve it. Cloudflare Pages currently uses a static app shell
1671
+ // instead so the worker stays under the platform bundle size limit.
1672
+ // Name the entry "index.js" so esbuild outputs index.js in the outdir,
1673
+ // matching the _worker.js/index.js entry point that Cloudflare Pages expects.
1674
+ const tmpEntry = path.join(tmpDir, "index.js");
1675
+ fs.writeFileSync(tmpEntry, adjustedEntry);
1676
+
1677
+ if (includeReactRouterSsr) {
1678
+ copyDir(serverDir, path.join(tmpDir, "server"));
1679
+ }
1680
+
1681
+ // Create a require shim so CJS require("fs") calls resolve via ESM imports.
1682
+ // This is injected via esbuild --inject to replace its broken __require shim.
1683
+ fs.writeFileSync(
1684
+ path.join(tmpDir, "_require-shim.js"),
1685
+ generateRequireShim(),
1686
+ );
1687
+
1688
+ const nitroServerAssetsStub = path.join(
1689
+ tmpDir,
1690
+ "_nitro-server-assets-stub.js",
1691
+ );
1692
+ fs.writeFileSync(
1693
+ nitroServerAssetsStub,
1694
+ [
1695
+ "const empty = async () => undefined;",
1696
+ "export const assets = {",
1697
+ " getItem: empty,",
1698
+ " getItemRaw: empty,",
1699
+ " getKeys: async () => [],",
1700
+ " getMeta: async () => undefined,",
1701
+ " hasItem: async () => false,",
1702
+ "};",
1703
+ "export default assets;",
1704
+ "",
1705
+ ].join("\n"),
1706
+ );
1707
+
1708
+ // Create stub modules for native/Node-only deps that can't run on Workers.
1709
+ // These get resolved by esbuild instead of the real modules, avoiding bundling
1710
+ // native code that would fail on the Workers runtime.
1711
+ const stubDir = path.join(tmpDir, "node_modules");
1712
+ for (const [mod, source] of Object.entries(CLOUDFLARE_WORKER_STUB_MODULES)) {
1713
+ const modDir = path.join(stubDir, mod);
1714
+ fs.mkdirSync(modDir, { recursive: true });
1715
+ fs.writeFileSync(path.join(modDir, "index.js"), source);
1716
+ fs.writeFileSync(
1717
+ path.join(modDir, "package.json"),
1718
+ JSON.stringify({ name: mod, main: "index.js", type: "module" }),
1719
+ );
1720
+ }
1721
+ for (const [mod, source] of Object.entries(
1722
+ CLOUDFLARE_WORKER_STUB_SUBPATH_MODULES,
1723
+ )) {
1724
+ fs.writeFileSync(
1725
+ path.join(stubDir, `${mod.replace(/\//g, "__")}.js`),
1726
+ source,
1727
+ );
1728
+ }
1729
+ const stubAliases = cloudflareWorkerStubAliasArgs(stubDir);
1730
+ const nodeBuiltinStubDir = path.join(tmpDir, "node-builtin-stubs");
1731
+ fs.mkdirSync(nodeBuiltinStubDir, { recursive: true });
1732
+ const nodeBuiltinStubAliases: string[] = [];
1733
+ for (const [mod, source] of Object.entries(
1734
+ CLOUDFLARE_WORKER_NODE_BUILTIN_STUB_MODULES,
1735
+ ).sort(([a], [b]) => b.length - a.length)) {
1736
+ const stubFile = path.join(
1737
+ nodeBuiltinStubDir,
1738
+ `${mod.replace(/\W+/g, "_")}.js`,
1739
+ );
1740
+ fs.writeFileSync(stubFile, source);
1741
+ nodeBuiltinStubAliases.push(
1742
+ `--alias:${mod}=${stubFile}`,
1743
+ `--alias:node:${mod}=${stubFile}`,
1744
+ );
1745
+ }
1746
+
1747
+ const esbuildBin = findEsbuild();
1748
+
1749
+ // Externalize node builtins (both bare and node: prefixed) — the require
1750
+ // shim handles bare ones. Also alias every `node:*` specifier to its bare
1751
+ // name so esbuild emits `import from "fs"` everywhere, never
1752
+ // `import from "node:fs"`. CF Pages Functions (wrangler 3.x, nodejs_compat
1753
+ // v1) rejects the `node:` prefix in chunks with:
1754
+ // No such module "node:fs" imported from chunks/...
1755
+ // The alias is the authoritative fix; the post-build strip stays as belt
1756
+ // & suspenders in case esbuild emits a node: string via some other path.
1757
+ const builtinNames = getNodeBuiltinNames();
1758
+ // Only externalize bare names. node:* externals would otherwise pin
1759
+ // the prefix in output; instead we alias node:* → bare so anything that
1760
+ // resolves past alias land as bare externals.
1761
+ const nodeBuiltinStubs = new Set(
1762
+ Object.keys(CLOUDFLARE_WORKER_NODE_BUILTIN_STUB_MODULES),
1763
+ );
1764
+ const nodeExternals = builtinNames
1765
+ .filter((n) => !nodeBuiltinStubs.has(n))
1766
+ .sort((a, b) => b.length - a.length)
1767
+ .map((n) => `--external:${n}`);
1768
+ const nodeAliases = builtinNames
1769
+ .filter((n) => !nodeBuiltinStubs.has(n))
1770
+ .sort((a, b) => b.length - a.length)
1771
+ .map((n) => `--alias:node:${n}=${n}`);
1772
+
1773
+ // Hard externalize large client-only / node-only libraries so they don't
1774
+ // bloat the edge worker. These are never executed in the CF Pages runtime
1775
+ // — mermaid/excalidraw render in the browser, pdf-parse and @google/genai
1776
+ // run from node-only action scripts. Without this, slides' bundle hits
1777
+ // the 25 MiB Pages Functions limit.
1778
+ //
1779
+ // @anthropic-ai/tokenizer (tiktoken .wasm) and @resvg/resvg-js (native
1780
+ // .node binding) can't be bundled by esbuild at all — no loader for those
1781
+ // files. Both import sites degrade gracefully when the runtime import
1782
+ // fails: context-xray token counts fall back to char/4 estimates and the
1783
+ // OG image route falls back to SVG.
1784
+ const heavyClientExternals = CLOUDFLARE_WORKER_ESBUILD_EXTERNALS.filter(
1785
+ (p) => !Object.hasOwn(CLOUDFLARE_WORKER_STUB_MODULES, p),
1786
+ ).map((p) => `--external:${p}`);
1787
+
1788
+ execFileSync(
1789
+ esbuildBin,
1790
+ [
1791
+ tmpEntry,
1792
+ "--bundle",
1793
+ "--format=esm",
1794
+ "--target=es2022",
1795
+ // browser platform for npm resolution; node builtins externalized separately
1796
+ "--platform=browser",
1797
+ "--minify",
1798
+ // Single-file bundle (no --splitting). CF Pages Functions' deploy
1799
+ // validator fails to load chunked _worker.js/ bundles even when the
1800
+ // chunks contain only bare node-builtin imports (wrangler 3.101.0
1801
+ // + nodejs_compat v2). Matches main's working config.
1802
+ `--outdir=${workerOutDir}`,
1803
+ "--conditions=workerd,worker,import",
1804
+ // The ssr-handler imports a virtual module that only exists at dev time
1805
+ "--external:virtual:react-router/server-build",
1806
+ `--alias:#nitro/virtual/server-assets=${nitroServerAssetsStub}`,
1807
+ // Banner: override the __require shim that esbuild generates for CJS modules.
1808
+ // This provides a real require() backed by ESM imports of node builtins.
1809
+ // Without this, CF Workers rejects the bundle because esbuild's default
1810
+ // __require shim throws "Dynamic require of X is not supported".
1811
+ `--banner:js=${generateRequireShim()}`,
1812
+ // Externalize node: builtins — CF Workers runtime provides them
1813
+ ...nodeExternals,
1814
+ ...heavyClientExternals,
1815
+ ...stubAliases,
1816
+ ...nodeBuiltinStubAliases,
1817
+ // Rewrite node:* -> bare names so chunks never contain node: imports
1818
+ ...nodeAliases,
1819
+ ],
1820
+ { stdio: "inherit", cwd },
1821
+ );
1822
+
1823
+ // Clean up tmp
1824
+ fs.rmSync(tmpDir, { recursive: true });
1825
+
1826
+ // Rewrite the external virtual import to a local stub.
1827
+ // esbuild externalizes "virtual:react-router/server-build" (used by ssr-handler),
1828
+ // but wrangler re-bundles and chokes on it. Replace the import with a no-op stub.
1829
+ const virtualStub = path.join(workerOutDir, "chunks", "_virtual-stub.js");
1830
+ fs.mkdirSync(path.dirname(virtualStub), { recursive: true });
1831
+ fs.writeFileSync(virtualStub, "export default {};\n");
1832
+
1833
+ // Post-build patches — apply to ALL .js files in the worker output directory
1834
+ // (entry + chunks) since code can land in any chunk after splitting.
1835
+ const allJsFiles = getAllJsFiles(workerOutDir);
1836
+ for (const jsFile of allJsFiles) {
1837
+ let code = fs.readFileSync(jsFile, "utf-8");
1838
+ const isEntry = path.basename(jsFile) === "index.js";
1839
+
1840
+ // Strip "node:" prefix from all imports/requires. Cloudflare Pages
1841
+ // Functions runs under nodejs_compat v1, which exposes builtins as
1842
+ // bare names ("fs") and rejects "node:fs" at worker init:
1843
+ // No such module "node:fs" imported from chunks/...
1844
+ // (Workers-on-the-edge use v2 and require the prefix; Pages lags.)
1845
+ // Preserve the original quote char (single vs double) when rewriting —
1846
+ // esbuild's minifier sometimes places `import('node:buffer')` inside a
1847
+ // double-quoted string literal; swapping to double quotes breaks the
1848
+ // outer literal and produces `Unexpected identifier 'buffer'`.
1849
+ code = code.replace(
1850
+ /\bfrom(\s*)(["'])node:([^"']+)\2/g,
1851
+ (_, ws, q, mod) => `from${ws}${q}${mod}${q}`,
1852
+ );
1853
+ code = code.replace(
1854
+ /\bimport(\s*)(["'])node:([^"']+)\2/g,
1855
+ (_, ws, q, mod) => `import${ws}${q}${mod}${q}`,
1856
+ );
1857
+ // Strip `node:` prefix from any string literal that names a node
1858
+ // builtin. Covers dynamic imports, require(), getBuiltinModule(),
1859
+ // and minified wrappers like `Ut("node:fs")` that Nitro/h3 emit.
1860
+ // Pages' loader scans chunks for `"node:*"` literals and fails with
1861
+ // 'No such module "node:fs"' whether or not the string is reached
1862
+ // at runtime. Scoping to known builtins avoids touching user data.
1863
+ // Sorted longest-first so `fs/promises` matches before `fs`.
1864
+ const builtinsPattern = [...NODE_BUILTINS]
1865
+ .sort((a, b) => b.length - a.length)
1866
+ .join("|");
1867
+ const builtinRe = new RegExp(`(["'])node:(${builtinsPattern})\\1`, "g");
1868
+ code = code.replace(
1869
+ builtinRe,
1870
+ (_, q: string, mod: string) => `${q}${mod}${q}`,
1871
+ );
1872
+
1873
+ // Rewrite virtual:react-router/server-build imports to the local stub.
1874
+ // The generated entry handles SSR directly; this import is dead code from ssr-handler.
1875
+ const relStub = path
1876
+ .relative(path.dirname(jsFile), virtualStub)
1877
+ .replace(/\\/g, "/");
1878
+ code = code.replace(
1879
+ /["']virtual:react-router\/server-build["']/g,
1880
+ `"./${relStub}"`,
1881
+ );
1882
+
1883
+ // Patch createRequire(import.meta.url) — import.meta.url is undefined in CF Workers.
1884
+ // Matches both `from "module"` and `from "node:module"` — with the node:
1885
+ // prefix preserved (for nodejs_compat_v2), the latter is what esbuild now emits.
1886
+ code = code.replace(
1887
+ /\bimport\s*\{\s*createRequire\s+as\s+([\w$]+)\s*\}\s*from\s*["'](?:node:)?module["']\s*;/g,
1888
+ "var $1 = function() { return typeof require !== 'undefined' ? require : function(m) { throw new Error('require not supported: ' + m); }; };",
1889
+ );
1890
+
1891
+ // Patch setInterval/setTimeout at module scope — CF Workers disallows timers in global scope.
1892
+ // Some dependencies (e.g. Anthropic SDK rate limiter) call setInterval at module init.
1893
+ // With code splitting, chunks evaluate before the entry, so the shim must be in every file.
1894
+ // The restore only happens in the entry's fetch() handler.
1895
+ if (!code.includes("__origSetInterval")) {
1896
+ const timerShim = [
1897
+ "var __origSetInterval=globalThis.setInterval;",
1898
+ "globalThis.setInterval=function(){return{unref(){},ref(){},close(){}}};",
1899
+ ].join("");
1900
+ code = timerShim + code;
1901
+ }
1902
+ if (isEntry) {
1903
+ const timerRestore =
1904
+ "if(__origSetInterval)globalThis.setInterval=__origSetInterval;";
1905
+ code = code.replace(
1906
+ /async fetch\(request,\s*env,\s*ctx\)\s*\{/,
1907
+ (match) => match + timerRestore,
1908
+ );
1909
+ }
1910
+
1911
+ assertNoCloudflareWorkerStubDynamicImports(code, jsFile);
1912
+
1913
+ fs.writeFileSync(jsFile, code);
1914
+ }
1915
+
1916
+ // Report size
1917
+ const entrySize = fs.statSync(entryFile).size;
1918
+ const totalSize = getDirSize(workerOutDir);
1919
+ const chunkCount = allJsFiles.length - 1; // exclude entry
1920
+ console.log(
1921
+ `[deploy] Cloudflare Pages output written to dist/ (entry: ${(entrySize / 1024).toFixed(0)}KB, ${chunkCount} chunks, total: ${(totalSize / 1024 / 1024).toFixed(1)}MB)`,
1922
+ );
1923
+ }
1924
+
1925
+ const NODE_BUILTINS = [
1926
+ "assert",
1927
+ "async_hooks",
1928
+ "buffer",
1929
+ "child_process",
1930
+ "cluster",
1931
+ "console",
1932
+ "constants",
1933
+ "crypto",
1934
+ "dgram",
1935
+ "diagnostics_channel",
1936
+ "dns",
1937
+ "dns/promises",
1938
+ "domain",
1939
+ "events",
1940
+ "fs",
1941
+ "fs/promises",
1942
+ "http",
1943
+ "http2",
1944
+ "https",
1945
+ "inspector",
1946
+ "module",
1947
+ "net",
1948
+ "os",
1949
+ "path",
1950
+ "perf_hooks",
1951
+ "process",
1952
+ "punycode",
1953
+ "querystring",
1954
+ "readline",
1955
+ "repl",
1956
+ "sqlite",
1957
+ "stream",
1958
+ "stream/web",
1959
+ "string_decoder",
1960
+ "sys",
1961
+ "timers",
1962
+ "tls",
1963
+ "trace_events",
1964
+ "tty",
1965
+ "url",
1966
+ "util",
1967
+ "v8",
1968
+ "vm",
1969
+ "wasi",
1970
+ "worker_threads",
1971
+ "zlib",
1972
+ ];
1973
+
1974
+ export function getNodeBuiltinNames(): string[] {
1975
+ return NODE_BUILTINS;
1976
+ }
1977
+
1978
+ /**
1979
+ * Generate a require() shim that bridges CJS require("fs") calls to ESM imports.
1980
+ * Injected via esbuild --inject so CJS deps work on Workers runtime.
1981
+ */
1982
+ function generateRequireShim(): string {
1983
+ // Shim Node builtins that Cloudflare Pages can import, and return lazy
1984
+ // unavailable proxies for builtins that Pages Functions reject at upload
1985
+ // time (child_process, fs, net, etc.). This lets optional Node-only code stay
1986
+ // present in the shared bundle without making worker initialization fail.
1987
+ const stubbed = new Set(
1988
+ Object.keys(CLOUDFLARE_WORKER_NODE_BUILTIN_STUB_MODULES),
1989
+ );
1990
+ const shimmed = NODE_BUILTINS.filter((name) => !stubbed.has(name));
1991
+
1992
+ // Bare module names — CF Pages Functions runs under nodejs_compat v1,
1993
+ // which rejects "node:fs" and only accepts "fs". The post-build pass in
1994
+ // buildCloudflarePages() also strips any `node:` prefix that esbuild or
1995
+ // dependencies emit elsewhere.
1996
+ const imports = shimmed
1997
+ .map((m) => `import __${m.replace("/", "_")} from "${m}";`)
1998
+ .join("");
1999
+ // Only bare-name keys. Pages' Functions loader appears to scan chunks
2000
+ // for "node:*" string literals and pre-resolves them as module specs —
2001
+ // so keeping "node:fs" as an object key caused deploy to fail with
2002
+ // 'No such module "node:fs"' even though nothing imported it. The
2003
+ // post-build strip turns every runtime `require("node:fs")` into
2004
+ // `require("fs")` so bare keys are sufficient.
2005
+ const entries = shimmed
2006
+ .map((m) => `"${m}":__${m.replace("/", "_")}`)
2007
+ .join(",");
2008
+ const stubEntries = Array.from(stubbed)
2009
+ .sort()
2010
+ .map((m) => `"${m}":__unavailable("${m}")`)
2011
+ .join(",");
2012
+ const allEntries = [entries, stubEntries].filter(Boolean).join(",");
2013
+
2014
+ const messageChannelPolyfill = `if(typeof MessageChannel==="undefined"){globalThis.MessageChannel=class{constructor(){const a={onmessage:null},b={onmessage:null};a.postMessage=d=>{if(b.onmessage)setTimeout(()=>b.onmessage({data:d}),0)};b.postMessage=d=>{if(a.onmessage)setTimeout(()=>a.onmessage({data:d}),0)};this.port1=a;this.port2=b}}}`;
2015
+ return `${imports}\n${messageChannelPolyfill}\nconst __unavailable=(m)=>new Proxy({}, { get(_target, prop) { return (..._args) => { throw new Error(m + "." + String(prop) + " is unavailable in Cloudflare Pages workers"); }; } });\nconst __mods={${allEntries}};export var require=globalThis.require||function(m){const r=__mods[m];if(r!==undefined)return r;throw new Error("Cannot require: "+m)};\n`;
2016
+ }
2017
+
2018
+ function findEsbuild(): string {
2019
+ // Try to resolve esbuild's binary via Node module resolution
2020
+ // This works regardless of hoisting or .bin symlink creation
2021
+ try {
2022
+ const _require = createRequire(cwd + "/");
2023
+ const esbuildPkg = path.dirname(_require.resolve("esbuild/package.json"));
2024
+ const bin = path.join(esbuildPkg, "bin", "esbuild");
2025
+ if (fs.existsSync(bin)) return bin;
2026
+ } catch {}
2027
+
2028
+ // Fallback: check local and workspace .bin
2029
+ const localBin = path.resolve(cwd, "node_modules/.bin/esbuild");
2030
+ if (fs.existsSync(localBin)) return localBin;
2031
+
2032
+ const workspaceRoot = findWorkspaceRoot(cwd);
2033
+ if (workspaceRoot) {
2034
+ const workspaceBin = path.resolve(
2035
+ workspaceRoot,
2036
+ "node_modules/.bin/esbuild",
2037
+ );
2038
+ if (fs.existsSync(workspaceBin)) return workspaceBin;
2039
+ }
2040
+
2041
+ return "esbuild";
2042
+ }
2043
+
2044
+ function findWorkspaceRoot(dir: string): string | null {
2045
+ let current = dir;
2046
+ while (current !== path.dirname(current)) {
2047
+ if (
2048
+ fs.existsSync(path.join(current, "pnpm-workspace.yaml")) ||
2049
+ fs.existsSync(path.join(current, "pnpm-lock.yaml"))
2050
+ ) {
2051
+ return current;
2052
+ }
2053
+ current = path.dirname(current);
2054
+ }
2055
+ return null;
2056
+ }
2057
+
2058
+ /** Recursively collect all .js files in a directory. */
2059
+ function getAllJsFiles(dir: string): string[] {
2060
+ const results: string[] = [];
2061
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
2062
+ for (const entry of entries) {
2063
+ const fullPath = path.join(dir, entry.name);
2064
+ if (entry.isDirectory()) {
2065
+ results.push(...getAllJsFiles(fullPath));
2066
+ } else if (entry.name.endsWith(".js")) {
2067
+ results.push(fullPath);
2068
+ }
2069
+ }
2070
+ return results;
2071
+ }
2072
+
2073
+ function getDirSize(dir: string): number {
2074
+ let size = 0;
2075
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
2076
+ for (const entry of entries) {
2077
+ const fullPath = path.join(dir, entry.name);
2078
+ if (entry.isDirectory()) {
2079
+ size += getDirSize(fullPath);
2080
+ } else {
2081
+ size += fs.statSync(fullPath).size;
2082
+ }
2083
+ }
2084
+ return size;
2085
+ }
2086
+
2087
+ export function copyDir(
2088
+ src: string,
2089
+ dest: string,
2090
+ ancestorRealPaths = new Set<string>(),
2091
+ ) {
2092
+ const realSrc = fs.realpathSync(src);
2093
+ if (ancestorRealPaths.has(realSrc)) return;
2094
+ const nextAncestorRealPaths = new Set(ancestorRealPaths);
2095
+ nextAncestorRealPaths.add(realSrc);
2096
+
2097
+ fs.mkdirSync(dest, { recursive: true });
2098
+ const entries = fs.readdirSync(src, { withFileTypes: true });
2099
+ for (const entry of entries) {
2100
+ const srcPath = path.join(src, entry.name);
2101
+ const destPath = path.join(dest, entry.name);
2102
+ if (entry.isSymbolicLink()) {
2103
+ let stat: fs.Stats;
2104
+ try {
2105
+ stat = fs.statSync(srcPath);
2106
+ } catch (error) {
2107
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") {
2108
+ console.warn(
2109
+ `[deploy] Skipping broken symlink while copying ${srcPath}`,
2110
+ );
2111
+ continue;
2112
+ }
2113
+ throw error;
2114
+ }
2115
+ if (stat.isDirectory()) {
2116
+ copyDir(srcPath, destPath, nextAncestorRealPaths);
2117
+ } else {
2118
+ fs.copyFileSync(srcPath, destPath);
2119
+ }
2120
+ } else if (entry.isDirectory()) {
2121
+ copyDir(srcPath, destPath, nextAncestorRealPaths);
2122
+ } else {
2123
+ fs.copyFileSync(srcPath, destPath);
2124
+ }
2125
+ }
2126
+ }
2127
+
2128
+ const LIBSQL_NATIVE_PACKAGE_NAMES = [
2129
+ "darwin-arm64",
2130
+ "darwin-x64",
2131
+ "linux-arm-gnueabihf",
2132
+ "linux-arm-musleabihf",
2133
+ "linux-arm64-gnu",
2134
+ "linux-arm64-musl",
2135
+ "linux-x64-gnu",
2136
+ "linux-x64-musl",
2137
+ "win32-x64-msvc",
2138
+ ];
2139
+ const FFMPEG_STATIC_PACKAGE_NAME = "ffmpeg-static";
2140
+ const RESVG_SCOPE = "@resvg";
2141
+ const RESVG_PACKAGE_PREFIX = "resvg-js";
2142
+ const FFMPEG_STATIC_BINARY_NAMES =
2143
+ process.platform === "win32" ? ["ffmpeg.exe", "ffmpeg"] : ["ffmpeg"];
2144
+ const SERVERLESS_FFMPEG_STATIC_PLATFORM = "linux";
2145
+ const SERVERLESS_FFMPEG_STATIC_ARCHES = new Set<NodeJS.Architecture>([
2146
+ "arm64",
2147
+ "x64",
2148
+ ]);
2149
+ const SERVERLESS_FUNCTION_PACKAGE_DENYLIST = new Set([
2150
+ "@vscode/test-electron",
2151
+ "electron",
2152
+ "electron-builder",
2153
+ "electron-updater",
2154
+ "electron-vite",
2155
+ "fsevents",
2156
+ "node-pty",
2157
+ "playwright",
2158
+ ]);
2159
+ type ServerlessFfmpegStaticArch = "arm64" | "x64";
2160
+
2161
+ function serverlessFfmpegStaticTargetArchFromEnv(): ServerlessFfmpegStaticArch | null {
2162
+ const value = process.env.AGENT_NATIVE_SERVERLESS_FFMPEG_ARCH;
2163
+ if (value === "arm64" || value === "x64") return value;
2164
+ return null;
2165
+ }
2166
+
2167
+ export function shouldBundleFfmpegStaticForServerless(
2168
+ hostPlatform: NodeJS.Platform = process.platform,
2169
+ hostArch: NodeJS.Architecture = process.arch,
2170
+ targetArch: ServerlessFfmpegStaticArch | null = serverlessFfmpegStaticTargetArchFromEnv(),
2171
+ ): boolean {
2172
+ return (
2173
+ hostPlatform === SERVERLESS_FFMPEG_STATIC_PLATFORM &&
2174
+ targetArch !== null &&
2175
+ hostArch === targetArch &&
2176
+ SERVERLESS_FFMPEG_STATIC_ARCHES.has(targetArch)
2177
+ );
2178
+ }
2179
+
2180
+ function nodeModulesAncestors(startDir: string): string[] {
2181
+ const dirs: string[] = [];
2182
+ let current = path.resolve(startDir);
2183
+ while (true) {
2184
+ const candidate = path.join(current, "node_modules");
2185
+ if (fs.existsSync(candidate)) dirs.push(candidate);
2186
+ const parent = path.dirname(current);
2187
+ if (parent === current) break;
2188
+ current = parent;
2189
+ }
2190
+ return dirs;
2191
+ }
2192
+
2193
+ function findInstalledLibsqlNativePackage(
2194
+ nodeModulesRoots: string[],
2195
+ packageName: string,
2196
+ ): string | null {
2197
+ for (const root of nodeModulesRoots) {
2198
+ const direct = path.join(root, "@libsql", packageName);
2199
+ if (fs.existsSync(path.join(direct, "index.node"))) return direct;
2200
+
2201
+ const pnpmRoot = path.join(root, ".pnpm");
2202
+ if (!fs.existsSync(pnpmRoot)) continue;
2203
+ const pnpmPrefix = `@libsql+${packageName}@`;
2204
+ for (const entry of fs.readdirSync(pnpmRoot)) {
2205
+ if (!entry.startsWith(pnpmPrefix)) continue;
2206
+ const nested = path.join(
2207
+ pnpmRoot,
2208
+ entry,
2209
+ "node_modules",
2210
+ "@libsql",
2211
+ packageName,
2212
+ );
2213
+ if (fs.existsSync(path.join(nested, "index.node"))) return nested;
2214
+ }
2215
+ }
2216
+ return null;
2217
+ }
2218
+
2219
+ function hasFfmpegStaticBinary(packageDir: string): boolean {
2220
+ return FFMPEG_STATIC_BINARY_NAMES.some((binaryName) =>
2221
+ fs.existsSync(path.join(packageDir, binaryName)),
2222
+ );
2223
+ }
2224
+
2225
+ function hasInstalledFfmpegStaticPackage(nodeModulesRoots: string[]): boolean {
2226
+ for (const root of nodeModulesRoots) {
2227
+ const direct = path.join(root, FFMPEG_STATIC_PACKAGE_NAME);
2228
+ if (fs.existsSync(path.join(direct, "package.json"))) return true;
2229
+
2230
+ const pnpmRoot = path.join(root, ".pnpm");
2231
+ if (!fs.existsSync(pnpmRoot)) continue;
2232
+ const pnpmPrefix = `${FFMPEG_STATIC_PACKAGE_NAME}@`;
2233
+ for (const entry of fs.readdirSync(pnpmRoot)) {
2234
+ if (!entry.startsWith(pnpmPrefix)) continue;
2235
+ const nested = path.join(
2236
+ pnpmRoot,
2237
+ entry,
2238
+ "node_modules",
2239
+ FFMPEG_STATIC_PACKAGE_NAME,
2240
+ );
2241
+ if (fs.existsSync(path.join(nested, "package.json"))) return true;
2242
+ }
2243
+ }
2244
+ return false;
2245
+ }
2246
+
2247
+ export function findInstalledFfmpegStaticPackage(
2248
+ nodeModulesRoots: string[],
2249
+ ): string | null {
2250
+ for (const root of nodeModulesRoots) {
2251
+ const direct = path.join(root, FFMPEG_STATIC_PACKAGE_NAME);
2252
+ if (
2253
+ fs.existsSync(path.join(direct, "package.json")) &&
2254
+ hasFfmpegStaticBinary(direct)
2255
+ ) {
2256
+ return direct;
2257
+ }
2258
+
2259
+ const pnpmRoot = path.join(root, ".pnpm");
2260
+ if (!fs.existsSync(pnpmRoot)) continue;
2261
+ const pnpmPrefix = `${FFMPEG_STATIC_PACKAGE_NAME}@`;
2262
+ for (const entry of fs.readdirSync(pnpmRoot)) {
2263
+ if (!entry.startsWith(pnpmPrefix)) continue;
2264
+ const nested = path.join(
2265
+ pnpmRoot,
2266
+ entry,
2267
+ "node_modules",
2268
+ FFMPEG_STATIC_PACKAGE_NAME,
2269
+ );
2270
+ if (
2271
+ fs.existsSync(path.join(nested, "package.json")) &&
2272
+ hasFfmpegStaticBinary(nested)
2273
+ ) {
2274
+ return nested;
2275
+ }
2276
+ }
2277
+ }
2278
+ return null;
2279
+ }
2280
+
2281
+ export function findInstalledResvgPackages(
2282
+ nodeModulesRoots: string[],
2283
+ ): Array<{ packageName: string; packageDir: string }> {
2284
+ const found = new Map<string, string>();
2285
+
2286
+ for (const root of nodeModulesRoots) {
2287
+ const directScope = path.join(root, RESVG_SCOPE);
2288
+ if (fs.existsSync(directScope)) {
2289
+ for (const entry of fs.readdirSync(directScope)) {
2290
+ if (!entry.startsWith(RESVG_PACKAGE_PREFIX)) continue;
2291
+ const packageDir = path.join(directScope, entry);
2292
+ if (fs.existsSync(path.join(packageDir, "package.json"))) {
2293
+ found.set(entry, packageDir);
2294
+ }
2295
+ }
2296
+ }
2297
+
2298
+ const pnpmRoot = path.join(root, ".pnpm");
2299
+ if (!fs.existsSync(pnpmRoot)) continue;
2300
+ for (const entry of fs.readdirSync(pnpmRoot)) {
2301
+ const match = entry.match(/^@resvg\+(resvg-js[^@]*)@/);
2302
+ if (!match) continue;
2303
+ const packageName = match[1];
2304
+ const packageDir = path.join(
2305
+ pnpmRoot,
2306
+ entry,
2307
+ "node_modules",
2308
+ RESVG_SCOPE,
2309
+ packageName,
2310
+ );
2311
+ if (fs.existsSync(path.join(packageDir, "package.json"))) {
2312
+ found.set(packageName, packageDir);
2313
+ }
2314
+ }
2315
+ }
2316
+
2317
+ return [...found.entries()]
2318
+ .sort(([a], [b]) => a.localeCompare(b))
2319
+ .map(([packageName, packageDir]) => ({ packageName, packageDir }));
2320
+ }
2321
+
2322
+ /**
2323
+ * Deploy-time gate for emitting the second `-background` Netlify function.
2324
+ * Reads the same env flag the runtime gate uses
2325
+ * (`AGENT_CHAT_DURABLE_BACKGROUND`).
2326
+ *
2327
+ * DEFAULT-OFF (opt-in), matching the runtime gate (`isFlagEnabled` in
2328
+ * durable-background.ts): unset/empty/unknown means DISABLED; an app opts IN
2329
+ * only with an explicit truthy value (`true`/`1`/`yes`/`on`). A premature
2330
+ * fleet-wide default-on caused real-user incidents (2026-06-24) before the
2331
+ * async worker path was proven, so durable is opt-in until verified live. This
2332
+ * gate is what emits the 15-min `-background` function so the `_process-run`
2333
+ * dispatch lands on it (async 202 → the worker runs with the real 15-min budget
2334
+ * → its ~13-min soft-timeout fits). The deploy gate and runtime gate MUST agree:
2335
+ * if the deploy emitted no `-background` function but the runtime still routed
2336
+ * the worker into the ~13-min timeout regime, the worker would overshoot the
2337
+ * ~60s synchronous wall and re-dispatch in a loop. (The runtime now also guards
2338
+ * the ~13-min budget on the real function name via `isInBackgroundFunctionRuntime`,
2339
+ * so a missing emit degrades to clean 40s-chunked runs rather than the loop.)
2340
+ */
2341
+ export function isDurableBackgroundDeployEnabled(): boolean {
2342
+ const raw = process.env.AGENT_CHAT_DURABLE_BACKGROUND;
2343
+ if (raw == null) return false;
2344
+ const v = raw.trim().toLowerCase();
2345
+ return v === "1" || v === "true" || v === "yes" || v === "on";
2346
+ }
2347
+
2348
+ /**
2349
+ * Single-template Netlify build: emit an async (background) function INSIDE the
2350
+ * scanned functions dir so the chat `_process-run` worker runs on Netlify's
2351
+ * 15-min async function instead of the synchronous `/*` catch-all.
2352
+ * Additive + flag-gated (see `isDurableBackgroundDeployEnabled`).
2353
+ *
2354
+ * GROUNDED IN THE REAL NETLIFY BUILD OUTPUT (verified from a local Nitro build)
2355
+ * AND THE NETLIFY DOCS DEFAULT-URL RULE:
2356
+ * - Nitro's `netlify` preset emits exactly ONE function source at
2357
+ * `.netlify/functions-internal/server/`. `server.mjs` re-exports `main.mjs`
2358
+ * and declares `export const config = { path: "/*", excludedPath:
2359
+ * ["/.netlify/*"], preferStatic: true, ... }`. The `/*` catch-all is an
2360
+ * IN-CODE Functions-API-v2 `config.path` and it ALREADY EXCLUDES
2361
+ * `/.netlify/*`.
2362
+ * - The generated `.netlify/netlify.toml` sets
2363
+ * `functionsDirectory = ".netlify/functions-internal"`. Netlify scans EXACTLY
2364
+ * that dir; functions placed anywhere else (e.g. `.netlify/functions/`, which
2365
+ * is the BUILD OUTPUT dir where `@netlify/build` later writes the zipped
2366
+ * functions + `manifest.json`) are NEVER deployed.
2367
+ * - Every scanned function is reachable at its DEFAULT url
2368
+ * `/.netlify/functions/<name>` BY DEFAULT. A custom `config.path` REMOVES
2369
+ * that default url; declaring NO custom `config.path` KEEPS it.
2370
+ *
2371
+ * THEREFORE we:
2372
+ * 1. Emit the background function INTO the scanned dir
2373
+ * (`.netlify/functions-internal/server-agent-background/`), sharing the same
2374
+ * built `main.mjs` bundle, so Netlify discovers it and honors its config.
2375
+ * 2. Give its `export const config` `background: true` (→ async invoke,
2376
+ * immediate 202, 15-min budget) and NO custom `config.path`. With no custom
2377
+ * path the function keeps its DEFAULT url
2378
+ * `/.netlify/functions/server-agent-background`, and because the Nitro
2379
+ * `server` function's `/*` catch-all already excludes `/.netlify/*`, that
2380
+ * default-url namespace is NEVER shadowed by the synchronous function — no
2381
+ * catch-all patch is needed.
2382
+ * 3. The entry NORMALIZES/rewrites the incoming request pathname to
2383
+ * `AGENT_CHAT_PROCESS_RUN_PATH` before delegating to `./main.mjs`. The
2384
+ * function is reached at its default url
2385
+ * (`/.netlify/functions/server-agent-background`), so the Nitro router needs
2386
+ * the path rewritten to the framework `_process-run` route, preserving the
2387
+ * method, ALL headers (the HMAC `Authorization: Bearer` MUST survive), and
2388
+ * the body.
2389
+ * 4. Set `globalThis.__AGENT_NATIVE_BACKGROUND_RUNTIME__ = true` at cold start
2390
+ * (read back by `isInBackgroundFunctionRuntime()` so the worker takes the
2391
+ * ~13-min soft-timeout). A `globalThis` flag — NOT `process.env` — keeps the
2392
+ * no-env-mutation guard satisfied and carries no cross-request state.
2393
+ *
2394
+ * The foreground dispatches to this DEFAULT url on hosted Netlify
2395
+ * (`resolveAgentChatProcessRunDispatchPath` → `AGENT_BACKGROUND_FUNCTION_URL_PATH`).
2396
+ *
2397
+ * WHY THIS IS THE DOC-CORRECT FIX: a prior attempt gave the function a custom
2398
+ * `config.path` (= the framework route) plus a catch-all `excludedPath` patch.
2399
+ * The custom `config.path` was NOT honored as a route in prod — a probe of
2400
+ * `POST /_agent-native/agent-chat/_process-run` returned 404. The doc-correct
2401
+ * approach (confirmed against the Netlify docs) is to use the DEFAULT function
2402
+ * url with no custom path: the function stays reachable at
2403
+ * `/.netlify/functions/<name>` and is never shadowed because `/.netlify/*` is
2404
+ * already excluded from the `server` catch-all.
2405
+ *
2406
+ * Safety net regardless of Netlify routing nuance: if the dispatch fast-fails
2407
+ * (e.g. the function was not emitted), the foreground handler degrades to an
2408
+ * inline 40s synchronous run (see production-agent.ts).
2409
+ */
2410
+ export function emitSingleTemplateNetlifyBackgroundFunction(
2411
+ projectCwd: string,
2412
+ ): void {
2413
+ const internalDir = path.join(projectCwd, ".netlify", "functions-internal");
2414
+ const serverDir = path.join(internalDir, "server");
2415
+ if (!fs.existsSync(path.join(serverDir, "main.mjs"))) {
2416
+ // Nitro output layout differs from what we expected — skip rather than
2417
+ // guess. The single-function deploy is unaffected.
2418
+ console.warn(
2419
+ "[build] Durable-background emit skipped: expected Nitro Netlify function " +
2420
+ "at .netlify/functions-internal/server/main.mjs was not found.",
2421
+ );
2422
+ return;
2423
+ }
2424
+ const backgroundName = AGENT_BACKGROUND_FUNCTION_NAME;
2425
+ // Emit INTO the SCANNED functions dir (functions-internal) so Netlify discovers
2426
+ // the function and honors its `export const config`. `.netlify/functions/` is
2427
+ // the build OUTPUT dir (where @netlify/build writes the zip + manifest) and is
2428
+ // NOT scanned — emitting there is why the standalone attempt 404'd.
2429
+ const dest = path.join(internalDir, backgroundName);
2430
+ fs.rmSync(dest, { recursive: true, force: true });
2431
+ copyDir(serverDir, dest);
2432
+ // Drop the original Nitro `/*` entry so our entry is the entrypoint and the
2433
+ // copied bundle does NOT re-register the catch-all `config.path`.
2434
+ fs.rmSync(path.join(dest, "server.mjs"), { force: true });
2435
+
2436
+ const processRunPath = JSON.stringify(AGENT_CHAT_PROCESS_RUN_PATH);
2437
+ const a2aProcessTaskPath = JSON.stringify("/_agent-native/a2a/_process-task");
2438
+ const backgroundProcessorField = JSON.stringify(
2439
+ AGENT_BACKGROUND_PROCESSOR_FIELD,
2440
+ );
2441
+ const backgroundProcessorA2A = JSON.stringify(AGENT_BACKGROUND_PROCESSOR_A2A);
2442
+ const backgroundProcessorRoute = JSON.stringify(
2443
+ AGENT_BACKGROUND_PROCESSOR_ROUTE,
2444
+ );
2445
+ const backgroundProcessorRouteField = JSON.stringify(
2446
+ AGENT_BACKGROUND_PROCESSOR_ROUTE_FIELD,
2447
+ );
2448
+ const entry = `// Mark this isolate as the durable background runtime BEFORE the handler
2449
+ // bundle is imported, so isInBackgroundFunctionRuntime() reliably returns true
2450
+ // in this function. The deployed Lambda name is NOT guaranteed to end in
2451
+ // "-background" (Netlify may mangle/prefix it), so we cannot depend on
2452
+ // AWS_LAMBDA_FUNCTION_NAME alone. A globalThis flag (NOT process.env) avoids the
2453
+ // no-env-mutation guard and carries no cross-request state — it is a static,
2454
+ // set-once isolate marker read back by isInBackgroundFunctionRuntime().
2455
+ globalThis.__AGENT_NATIVE_BACKGROUND_RUNTIME__ = true;
2456
+
2457
+ // The framework route the Nitro router dispatches to (the _process-run plugin).
2458
+ const PROCESS_RUN_PATH = ${processRunPath};
2459
+ const A2A_PROCESS_TASK_PATH = ${a2aProcessTaskPath};
2460
+ const BACKGROUND_PROCESSOR_FIELD = ${backgroundProcessorField};
2461
+ const BACKGROUND_PROCESSOR_A2A = ${backgroundProcessorA2A};
2462
+ const BACKGROUND_PROCESSOR_ROUTE = ${backgroundProcessorRoute};
2463
+ const BACKGROUND_PROCESSOR_ROUTE_FIELD = ${backgroundProcessorRouteField};
2464
+
2465
+ function processorPathFromBody(body) {
2466
+ if (!body) return null;
2467
+ try {
2468
+ const parsed = JSON.parse(body);
2469
+ if (parsed?.[BACKGROUND_PROCESSOR_FIELD] === BACKGROUND_PROCESSOR_A2A) {
2470
+ return A2A_PROCESS_TASK_PATH;
2471
+ }
2472
+ const route = parsed?.[BACKGROUND_PROCESSOR_ROUTE_FIELD];
2473
+ if (
2474
+ parsed?.[BACKGROUND_PROCESSOR_FIELD] === BACKGROUND_PROCESSOR_ROUTE &&
2475
+ typeof route === "string" &&
2476
+ route.startsWith("/") &&
2477
+ route.includes("/api/_agent-native-background/") &&
2478
+ !route.includes("?") &&
2479
+ !route.includes("#")
2480
+ ) {
2481
+ return route;
2482
+ }
2483
+ return null;
2484
+ } catch {
2485
+ return null;
2486
+ }
2487
+ }
2488
+
2489
+ let cachedHandler;
2490
+
2491
+ // Netlify v2 invokes this as (request, context). The Nitro netlify handler is a
2492
+ // Web-standard \`async (Request) => Response\` (see nitro/presets/netlify/runtime).
2493
+ // This function declares NO custom \`config.path\`, so it is reached at its
2494
+ // DEFAULT url (/.netlify/functions/${backgroundName}). The Nitro router only
2495
+ // knows the framework route, so we REWRITE the incoming pathname to
2496
+ // PROCESS_RUN_PATH before delegating. Method, ALL headers (the HMAC
2497
+ // Authorization: Bearer MUST survive — the plugin verifies it) and the body are
2498
+ // preserved by cloning the incoming Request with only its URL pathname set.
2499
+ export default async function handler(request, context) {
2500
+ try {
2501
+ cachedHandler ??= (await import("./main.mjs")).default;
2502
+ const url = new URL(request.url);
2503
+ // Read the body once and pass it through. GET/HEAD have no body.
2504
+ const method = request.method || "POST";
2505
+ const hasBody = method !== "GET" && method !== "HEAD";
2506
+ const body = hasBody ? await request.text() : undefined;
2507
+ url.pathname = processorPathFromBody(body) || PROCESS_RUN_PATH;
2508
+ const rewritten = new Request(url.toString(), {
2509
+ method,
2510
+ headers: request.headers,
2511
+ body,
2512
+ });
2513
+ // Netlify Functions v2 invokes the handler as (request, context); the Nitro
2514
+ // netlify handler accepts (request[, context]). Pass context through so a
2515
+ // handler that uses it (e.g. waitUntil) does not trip over an undefined arg
2516
+ // before it ever routes the request.
2517
+ return await cachedHandler(rewritten, context);
2518
+ } catch (err) {
2519
+ // Netlify already returned 202 for this background invocation and DISCARDS
2520
+ // this return, so a throw here is otherwise INVISIBLE — it would only surface
2521
+ // downstream as the reaper's "worker never claimed the run". Log it loudly
2522
+ // for the function log; the FOREGROUND circuit-breaker (production-agent.ts)
2523
+ // is what recovers the run by executing it inline when no worker claims.
2524
+ console.error(
2525
+ "[agent-background] wrapper failed before reaching the route:",
2526
+ (err && err.stack) || err,
2527
+ );
2528
+ throw err;
2529
+ }
2530
+ }
2531
+
2532
+ export const config = {
2533
+ name: "agent background handler",
2534
+ generator: "agent-native build",
2535
+ // background: true makes Netlify invoke this ASYNCHRONOUSLY (immediate HTTP
2536
+ // 202 ack) with the 15-minute budget (Netlify docs:
2537
+ // build/functions/background-functions + build/functions/api). We declare NO
2538
+ // custom path, so the function keeps its DEFAULT url
2539
+ // /.netlify/functions/${backgroundName}; the Nitro \`server\` /* catch-all
2540
+ // already excludes /.netlify/* so that default url is never shadowed by the
2541
+ // synchronous function. The foreground dispatches to that default url.
2542
+ background: true,
2543
+ nodeBundler: "none",
2544
+ includedFiles: ["**"],
2545
+ preferStatic: false,
2546
+ };
2547
+ `;
2548
+ fs.writeFileSync(path.join(dest, `${backgroundName}.mjs`), entry);
2549
+ console.log(
2550
+ `[build] Emitted durable-background function "${backgroundName}" into the ` +
2551
+ `scanned dir .netlify/functions-internal with config { background:true } ` +
2552
+ `and NO custom path — reachable at its default url ` +
2553
+ `/.netlify/functions/${backgroundName} (never shadowed; the server /* ` +
2554
+ `catch-all already excludes /.netlify/*). REQUIRES real-deploy ` +
2555
+ `verification of Netlify async (202) invocation — see ` +
2556
+ `docs/design/durable-agent-runs.md.`,
2557
+ );
2558
+ }
2559
+
2560
+ /**
2561
+ * Nitro's Netlify preset can emit a harmful fallback rewrite to
2562
+ * `/.netlify/functions/server`. With `config.path: "/*"`, that default URL is
2563
+ * removed, so the rewrite publishes platform 404s. Single-template deploys keep
2564
+ * Nitro's `preferStatic: true` so hashed `/assets/*` files in dist win before
2565
+ * the SSR catch-all runs.
2566
+ */
2567
+ const NETLIFY_DEFAULT_FUNCTION_URL_REDIRECT =
2568
+ "/* /.netlify/functions/server 200";
2569
+
2570
+ function hasBareYjsRuntimeImport(source: string): boolean {
2571
+ return /\b(?:from\s*|import\s*\(\s*|import\s*)["']yjs(?:\/[^"']*)?["']/.test(
2572
+ source,
2573
+ );
2574
+ }
2575
+
2576
+ const NETLIFY_BUNDLED_INGESTION_DEPENDENCIES = [
2577
+ "fast-xml-parser",
2578
+ "jszip",
2579
+ "officeparser",
2580
+ "pdf-parse",
2581
+ "pdfjs-dist",
2582
+ ] as const;
2583
+
2584
+ function hasBareRuntimeImport(source: string, packageName: string): boolean {
2585
+ const escapedPackageName = packageName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2586
+ return new RegExp(
2587
+ `\\b(?:from\\s*|import\\s*\\(\\s*|import\\s*)(["'\\\`])${escapedPackageName}(?:/[^"'\\\`]+)?\\1`,
2588
+ ).test(source);
2589
+ }
2590
+
2591
+ function hasUnsupportedYjsSubpathImport(source: string): boolean {
2592
+ return /\b(?:from\s*|import\s*\(\s*|import\s*)["']yjs\/[^"']*["']/.test(
2593
+ source,
2594
+ );
2595
+ }
2596
+
2597
+ function hasBundledVitestRuntime(source: string): boolean {
2598
+ return (
2599
+ /["'`]@vitest\//.test(source) ||
2600
+ /["'`]vitest\/(?:dist|src)\//.test(source) ||
2601
+ /__vitest_\d+__/.test(source)
2602
+ );
2603
+ }
2604
+
2605
+ function walkServerJavaScriptFiles(
2606
+ dir: string,
2607
+ onFile: (filePath: string) => void,
2608
+ ): void {
2609
+ if (!fs.existsSync(dir)) return;
2610
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
2611
+ const entryPath = path.join(dir, entry.name);
2612
+ if (entry.isDirectory()) {
2613
+ walkServerJavaScriptFiles(entryPath, onFile);
2614
+ continue;
2615
+ }
2616
+ if (/\.(?:[cm]?js)$/.test(entry.name)) onFile(entryPath);
2617
+ }
2618
+ }
2619
+
2620
+ /**
2621
+ * Nitro receives the React Router SSR build as prebuilt chunks, so its normal
2622
+ * dependency resolver cannot reliably fold the preserved bare `yjs` imports
2623
+ * into the same module instance used by core's server collaboration code.
2624
+ * Keep Yjs external through Nitro, bundle its complete public ESM surface once,
2625
+ * then point every emitted server chunk at that one portable runtime module.
2626
+ */
2627
+ export function bundleYjsRuntimeForServerlessOutput(
2628
+ serverDir: string,
2629
+ projectCwd: string,
2630
+ ): string[] {
2631
+ const bareImports: string[] = [];
2632
+ const unsupportedSubpathImports: string[] = [];
2633
+
2634
+ walkServerJavaScriptFiles(serverDir, (filePath) => {
2635
+ const source = fs.readFileSync(filePath, "utf-8");
2636
+ if (!hasBareYjsRuntimeImport(source)) return;
2637
+ if (hasUnsupportedYjsSubpathImport(source)) {
2638
+ unsupportedSubpathImports.push(filePath);
2639
+ return;
2640
+ }
2641
+ bareImports.push(filePath);
2642
+ });
2643
+
2644
+ if (unsupportedSubpathImports.length > 0) {
2645
+ throw new Error(
2646
+ `[deploy] Serverless output left unsupported yjs subpath imports in ${unsupportedSubpathImports.join(", ")}`,
2647
+ );
2648
+ }
2649
+ if (bareImports.length === 0) return [];
2650
+
2651
+ const bundledYjsPath = path.join(serverDir, "_libs", "yjs-runtime.mjs");
2652
+ fs.mkdirSync(path.dirname(bundledYjsPath), { recursive: true });
2653
+ execFileSync(
2654
+ findEsbuild(),
2655
+ [
2656
+ resolveNitroBundledYjsEntry(),
2657
+ "--bundle",
2658
+ "--format=esm",
2659
+ "--platform=node",
2660
+ "--target=node22",
2661
+ "--minify",
2662
+ `--outfile=${bundledYjsPath}`,
2663
+ ],
2664
+ { cwd: projectCwd, stdio: "pipe" },
2665
+ );
2666
+
2667
+ for (const filePath of bareImports) {
2668
+ const bundledImport = path
2669
+ .relative(path.dirname(filePath), bundledYjsPath)
2670
+ .split(path.sep)
2671
+ .join("/");
2672
+ const relativeBundledImport = bundledImport.startsWith(".")
2673
+ ? bundledImport
2674
+ : `./${bundledImport}`;
2675
+ const source = fs.readFileSync(filePath, "utf-8");
2676
+ fs.writeFileSync(
2677
+ filePath,
2678
+ source.replace(
2679
+ /(\b(?:from\s*|import\s*\(\s*|import\s*))(["'])yjs\2/g,
2680
+ (_match, importPrefix: string, quote: string) =>
2681
+ `${importPrefix}${quote}${relativeBundledImport}${quote}`,
2682
+ ),
2683
+ );
2684
+ }
2685
+
2686
+ return bareImports;
2687
+ }
2688
+
2689
+ export function assertSingleTemplateNetlifyBuildOutput(
2690
+ projectCwd: string,
2691
+ ): void {
2692
+ const failures: string[] = [];
2693
+ const publishDir = path.join(projectCwd, "dist");
2694
+ const workspaceAppBasePath =
2695
+ process.env.AGENT_NATIVE_WORKSPACE === "1" ||
2696
+ process.env.VITE_AGENT_NATIVE_WORKSPACE === "1"
2697
+ ? normalizeConfiguredAppBasePath()
2698
+ : "";
2699
+ const assetsRelativeDir = workspaceAppBasePath
2700
+ ? path.join(workspaceAppBasePath.slice(1), "assets")
2701
+ : "assets";
2702
+ const assetsDisplayPath = path
2703
+ .join("dist", assetsRelativeDir)
2704
+ .split(path.sep)
2705
+ .join("/");
2706
+ const redirectsPath = path.join(publishDir, "_redirects");
2707
+ const internalDir = path.join(projectCwd, ".netlify", "functions-internal");
2708
+ const serverDir = path.join(internalDir, "server");
2709
+ const serverEntryPath = path.join(serverDir, "server.mjs");
2710
+ const serverMainPath = path.join(serverDir, "main.mjs");
2711
+
2712
+ if (!fs.existsSync(publishDir)) {
2713
+ failures.push("missing publish directory: dist");
2714
+ } else {
2715
+ const assetsDir = path.join(publishDir, assetsRelativeDir);
2716
+ if (
2717
+ !fs.existsSync(assetsDir) ||
2718
+ fs.readdirSync(assetsDir).every((name) => name.startsWith("."))
2719
+ ) {
2720
+ failures.push(
2721
+ `${assetsDisplayPath} is missing hashed client assets — the publish dir would load an infinite spinner`,
2722
+ );
2723
+ }
2724
+ }
2725
+
2726
+ if (fs.existsSync(publishDir) && fs.existsSync(redirectsPath)) {
2727
+ const redirects = fs.readFileSync(redirectsPath, "utf-8");
2728
+ if (
2729
+ redirects
2730
+ .split(/\r?\n/)
2731
+ .some(
2732
+ (line) =>
2733
+ line.trim().replace(/\s+/g, " ") ===
2734
+ NETLIFY_DEFAULT_FUNCTION_URL_REDIRECT,
2735
+ )
2736
+ ) {
2737
+ failures.push(
2738
+ 'dist/_redirects must not contain "/* /.netlify/functions/server 200" — Nitro\'s custom config.path: "/*" removes that default function URL',
2739
+ );
2740
+ }
2741
+ }
2742
+
2743
+ if (!fs.existsSync(serverDir)) {
2744
+ failures.push(
2745
+ "missing scanned Netlify server function: .netlify/functions-internal/server",
2746
+ );
2747
+ }
2748
+
2749
+ if (!fs.existsSync(serverMainPath)) {
2750
+ failures.push(
2751
+ "missing Netlify server bundle: .netlify/functions-internal/server/main.mjs",
2752
+ );
2753
+ }
2754
+
2755
+ if (!fs.existsSync(serverEntryPath)) {
2756
+ failures.push(
2757
+ "missing Netlify server entry: .netlify/functions-internal/server/server.mjs",
2758
+ );
2759
+ } else {
2760
+ const serverEntry = fs.readFileSync(serverEntryPath, "utf-8");
2761
+ if (!/\bpath\s*:\s*["']\/\*["']/.test(serverEntry)) {
2762
+ failures.push(
2763
+ 'Netlify server entry is missing the "/*" catch-all function path',
2764
+ );
2765
+ }
2766
+ if (!serverEntry.includes('"/.netlify/*"')) {
2767
+ failures.push(
2768
+ 'Netlify server catch-all is missing the "/.netlify/*" exclusion',
2769
+ );
2770
+ }
2771
+ if (!serverEntry.includes("./main.mjs")) {
2772
+ failures.push(
2773
+ "Netlify server entry does not reference the generated main.mjs bundle",
2774
+ );
2775
+ }
2776
+ if (!/\bpreferStatic:\s*true\b/.test(serverEntry)) {
2777
+ failures.push(
2778
+ "Netlify server entry must keep preferStatic: true so /assets/* is served from dist before the SSR catch-all",
2779
+ );
2780
+ }
2781
+ }
2782
+
2783
+ // Netlify's function packager does not install arbitrary runtime package
2784
+ // imports left in Nitro chunks. A bare Yjs import here would deploy
2785
+ // successfully but fail on the first SSR request with ERR_MODULE_NOT_FOUND.
2786
+ // Keep this check adjacent to the output guard so both local builds and CI
2787
+ // reject that artifact before it reaches Netlify.
2788
+ const bareYjsImports: string[] = [];
2789
+ walkServerJavaScriptFiles(serverDir, (filePath) => {
2790
+ if (hasBareYjsRuntimeImport(fs.readFileSync(filePath, "utf-8"))) {
2791
+ bareYjsImports.push(path.relative(projectCwd, filePath));
2792
+ }
2793
+ });
2794
+ if (bareYjsImports.length > 0) {
2795
+ failures.push(
2796
+ `Netlify server bundle leaves yjs as a runtime import: ${bareYjsImports.join(", ")}`,
2797
+ );
2798
+ }
2799
+
2800
+ const bareIngestionImports: string[] = [];
2801
+ walkServerJavaScriptFiles(serverDir, (filePath) => {
2802
+ const source = fs.readFileSync(filePath, "utf-8");
2803
+ for (const dependency of NETLIFY_BUNDLED_INGESTION_DEPENDENCIES) {
2804
+ if (hasBareRuntimeImport(source, dependency)) {
2805
+ bareIngestionImports.push(
2806
+ `${dependency} in ${path.relative(projectCwd, filePath)}`,
2807
+ );
2808
+ }
2809
+ }
2810
+ });
2811
+ if (bareIngestionImports.length > 0) {
2812
+ failures.push(
2813
+ `Netlify server bundle leaves ingestion dependencies as runtime imports: ${bareIngestionImports.join(", ")}`,
2814
+ );
2815
+ }
2816
+
2817
+ // Nitro's `_libs/yjs.mjs` is a private tree-shaken chunk, not a package
2818
+ // facade. Repointing a prebuilt SSR chunk at it can request public exports
2819
+ // (notably `Text`) that the private chunk did not retain. The controlled
2820
+ // serverless pass must instead target the complete `yjs-runtime.mjs` bundle.
2821
+ const privateYjsImports: string[] = [];
2822
+ walkServerJavaScriptFiles(serverDir, (filePath) => {
2823
+ if (
2824
+ /\b(?:from\s*|import\s*\(\s*|import\s*)(["'])[^"']*_libs\/yjs\.mjs\1/.test(
2825
+ fs.readFileSync(filePath, "utf-8"),
2826
+ )
2827
+ ) {
2828
+ privateYjsImports.push(path.relative(projectCwd, filePath));
2829
+ }
2830
+ });
2831
+ if (privateYjsImports.length > 0) {
2832
+ failures.push(
2833
+ `Netlify server bundle imports Nitro's internal tree-shaken _libs/yjs.mjs: ${privateYjsImports.join(", ")}`,
2834
+ );
2835
+ }
2836
+
2837
+ // React Router's filesystem route discovery can accidentally treat a
2838
+ // co-located *.test.ts route as production code. That bundles Vitest into
2839
+ // SSR and only fails when the first request executes the test helpers.
2840
+ const bundledVitestRuntime: string[] = [];
2841
+ walkServerJavaScriptFiles(serverDir, (filePath) => {
2842
+ if (hasBundledVitestRuntime(fs.readFileSync(filePath, "utf-8"))) {
2843
+ bundledVitestRuntime.push(path.relative(projectCwd, filePath));
2844
+ }
2845
+ });
2846
+ if (bundledVitestRuntime.length > 0) {
2847
+ failures.push(
2848
+ `Netlify server bundle contains Vitest test runtime code: ${bundledVitestRuntime.join(", ")}`,
2849
+ );
2850
+ }
2851
+
2852
+ if (isDurableBackgroundDeployEnabled()) {
2853
+ const backgroundDir = path.join(
2854
+ internalDir,
2855
+ AGENT_BACKGROUND_FUNCTION_NAME,
2856
+ );
2857
+ const backgroundEntryPath = path.join(
2858
+ backgroundDir,
2859
+ `${AGENT_BACKGROUND_FUNCTION_NAME}.mjs`,
2860
+ );
2861
+ if (!fs.existsSync(backgroundEntryPath)) {
2862
+ failures.push(
2863
+ `durable background is enabled but ${path.relative(
2864
+ projectCwd,
2865
+ backgroundEntryPath,
2866
+ )} was not emitted`,
2867
+ );
2868
+ } else {
2869
+ const backgroundEntry = fs.readFileSync(backgroundEntryPath, "utf-8");
2870
+ if (!/\bbackground\s*:\s*true\b/.test(backgroundEntry)) {
2871
+ failures.push(
2872
+ `durable background entry ${path.relative(
2873
+ projectCwd,
2874
+ backgroundEntryPath,
2875
+ )} is missing background: true`,
2876
+ );
2877
+ }
2878
+ if (/^\s*path\s*:/m.test(backgroundEntry)) {
2879
+ failures.push(
2880
+ `durable background entry ${path.relative(
2881
+ projectCwd,
2882
+ backgroundEntryPath,
2883
+ )} must not declare a custom path`,
2884
+ );
2885
+ }
2886
+ }
2887
+ }
2888
+
2889
+ if (failures.length > 0) {
2890
+ throw new Error(
2891
+ "[deploy] Netlify deploy guard failed; refusing to publish an output " +
2892
+ "that would likely serve Netlify 404s:\n" +
2893
+ failures.map((failure) => `- ${failure}`).join("\n"),
2894
+ );
2895
+ }
2896
+
2897
+ console.log(
2898
+ "[deploy] Netlify deploy guard passed: publish dir and catch-all server function are present.",
2899
+ );
2900
+ }
2901
+
2902
+ /**
2903
+ * Strip the harmful single-template catch-all rewrite that points at
2904
+ * `/.netlify/functions/server`. Nitro declares `config.path: "/*"`, which
2905
+ * removes the default function URL, so rewriting to that URL publishes
2906
+ * Netlify platform 404s. Preserve any real redirects from `public/_redirects`.
2907
+ */
2908
+ export function writeSingleTemplateNetlifyRedirects(projectCwd: string): void {
2909
+ const publishDir = path.join(projectCwd, "dist");
2910
+ const redirectsPath = path.join(publishDir, "_redirects");
2911
+ if (!fs.existsSync(redirectsPath)) return;
2912
+
2913
+ const existing = fs.readFileSync(redirectsPath, "utf-8");
2914
+ const kept: string[] = [];
2915
+ let removed = 0;
2916
+
2917
+ for (const line of existing.split(/\r?\n/)) {
2918
+ const normalized = line.trim().replace(/\s+/g, " ");
2919
+ if (
2920
+ normalized === NETLIFY_DEFAULT_FUNCTION_URL_REDIRECT ||
2921
+ normalized ===
2922
+ "# Generated by agent-native build for Netlify single-template deploys" ||
2923
+ normalized ===
2924
+ "# Static files are served first; dynamic routes fall through to the server function."
2925
+ ) {
2926
+ removed += 1;
2927
+ continue;
2928
+ }
2929
+ kept.push(line);
2930
+ }
2931
+
2932
+ while (kept.length > 0 && kept[kept.length - 1].trim() === "") {
2933
+ kept.pop();
2934
+ }
2935
+
2936
+ if (removed === 0) return;
2937
+
2938
+ if (kept.every((line) => line.trim() === "")) {
2939
+ fs.rmSync(redirectsPath, { force: true });
2940
+ } else {
2941
+ fs.writeFileSync(redirectsPath, kept.join("\n").trimEnd() + "\n");
2942
+ }
2943
+ console.log(
2944
+ '[deploy] Removed Netlify fallback rewrite to /.netlify/functions/server (incompatible with Nitro config.path: "/*").',
2945
+ );
2946
+ }
2947
+
2948
+ function copyInstalledLibsqlNativePackages(serverDir: string | undefined) {
2949
+ if (!serverDir || !fs.existsSync(serverDir)) return;
2950
+ const nodeModulesRoots = nodeModulesAncestors(cwd);
2951
+ const destScopeDir = path.join(serverDir, "node_modules", "@libsql");
2952
+ let copied = 0;
2953
+
2954
+ for (const packageName of LIBSQL_NATIVE_PACKAGE_NAMES) {
2955
+ const src = findInstalledLibsqlNativePackage(nodeModulesRoots, packageName);
2956
+ if (!src) continue;
2957
+
2958
+ copyDir(src, path.join(destScopeDir, packageName));
2959
+ copied += 1;
2960
+ }
2961
+
2962
+ if (copied > 0) {
2963
+ console.log(
2964
+ `[deploy] Copied ${copied} installed libsql native package(s) into the server bundle.`,
2965
+ );
2966
+ }
2967
+ }
2968
+
2969
+ function copyInstalledResvgPackages(serverDir: string | undefined) {
2970
+ if (!serverDir || !fs.existsSync(serverDir)) return;
2971
+ const packages = findInstalledResvgPackages(nodeModulesAncestors(cwd));
2972
+ if (packages.length === 0) return;
2973
+
2974
+ const destScopeDir = path.join(serverDir, "node_modules", RESVG_SCOPE);
2975
+ for (const { packageName, packageDir } of packages) {
2976
+ copyDir(packageDir, path.join(destScopeDir, packageName));
2977
+ }
2978
+
2979
+ console.log(
2980
+ `[deploy] Copied ${packages.length} resvg package(s) into the server bundle for OG image rendering.`,
2981
+ );
2982
+ }
2983
+
2984
+ function copyInstalledFfmpegStaticPackage(serverDir: string | undefined) {
2985
+ if (!serverDir || !fs.existsSync(serverDir)) return;
2986
+ const nodeModulesRoots = nodeModulesAncestors(cwd);
2987
+ if (!shouldBundleFfmpegStaticForServerless()) {
2988
+ if (hasInstalledFfmpegStaticPackage(nodeModulesRoots)) {
2989
+ console.warn(
2990
+ `[deploy] ffmpeg-static installs a ${process.platform}-${process.arch} binary, but the serverless runtime architecture is not known to match it; ` +
2991
+ "set AGENT_NATIVE_SERVERLESS_FFMPEG_ARCH=x64 or arm64 to bundle a matching binary, otherwise server-side media transcription fallback will require FFMPEG_PATH or a system ffmpeg.",
2992
+ );
2993
+ }
2994
+ return;
2995
+ }
2996
+
2997
+ const src = findInstalledFfmpegStaticPackage(nodeModulesRoots);
2998
+ if (!src) {
2999
+ if (hasInstalledFfmpegStaticPackage(nodeModulesRoots)) {
3000
+ console.warn(
3001
+ "[deploy] ffmpeg-static is installed without a downloaded ffmpeg binary; " +
3002
+ "server-side media transcription fallback will require FFMPEG_PATH or a system ffmpeg.",
3003
+ );
3004
+ }
3005
+ return;
3006
+ }
3007
+
3008
+ copyDir(
3009
+ src,
3010
+ path.join(serverDir, "node_modules", FFMPEG_STATIC_PACKAGE_NAME),
3011
+ );
3012
+ console.log(
3013
+ "[deploy] Copied ffmpeg-static into the server bundle for media transcription fallback.",
3014
+ );
3015
+ }
3016
+
3017
+ /**
3018
+ * Nitro's file tracer can over-include optional desktop/dev packages that are
3019
+ * present in a monorepo install but cannot run in serverless. Netlify installs
3020
+ * the generated per-function package.json before upload; if `electron` remains
3021
+ * there, the function can exceed Netlify's 250 MB unzipped size limit even
3022
+ * though the server bundle never imports Electron at runtime.
3023
+ */
3024
+ export function sanitizeServerlessFunctionPackageManifest(
3025
+ functionDir: string | undefined,
3026
+ ): void {
3027
+ if (!functionDir || !fs.existsSync(functionDir)) return;
3028
+
3029
+ const packageJsonPath = path.join(functionDir, "package.json");
3030
+ if (!fs.existsSync(packageJsonPath)) return;
3031
+
3032
+ let packageJson: Record<string, unknown>;
3033
+ try {
3034
+ packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
3035
+ } catch {
3036
+ return;
3037
+ }
3038
+
3039
+ let removed = 0;
3040
+ const depFields = [
3041
+ "dependencies",
3042
+ "optionalDependencies",
3043
+ "devDependencies",
3044
+ "peerDependencies",
3045
+ ];
3046
+ for (const field of depFields) {
3047
+ const deps = packageJson[field];
3048
+ if (!deps || typeof deps !== "object" || Array.isArray(deps)) continue;
3049
+ const depRecord = deps as Record<string, unknown>;
3050
+ for (const packageName of SERVERLESS_FUNCTION_PACKAGE_DENYLIST) {
3051
+ if (Object.prototype.hasOwnProperty.call(depRecord, packageName)) {
3052
+ delete depRecord[packageName];
3053
+ removed++;
3054
+ }
3055
+ }
3056
+ if (Object.keys(depRecord).length === 0) {
3057
+ delete packageJson[field];
3058
+ }
3059
+ }
3060
+
3061
+ const nodeModulesDir = path.join(functionDir, "node_modules");
3062
+ for (const packageName of SERVERLESS_FUNCTION_PACKAGE_DENYLIST) {
3063
+ const packageDir = path.join(nodeModulesDir, ...packageName.split("/"));
3064
+ if (fs.existsSync(packageDir)) {
3065
+ fs.rmSync(packageDir, { recursive: true, force: true });
3066
+ removed++;
3067
+ }
3068
+ }
3069
+
3070
+ if (removed > 0) {
3071
+ fs.writeFileSync(
3072
+ packageJsonPath,
3073
+ `${JSON.stringify(packageJson, null, 2)}\n`,
3074
+ );
3075
+ console.log(
3076
+ `[deploy] Removed ${removed} desktop-only package reference(s) from ${path.relative(cwd, functionDir)}.`,
3077
+ );
3078
+ }
3079
+ }
3080
+
3081
+ /**
3082
+ * Create stub directories for dangling platform-specific optional dependency
3083
+ * symlinks in the pnpm store.
3084
+ *
3085
+ * pnpm's store at `node_modules/.pnpm/<pkg>@<ver>/node_modules/<pkg>/<dep>`
3086
+ * contains symlinks for ALL optional deps declared by a package, but only
3087
+ * installs the ones matching the current OS/CPU as real packages. The other
3088
+ * symlinks dangle — their targets at `.pnpm/<scope>+<pkg>@<ver>/node_modules/...`
3089
+ * don't exist.
3090
+ *
3091
+ * Nitro's `nitro:externals` plugin (via nf3 / @vercel/nft) walks
3092
+ * optionalDependencies when tracing files and calls `realpath` on them, which
3093
+ * throws ENOENT on dangling targets. This blocks builds with presets like
3094
+ * netlify / vercel / aws-lambda on macOS when packages like `libsql` declare
3095
+ * Linux-only platform variants as optional deps.
3096
+ *
3097
+ * Fix: walk `node_modules/.pnpm/` and for every dangling symlink under
3098
+ * `<pkg>/node_modules/<scope>/<dep>`, create the symlink's target as a tiny
3099
+ * stub directory containing just a valid `package.json`. The tracer can now
3100
+ * `realpath` and read the package.json without throwing — the stub is empty
3101
+ * so no binary is bundled (which is what we want: we're building from macOS,
3102
+ * the target deploy platform will install its own native binary).
3103
+ */
3104
+ function createDanglingOptionalDepStubs() {
3105
+ // In pnpm monorepos, the store may live at the workspace root rather than
3106
+ // in the template dir. Walk up from `cwd` to find every `.pnpm` directory.
3107
+ const pnpmRoots: string[] = [];
3108
+ let dir = cwd;
3109
+ while (true) {
3110
+ const candidate = path.join(dir, "node_modules", ".pnpm");
3111
+ if (fs.existsSync(candidate)) pnpmRoots.push(candidate);
3112
+ const parent = path.dirname(dir);
3113
+ if (parent === dir) break;
3114
+ dir = parent;
3115
+ }
3116
+ if (pnpmRoots.length === 0) return;
3117
+
3118
+ let stubsCreated = 0;
3119
+
3120
+ for (const pnpmRoot of pnpmRoots) {
3121
+ let pkgDirs: string[];
3122
+ try {
3123
+ pkgDirs = fs.readdirSync(pnpmRoot);
3124
+ } catch {
3125
+ continue;
3126
+ }
3127
+
3128
+ for (const pkgDir of pkgDirs) {
3129
+ // e.g. `libsql@0.5.29`, `@libsql+client@0.15.15`
3130
+ const innerNm = path.join(pnpmRoot, pkgDir, "node_modules");
3131
+ if (!fs.existsSync(innerNm)) continue;
3132
+
3133
+ let innerEntries: fs.Dirent[];
3134
+ try {
3135
+ innerEntries = fs.readdirSync(innerNm, { withFileTypes: true });
3136
+ } catch {
3137
+ continue;
3138
+ }
3139
+
3140
+ for (const entry of innerEntries) {
3141
+ // Top-level entry: either `foo` (unscoped) or `@scope` (scoped)
3142
+ const entryPath = path.join(innerNm, entry.name);
3143
+ const candidates: { symlinkPath: string; pkgName: string }[] = [];
3144
+ if (entry.name.startsWith("@")) {
3145
+ // Scoped — iterate children
3146
+ let scopedChildren: fs.Dirent[];
3147
+ try {
3148
+ scopedChildren = fs.readdirSync(entryPath, {
3149
+ withFileTypes: true,
3150
+ });
3151
+ } catch {
3152
+ continue;
3153
+ }
3154
+ for (const child of scopedChildren) {
3155
+ candidates.push({
3156
+ symlinkPath: path.join(entryPath, child.name),
3157
+ pkgName: `${entry.name}/${child.name}`,
3158
+ });
3159
+ }
3160
+ } else {
3161
+ candidates.push({ symlinkPath: entryPath, pkgName: entry.name });
3162
+ }
3163
+
3164
+ for (const { symlinkPath, pkgName } of candidates) {
3165
+ let isSymlink = false;
3166
+ try {
3167
+ isSymlink = fs.lstatSync(symlinkPath).isSymbolicLink();
3168
+ } catch {
3169
+ continue;
3170
+ }
3171
+ if (!isSymlink) continue;
3172
+
3173
+ // Check if the symlink target exists
3174
+ try {
3175
+ fs.statSync(symlinkPath);
3176
+ continue; // Target exists — nothing to do
3177
+ } catch {
3178
+ // Dangling symlink — create a stub at the target
3179
+ }
3180
+
3181
+ let linkTarget: string;
3182
+ try {
3183
+ linkTarget = fs.readlinkSync(symlinkPath);
3184
+ } catch {
3185
+ continue;
3186
+ }
3187
+ const resolvedTarget = path.resolve(
3188
+ path.dirname(symlinkPath),
3189
+ linkTarget,
3190
+ );
3191
+
3192
+ try {
3193
+ fs.mkdirSync(resolvedTarget, { recursive: true });
3194
+ const stubPkgJson = {
3195
+ name: pkgName,
3196
+ version: "0.0.0-stub",
3197
+ description:
3198
+ "Empty stub created by @agent-native/core deploy build to satisfy nitro's file tracer on platforms where this optional dep is not installed.",
3199
+ };
3200
+ fs.writeFileSync(
3201
+ path.join(resolvedTarget, "package.json"),
3202
+ JSON.stringify(stubPkgJson, null, 2),
3203
+ );
3204
+ stubsCreated++;
3205
+ } catch {
3206
+ // Best-effort — ignore failures
3207
+ }
3208
+ }
3209
+ }
3210
+ }
3211
+ }
3212
+
3213
+ if (stubsCreated > 0) {
3214
+ console.log(
3215
+ `[deploy] Created ${stubsCreated} stub package dir(s) for dangling optional deps (platform-specific binaries not installed on this host).`,
3216
+ );
3217
+ }
3218
+ }
3219
+
3220
+ /**
3221
+ * Build for any non-Cloudflare preset using Nitro's programmatic build API.
3222
+ * Handles netlify, vercel, deno_deploy, aws-lambda, and all other targets.
3223
+ */
3224
+ export interface NitroBuildHooks {
3225
+ prepare: (nitro: any) => Promise<void>;
3226
+ copyPublicAssets: (nitro: any) => Promise<void>;
3227
+ nitroBuild: (nitro: any) => Promise<void>;
3228
+ }
3229
+
3230
+ export interface NitroBuildPipelineOptions {
3231
+ nitro: any;
3232
+ hooks: NitroBuildHooks;
3233
+ clientDir: string;
3234
+ publicOutputDir: string | undefined;
3235
+ appBasePath: string;
3236
+ cwd: string;
3237
+ }
3238
+
3239
+ /**
3240
+ * Run Nitro's lifecycle in the order required to ship a working React Router
3241
+ * framework-mode build.
3242
+ *
3243
+ * The critical ordering constraint is that the React Router client build must
3244
+ * be copied into `publicOutputDir` *before* `nitroBuild` runs. Nitro generates
3245
+ * the static-asset manifest baked into the server bundle by globbing
3246
+ * `publicDir` during the server build; files copied in after that point exist
3247
+ * on disk but are invisible to the runtime `serveStatic` handler. Every
3248
+ * /assets/* request then falls through to the SSR catch-all, which 404s
3249
+ * anything with a file extension.
3250
+ */
3251
+ export async function runNitroBuildPipeline(
3252
+ opts: NitroBuildPipelineOptions,
3253
+ ): Promise<void> {
3254
+ const { nitro, hooks, clientDir, publicOutputDir, appBasePath, cwd } = opts;
3255
+ const hasClientBuild = fs.existsSync(clientDir) && Boolean(publicOutputDir);
3256
+
3257
+ if (hasClientBuild) {
3258
+ // Install hashed-asset route rules before Nitro prepares platform output.
3259
+ // Some presets materialize headers during prepare/copy phases, not only in
3260
+ // nitroBuild; adding these later leaves Netlify/Vercel static assets without
3261
+ // the one-year immutable CDN policy even though the runtime manifest works.
3262
+ nitro.options.routeRules ??= {};
3263
+ addImmutableAssetRouteRulesForClientBuild(
3264
+ nitro.options.routeRules,
3265
+ clientDir,
3266
+ appBasePath,
3267
+ );
3268
+ }
3269
+
3270
+ await hooks.prepare(nitro);
3271
+ await hooks.copyPublicAssets(nitro);
3272
+
3273
+ if (hasClientBuild && publicOutputDir) {
3274
+ copyDir(clientDir, publicOutputDir);
3275
+ if (appBasePath) {
3276
+ copyDir(clientDir, path.join(publicOutputDir, appBasePath.slice(1)));
3277
+ }
3278
+ console.log(
3279
+ `[deploy] Copied client assets to ${path.relative(cwd, publicOutputDir)}`,
3280
+ );
3281
+ }
3282
+
3283
+ await hooks.nitroBuild(nitro);
3284
+ }
3285
+
3286
+ /**
3287
+ * Browser-only diagram/drawing renderers that execute `window`-touching code at
3288
+ * module-evaluation time. They are rendered exclusively client-side — core's
3289
+ * `MermaidBlock` and templates' Excalidraw slides mount them inside `useEffect` /
3290
+ * `React.lazy`, never during SSR — so the server never needs the real module.
3291
+ *
3292
+ * Keep this list to libraries that are *provably never* invoked on the server.
3293
+ * Node-only deps that DO run server-side (pdf-parse, @google/genai, canvas, …)
3294
+ * must NOT go here — see `heavyClientExternals` for the edge-worker externals.
3295
+ */
3296
+ const BROWSER_ONLY_SERVER_LIBS = [
3297
+ "@excalidraw/excalidraw",
3298
+ "@excalidraw/mermaid-to-excalidraw",
3299
+ "mermaid",
3300
+ ];
3301
+
3302
+ /**
3303
+ * Dependencies Nitro itself must bundle outside the controlled serverless
3304
+ * output pass. Netlify, Vercel, and Lambda keep Yjs external through Nitro;
3305
+ * `bundleYjsRuntimeForServerlessOutput` then creates their one portable copy.
3306
+ */
3307
+ export const NITRO_SERVER_RUNTIME_BUNDLED_DEPS = ["yjs"] as const;
3308
+
3309
+ /**
3310
+ * Locate the core-owned ESM entry used by the controlled serverless bundling
3311
+ * pass. Resolving from this module keeps the build independent of whether a
3312
+ * template exposes core's transitive Yjs dependency at its own package root.
3313
+ */
3314
+ export function resolveNitroBundledYjsEntry(): string {
3315
+ const requireFromCore = createRequire(import.meta.url);
3316
+ const packageDir = path.dirname(requireFromCore.resolve("yjs/package.json"));
3317
+ const entry = path.join(packageDir, "dist", "yjs.mjs");
3318
+ if (!fs.existsSync(entry)) {
3319
+ throw new Error(`[build] Could not resolve the Yjs ESM entry at ${entry}`);
3320
+ }
3321
+ return entry;
3322
+ }
3323
+
3324
+ /**
3325
+ * Edge runtimes have no node_modules, while Node/serverless outputs only need
3326
+ * the small set above bundled to keep their package manifests traceable.
3327
+ */
3328
+ export function nitroNoExternalsForPreset(
3329
+ targetPreset: string,
3330
+ ): true | readonly string[] {
3331
+ return targetPreset.startsWith("cloudflare") ||
3332
+ targetPreset.startsWith("deno")
3333
+ ? true
3334
+ : targetPreset === "netlify" ||
3335
+ targetPreset === "vercel" ||
3336
+ targetPreset === "aws-lambda"
3337
+ ? []
3338
+ : NITRO_SERVER_RUNTIME_BUNDLED_DEPS;
3339
+ }
3340
+
3341
+ /**
3342
+ * Rolldown plugin for the Nitro server bundle that replaces the browser-only
3343
+ * renderers above with an inert proxy module.
3344
+ *
3345
+ * Why this is needed: Nitro re-bundles the server from node_modules with its own
3346
+ * Rolldown pipeline, and Rolldown merges Excalidraw into a SHARED vendor chunk
3347
+ * that the SSR render path (tiptap / radix-ui / recharts) imports *statically*.
3348
+ * That evaluates Excalidraw's top-level `window` access at function cold-start
3349
+ * and crashes every request with `ReferenceError: window is not defined` (HTTP
3350
+ * 502). The Vite SSR build already stubs these via `ssrStubPlugin` for
3351
+ * `build/server`, but that Vite plugin doesn't run during Nitro's separate
3352
+ * bundle — so mirror the same stub here.
3353
+ */
3354
+ function createBrowserOnlyServerStubPlugin() {
3355
+ const stubbed = new Set(BROWSER_ONLY_SERVER_LIBS);
3356
+ const STUB_ID = "\0agent-native-browser-only-server-stub";
3357
+ return {
3358
+ name: "agent-native-browser-only-server-stub",
3359
+ // enforce: "pre" so we intercept before Nitro's node resolver bundles the
3360
+ // real package. defu concatenates rollupConfig.plugins ahead of Nitro's own.
3361
+ resolveId(id: string) {
3362
+ // Match the bare package name or any subpath (incl. `/index.css`).
3363
+ const pkg = id
3364
+ .split("/")
3365
+ .slice(0, id.startsWith("@") ? 2 : 1)
3366
+ .join("/");
3367
+ return stubbed.has(pkg) ? STUB_ID : null;
3368
+ },
3369
+ load(id: string) {
3370
+ if (id !== STUB_ID) return null;
3371
+ // A Proxy answers any property access (default or named) with another
3372
+ // proxy, so every import shape resolves without evaluating real browser
3373
+ // code. It is never actually invoked on the server, so it never throws.
3374
+ return (
3375
+ "const handler = { get(_t, p) {" +
3376
+ " if (p === Symbol.toPrimitive) return () => '';" +
3377
+ " if (p === 'then') return undefined;" +
3378
+ " if (p === '__esModule') return true;" +
3379
+ " return new Proxy(function () {}, handler); } };" +
3380
+ "const stub = new Proxy(function () {}, handler);" +
3381
+ "export default stub;"
3382
+ );
3383
+ },
3384
+ };
3385
+ }
3386
+
3387
+ async function buildWithNitro() {
3388
+ console.log(`[deploy] Building for preset "${preset}" via Nitro...`);
3389
+ const appBasePath = normalizeConfiguredAppBasePath();
3390
+
3391
+ // Nitro runs its own server build after the React Router/Vite build. The
3392
+ // template's agent-chat plugin imports .generated/actions-registry.ts so the
3393
+ // serverless bundle has static imports for every domain action. Regenerate
3394
+ // here as well so deploy builds are not coupled to a previous Vite run or to
3395
+ // ignored local .generated files being present.
3396
+ generateActionRegistryForProject(cwd);
3397
+
3398
+ // Work around pnpm + nitro:externals (nf3) bug where dangling symlinks for
3399
+ // platform-specific optional deps cause realpath ENOENT during file tracing.
3400
+ createDanglingOptionalDepStubs();
3401
+
3402
+ const {
3403
+ createNitro,
3404
+ prepare,
3405
+ copyPublicAssets,
3406
+ build: nitroBuild,
3407
+ } = await import("nitro/builder");
3408
+
3409
+ // Resolve the React Router server build so the SSR catch-all route
3410
+ // can import "virtual:react-router/server-build" in production.
3411
+ const rrServerBuild = path.join(cwd, "build", "server", "index.js");
3412
+
3413
+ // Inline the template's AGENTS.md + .agents/skills/ content into the Nitro
3414
+ // bundle via the `virtual` config option. Nitro's internal `nitro:virtual`
3415
+ // Rollup plugin picks this up and resolves `virtual:agents-bundle` to the
3416
+ // generated ES module source. Without this, Nitro's Rolldown build (used for
3417
+ // netlify, vercel, aws-lambda, node presets) can't resolve the virtual
3418
+ // module that `server/agents-bundle.ts` imports — it silently falls through
3419
+ // to an empty bundle and the agent gets no instructions/skills at runtime.
3420
+ //
3421
+ // The Vite plugin at `vite/agents-bundle-plugin.ts` handles this for the
3422
+ // React Router client/server build (and cloudflare via esbuild rebundle),
3423
+ // but Nitro runs its OWN build from ./server/ without Vite, so it needs its
3424
+ // own virtual module registration. Both paths reuse `readAgentsBundleFromFs`
3425
+ // from `server/agents-bundle.ts` to guarantee identical content.
3426
+ const { readAgentsBundleFromFs } = await import("../server/agents-bundle.js");
3427
+ // Resolve the workspace core (if present) up front so the bundle embeds
3428
+ // enterprise-wide AGENTS.md + skills alongside the template's.
3429
+ const nitroWorkspaceCore = await getWorkspaceCoreExports(cwd);
3430
+ const nitroWorkspaceSource = nitroWorkspaceCore
3431
+ ? {
3432
+ skillsDir: nitroWorkspaceCore.skillsDir,
3433
+ agentsMdPath: nitroWorkspaceCore.agentsMdPath,
3434
+ rootDir: nitroWorkspaceCore.packageDir,
3435
+ }
3436
+ : null;
3437
+ const agentsBundleModuleSource = () => {
3438
+ const bundle = readAgentsBundleFromFs(cwd, nitroWorkspaceSource);
3439
+ return `// AUTO-GENERATED by @agent-native/core deploy build (Nitro virtual)
3440
+ // Contains the inlined AGENTS.md + .agents/skills/ content from the template,
3441
+ // merged with the workspace core's AGENTS.md + skills/ when present.
3442
+ const bundle = ${JSON.stringify(bundle)};
3443
+ export default bundle;
3444
+ `;
3445
+ };
3446
+
3447
+ // Path aliases used by templates (mirrors tsconfig + Vite config). Nitro
3448
+ // bundles server/ and actions/ with its own Rolldown pipeline that doesn't
3449
+ // see Vite's resolve.alias — so without this, action files that import
3450
+ // `@/foo` (= `app/foo`) end up with the literal `@/foo` specifier in the
3451
+ // serverless function output and crash at runtime with
3452
+ // "Cannot find package '@/foo' imported from /var/task/main.mjs".
3453
+ const appDir = path.join(cwd, "app");
3454
+ const sharedDir = path.join(cwd, "shared");
3455
+ const pathAliases: Record<string, string> = {};
3456
+ if (fs.existsSync(appDir)) pathAliases["@"] = appDir;
3457
+ if (fs.existsSync(sharedDir)) pathAliases["@shared"] = sharedDir;
3458
+
3459
+ const providedPluginsNitroPlugin = await writeProvidedPluginsNitroPlugin();
3460
+
3461
+ const nitro = await createNitro({
3462
+ rootDir: cwd,
3463
+ dev: false,
3464
+ preset,
3465
+ baseURL: appBasePath || "/",
3466
+ minify: true,
3467
+ serverDir: "./server",
3468
+ ignore: NITRO_RUNTIME_IGNORE_PATTERNS,
3469
+ alias: {
3470
+ ...pathAliases,
3471
+ ...(fs.existsSync(rrServerBuild)
3472
+ ? { "virtual:react-router/server-build": rrServerBuild }
3473
+ : {}),
3474
+ },
3475
+ virtual: {
3476
+ "virtual:agents-bundle": agentsBundleModuleSource,
3477
+ },
3478
+ replace: {
3479
+ "process.env.AGENT_NATIVE_BUILD_GA_MEASUREMENT_ID": JSON.stringify(
3480
+ process.env.GA_MEASUREMENT_ID?.trim() || "",
3481
+ ),
3482
+ },
3483
+ // Replace browser-only renderers (Excalidraw/Mermaid) with an inert proxy in
3484
+ // the server bundle. Without this, Nitro's Rolldown build pulls the real
3485
+ // Excalidraw into a shared vendor chunk imported statically by the SSR render
3486
+ // path, and its top-level `window` access crashes the function at cold-start
3487
+ // (ReferenceError: window is not defined → every request 502s). Mirrors the
3488
+ // Vite `ssrStubPlugin`, which only covers the `build/server` step.
3489
+ rollupConfig: {
3490
+ // Nitro treats the intermediate React Router SSR files as prebuilt
3491
+ // chunks, while core's server collaboration files participate in the
3492
+ // final Rolldown graph. Externalize Yjs consistently on serverless so
3493
+ // both graphs retain their public import shapes; the controlled
3494
+ // post-build pass below bundles and rewrites them to one module.
3495
+ ...(preset === "netlify" || preset === "vercel" || preset === "aws-lambda"
3496
+ ? { external: ["yjs"] }
3497
+ : {}),
3498
+ plugins: [createBrowserOnlyServerStubPlugin()],
3499
+ },
3500
+ ...(providedPluginsNitroPlugin
3501
+ ? { plugins: [providedPluginsNitroPlugin] }
3502
+ : {}),
3503
+ routeRules: mcpEmbedStaticAssetRouteRules(appBasePath),
3504
+ // Edge presets (cloudflare, deno) bundle all deps because node_modules are
3505
+ // unavailable at runtime. Ordinary Node presets bundle Yjs through Nitro.
3506
+ // Controlled serverless presets externalize it above, then emit one full
3507
+ // runtime module after Nitro has preserved every consumer's public imports.
3508
+ noExternals: nitroNoExternalsForPreset(preset),
3509
+ } as any);
3510
+
3511
+ await runNitroBuildPipeline({
3512
+ nitro,
3513
+ hooks: { prepare, copyPublicAssets, nitroBuild },
3514
+ clientDir: path.join(cwd, "build", "client"),
3515
+ publicOutputDir: nitro.options.output.publicDir,
3516
+ appBasePath,
3517
+ cwd,
3518
+ });
3519
+
3520
+ if (preset === "netlify" || preset === "vercel" || preset === "aws-lambda") {
3521
+ copyInstalledLibsqlNativePackages(nitro.options.output.serverDir);
3522
+ copyInstalledResvgPackages(nitro.options.output.serverDir);
3523
+ copyInstalledFfmpegStaticPackage(nitro.options.output.serverDir);
3524
+ sanitizeServerlessFunctionPackageManifest(nitro.options.output.serverDir);
3525
+ bundleYjsRuntimeForServerlessOutput(nitro.options.output.serverDir, cwd);
3526
+ }
3527
+
3528
+ // Durable background agent runs (default-OFF / opt-in; enable with a truthy
3529
+ // AGENT_CHAT_DURABLE_BACKGROUND). Additive ONLY: emits a SECOND Netlify
3530
+ // function whose name ends in `-background` re-exporting the same handler
3531
+ // bundle, so the chat `_process-run` POST lands on Netlify's async (15-min)
3532
+ // function. When not opted in this is a no-op and the single-function
3533
+ // deploy is byte-for-byte unchanged.
3534
+ if (preset === "netlify" && isDurableBackgroundDeployEnabled()) {
3535
+ try {
3536
+ emitSingleTemplateNetlifyBackgroundFunction(cwd);
3537
+ } catch (err) {
3538
+ console.warn(
3539
+ "[build] Failed to emit durable-background Netlify function (non-fatal):",
3540
+ err instanceof Error ? err.message : err,
3541
+ );
3542
+ }
3543
+ }
3544
+
3545
+ if (preset === "netlify") {
3546
+ writeSingleTemplateNetlifyRedirects(cwd);
3547
+ assertSingleTemplateNetlifyBuildOutput(cwd);
3548
+ }
3549
+
3550
+ // Resolve remaining bare npm imports by bundling them into _libs/.
3551
+ // Nitro sometimes leaves small packages as externals even with noExternals.
3552
+ if (preset.startsWith("cloudflare") || preset.startsWith("deno")) {
3553
+ const { execFileSync } = await import("child_process");
3554
+ const { createRequire } = await import("module");
3555
+ const esbuildBin = (() => {
3556
+ try {
3557
+ const _req = createRequire(cwd + "/");
3558
+ const pkg = path.dirname(_req.resolve("esbuild/package.json"));
3559
+ const bin = path.join(pkg, "bin", "esbuild");
3560
+ if (fs.existsSync(bin)) return bin;
3561
+ } catch {}
3562
+ return "esbuild";
3563
+ })();
3564
+
3565
+ // Scan all output files for bare npm imports
3566
+ const outputDir =
3567
+ nitro.options.output.serverDir || path.join(cwd, "dist", "_worker.js");
3568
+ const bareImports = new Set<string>();
3569
+ function scanForBareImports(dir: string) {
3570
+ if (!fs.existsSync(dir)) return;
3571
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
3572
+ const p = path.join(dir, entry.name);
3573
+ if (entry.isDirectory()) {
3574
+ scanForBareImports(p);
3575
+ continue;
3576
+ }
3577
+ if (!entry.name.endsWith(".mjs") && !entry.name.endsWith(".js"))
3578
+ continue;
3579
+ const code = fs.readFileSync(p, "utf-8");
3580
+ const matches = code.matchAll(/from\s*["']([a-z@][a-z0-9._\-/]*)["']/g);
3581
+ for (const m of matches) {
3582
+ const mod = m[1];
3583
+ if (mod.startsWith("node:")) continue;
3584
+ // Skip Node builtins that are available via nodejs_compat
3585
+ const builtins = new Set([
3586
+ "fs",
3587
+ "path",
3588
+ "os",
3589
+ "crypto",
3590
+ "http",
3591
+ "https",
3592
+ "stream",
3593
+ "url",
3594
+ "util",
3595
+ "events",
3596
+ "buffer",
3597
+ "console",
3598
+ "net",
3599
+ "tls",
3600
+ "assert",
3601
+ "timers",
3602
+ "child_process",
3603
+ "module",
3604
+ "process",
3605
+ "sqlite",
3606
+ "worker_threads",
3607
+ "querystring",
3608
+ "zlib",
3609
+ "vm",
3610
+ "string_decoder",
3611
+ "diagnostics_channel",
3612
+ "async_hooks",
3613
+ "perf_hooks",
3614
+ "inspector",
3615
+ ]);
3616
+ if (builtins.has(mod)) continue;
3617
+ bareImports.add(mod);
3618
+ }
3619
+ }
3620
+ }
3621
+ scanForBareImports(outputDir);
3622
+
3623
+ // For each bare import, try to bundle it as a standalone module
3624
+ if (bareImports.size > 0) {
3625
+ const libsDir = path.join(outputDir, "_libs");
3626
+ fs.mkdirSync(libsDir, { recursive: true });
3627
+ for (const mod of bareImports) {
3628
+ const outFile = path.join(libsDir, `${mod.replace(/[/@]/g, "_")}.mjs`);
3629
+ try {
3630
+ // Resolve the module — check workspace node_modules and pnpm store
3631
+ let resolvedMod = mod;
3632
+ const _require = createRequire(cwd + "/");
3633
+ try {
3634
+ const resolved = _require.resolve(mod);
3635
+ resolvedMod = resolved;
3636
+ } catch {
3637
+ // Try from workspace root
3638
+ try {
3639
+ const wsRequire = createRequire(
3640
+ path.resolve(cwd, "../../package.json"),
3641
+ );
3642
+ resolvedMod = wsRequire.resolve(mod);
3643
+ } catch {
3644
+ // Will fail at esbuild
3645
+ }
3646
+ }
3647
+ // Scan what named imports the consumer expects, then generate
3648
+ // explicit re-exports to handle CJS modules properly.
3649
+ const neededExports = new Set<string>();
3650
+ function findNeededExports(dir: string) {
3651
+ if (!fs.existsSync(dir)) return;
3652
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
3653
+ const p = path.join(dir, entry.name);
3654
+ if (entry.isDirectory()) {
3655
+ findNeededExports(p);
3656
+ continue;
3657
+ }
3658
+ if (!entry.name.endsWith(".mjs") && !entry.name.endsWith(".js"))
3659
+ continue;
3660
+ const code = fs.readFileSync(p, "utf-8");
3661
+ // Match: import{foo as bar,baz}from"<mod>"
3662
+ const escaped = mod.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3663
+ const re = new RegExp(
3664
+ `import\\{([^}]+)\\}from["']${escaped}["']`,
3665
+ "g",
3666
+ );
3667
+ for (const m2 of code.matchAll(re)) {
3668
+ for (const part of m2[1].split(",")) {
3669
+ const name = part
3670
+ .trim()
3671
+ .split(/\s+as\s+/)[0]
3672
+ .trim();
3673
+ if (name && /^[a-zA-Z_$]/.test(name)) neededExports.add(name);
3674
+ }
3675
+ }
3676
+ }
3677
+ }
3678
+ findNeededExports(outputDir);
3679
+
3680
+ const entryCode =
3681
+ neededExports.size > 0
3682
+ ? [
3683
+ `import _mod from "${resolvedMod}";`,
3684
+ `export default _mod;`,
3685
+ ...Array.from(neededExports).map(
3686
+ (n) =>
3687
+ `export const ${n} = _mod.${n} ?? _mod?.default?.${n};`,
3688
+ ),
3689
+ ].join("\n")
3690
+ : `export * from "${resolvedMod}"; export { default } from "${resolvedMod}";`;
3691
+
3692
+ execFileSync(
3693
+ esbuildBin,
3694
+ [
3695
+ "--bundle",
3696
+ `--outfile=${outFile}`,
3697
+ "--format=esm",
3698
+ "--platform=neutral",
3699
+ "--target=es2022",
3700
+ "--external:node:*",
3701
+ ],
3702
+ {
3703
+ input: entryCode,
3704
+ cwd,
3705
+ stdio: ["pipe", "pipe", "pipe"],
3706
+ },
3707
+ );
3708
+ // Rewrite imports in all files to point to the bundled module
3709
+ function rewriteImports(dir: string) {
3710
+ if (!fs.existsSync(dir)) return;
3711
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
3712
+ const p = path.join(dir, entry.name);
3713
+ if (entry.isDirectory()) {
3714
+ rewriteImports(p);
3715
+ continue;
3716
+ }
3717
+ if (!entry.name.endsWith(".mjs") && !entry.name.endsWith(".js"))
3718
+ continue;
3719
+ let code = fs.readFileSync(p, "utf-8");
3720
+ const relPath = path
3721
+ .relative(path.dirname(p), outFile)
3722
+ .replace(/\\/g, "/");
3723
+ const importPath = relPath.startsWith(".")
3724
+ ? relPath
3725
+ : "./" + relPath;
3726
+ const re = new RegExp(
3727
+ `from["']${mod.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}["']`,
3728
+ "g",
3729
+ );
3730
+ if (re.test(code)) {
3731
+ code = code.replace(re, `from"${importPath}"`);
3732
+ fs.writeFileSync(p, code);
3733
+ }
3734
+ }
3735
+ }
3736
+ rewriteImports(outputDir);
3737
+ console.log(`[deploy] Bundled external: ${mod}`);
3738
+ } catch {
3739
+ console.warn(
3740
+ `[deploy] Could not bundle: ${mod} (may not be needed at runtime)`,
3741
+ );
3742
+ }
3743
+ }
3744
+ }
3745
+ }
3746
+
3747
+ // Cloudflare-specific post-build patches
3748
+ if (preset.startsWith("cloudflare")) {
3749
+ const serverDir2 = nitro.options.output.serverDir;
3750
+ const scanDirs = [serverDir2];
3751
+ if (serverDir2) {
3752
+ const chunksDir = path.join(serverDir2, "_chunks");
3753
+ const libsDir = path.join(serverDir2, "_libs");
3754
+ if (fs.existsSync(chunksDir)) scanDirs.push(chunksDir);
3755
+ if (fs.existsSync(libsDir)) scanDirs.push(libsDir);
3756
+ }
3757
+
3758
+ for (const scanDir of scanDirs) {
3759
+ if (!scanDir || !fs.existsSync(scanDir)) continue;
3760
+ for (const file of fs.readdirSync(scanDir)) {
3761
+ if (!file.endsWith(".mjs") && !file.endsWith(".js")) continue;
3762
+ const filePath = path.join(scanDir, file);
3763
+ let code = fs.readFileSync(filePath, "utf-8");
3764
+ let changed = false;
3765
+
3766
+ // 1. Rewrite bare Node.js imports to node: prefixed.
3767
+ // CF Workers requires the node: prefix for built-in modules.
3768
+ const NODE_BUILTINS = [
3769
+ "fs",
3770
+ "path",
3771
+ "os",
3772
+ "crypto",
3773
+ "http",
3774
+ "https",
3775
+ "stream",
3776
+ "url",
3777
+ "util",
3778
+ "events",
3779
+ "buffer",
3780
+ "console",
3781
+ "querystring",
3782
+ "zlib",
3783
+ "net",
3784
+ "tls",
3785
+ "assert",
3786
+ "timers",
3787
+ "child_process",
3788
+ "module",
3789
+ "process",
3790
+ "sqlite",
3791
+ "worker_threads",
3792
+ "string_decoder",
3793
+ "diagnostics_channel",
3794
+ "async_hooks",
3795
+ "perf_hooks",
3796
+ "inspector",
3797
+ "vm",
3798
+ ];
3799
+ for (const mod of NODE_BUILTINS) {
3800
+ // Match: from"fs" or from "fs" (but not from"node:fs")
3801
+ const re = new RegExp(`from\\s*["']${mod}["']`, "g");
3802
+ if (re.test(code)) {
3803
+ code = code.replace(re, `from"node:${mod}"`);
3804
+ changed = true;
3805
+ }
3806
+ }
3807
+
3808
+ // 2. Patch import.meta.url for createRequire().
3809
+ // React Router's server build uses createRequire(import.meta.url)
3810
+ // but import.meta.url is undefined on CF Workers.
3811
+ if (code.includes("import.meta.url")) {
3812
+ code = code.replace(/import\.meta\.url/g, '"file:///worker.mjs"');
3813
+ changed = true;
3814
+ }
3815
+
3816
+ // 3. Patch setInterval/setTimeout at global scope.
3817
+ // CF Workers disallows timers in global scope.
3818
+ if (code.includes("setInterval") && !code.includes("__timer_shim__")) {
3819
+ const shim =
3820
+ "/* __timer_shim__ */" +
3821
+ "var __origSetInterval=globalThis.setInterval;" +
3822
+ "globalThis.setInterval=function(){return{unref(){},ref(){},close(){}}};";
3823
+ const restore =
3824
+ ";(function(){if(typeof __origSetInterval!=='undefined')globalThis.setInterval=__origSetInterval})();";
3825
+ code = shim + code + "\n" + restore;
3826
+ changed = true;
3827
+ }
3828
+
3829
+ if (changed) fs.writeFileSync(filePath, code);
3830
+ }
3831
+ }
3832
+ // 3. Create stub modules in _libs/ for native deps that Nitro's rolldown
3833
+ // bundler references but can't resolve on CF Workers, and rewrite
3834
+ // bare imports to point to the stub files.
3835
+ const libsDir2 = path.join(
3836
+ serverDir2 || path.join(cwd, "dist", "_worker.js"),
3837
+ "_libs",
3838
+ );
3839
+ if (fs.existsSync(libsDir2)) {
3840
+ const NATIVE_STUBS = ["better-sqlite3", "node-pty", "cron-parser"];
3841
+ for (const mod of NATIVE_STUBS) {
3842
+ const libFiles = fs
3843
+ .readdirSync(libsDir2)
3844
+ .filter((f) => f.endsWith(".mjs"));
3845
+ const referencingFiles: string[] = [];
3846
+ for (const f of libFiles) {
3847
+ const filePath = path.join(libsDir2, f);
3848
+ const content = fs.readFileSync(filePath, "utf-8");
3849
+ if (content.includes(`"${mod}"`) || content.includes(`'${mod}'`)) {
3850
+ referencingFiles.push(filePath);
3851
+ }
3852
+ }
3853
+ if (referencingFiles.length === 0) continue;
3854
+
3855
+ // Create a stub _libs/<mod>.mjs that exports empty defaults
3856
+ const stubName = mod.replace(/[/@]/g, "__") + ".mjs";
3857
+ const stubPath = path.join(libsDir2, stubName);
3858
+ if (!fs.existsSync(stubPath)) {
3859
+ fs.writeFileSync(
3860
+ stubPath,
3861
+ `export default {}; export const watch = () => ({ close() {} });\n`,
3862
+ );
3863
+ console.log(`[deploy] Created stub for _libs/${stubName}`);
3864
+ }
3865
+
3866
+ // Rewrite bare imports in _libs/ and _chunks/ to use the stub
3867
+ const escaped = mod.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3868
+ const importRe = new RegExp(`(from\\s*["'])${escaped}(["'])`, "g");
3869
+ // Scan _libs/ files
3870
+ for (const filePath of referencingFiles) {
3871
+ let code = fs.readFileSync(filePath, "utf-8");
3872
+ if (importRe.test(code)) {
3873
+ code = code.replace(importRe, `$1./${stubName}$2`);
3874
+ fs.writeFileSync(filePath, code);
3875
+ console.log(
3876
+ `[deploy] Rewrote ${mod} imports in _libs/${path.basename(filePath)}`,
3877
+ );
3878
+ }
3879
+ }
3880
+ // Also scan _chunks/ files (they import native deps too)
3881
+ const chunksDir2 = path.join(
3882
+ serverDir2 || path.join(cwd, "dist", "_worker.js"),
3883
+ "_chunks",
3884
+ );
3885
+ if (fs.existsSync(chunksDir2)) {
3886
+ for (const f of fs
3887
+ .readdirSync(chunksDir2)
3888
+ .filter((f) => f.endsWith(".mjs") || f.endsWith(".js"))) {
3889
+ const filePath = path.join(chunksDir2, f);
3890
+ let code = fs.readFileSync(filePath, "utf-8");
3891
+ if (importRe.test(code)) {
3892
+ // From _chunks/, the stub is at ../_libs/<stubName>
3893
+ code = code.replace(importRe, `$1../_libs/${stubName}$2`);
3894
+ fs.writeFileSync(filePath, code);
3895
+ console.log(`[deploy] Rewrote ${mod} imports in _chunks/${f}`);
3896
+ }
3897
+ }
3898
+ }
3899
+ }
3900
+ }
3901
+
3902
+ console.log(
3903
+ "[deploy] Patched bare Node imports, timer calls, and route finder for CF Workers",
3904
+ );
3905
+ }
3906
+
3907
+ await nitro.close();
3908
+ console.log(`[deploy] Nitro build complete for preset "${preset}".`);
3909
+ }
3910
+
3911
+ async function main() {
3912
+ console.log(`[deploy] Building for ${preset}...`);
3913
+
3914
+ switch (preset) {
3915
+ case "cloudflare_pages":
3916
+ case "cloudflare-pages":
3917
+ // Cloudflare Workers require a single-file bundle that wrangler can deploy.
3918
+ // Nitro's native presets produce split chunks that wrangler can't upload
3919
+ // as multi-module Workers. Use the custom esbuild-based bundler.
3920
+ await buildCloudflarePages();
3921
+ break;
3922
+ default:
3923
+ // All other presets (netlify, vercel, deno_deploy, aws-lambda, etc.)
3924
+ // are handled natively by Nitro's build API.
3925
+ await buildWithNitro();
3926
+ break;
3927
+ }
3928
+ }
3929
+
3930
+ if (
3931
+ process.argv[1] &&
3932
+ path.resolve(process.argv[1]) === path.resolve(fileURLToPath(import.meta.url))
3933
+ ) {
3934
+ await main();
3935
+ }