@agent-native/core 0.127.1 → 0.128.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 (431) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +92 -0
  3. package/corpus/core/README.md +5 -26
  4. package/corpus/core/docs/content/actions.mdx +47 -4
  5. package/corpus/core/docs/content/native-chat-ui.mdx +7 -0
  6. package/corpus/core/docs/content/organizations-teams-permissions.mdx +109 -3
  7. package/corpus/core/docs/content/template-design-collaboration-and-full-apps.mdx +15 -0
  8. package/corpus/core/docs/content/toolkit-org-team.mdx +72 -12
  9. package/corpus/core/package.json +1 -1
  10. package/corpus/core/src/a2a/artifact-response.ts +36 -29
  11. package/corpus/core/src/action.ts +83 -2
  12. package/corpus/core/src/chat-threads/store.ts +48 -43
  13. package/corpus/core/src/cli/skills-content/design-visual-edit-skill.ts +46 -3
  14. package/corpus/core/src/cli/template-sync.ts +96 -0
  15. package/corpus/core/src/client/AgentPanel.tsx +26 -6
  16. package/corpus/core/src/client/AssistantChat.tsx +63 -7
  17. package/corpus/core/src/client/DefaultSpinner.tsx +29 -0
  18. package/corpus/core/src/client/org/TeamPage.tsx +161 -6
  19. package/corpus/core/src/client/org/hooks.ts +67 -0
  20. package/corpus/core/src/client/org/index.ts +9 -0
  21. package/corpus/core/src/client/transcription/use-live-transcription.ts +62 -10
  22. package/corpus/core/src/db/client.ts +42 -3
  23. package/corpus/core/src/db/ensure-additive-columns.ts +60 -33
  24. package/corpus/core/src/deploy/build.ts +31 -2
  25. package/corpus/core/src/mcp-client/routes.ts +10 -1
  26. package/corpus/core/src/org/app-roles-handlers.ts +152 -0
  27. package/corpus/core/src/org/app-roles.ts +355 -0
  28. package/corpus/core/src/org/index.ts +27 -1
  29. package/corpus/core/src/org/migrations.ts +22 -0
  30. package/corpus/core/src/org/plugin.ts +27 -0
  31. package/corpus/core/src/org/schema.ts +15 -0
  32. package/corpus/core/src/scripts/docs/search.ts +17 -0
  33. package/corpus/core/src/scripts/docs/source-search.ts +10 -0
  34. package/corpus/core/src/server/agent-chat/script-entries.ts +3 -0
  35. package/corpus/core/src/server/agent-chat-plugin.ts +53 -52
  36. package/corpus/core/src/server/builder-design-systems.ts +1 -1
  37. package/corpus/core/src/server/core-routes-plugin.ts +6 -1
  38. package/corpus/core/src/server/framework-request-handler.ts +44 -6
  39. package/corpus/core/src/templates/default/.agents/skills/actions/SKILL.md +32 -0
  40. package/corpus/core/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +7 -0
  41. package/corpus/core/src/templates/default/.agents/skills/security/SKILL.md +31 -0
  42. package/corpus/core/src/templates/headless/.agents/skills/actions/SKILL.md +32 -0
  43. package/corpus/core/src/templates/workspace-core/.agents/skills/actions/SKILL.md +32 -0
  44. package/corpus/core/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +7 -0
  45. package/corpus/core/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +40 -0
  46. package/corpus/core/src/templates/workspace-core/.agents/skills/security/SKILL.md +31 -0
  47. package/corpus/core/src/templates/workspace-core/.agents/skills/sharing/SKILL.md +4 -0
  48. package/corpus/templates/analytics/.agents/skills/actions/SKILL.md +32 -0
  49. package/corpus/templates/analytics/.agents/skills/security/SKILL.md +31 -0
  50. package/corpus/templates/analytics/.agents/skills/sharing/SKILL.md +4 -0
  51. package/corpus/templates/analytics/actions/data-source-status.ts +21 -12
  52. package/corpus/templates/analytics/app/global.css +7 -7
  53. package/corpus/templates/analytics/app/i18n-data.ts +30 -0
  54. package/corpus/templates/analytics/app/lib/data-source-status.ts +2 -1
  55. package/corpus/templates/analytics/app/pages/DataSources.tsx +54 -10
  56. package/corpus/templates/analytics/changelog/2026-07-28-analytics-pages-load-reliably-with-large-dashboard-workspaces.md +6 -0
  57. package/corpus/templates/analytics/changelog/2026-07-28-dashboard-loading-shimmer-now-flows-smoothly-in-one-directi.md +6 -0
  58. package/corpus/templates/analytics/server/lib/first-party-dashboard-repair.ts +5 -4
  59. package/corpus/templates/analytics/server/plugins/agent-chat.ts +54 -42
  60. package/corpus/templates/analytics/server/plugins/db.ts +1 -18
  61. package/corpus/templates/assets/.agents/skills/actions/SKILL.md +32 -0
  62. package/corpus/templates/assets/.agents/skills/security/SKILL.md +31 -0
  63. package/corpus/templates/assets/.agents/skills/sharing/SKILL.md +4 -0
  64. package/corpus/templates/brain/.agents/skills/actions/SKILL.md +32 -0
  65. package/corpus/templates/brain/.agents/skills/adding-a-feature/SKILL.md +7 -0
  66. package/corpus/templates/brain/.agents/skills/security/SKILL.md +31 -0
  67. package/corpus/templates/brain/.agents/skills/sharing/SKILL.md +4 -0
  68. package/corpus/templates/calendar/.agents/skills/actions/SKILL.md +32 -0
  69. package/corpus/templates/calendar/.agents/skills/security/SKILL.md +31 -0
  70. package/corpus/templates/calendar/.agents/skills/sharing/SKILL.md +4 -0
  71. package/corpus/templates/chat/.agents/skills/actions/SKILL.md +32 -0
  72. package/corpus/templates/chat/.agents/skills/adding-a-feature/SKILL.md +7 -0
  73. package/corpus/templates/chat/.agents/skills/security/SKILL.md +31 -0
  74. package/corpus/templates/chat/.agents/skills/sharing/SKILL.md +4 -0
  75. package/corpus/templates/chat/_gitignore +2 -0
  76. package/corpus/templates/clips/.agents/skills/actions/SKILL.md +32 -0
  77. package/corpus/templates/clips/.agents/skills/security/SKILL.md +31 -0
  78. package/corpus/templates/clips/actions/request-transcript.ts +77 -11
  79. package/corpus/templates/clips/actions/save-browser-transcript.ts +28 -7
  80. package/corpus/templates/clips/app/routes/record.tsx +11 -3
  81. package/corpus/templates/clips/changelog/2026-07-28-browser-recordings-no-longer-save-a-truncated-transcript-as-.md +6 -0
  82. package/corpus/templates/clips/changelog/2026-07-28-browser-recordings-no-longer-stop-transcribing-partway-throu.md +6 -0
  83. package/corpus/templates/clips/changelog/2026-07-28-desktop-full-screen-clips-now-get-an-instant-local-transcrip.md +6 -0
  84. package/corpus/templates/clips/changelog/2026-07-28-long-transcriptions-no-longer-show-a-false-transcription-sto.md +6 -0
  85. package/corpus/templates/clips/changelog/2026-07-28-restarting-for-an-update-now-installs-the-newest-release-ins.md +6 -0
  86. package/corpus/templates/clips/changelog/2026-07-28-the-meeting-recording-pill-now-anchors-to-the-right-edge-of-.md +6 -0
  87. package/corpus/templates/clips/desktop/src/lib/audio-meter.ts +31 -2
  88. package/corpus/templates/clips/desktop/src/lib/recorder.ts +114 -13
  89. package/corpus/templates/clips/desktop/src/lib/updater.ts +12 -4
  90. package/corpus/templates/clips/desktop/src/overlays/live-audio-bars.tsx +40 -15
  91. package/corpus/templates/clips/desktop/src/styles.css +10 -7
  92. package/corpus/templates/clips/desktop/src-tauri/src/recording_indicator.rs +21 -14
  93. package/corpus/templates/clips/shared/transcript-status.ts +10 -0
  94. package/corpus/templates/content/.agents/skills/actions/SKILL.md +32 -0
  95. package/corpus/templates/content/.agents/skills/security/SKILL.md +31 -0
  96. package/corpus/templates/content/.agents/skills/sharing/SKILL.md +4 -0
  97. package/corpus/templates/crm/.agents/skills/sharing/SKILL.md +4 -0
  98. package/corpus/templates/design/.agents/skills/actions/SKILL.md +32 -0
  99. package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +23 -0
  100. package/corpus/templates/design/.agents/skills/security/SKILL.md +31 -0
  101. package/corpus/templates/design/.agents/skills/sharing/SKILL.md +4 -0
  102. package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +46 -3
  103. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +7 -5
  104. package/corpus/templates/design/actions/create-file.ts +15 -0
  105. package/corpus/templates/design/actions/generate-design.ts +40 -0
  106. package/corpus/templates/design/actions/present-design-variants.ts +16 -0
  107. package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +2 -2
  108. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +7 -4
  109. package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +1 -1
  110. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +10 -4
  111. package/corpus/templates/design/app/lib/design-ui-events.ts +5 -0
  112. package/corpus/templates/design/app/pages/design-editor/save-failure.ts +7 -1
  113. package/corpus/templates/design/app/root.tsx +18 -1
  114. package/corpus/templates/design/changelog/2026-07-28-generated-designs-with-malformed-html-are-now-rejected-at-sa.md +6 -0
  115. package/corpus/templates/design/changelog/2026-07-28-show-or-hide-design-editing-chrome-with-cmd-on-apple-devices.md +6 -0
  116. package/corpus/templates/design/server/source-workspace.ts +1 -0
  117. package/corpus/templates/design/shared/html-integrity.ts +608 -18
  118. package/corpus/templates/dispatch/.agents/skills/actions/SKILL.md +32 -0
  119. package/corpus/templates/dispatch/.agents/skills/security/SKILL.md +31 -0
  120. package/corpus/templates/dispatch/.agents/skills/sharing/SKILL.md +4 -0
  121. package/corpus/templates/forms/.agents/skills/actions/SKILL.md +32 -0
  122. package/corpus/templates/forms/.agents/skills/security/SKILL.md +31 -0
  123. package/corpus/templates/forms/.agents/skills/sharing/SKILL.md +4 -0
  124. package/corpus/templates/macros/.agents/skills/security/SKILL.md +31 -0
  125. package/corpus/templates/macros/.agents/skills/sharing/SKILL.md +4 -0
  126. package/corpus/templates/mail/.agents/skills/actions/SKILL.md +32 -0
  127. package/corpus/templates/mail/.agents/skills/security/SKILL.md +31 -0
  128. package/corpus/templates/mail/.agents/skills/sharing/SKILL.md +4 -0
  129. package/corpus/templates/plan/.agents/skills/actions/SKILL.md +32 -0
  130. package/corpus/templates/plan/.agents/skills/adding-a-feature/SKILL.md +7 -0
  131. package/corpus/templates/plan/.agents/skills/security/SKILL.md +31 -0
  132. package/corpus/templates/plan/.agents/skills/sharing/SKILL.md +4 -0
  133. package/corpus/templates/slides/.agents/skills/actions/SKILL.md +32 -0
  134. package/corpus/templates/slides/.agents/skills/security/SKILL.md +31 -0
  135. package/corpus/templates/slides/.agents/skills/sharing/SKILL.md +4 -0
  136. package/corpus/templates/slides/app/components/deck/DeckCard.tsx +2 -6
  137. package/corpus/templates/tasks/.agents/skills/actions/SKILL.md +32 -0
  138. package/corpus/templates/tasks/.agents/skills/adding-a-feature/SKILL.md +7 -0
  139. package/corpus/templates/tasks/.agents/skills/security/SKILL.md +31 -0
  140. package/corpus/templates/tasks/.agents/skills/sharing/SKILL.md +4 -0
  141. package/dist/a2a/artifact-response.d.ts.map +1 -1
  142. package/dist/a2a/artifact-response.js +30 -29
  143. package/dist/a2a/artifact-response.js.map +1 -1
  144. package/dist/action.d.ts +36 -0
  145. package/dist/action.d.ts.map +1 -1
  146. package/dist/action.js +37 -2
  147. package/dist/action.js.map +1 -1
  148. package/dist/chat-threads/store.d.ts +12 -0
  149. package/dist/chat-threads/store.d.ts.map +1 -1
  150. package/dist/chat-threads/store.js +48 -42
  151. package/dist/chat-threads/store.js.map +1 -1
  152. package/dist/cli/skills-content/design-visual-edit-skill.d.ts +1 -1
  153. package/dist/cli/skills-content/design-visual-edit-skill.d.ts.map +1 -1
  154. package/dist/cli/skills-content/design-visual-edit-skill.js +46 -3
  155. package/dist/cli/skills-content/design-visual-edit-skill.js.map +1 -1
  156. package/dist/cli/template-sync.d.ts.map +1 -1
  157. package/dist/cli/template-sync.js +88 -0
  158. package/dist/cli/template-sync.js.map +1 -1
  159. package/dist/client/AgentPanel.d.ts +3 -1
  160. package/dist/client/AgentPanel.d.ts.map +1 -1
  161. package/dist/client/AgentPanel.js +11 -9
  162. package/dist/client/AgentPanel.js.map +1 -1
  163. package/dist/client/AssistantChat.d.ts.map +1 -1
  164. package/dist/client/AssistantChat.js +57 -6
  165. package/dist/client/AssistantChat.js.map +1 -1
  166. package/dist/client/DefaultSpinner.d.ts +7 -0
  167. package/dist/client/DefaultSpinner.d.ts.map +1 -1
  168. package/dist/client/DefaultSpinner.js +25 -1
  169. package/dist/client/DefaultSpinner.js.map +1 -1
  170. package/dist/client/org/TeamPage.d.ts +13 -1
  171. package/dist/client/org/TeamPage.d.ts.map +1 -1
  172. package/dist/client/org/TeamPage.js +41 -11
  173. package/dist/client/org/TeamPage.js.map +1 -1
  174. package/dist/client/org/hooks.d.ts +37 -0
  175. package/dist/client/org/hooks.d.ts.map +1 -1
  176. package/dist/client/org/hooks.js +37 -0
  177. package/dist/client/org/hooks.js.map +1 -1
  178. package/dist/client/org/index.d.ts +3 -2
  179. package/dist/client/org/index.d.ts.map +1 -1
  180. package/dist/client/org/index.js +1 -1
  181. package/dist/client/org/index.js.map +1 -1
  182. package/dist/client/transcription/use-live-transcription.d.ts +8 -0
  183. package/dist/client/transcription/use-live-transcription.d.ts.map +1 -1
  184. package/dist/client/transcription/use-live-transcription.js +38 -11
  185. package/dist/client/transcription/use-live-transcription.js.map +1 -1
  186. package/dist/collab/routes.d.ts +1 -1
  187. package/dist/collab/struct-routes.d.ts +1 -1
  188. package/dist/db/client.d.ts +12 -0
  189. package/dist/db/client.d.ts.map +1 -1
  190. package/dist/db/client.js +40 -3
  191. package/dist/db/client.js.map +1 -1
  192. package/dist/db/ensure-additive-columns.d.ts.map +1 -1
  193. package/dist/db/ensure-additive-columns.js +54 -32
  194. package/dist/db/ensure-additive-columns.js.map +1 -1
  195. package/dist/deploy/build.d.ts +1 -0
  196. package/dist/deploy/build.d.ts.map +1 -1
  197. package/dist/deploy/build.js +23 -2
  198. package/dist/deploy/build.js.map +1 -1
  199. package/dist/mcp-client/routes.d.ts +3 -1
  200. package/dist/mcp-client/routes.d.ts.map +1 -1
  201. package/dist/mcp-client/routes.js +8 -2
  202. package/dist/mcp-client/routes.js.map +1 -1
  203. package/dist/notifications/routes.d.ts +1 -1
  204. package/dist/observability/routes.d.ts +3 -3
  205. package/dist/org/app-roles-handlers.d.ts +27 -0
  206. package/dist/org/app-roles-handlers.d.ts.map +1 -0
  207. package/dist/org/app-roles-handlers.js +125 -0
  208. package/dist/org/app-roles-handlers.js.map +1 -0
  209. package/dist/org/app-roles.d.ts +136 -0
  210. package/dist/org/app-roles.d.ts.map +1 -0
  211. package/dist/org/app-roles.js +216 -0
  212. package/dist/org/app-roles.js.map +1 -0
  213. package/dist/org/index.d.ts +4 -1
  214. package/dist/org/index.d.ts.map +1 -1
  215. package/dist/org/index.js +3 -1
  216. package/dist/org/index.js.map +1 -1
  217. package/dist/org/migrations.d.ts.map +1 -1
  218. package/dist/org/migrations.js +22 -0
  219. package/dist/org/migrations.js.map +1 -1
  220. package/dist/org/plugin.d.ts +2 -0
  221. package/dist/org/plugin.d.ts.map +1 -1
  222. package/dist/org/plugin.js +20 -0
  223. package/dist/org/plugin.js.map +1 -1
  224. package/dist/org/schema.d.ts +143 -0
  225. package/dist/org/schema.d.ts.map +1 -1
  226. package/dist/org/schema.js +14 -0
  227. package/dist/org/schema.js.map +1 -1
  228. package/dist/provider-api/actions/custom-provider-registration.d.ts +4 -4
  229. package/dist/provider-api/actions/provider-api.d.ts +12 -12
  230. package/dist/resources/handlers.d.ts +1 -1
  231. package/dist/scripts/docs/search.d.ts.map +1 -1
  232. package/dist/scripts/docs/search.js +15 -0
  233. package/dist/scripts/docs/search.js.map +1 -1
  234. package/dist/scripts/docs/source-search.d.ts +7 -0
  235. package/dist/scripts/docs/source-search.d.ts.map +1 -1
  236. package/dist/scripts/docs/source-search.js +9 -0
  237. package/dist/scripts/docs/source-search.js.map +1 -1
  238. package/dist/server/agent-chat/script-entries.d.ts.map +1 -1
  239. package/dist/server/agent-chat/script-entries.js +3 -0
  240. package/dist/server/agent-chat/script-entries.js.map +1 -1
  241. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  242. package/dist/server/agent-chat-plugin.js +46 -48
  243. package/dist/server/agent-chat-plugin.js.map +1 -1
  244. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  245. package/dist/server/builder-design-systems.js +1 -1
  246. package/dist/server/builder-design-systems.js.map +1 -1
  247. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  248. package/dist/server/core-routes-plugin.js +6 -1
  249. package/dist/server/core-routes-plugin.js.map +1 -1
  250. package/dist/server/framework-request-handler.d.ts.map +1 -1
  251. package/dist/server/framework-request-handler.js +42 -6
  252. package/dist/server/framework-request-handler.js.map +1 -1
  253. package/dist/server/transcribe-voice.d.ts +1 -1
  254. package/dist/templates/chat/.agents/skills/actions/SKILL.md +32 -0
  255. package/dist/templates/chat/.agents/skills/adding-a-feature/SKILL.md +7 -0
  256. package/dist/templates/chat/.agents/skills/security/SKILL.md +31 -0
  257. package/dist/templates/chat/.agents/skills/sharing/SKILL.md +4 -0
  258. package/dist/templates/chat/_gitignore +2 -0
  259. package/dist/templates/default/.agents/skills/actions/SKILL.md +32 -0
  260. package/dist/templates/default/.agents/skills/adding-a-feature/SKILL.md +7 -0
  261. package/dist/templates/default/.agents/skills/security/SKILL.md +31 -0
  262. package/dist/templates/headless/.agents/skills/actions/SKILL.md +32 -0
  263. package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +32 -0
  264. package/dist/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +7 -0
  265. package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +40 -0
  266. package/dist/templates/workspace-core/.agents/skills/security/SKILL.md +31 -0
  267. package/dist/templates/workspace-core/.agents/skills/sharing/SKILL.md +4 -0
  268. package/docs/content/actions.mdx +47 -4
  269. package/docs/content/native-chat-ui.mdx +7 -0
  270. package/docs/content/organizations-teams-permissions.mdx +109 -3
  271. package/docs/content/template-design-collaboration-and-full-apps.mdx +15 -0
  272. package/docs/content/toolkit-org-team.mdx +72 -12
  273. package/package.json +1 -1
  274. package/src/a2a/artifact-response.ts +36 -29
  275. package/src/action.ts +83 -2
  276. package/src/chat-threads/store.ts +48 -43
  277. package/src/cli/skills-content/design-visual-edit-skill.ts +46 -3
  278. package/src/cli/template-sync.ts +96 -0
  279. package/src/client/AgentPanel.tsx +26 -6
  280. package/src/client/AssistantChat.tsx +63 -7
  281. package/src/client/DefaultSpinner.tsx +29 -0
  282. package/src/client/org/TeamPage.tsx +161 -6
  283. package/src/client/org/hooks.ts +67 -0
  284. package/src/client/org/index.ts +9 -0
  285. package/src/client/transcription/use-live-transcription.ts +62 -10
  286. package/src/db/client.ts +42 -3
  287. package/src/db/ensure-additive-columns.ts +60 -33
  288. package/src/deploy/build.ts +31 -2
  289. package/src/mcp-client/routes.ts +10 -1
  290. package/src/org/app-roles-handlers.ts +152 -0
  291. package/src/org/app-roles.ts +355 -0
  292. package/src/org/index.ts +27 -1
  293. package/src/org/migrations.ts +22 -0
  294. package/src/org/plugin.ts +27 -0
  295. package/src/org/schema.ts +15 -0
  296. package/src/scripts/docs/search.ts +17 -0
  297. package/src/scripts/docs/source-search.ts +10 -0
  298. package/src/server/agent-chat/script-entries.ts +3 -0
  299. package/src/server/agent-chat-plugin.ts +53 -52
  300. package/src/server/builder-design-systems.ts +1 -1
  301. package/src/server/core-routes-plugin.ts +6 -1
  302. package/src/server/framework-request-handler.ts +44 -6
  303. package/src/templates/chat/.agents/skills/actions/SKILL.md +32 -0
  304. package/src/templates/chat/.agents/skills/adding-a-feature/SKILL.md +7 -0
  305. package/src/templates/chat/.agents/skills/security/SKILL.md +31 -0
  306. package/src/templates/chat/.agents/skills/sharing/SKILL.md +4 -0
  307. package/src/templates/chat/_gitignore +2 -0
  308. package/src/templates/default/.agents/skills/actions/SKILL.md +32 -0
  309. package/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +7 -0
  310. package/src/templates/default/.agents/skills/security/SKILL.md +31 -0
  311. package/src/templates/headless/.agents/skills/actions/SKILL.md +32 -0
  312. package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +32 -0
  313. package/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +7 -0
  314. package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +40 -0
  315. package/src/templates/workspace-core/.agents/skills/security/SKILL.md +31 -0
  316. package/src/templates/workspace-core/.agents/skills/sharing/SKILL.md +4 -0
  317. package/corpus/core/src/templates/chat/.agents/skills/actions/SKILL.md +0 -530
  318. package/corpus/core/src/templates/chat/.agents/skills/adding-a-feature/SKILL.md +0 -191
  319. package/corpus/core/src/templates/chat/.agents/skills/agent-native-docs/SKILL.md +0 -115
  320. package/corpus/core/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +0 -177
  321. package/corpus/core/src/templates/chat/.agents/skills/capture-learnings/SKILL.md +0 -89
  322. package/corpus/core/src/templates/chat/.agents/skills/create-skill/SKILL.md +0 -221
  323. package/corpus/core/src/templates/chat/.agents/skills/customizing-agent-native/SKILL.md +0 -220
  324. package/corpus/core/src/templates/chat/.agents/skills/delegate-to-agent/SKILL.md +0 -263
  325. package/corpus/core/src/templates/chat/.agents/skills/feature-flags/SKILL.md +0 -169
  326. package/corpus/core/src/templates/chat/.agents/skills/frontend-design/SKILL.md +0 -174
  327. package/corpus/core/src/templates/chat/.agents/skills/real-time-sync/SKILL.md +0 -232
  328. package/corpus/core/src/templates/chat/.agents/skills/security/SKILL.md +0 -282
  329. package/corpus/core/src/templates/chat/.agents/skills/self-modifying-code/SKILL.md +0 -119
  330. package/corpus/core/src/templates/chat/.agents/skills/shadcn-ui/SKILL.md +0 -123
  331. package/corpus/core/src/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +0 -122
  332. package/corpus/core/src/templates/chat/.env.example +0 -5
  333. package/corpus/core/src/templates/chat/.ignore +0 -0
  334. package/corpus/core/src/templates/chat/.oxfmtrc.json +0 -8
  335. package/corpus/core/src/templates/chat/AGENTS.md +0 -77
  336. package/corpus/core/src/templates/chat/CHANGELOG.md +0 -10
  337. package/corpus/core/src/templates/chat/DEVELOPING.md +0 -185
  338. package/corpus/core/src/templates/chat/README.md +0 -32
  339. package/corpus/core/src/templates/chat/_gitignore +0 -44
  340. package/corpus/core/src/templates/chat/actions/hello.ts +0 -13
  341. package/corpus/core/src/templates/chat/actions/navigate.ts +0 -41
  342. package/corpus/core/src/templates/chat/actions/run.ts +0 -2
  343. package/corpus/core/src/templates/chat/actions/view-screen.ts +0 -31
  344. package/corpus/core/src/templates/chat/app/components/layout/Header.tsx +0 -60
  345. package/corpus/core/src/templates/chat/app/components/layout/Layout.tsx +0 -188
  346. package/corpus/core/src/templates/chat/app/components/layout/Sidebar.tsx +0 -505
  347. package/corpus/core/src/templates/chat/app/components/ui/button.tsx +0 -1
  348. package/corpus/core/src/templates/chat/app/components/ui/card.tsx +0 -1
  349. package/corpus/core/src/templates/chat/app/components/ui/dropdown-menu.tsx +0 -1
  350. package/corpus/core/src/templates/chat/app/components/ui/input.tsx +0 -1
  351. package/corpus/core/src/templates/chat/app/components/ui/label.tsx +0 -1
  352. package/corpus/core/src/templates/chat/app/components/ui/sheet.tsx +0 -1
  353. package/corpus/core/src/templates/chat/app/components/ui/toolkit-provider.tsx +0 -17
  354. package/corpus/core/src/templates/chat/app/components/ui/tooltip.tsx +0 -1
  355. package/corpus/core/src/templates/chat/app/design-system.ts +0 -3
  356. package/corpus/core/src/templates/chat/app/entry.client.tsx +0 -22
  357. package/corpus/core/src/templates/chat/app/entry.server.tsx +0 -10
  358. package/corpus/core/src/templates/chat/app/global.css +0 -93
  359. package/corpus/core/src/templates/chat/app/hooks/use-navigation-state.ts +0 -93
  360. package/corpus/core/src/templates/chat/app/i18n/ar-SA.ts +0 -68
  361. package/corpus/core/src/templates/chat/app/i18n/de-DE.ts +0 -71
  362. package/corpus/core/src/templates/chat/app/i18n/en-US.ts +0 -70
  363. package/corpus/core/src/templates/chat/app/i18n/es-ES.ts +0 -71
  364. package/corpus/core/src/templates/chat/app/i18n/fr-FR.ts +0 -71
  365. package/corpus/core/src/templates/chat/app/i18n/hi-IN.ts +0 -69
  366. package/corpus/core/src/templates/chat/app/i18n/index.ts +0 -34
  367. package/corpus/core/src/templates/chat/app/i18n/ja-JP.ts +0 -70
  368. package/corpus/core/src/templates/chat/app/i18n/ko-KR.ts +0 -70
  369. package/corpus/core/src/templates/chat/app/i18n/pt-BR.ts +0 -71
  370. package/corpus/core/src/templates/chat/app/i18n/zh-CN.ts +0 -66
  371. package/corpus/core/src/templates/chat/app/i18n/zh-TW.ts +0 -66
  372. package/corpus/core/src/templates/chat/app/i18n-data.ts +0 -556
  373. package/corpus/core/src/templates/chat/app/lib/agent-page.tsx +0 -49
  374. package/corpus/core/src/templates/chat/app/lib/app-config.ts +0 -11
  375. package/corpus/core/src/templates/chat/app/lib/tab-id.ts +0 -1
  376. package/corpus/core/src/templates/chat/app/lib/utils.ts +0 -1
  377. package/corpus/core/src/templates/chat/app/root.tsx +0 -173
  378. package/corpus/core/src/templates/chat/app/routes/_index.tsx +0 -94
  379. package/corpus/core/src/templates/chat/app/routes/agent.tsx +0 -24
  380. package/corpus/core/src/templates/chat/app/routes/chat.$threadId.tsx +0 -1
  381. package/corpus/core/src/templates/chat/app/routes/database.tsx +0 -17
  382. package/corpus/core/src/templates/chat/app/routes/extensions.$id.$slug.tsx +0 -2
  383. package/corpus/core/src/templates/chat/app/routes/extensions.$id.tsx +0 -11
  384. package/corpus/core/src/templates/chat/app/routes/extensions._index.tsx +0 -11
  385. package/corpus/core/src/templates/chat/app/routes/extensions.tsx +0 -5
  386. package/corpus/core/src/templates/chat/app/routes/observability.tsx +0 -19
  387. package/corpus/core/src/templates/chat/app/routes/settings.tsx +0 -89
  388. package/corpus/core/src/templates/chat/app/routes/team.tsx +0 -11
  389. package/corpus/core/src/templates/chat/app/routes.ts +0 -4
  390. package/corpus/core/src/templates/chat/app/vite-env.d.ts +0 -6
  391. package/corpus/core/src/templates/chat/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +0 -6
  392. package/corpus/core/src/templates/chat/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +0 -6
  393. package/corpus/core/src/templates/chat/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +0 -6
  394. package/corpus/core/src/templates/chat/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +0 -6
  395. package/corpus/core/src/templates/chat/changelog/2026-06-29-chat-layouts-adapt-when-the-agent-sidebar-is-open.md +0 -6
  396. package/corpus/core/src/templates/chat/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +0 -5
  397. package/corpus/core/src/templates/chat/changelog/2026-07-10-chat-now-makes-ai-connection-setup-clear-without-shifting-th.md +0 -6
  398. package/corpus/core/src/templates/chat/changelog/2026-07-13-a-full-agent-page-now-brings-context-files-connections-jobs-.md +0 -6
  399. package/corpus/core/src/templates/chat/changelog/2026-07-14-chat-opens-reliably-on-hosted-deployments-instead-of-failing.md +0 -6
  400. package/corpus/core/src/templates/chat/changelog/2026-07-14-fixed-chat-template-startup-with-older-core-versions.md +0 -6
  401. package/corpus/core/src/templates/chat/changelog/2026-07-15-chat-navigation-focuses-on-chat-and-agent.md +0 -6
  402. package/corpus/core/src/templates/chat/changelog/2026-07-17-the-agent-chat-sidebar-stays-closed-until-you-open-it-or-sta.md +0 -6
  403. package/corpus/core/src/templates/chat/changelog/2026-07-22-compact-sidebar-footer.md +0 -6
  404. package/corpus/core/src/templates/chat/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +0 -6
  405. package/corpus/core/src/templates/chat/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +0 -6
  406. package/corpus/core/src/templates/chat/changelog/2026-07-22-recent-chats-are-easier-to-scan-and-expand.md +0 -6
  407. package/corpus/core/src/templates/chat/changelog/2026-07-23-full-page-chat-is-better-centered-with-quieter-chat-history-.md +0 -6
  408. package/corpus/core/src/templates/chat/changelog/2026-07-24-borderless-secondary-surfaces.md +0 -6
  409. package/corpus/core/src/templates/chat/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +0 -6
  410. package/corpus/core/src/templates/chat/changelog/2026-07-25-settings-navigation-now-keeps-manage-agent-as-a-dedicated-li.md +0 -6
  411. package/corpus/core/src/templates/chat/components.json +0 -20
  412. package/corpus/core/src/templates/chat/learnings.defaults.md +0 -5
  413. package/corpus/core/src/templates/chat/netlify.toml +0 -11
  414. package/corpus/core/src/templates/chat/package.json +0 -92
  415. package/corpus/core/src/templates/chat/public/agent-native-icon-dark.svg +0 -10
  416. package/corpus/core/src/templates/chat/public/agent-native-icon-light.svg +0 -10
  417. package/corpus/core/src/templates/chat/public/agent-native-logo-dark.svg +0 -21
  418. package/corpus/core/src/templates/chat/public/agent-native-logo-light.svg +0 -21
  419. package/corpus/core/src/templates/chat/public/favicon.svg +0 -1
  420. package/corpus/core/src/templates/chat/public/icon-180.svg +0 -1
  421. package/corpus/core/src/templates/chat/public/icon-192.svg +0 -1
  422. package/corpus/core/src/templates/chat/public/icon-512.svg +0 -1
  423. package/corpus/core/src/templates/chat/public/manifest.json +0 -21
  424. package/corpus/core/src/templates/chat/react-router.config.ts +0 -7
  425. package/corpus/core/src/templates/chat/server/middleware/auth.ts +0 -15
  426. package/corpus/core/src/templates/chat/server/plugins/agent-chat.ts +0 -21
  427. package/corpus/core/src/templates/chat/server/plugins/auth.ts +0 -17
  428. package/corpus/core/src/templates/chat/server/routes/[...page].get.ts +0 -5
  429. package/corpus/core/src/templates/chat/ssr-entry.ts +0 -15
  430. package/corpus/core/src/templates/chat/tsconfig.json +0 -21
  431. package/corpus/core/src/templates/chat/vite.config.ts +0 -19
package/src/db/client.ts CHANGED
@@ -1595,6 +1595,35 @@ async function initClient(): Promise<void> {
1595
1595
  * Get the singleton database client. Returns a `DbExec` whose first
1596
1596
  * `execute()` call lazily initializes the underlying driver.
1597
1597
  */
1598
+ /**
1599
+ * Point a missing-table failure at the cause instead of the symptom.
1600
+ *
1601
+ * The driver reports `no such table: x` / `relation "x" does not exist` from
1602
+ * whichever query happened to touch it first, so the stack lands in an action
1603
+ * and reads as a bug in that action. The actual cause is almost always that no
1604
+ * migration ever created the table — a template with no `server/plugins/db.ts`
1605
+ * creates none, and core's own tables self-heal, so app tables are the only
1606
+ * ones that fail this way. Appends rather than replaces: `isDuplicateColumnError`
1607
+ * and friends match substrings of the driver's original text.
1608
+ */
1609
+ export function annotateMissingTable(err: unknown, sql: unknown): unknown {
1610
+ if (!(err instanceof Error)) return err;
1611
+ const match =
1612
+ /no such table:?\s*["'`]?([\w.]+)/i.exec(err.message) ??
1613
+ /relation\s+["'`]?([\w.]+)["'`]?\s+does not exist/i.exec(err.message);
1614
+ if (!match) return err;
1615
+ if (err.message.includes("server/plugins/db.ts")) return err;
1616
+ const statement =
1617
+ typeof sql === "string" ? sql : (sql as { sql?: string })?.sql;
1618
+ err.message =
1619
+ `${err.message}\n` +
1620
+ ` [agent-native] Table "${match[1]}" does not exist. App tables are created by migrations in ` +
1621
+ `server/plugins/db.ts — check that the plugin exists and declares a migration for this table, ` +
1622
+ `then restart the dev server so it runs.` +
1623
+ (statement ? `\n Statement: ${statement.slice(0, 200)}` : "");
1624
+ return err;
1625
+ }
1626
+
1598
1627
  export function getDbExec(): DbExec {
1599
1628
  if (_exec) return _exec;
1600
1629
 
@@ -1608,6 +1637,16 @@ export function getDbExec(): DbExec {
1608
1637
  return sql;
1609
1638
  }
1610
1639
 
1640
+ async function execAnnotated(
1641
+ s: string | { sql: string; args?: unknown[] },
1642
+ ): ReturnType<DbExec["execute"]> {
1643
+ try {
1644
+ return await _exec!.execute(sanitize(s));
1645
+ } catch (err) {
1646
+ throw annotateMissingTable(err, s);
1647
+ }
1648
+ }
1649
+
1611
1650
  // Return a proxy that lazy-inits on first call
1612
1651
  const proxy: DbExec = {
1613
1652
  async execute(sql) {
@@ -1624,7 +1663,7 @@ export function getDbExec(): DbExec {
1624
1663
  }
1625
1664
  // After init, swap to a sanitizing wrapper around the real client
1626
1665
  const wrapper: DbExec = {
1627
- execute: (s) => _exec!.execute(sanitize(s)),
1666
+ execute: (s) => execAnnotated(s),
1628
1667
  atomicBatch: _exec!.atomicBatch
1629
1668
  ? (statements) =>
1630
1669
  _exec!.atomicBatch!(statements.map((s) => sanitize(s)))
@@ -1640,7 +1679,7 @@ export function getDbExec(): DbExec {
1640
1679
  : undefined,
1641
1680
  };
1642
1681
  Object.assign(proxy, wrapper);
1643
- return _exec!.execute(sanitize(sql));
1682
+ return execAnnotated(sql);
1644
1683
  },
1645
1684
  async transaction(fn) {
1646
1685
  if (!_initPromise) _initPromise = initClient();
@@ -1652,7 +1691,7 @@ export function getDbExec(): DbExec {
1652
1691
  throw err;
1653
1692
  }
1654
1693
  const wrapper: DbExec = {
1655
- execute: (s) => _exec!.execute(sanitize(s)),
1694
+ execute: (s) => execAnnotated(s),
1656
1695
  atomicBatch: _exec!.atomicBatch
1657
1696
  ? (statements) =>
1658
1697
  _exec!.atomicBatch!(statements.map((s) => sanitize(s)))
@@ -132,38 +132,56 @@ async function loadGetTableConfig(): Promise<
132
132
  }
133
133
 
134
134
  /**
135
- * Live columns already present on `table`, keyed by column name.
136
- * Postgres: `information_schema.columns` scoped to the table's schema
137
- * (default `public`). SQLite: `PRAGMA table_info(table)`.
138
- *
139
- * Returns `null` when the table itself does not exist (caller no-ops —
140
- * table creation owns that path) or when introspection fails outright.
135
+ * Load every requested Postgres table's live columns in one round trip.
136
+ * Calling information_schema separately for each table adds dozens of
137
+ * serialized network requests to every serverless cold start.
141
138
  */
142
- async function introspectLiveColumns(
139
+ async function introspectPostgresColumns(
143
140
  db: DbExec,
144
- table: string,
145
- schema: string | undefined,
146
- ): Promise<Set<string> | null> {
147
- if (isPostgres()) {
148
- try {
149
- const tableSchema = schema || "public";
150
- const { rows: existsRows } = await db.execute({
151
- sql: `SELECT 1 FROM information_schema.tables
152
- WHERE table_schema = ? AND table_name = ? LIMIT 1`,
153
- args: [tableSchema, table],
154
- });
155
- if (existsRows.length === 0) return null;
156
- const { rows } = await db.execute({
157
- sql: `SELECT column_name FROM information_schema.columns
158
- WHERE table_schema = ? AND table_name = ?`,
159
- args: [tableSchema, table],
160
- });
161
- return new Set(rows.map((r) => String(r.column_name)));
162
- } catch {
163
- return null;
141
+ tables: DeclaredTableLike[],
142
+ ): Promise<Map<string, Set<string>> | null> {
143
+ if (tables.length === 0) return new Map();
144
+ const pairs = [
145
+ ...new Map(
146
+ tables.map((table) => {
147
+ const schema = table.schema || "public";
148
+ return [`${schema}.${table.name}`, { schema, table: table.name }];
149
+ }),
150
+ ).values(),
151
+ ];
152
+ const args: unknown[] = [];
153
+ const predicates = pairs.map(({ schema, table }) => {
154
+ args.push(schema, table);
155
+ return `(table_schema = ? AND table_name = ?)`;
156
+ });
157
+ try {
158
+ const { rows } = await db.execute({
159
+ sql: `SELECT table_schema, table_name, column_name
160
+ FROM information_schema.columns
161
+ WHERE ${predicates.join(" OR ")}`,
162
+ args,
163
+ });
164
+ const columns = new Map<string, Set<string>>();
165
+ for (const row of rows) {
166
+ const key = `${String(row.table_schema)}.${String(row.table_name)}`;
167
+ const tableColumns = columns.get(key) ?? new Set<string>();
168
+ tableColumns.add(String(row.column_name));
169
+ columns.set(key, tableColumns);
164
170
  }
171
+ return columns;
172
+ } catch {
173
+ return null;
165
174
  }
175
+ }
166
176
 
177
+ /**
178
+ * Live SQLite columns already present on `table`, keyed by column name.
179
+ * Returns `null` when the table does not exist or introspection fails.
180
+ */
181
+ async function introspectSqliteLiveColumns(
182
+ db: DbExec,
183
+ table: string,
184
+ ): Promise<Set<string> | null> {
167
185
  // SQLite: PRAGMA table_info returns zero rows for a non-existent table
168
186
  // (no error), so we can't distinguish "missing table" from "no columns"
169
187
  // that way — probe sqlite_master first.
@@ -308,10 +326,13 @@ export async function ensureAdditiveColumns(
308
326
  return result;
309
327
  }
310
328
 
329
+ const declaredTables: DeclaredTableLike[] = [];
311
330
  for (const tableObj of tables) {
312
- let config: DeclaredTableLike;
313
331
  try {
314
- config = getTableConfig(tableObj);
332
+ const config = getTableConfig(tableObj);
333
+ if (config.name && PLAIN_IDENTIFIER.test(config.name)) {
334
+ declaredTables.push(config);
335
+ }
315
336
  } catch (err) {
316
337
  // Not a table this dialect's getTableConfig understands (e.g. a stray
317
338
  // export that isn't a Drizzle table) — skip quietly rather than
@@ -319,15 +340,21 @@ export async function ensureAdditiveColumns(
319
340
  logger.warn(
320
341
  `[ensure-additive-columns] skipping non-table export: ${err instanceof Error ? err.message : String(err)}`,
321
342
  );
322
- continue;
323
343
  }
344
+ }
324
345
 
325
- const tableName = config.name;
326
- if (!tableName || !PLAIN_IDENTIFIER.test(tableName)) continue;
346
+ const postgresColumns = isPostgres()
347
+ ? await introspectPostgresColumns(db, declaredTables)
348
+ : null;
327
349
 
350
+ for (const config of declaredTables) {
351
+ const tableName = config.name;
328
352
  let liveColumns: Set<string> | null;
329
353
  try {
330
- liveColumns = await introspectLiveColumns(db, tableName, config.schema);
354
+ liveColumns = isPostgres()
355
+ ? (postgresColumns?.get(`${config.schema || "public"}.${tableName}`) ??
356
+ null)
357
+ : await introspectSqliteLiveColumns(db, tableName);
331
358
  } catch (err) {
332
359
  result.errors.push({
333
360
  column: `${tableName}.*`,
@@ -1688,7 +1688,7 @@ export function generateCloudflarePagesStaticShellFromManifest(
1688
1688
  ? DEFAULT_ROOT_LOADER_REACT_ROUTER_TURBO_STREAM
1689
1689
  : EMPTY_REACT_ROUTER_TURBO_STREAM;
1690
1690
 
1691
- 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>`;
1691
+ 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;flex-direction:column;align-items:center;justify-content:center;gap:16px;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><p class="an-stall-hint">Still loading. If this does not finish, reload the page — the browser console may show what failed.</p><style>@keyframes an-spin { to { transform: rotate(360deg) } } @keyframes an-stall-in { to { opacity: 0.6 } } .an-stall-hint { opacity: 0; margin: 0; max-width: 32rem; padding: 0 1.5rem; text-align: center; font-size: 0.875rem; line-height: 1.5; font-family: ui-sans-serif, system-ui, sans-serif; animation: an-stall-in 0.4s ease-out 10s forwards } @media (prefers-reduced-motion: reduce) { .an-stall-hint { animation-duration: 0s } } @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>`;
1692
1692
  }
1693
1693
 
1694
1694
  function writeCloudflarePagesStaticShell({
@@ -2343,6 +2343,28 @@ const LIBSQL_NATIVE_PACKAGE_NAMES = [
2343
2343
  const FFMPEG_STATIC_PACKAGE_NAME = "ffmpeg-static";
2344
2344
  const RESVG_SCOPE = "@resvg";
2345
2345
  const RESVG_PACKAGE_PREFIX = "resvg-js";
2346
+
2347
+ // Serverless functions only ever run on 64-bit Linux. The darwin/win32/android
2348
+ // and 32-bit-arm prebuilds of these native packages are ~100MB that can never
2349
+ // execute there, and Netlify copies the whole server dir again for every extra
2350
+ // emitted function — so the dead weight is paid once per function. Cold start
2351
+ // scales with bundle size, and a page that opens several requests at once
2352
+ // scales out to that many cold containers, which is how this surfaces: 502/504
2353
+ // on the first burst rather than as an obviously slow deploy.
2354
+ const SERVERLESS_NATIVE_PACKAGE_SUFFIXES = [
2355
+ "linux-x64-gnu",
2356
+ "linux-x64-musl",
2357
+ "linux-arm64-gnu",
2358
+ "linux-arm64-musl",
2359
+ ];
2360
+
2361
+ export function isServerlessNativePlatformPackage(
2362
+ packageName: string,
2363
+ ): boolean {
2364
+ return SERVERLESS_NATIVE_PACKAGE_SUFFIXES.some((suffix) =>
2365
+ packageName.endsWith(suffix),
2366
+ );
2367
+ }
2346
2368
  const FFMPEG_STATIC_BINARY_NAMES =
2347
2369
  process.platform === "win32" ? ["ffmpeg.exe", "ffmpeg"] : ["ffmpeg"];
2348
2370
  const SERVERLESS_FFMPEG_STATIC_PLATFORM = "linux";
@@ -3441,6 +3463,7 @@ function copyInstalledLibsqlNativePackages(serverDir: string | undefined) {
3441
3463
  let copied = 0;
3442
3464
 
3443
3465
  for (const packageName of LIBSQL_NATIVE_PACKAGE_NAMES) {
3466
+ if (!isServerlessNativePlatformPackage(packageName)) continue;
3444
3467
  const src = findInstalledLibsqlNativePackage(nodeModulesRoots, packageName);
3445
3468
  if (!src) continue;
3446
3469
 
@@ -3457,7 +3480,13 @@ function copyInstalledLibsqlNativePackages(serverDir: string | undefined) {
3457
3480
 
3458
3481
  function copyInstalledResvgPackages(serverDir: string | undefined) {
3459
3482
  if (!serverDir || !fs.existsSync(serverDir)) return;
3460
- const packages = findInstalledResvgPackages(nodeModulesAncestors(cwd));
3483
+ // `resvg-js` itself is the JS wrapper that gets imported; everything else in
3484
+ // the scope is a per-platform prebuild.
3485
+ const packages = findInstalledResvgPackages(nodeModulesAncestors(cwd)).filter(
3486
+ ({ packageName }) =>
3487
+ packageName === RESVG_PACKAGE_PREFIX ||
3488
+ isServerlessNativePlatformPackage(packageName),
3489
+ );
3461
3490
  if (packages.length === 0) return;
3462
3491
 
3463
3492
  const destScopeDir = path.join(serverDir, "node_modules", RESVG_SCOPE);
@@ -367,6 +367,9 @@ async function reconfigureManager(manager: McpClientManager): Promise<void> {
367
367
  export function mountMcpServersRoutes(
368
368
  nitroApp: any,
369
369
  manager: McpClientManager,
370
+ options: {
371
+ waitUntilReady?: () => Promise<void>;
372
+ } = {},
370
373
  ): void {
371
374
  const mountedApps: WeakSet<object> = ((
372
375
  globalThis as any
@@ -375,13 +378,17 @@ export function mountMcpServersRoutes(
375
378
  mountedApps.add(nitroApp);
376
379
 
377
380
  mountMcpOAuthRoutes(nitroApp, {
378
- reconfigure: () => reconfigureManager(manager),
381
+ reconfigure: async () => {
382
+ await options.waitUntilReady?.();
383
+ await reconfigureManager(manager);
384
+ },
379
385
  });
380
386
 
381
387
  try {
382
388
  getH3App(nitroApp).use(
383
389
  "/_agent-native/mcp/servers",
384
390
  defineEventHandler(async (event: H3Event) => {
391
+ await options.waitUntilReady?.();
385
392
  const method = getMethod(event);
386
393
  const pathname = (event.url?.pathname || "")
387
394
  .replace(/^\/+/, "")
@@ -421,6 +428,7 @@ export function mountMcpServersRoutes(
421
428
  getH3App(nitroApp).use(
422
429
  "/_agent-native/mcp/builtin",
423
430
  defineEventHandler(async (event: H3Event) => {
431
+ await options.waitUntilReady?.();
424
432
  const method = getMethod(event);
425
433
  const pathname = (event.url?.pathname || "")
426
434
  .replace(/^\/+/, "")
@@ -442,6 +450,7 @@ export function mountMcpServersRoutes(
442
450
  getH3App(nitroApp).use(
443
451
  "/_agent-native/mcp/apps",
444
452
  defineEventHandler(async (event: H3Event) => {
453
+ await options.waitUntilReady?.();
445
454
  const method = getMethod(event);
446
455
  const pathname = (event.url?.pathname || "")
447
456
  .replace(/^\/+/, "")
@@ -0,0 +1,152 @@
1
+ import {
2
+ defineEventHandler,
3
+ getRequestURL,
4
+ createError,
5
+ type H3Event,
6
+ } from "h3";
7
+
8
+ import { getDbExec } from "../db/client.js";
9
+ import { readBody } from "../server/h3-helpers.js";
10
+ import {
11
+ getRegisteredAppRoles,
12
+ listAppMemberRoles,
13
+ setAppMemberRole,
14
+ type AppRolesDescriptor,
15
+ } from "./app-roles.js";
16
+ import { getOrgContext } from "./context.js";
17
+ import { canManageOrg } from "./permissions.js";
18
+
19
+ /**
20
+ * Resolve the descriptor a request is talking about.
21
+ *
22
+ * The `appId` arrives from the client but can only ever select among
23
+ * descriptors the server already declared through `defineAppRoles`; an
24
+ * unregistered id is a 404, never an implicit new app. That keeps the trusted
25
+ * vocabulary in app source while still letting one workspace host several apps.
26
+ */
27
+ function requireDescriptor(appId: string | null): AppRolesDescriptor<string> {
28
+ if (!appId?.trim()) {
29
+ throw createError({ statusCode: 400, message: "appId is required" });
30
+ }
31
+ const descriptor = getRegisteredAppRoles(appId.trim());
32
+ if (!descriptor) {
33
+ throw createError({
34
+ statusCode: 404,
35
+ message: `No app roles registered for "${appId}"`,
36
+ });
37
+ }
38
+ return descriptor;
39
+ }
40
+
41
+ /** Extract the :email tail. The mount prefix is stripped before we see it. */
42
+ function extractMemberEmail(event: H3Event): string | undefined {
43
+ const path = getRequestURL(event).pathname;
44
+ const match =
45
+ path.match(/^\/([^/]+)\/?$/) ?? path.match(/\/app-roles\/([^/]+)\/?$/);
46
+ return match?.[1] ? decodeURIComponent(match[1]) : undefined;
47
+ }
48
+
49
+ async function isOrgMember(orgId: string, email: string): Promise<boolean> {
50
+ const { rows } = await getDbExec().execute({
51
+ sql: `SELECT 1 FROM org_members WHERE org_id = ? AND LOWER(email) = ? LIMIT 1`,
52
+ args: [orgId, email.trim().toLowerCase()],
53
+ });
54
+ return rows.length > 0;
55
+ }
56
+
57
+ /**
58
+ * GET /_agent-native/org/app-roles?appId=X — the app's vocabulary plus every
59
+ * assignment in the active org, and the caller's own resolved role.
60
+ */
61
+ export const listAppRolesHandler = defineEventHandler(
62
+ async (event: H3Event) => {
63
+ const url = getRequestURL(event);
64
+ const descriptor = requireDescriptor(url.searchParams.get("appId"));
65
+ const ctx = await getOrgContext(event);
66
+
67
+ const base = {
68
+ appId: descriptor.appId,
69
+ roles: descriptor.roles,
70
+ defaultRole: descriptor.defaultRole ?? null,
71
+ roleLabels: descriptor.roleLabels ?? {},
72
+ canManage: canManageOrg(ctx.role),
73
+ };
74
+ if (!ctx.orgId) return { ...base, assignments: [], myRole: null };
75
+
76
+ const assignments = await listAppMemberRoles(descriptor.appId, ctx.orgId);
77
+ const mine = assignments.find(
78
+ (a) => a.email.toLowerCase() === ctx.email.toLowerCase(),
79
+ );
80
+ return {
81
+ ...base,
82
+ assignments,
83
+ // The caller's own role, for progressive disclosure only. Every guarded
84
+ // operation re-resolves this server-side; a client that lies about it gains
85
+ // nothing but a differently-shaped UI.
86
+ myRole: mine && descriptor.roles.includes(mine.role) ? mine.role : null,
87
+ };
88
+ },
89
+ );
90
+
91
+ /**
92
+ * PUT /_agent-native/org/app-roles/:email — assign or clear an app role.
93
+ * Body: `{ appId, role }`, where `role: null` clears the assignment.
94
+ *
95
+ * Org owner/admin only. App roles never confer the right to manage app roles:
96
+ * that would let an app admin escalate inside a team they cannot otherwise
97
+ * administer, and it is the org roster this overlay hangs off.
98
+ */
99
+ export const setAppRoleHandler = defineEventHandler(async (event: H3Event) => {
100
+ const ctx = await getOrgContext(event);
101
+ if (!ctx.email) {
102
+ throw createError({ statusCode: 401, message: "Authentication required" });
103
+ }
104
+ if (!ctx.orgId) {
105
+ throw createError({ statusCode: 400, message: "No active organization" });
106
+ }
107
+ if (!canManageOrg(ctx.role)) {
108
+ throw createError({
109
+ statusCode: 403,
110
+ message: "Organization admin role required",
111
+ });
112
+ }
113
+
114
+ const body = await readBody(event);
115
+ const descriptor = requireDescriptor(body?.appId ?? null);
116
+
117
+ const email = extractMemberEmail(event);
118
+ if (!email) {
119
+ throw createError({ statusCode: 400, message: "Member email is required" });
120
+ }
121
+
122
+ const role = body?.role ?? null;
123
+ if (role !== null && !descriptor.roles.includes(String(role))) {
124
+ throw createError({
125
+ statusCode: 400,
126
+ message: `Unknown ${descriptor.appId} role "${role}"`,
127
+ });
128
+ }
129
+
130
+ // Assignments hang off membership. Writing one for a non-member would leave a
131
+ // row that resolves to nothing and reappears if that person is ever invited.
132
+ if (!(await isOrgMember(ctx.orgId, email))) {
133
+ throw createError({
134
+ statusCode: 404,
135
+ message: "Not a member of this organization",
136
+ });
137
+ }
138
+
139
+ await setAppMemberRole({
140
+ appId: descriptor.appId,
141
+ orgId: ctx.orgId,
142
+ email,
143
+ role: role === null ? null : String(role),
144
+ updatedBy: ctx.email,
145
+ });
146
+
147
+ return {
148
+ appId: descriptor.appId,
149
+ email,
150
+ role: role === null ? null : String(role),
151
+ };
152
+ });