@agent-native/core 0.79.16 → 0.79.18

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 (344) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +14 -0
  3. package/corpus/core/docs/content/file-uploads.md +11 -4
  4. package/corpus/core/docs/content/locales/ar-SA/multi-app-workspace.md +3 -3
  5. package/corpus/core/docs/content/locales/de-DE/multi-app-workspace.md +3 -3
  6. package/corpus/core/docs/content/locales/es-ES/multi-app-workspace.md +3 -3
  7. package/corpus/core/docs/content/locales/fr-FR/multi-app-workspace.md +3 -3
  8. package/corpus/core/docs/content/locales/hi-IN/multi-app-workspace.md +3 -3
  9. package/corpus/core/docs/content/locales/ja-JP/multi-app-workspace.md +3 -3
  10. package/corpus/core/docs/content/locales/ko-KR/multi-app-workspace.md +3 -3
  11. package/corpus/core/docs/content/locales/pt-BR/multi-app-workspace.md +3 -3
  12. package/corpus/core/docs/content/locales/zh-CN/multi-app-workspace.md +3 -3
  13. package/corpus/core/docs/content/locales/zh-TW/multi-app-workspace.md +3 -3
  14. package/corpus/core/docs/content/multi-app-workspace.md +3 -3
  15. package/corpus/core/docs/content/template-clips.md +14 -5
  16. package/corpus/core/package.json +1 -1
  17. package/corpus/core/src/agent/engine/builder-engine.ts +8 -3
  18. package/corpus/core/src/cli/mcp.ts +11 -6
  19. package/corpus/core/src/client/AssistantChat.tsx +6 -2
  20. package/corpus/core/src/client/chat/markdown-renderer.tsx +1 -0
  21. package/corpus/core/src/client/index.ts +7 -1
  22. package/corpus/core/src/client/org/OrgSwitcher.tsx +5 -5
  23. package/corpus/core/src/client/org/TeamPage.tsx +11 -3
  24. package/corpus/core/src/client/settings/SettingsTabsPage.tsx +216 -0
  25. package/corpus/core/src/client/settings/index.ts +5 -0
  26. package/corpus/core/src/file-upload/index.ts +1 -0
  27. package/corpus/core/src/file-upload/registry.ts +22 -6
  28. package/corpus/core/src/file-upload/types.ts +6 -1
  29. package/corpus/core/src/integrations/adapters/email.ts +26 -18
  30. package/corpus/core/src/integrations/adapters/slack.ts +8 -7
  31. package/corpus/core/src/integrations/adapters/telegram.ts +9 -11
  32. package/corpus/core/src/integrations/adapters/whatsapp.ts +12 -9
  33. package/corpus/core/src/integrations/plugin.ts +79 -13
  34. package/corpus/core/src/onboarding/default-steps.ts +6 -3
  35. package/corpus/core/src/onboarding/types.ts +1 -1
  36. package/corpus/core/src/org/handlers.ts +1 -1
  37. package/corpus/core/src/server/agent-chat-plugin.ts +4 -7
  38. package/corpus/core/src/server/better-auth-instance.ts +19 -62
  39. package/corpus/core/src/server/core-routes-plugin.ts +93 -180
  40. package/corpus/core/src/server/create-server.ts +55 -116
  41. package/corpus/core/src/server/email-actions.ts +3 -6
  42. package/corpus/core/src/server/email.ts +52 -17
  43. package/corpus/core/src/server/index.ts +2 -1
  44. package/corpus/core/src/server/scoped-key-storage.ts +223 -0
  45. package/corpus/core/src/shared/agent-env.ts +3 -3
  46. package/corpus/core/src/sharing/actions/share-resource.ts +1 -1
  47. package/corpus/core/src/styles/agent-native.css +55 -3
  48. package/corpus/core/src/templates/workspace-root/AGENTS.md +3 -2
  49. package/corpus/core/src/templates/workspace-root/README.md +1 -1
  50. package/corpus/core/src/templates/workspace-root/scripts/repair-workspace-org.ts +29 -90
  51. package/corpus/core/src/terminal/pty-server.ts +3 -38
  52. package/corpus/core/src/triggers/dispatcher.ts +1 -2
  53. package/corpus/templates/.retired/issues/package.json +7 -0
  54. package/corpus/templates/.retired/meeting-notes/package.json +7 -0
  55. package/corpus/templates/.retired/recruiting/package.json +7 -0
  56. package/corpus/templates/.retired/scheduling/package.json +7 -0
  57. package/corpus/templates/.retired/voice/package.json +7 -0
  58. package/corpus/templates/analytics/app/components/layout/Header.tsx +0 -1
  59. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +0 -17
  60. package/corpus/templates/analytics/app/i18n/zh-TW.ts +7 -1
  61. package/corpus/templates/analytics/app/i18n-data.ts +71 -2
  62. package/corpus/templates/analytics/app/pages/Settings.tsx +120 -73
  63. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +0 -11
  64. package/corpus/templates/analytics/app/routes/catalog.tsx +33 -176
  65. package/corpus/templates/analytics/app/routes/team.tsx +3 -2
  66. package/corpus/templates/analytics/changelog/2026-06-26-dashboard-templates-are-tucked-into-settings-and-show-simple.md +6 -0
  67. package/corpus/templates/analytics/changelog/2026-06-26-the-sessions-page-shows-a-single-page-title-instead-of-repea.md +6 -0
  68. package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +37 -28
  69. package/corpus/templates/assets/app/routes/settings.tsx +65 -43
  70. package/corpus/templates/assets/app/routes/team.tsx +2 -10
  71. package/corpus/templates/brain/app/routes/settings.tsx +390 -358
  72. package/corpus/templates/brain/app/routes/team.tsx +2 -8
  73. package/corpus/templates/calendar/actions/db-connect.ts +5 -29
  74. package/corpus/templates/calendar/app/components/CloudUpgrade.tsx +8 -51
  75. package/corpus/templates/calendar/app/components/calendar/GoogleConnectBanner.tsx +2 -1
  76. package/corpus/templates/calendar/app/components/calendar/GoogleSetupWizard.tsx +4 -2
  77. package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +0 -2
  78. package/corpus/templates/calendar/app/pages/Settings.tsx +304 -271
  79. package/corpus/templates/calendar/app/routes/_app.team.tsx +2 -17
  80. package/corpus/templates/calendar/server/handlers/google-auth.ts +22 -9
  81. package/corpus/templates/calendar/server/lib/booking-emails.ts +1 -1
  82. package/corpus/templates/calendar/server/lib/event-guest-notifications.ts +1 -1
  83. package/corpus/templates/calendar/server/lib/google-calendar.ts +48 -28
  84. package/corpus/templates/chat/app/components/layout/Header.tsx +0 -1
  85. package/corpus/templates/chat/app/hooks/use-navigation-state.ts +4 -2
  86. package/corpus/templates/chat/app/routes/settings.tsx +54 -54
  87. package/corpus/templates/chat/app/routes/team.tsx +2 -10
  88. package/corpus/templates/clips/.agents/skills/ai-video-tools/SKILL.md +7 -2
  89. package/corpus/templates/clips/.agents/skills/recording/SKILL.md +1 -1
  90. package/corpus/templates/clips/.agents/skills/video-sharing/SKILL.md +7 -0
  91. package/corpus/templates/clips/AGENTS.md +8 -0
  92. package/corpus/templates/clips/actions/invite-member.ts +1 -1
  93. package/corpus/templates/clips/actions/request-transcript.ts +1 -1
  94. package/corpus/templates/clips/app/components/library/library-layout.tsx +3 -3
  95. package/corpus/templates/clips/app/components/player/transcript-panel.tsx +2 -0
  96. package/corpus/templates/clips/app/routes/_app.settings._index.tsx +629 -643
  97. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +219 -155
  98. package/corpus/templates/clips/changelog/2026-06-26-long-desktop-recordings-are-checkpointed-so-macos-finalizati.md +6 -0
  99. package/corpus/templates/clips/changelog/2026-06-26-non-mac-desktop-recordings-wait-for-upload-transcription.md +6 -0
  100. package/corpus/templates/clips/changelog/2026-06-26-s3-compatible-storage-keys-now-save-securely-from-clips-sett.md +6 -0
  101. package/corpus/templates/clips/changelog/2026-06-26-shared-clip-links-guide-agents-through-processing-transcripts.md +6 -0
  102. package/corpus/templates/clips/changelog/2026-06-26-the-clip-details-sidebar-now-collapses-into-a-slide-out-pane.md +6 -0
  103. package/corpus/templates/clips/changelog/2026-06-26-the-clips-library-now-matches-the-shared-recessed-shell-styl.md +6 -0
  104. package/corpus/templates/clips/desktop/src/lib/recorder.ts +55 -3
  105. package/corpus/templates/clips/desktop/src/lib/transcription-capture.ts +217 -5
  106. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +1 -0
  107. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +176 -5
  108. package/corpus/templates/clips/server/lib/public-agent-context.ts +31 -0
  109. package/corpus/templates/clips/server/lib/s3-upload-provider.ts +60 -14
  110. package/corpus/templates/clips/server/lib/video-storage.ts +37 -9
  111. package/corpus/templates/clips/server/routes/api/agent-transcript.json.get.ts +5 -0
  112. package/corpus/templates/content/app/components/layout/Header.tsx +0 -1
  113. package/corpus/templates/content/app/components/sidebar/NotionButton.tsx +1 -0
  114. package/corpus/templates/content/app/routes/_app.settings.tsx +54 -55
  115. package/corpus/templates/content/app/routes/_app.team.tsx +2 -28
  116. package/corpus/templates/content/server/lib/notion.ts +43 -11
  117. package/corpus/templates/content/server/routes/api/notion/auth-url.get.ts +2 -2
  118. package/corpus/templates/content/server/routes/api/notion/status.get.ts +3 -3
  119. package/corpus/templates/design/app/routes/settings.tsx +60 -38
  120. package/corpus/templates/design/app/routes/team.tsx +2 -10
  121. package/corpus/templates/dispatch/app/hooks/use-navigation-state.ts +2 -2
  122. package/corpus/templates/dispatch/app/routes/settings.tsx +70 -55
  123. package/corpus/templates/dispatch/app/routes/team.tsx +5 -1
  124. package/corpus/templates/forms/actions/db-connect.ts +7 -36
  125. package/corpus/templates/forms/actions/navigate.ts +2 -2
  126. package/corpus/templates/forms/app/components/CloudUpgrade.tsx +8 -47
  127. package/corpus/templates/forms/app/components/layout/Header.tsx +0 -1
  128. package/corpus/templates/forms/app/components/layout/Layout.tsx +42 -25
  129. package/corpus/templates/forms/app/components/layout/Sidebar.tsx +35 -76
  130. package/corpus/templates/forms/app/global.css +9 -25
  131. package/corpus/templates/forms/app/hooks/use-navigation-state.ts +4 -4
  132. package/corpus/templates/forms/app/i18n/ar-SA.ts +1 -0
  133. package/corpus/templates/forms/app/i18n/de-DE.ts +1 -0
  134. package/corpus/templates/forms/app/i18n/en-US.ts +1 -0
  135. package/corpus/templates/forms/app/i18n/es-ES.ts +1 -0
  136. package/corpus/templates/forms/app/i18n/fr-FR.ts +1 -0
  137. package/corpus/templates/forms/app/i18n/hi-IN.ts +1 -0
  138. package/corpus/templates/forms/app/i18n/ja-JP.ts +1 -0
  139. package/corpus/templates/forms/app/i18n/ko-KR.ts +1 -0
  140. package/corpus/templates/forms/app/i18n/pt-BR.ts +1 -0
  141. package/corpus/templates/forms/app/i18n/zh-CN.ts +1 -0
  142. package/corpus/templates/forms/app/i18n/zh-TW.ts +1 -0
  143. package/corpus/templates/forms/app/lib/route-prewarm.ts +9 -8
  144. package/corpus/templates/forms/app/pages/AskPage.tsx +70 -0
  145. package/corpus/templates/forms/app/pages/FormsListPage.tsx +74 -81
  146. package/corpus/templates/forms/app/root.tsx +1 -1
  147. package/corpus/templates/forms/app/routes/_app.ask.tsx +14 -0
  148. package/corpus/templates/forms/app/routes/_app.settings.tsx +54 -54
  149. package/corpus/templates/forms/app/routes/_app.team.tsx +2 -9
  150. package/corpus/templates/forms/app/routes/_index.tsx +21 -130
  151. package/corpus/templates/forms/changelog/2026-06-26-ask-forms-opens-as-a-standard-app-tab-with-a-simpler-sidebar.md +6 -0
  152. package/corpus/templates/forms/changelog/2026-06-26-forms-are-shown-in-a-tighter-row-list-with-a-denser-sidebar.md +6 -0
  153. package/corpus/templates/forms/shared/navigation.ts +4 -2
  154. package/corpus/templates/macros/app/routes/settings.tsx +54 -54
  155. package/corpus/templates/macros/app/routes/team.tsx +2 -10
  156. package/corpus/templates/mail/actions/helpers.ts +2 -2
  157. package/corpus/templates/mail/app/components/GoogleConnectBanner.tsx +2 -1
  158. package/corpus/templates/mail/app/pages/SettingsPage.tsx +5 -5
  159. package/corpus/templates/mail/app/routes/team.tsx +3 -2
  160. package/corpus/templates/mail/server/handlers/emails.ts +3 -2
  161. package/corpus/templates/mail/server/handlers/google-auth.ts +19 -12
  162. package/corpus/templates/mail/server/lib/automation-engine.ts +3 -2
  163. package/corpus/templates/mail/server/lib/email-state.ts +2 -3
  164. package/corpus/templates/mail/server/lib/google-auth.ts +28 -11
  165. package/corpus/templates/mail/server/lib/jobs.ts +3 -2
  166. package/corpus/templates/mail/server/onboarding.ts +9 -6
  167. package/corpus/templates/mail/server/routes/api/attachments.get.ts +3 -3
  168. package/corpus/templates/plan/actions/request-plan-access.ts +1 -1
  169. package/corpus/templates/plan/app/components/layout/Header.tsx +0 -1
  170. package/corpus/templates/plan/app/hooks/use-navigation-state.ts +4 -2
  171. package/corpus/templates/plan/app/lib/route-prewarm.ts +0 -4
  172. package/corpus/templates/plan/app/routes/settings.tsx +75 -73
  173. package/corpus/templates/plan/app/routes/team.tsx +2 -8
  174. package/corpus/templates/plan/server/lib/comment-notifications.ts +1 -1
  175. package/corpus/templates/slides/actions/check-image-gen.ts +2 -1
  176. package/corpus/templates/slides/actions/db-connect.ts +7 -45
  177. package/corpus/templates/slides/actions/edit-image.ts +6 -3
  178. package/corpus/templates/slides/actions/generate-image-api.ts +1 -1
  179. package/corpus/templates/slides/actions/generate-image.ts +2 -2
  180. package/corpus/templates/slides/actions/generate-slides-ai.ts +5 -3
  181. package/corpus/templates/slides/actions/image-gen-status.ts +4 -3
  182. package/corpus/templates/slides/actions/image-search.ts +6 -3
  183. package/corpus/templates/slides/actions/search-images.ts +6 -3
  184. package/corpus/templates/slides/app/components/CloudUpgrade.tsx +8 -51
  185. package/corpus/templates/slides/app/components/layout/Header.tsx +0 -1
  186. package/corpus/templates/slides/app/components/layout/Sidebar.tsx +0 -2
  187. package/corpus/templates/slides/app/routes/settings.tsx +54 -54
  188. package/corpus/templates/slides/app/routes/team.tsx +2 -12
  189. package/corpus/templates/slides/server/handlers/google-docs-auth.ts +9 -9
  190. package/corpus/templates/slides/server/handlers/image-gen.ts +5 -1
  191. package/corpus/templates/slides/server/handlers/image-providers/gemini.ts +9 -1
  192. package/corpus/templates/slides/server/handlers/image-providers/index.ts +18 -8
  193. package/corpus/templates/slides/server/handlers/image-providers/openai.ts +10 -4
  194. package/corpus/templates/slides/server/handlers/image-providers/types.ts +1 -0
  195. package/corpus/templates/slides/server/lib/google-docs-oauth.ts +59 -34
  196. package/corpus/templates/slides/server/register-secrets.ts +60 -0
  197. package/corpus/templates/videos/actions/db-connect.ts +7 -45
  198. package/corpus/templates/videos/app/components/CloudUpgrade.tsx +8 -51
  199. package/corpus/templates/videos/app/components/Sidebar.tsx +1 -9
  200. package/corpus/templates/videos/app/components/layout/Header.tsx +0 -1
  201. package/corpus/templates/videos/app/components/layout/NavSidebar.tsx +0 -3
  202. package/corpus/templates/videos/app/routes/settings.tsx +54 -54
  203. package/corpus/templates/videos/app/routes/team.tsx +2 -8
  204. package/dist/agent/engine/builder-engine.d.ts.map +1 -1
  205. package/dist/agent/engine/builder-engine.js +8 -3
  206. package/dist/agent/engine/builder-engine.js.map +1 -1
  207. package/dist/cli/mcp.d.ts.map +1 -1
  208. package/dist/cli/mcp.js +3 -4
  209. package/dist/cli/mcp.js.map +1 -1
  210. package/dist/client/AssistantChat.d.ts.map +1 -1
  211. package/dist/client/AssistantChat.js +6 -2
  212. package/dist/client/AssistantChat.js.map +1 -1
  213. package/dist/client/chat/markdown-renderer.d.ts.map +1 -1
  214. package/dist/client/chat/markdown-renderer.js +1 -0
  215. package/dist/client/chat/markdown-renderer.js.map +1 -1
  216. package/dist/client/index.d.ts +1 -1
  217. package/dist/client/index.d.ts.map +1 -1
  218. package/dist/client/index.js +1 -1
  219. package/dist/client/index.js.map +1 -1
  220. package/dist/client/org/OrgSwitcher.d.ts +3 -3
  221. package/dist/client/org/OrgSwitcher.js +2 -2
  222. package/dist/client/org/OrgSwitcher.js.map +1 -1
  223. package/dist/client/org/TeamPage.d.ts +6 -1
  224. package/dist/client/org/TeamPage.d.ts.map +1 -1
  225. package/dist/client/org/TeamPage.js +2 -2
  226. package/dist/client/org/TeamPage.js.map +1 -1
  227. package/dist/client/settings/SettingsTabsPage.d.ts +27 -0
  228. package/dist/client/settings/SettingsTabsPage.d.ts.map +1 -0
  229. package/dist/client/settings/SettingsTabsPage.js +108 -0
  230. package/dist/client/settings/SettingsTabsPage.js.map +1 -0
  231. package/dist/client/settings/index.d.ts +1 -0
  232. package/dist/client/settings/index.d.ts.map +1 -1
  233. package/dist/client/settings/index.js +1 -0
  234. package/dist/client/settings/index.js.map +1 -1
  235. package/dist/collab/awareness.d.ts +2 -2
  236. package/dist/collab/awareness.d.ts.map +1 -1
  237. package/dist/collab/routes.d.ts +1 -1
  238. package/dist/file-upload/index.d.ts +1 -1
  239. package/dist/file-upload/index.d.ts.map +1 -1
  240. package/dist/file-upload/index.js +1 -1
  241. package/dist/file-upload/index.js.map +1 -1
  242. package/dist/file-upload/registry.d.ts +1 -0
  243. package/dist/file-upload/registry.d.ts.map +1 -1
  244. package/dist/file-upload/registry.js +24 -6
  245. package/dist/file-upload/registry.js.map +1 -1
  246. package/dist/file-upload/types.d.ts +6 -1
  247. package/dist/file-upload/types.d.ts.map +1 -1
  248. package/dist/file-upload/types.js.map +1 -1
  249. package/dist/integrations/adapters/email.d.ts.map +1 -1
  250. package/dist/integrations/adapters/email.js +18 -18
  251. package/dist/integrations/adapters/email.js.map +1 -1
  252. package/dist/integrations/adapters/slack.d.ts.map +1 -1
  253. package/dist/integrations/adapters/slack.js +8 -7
  254. package/dist/integrations/adapters/slack.js.map +1 -1
  255. package/dist/integrations/adapters/telegram.d.ts.map +1 -1
  256. package/dist/integrations/adapters/telegram.js +9 -9
  257. package/dist/integrations/adapters/telegram.js.map +1 -1
  258. package/dist/integrations/adapters/whatsapp.d.ts.map +1 -1
  259. package/dist/integrations/adapters/whatsapp.js +10 -9
  260. package/dist/integrations/adapters/whatsapp.js.map +1 -1
  261. package/dist/integrations/plugin.d.ts.map +1 -1
  262. package/dist/integrations/plugin.js +47 -13
  263. package/dist/integrations/plugin.js.map +1 -1
  264. package/dist/notifications/routes.d.ts +1 -1
  265. package/dist/onboarding/default-steps.d.ts.map +1 -1
  266. package/dist/onboarding/default-steps.js +6 -5
  267. package/dist/onboarding/default-steps.js.map +1 -1
  268. package/dist/onboarding/types.d.ts +1 -1
  269. package/dist/onboarding/types.d.ts.map +1 -1
  270. package/dist/onboarding/types.js.map +1 -1
  271. package/dist/org/handlers.js +1 -1
  272. package/dist/org/handlers.js.map +1 -1
  273. package/dist/progress/routes.d.ts +1 -1
  274. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  275. package/dist/server/agent-chat-plugin.js +4 -6
  276. package/dist/server/agent-chat-plugin.js.map +1 -1
  277. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  278. package/dist/server/better-auth-instance.d.ts.map +1 -1
  279. package/dist/server/better-auth-instance.js +17 -56
  280. package/dist/server/better-auth-instance.js.map +1 -1
  281. package/dist/server/core-routes-plugin.d.ts +1 -1
  282. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  283. package/dist/server/core-routes-plugin.js +67 -153
  284. package/dist/server/core-routes-plugin.js.map +1 -1
  285. package/dist/server/create-server.d.ts +3 -9
  286. package/dist/server/create-server.d.ts.map +1 -1
  287. package/dist/server/create-server.js +37 -91
  288. package/dist/server/create-server.js.map +1 -1
  289. package/dist/server/email-actions.d.ts +2 -3
  290. package/dist/server/email-actions.d.ts.map +1 -1
  291. package/dist/server/email-actions.js +3 -6
  292. package/dist/server/email-actions.js.map +1 -1
  293. package/dist/server/email.d.ts +3 -3
  294. package/dist/server/email.d.ts.map +1 -1
  295. package/dist/server/email.js +40 -19
  296. package/dist/server/email.js.map +1 -1
  297. package/dist/server/index.d.ts +3 -3
  298. package/dist/server/index.d.ts.map +1 -1
  299. package/dist/server/index.js +3 -3
  300. package/dist/server/index.js.map +1 -1
  301. package/dist/server/scoped-key-storage.d.ts +22 -0
  302. package/dist/server/scoped-key-storage.d.ts.map +1 -0
  303. package/dist/server/scoped-key-storage.js +152 -0
  304. package/dist/server/scoped-key-storage.js.map +1 -0
  305. package/dist/shared/agent-env.d.ts +3 -3
  306. package/dist/shared/agent-env.d.ts.map +1 -1
  307. package/dist/shared/agent-env.js +3 -3
  308. package/dist/shared/agent-env.js.map +1 -1
  309. package/dist/sharing/actions/share-resource.js +1 -1
  310. package/dist/sharing/actions/share-resource.js.map +1 -1
  311. package/dist/styles/agent-native.css +55 -3
  312. package/dist/templates/workspace-root/AGENTS.md +3 -2
  313. package/dist/templates/workspace-root/README.md +1 -1
  314. package/dist/templates/workspace-root/scripts/repair-workspace-org.ts +29 -90
  315. package/dist/terminal/pty-server.d.ts.map +1 -1
  316. package/dist/terminal/pty-server.js +3 -36
  317. package/dist/terminal/pty-server.js.map +1 -1
  318. package/dist/triggers/dispatcher.js +1 -1
  319. package/dist/triggers/dispatcher.js.map +1 -1
  320. package/docs/content/file-uploads.md +11 -4
  321. package/docs/content/locales/ar-SA/multi-app-workspace.md +3 -3
  322. package/docs/content/locales/de-DE/multi-app-workspace.md +3 -3
  323. package/docs/content/locales/es-ES/multi-app-workspace.md +3 -3
  324. package/docs/content/locales/fr-FR/multi-app-workspace.md +3 -3
  325. package/docs/content/locales/hi-IN/multi-app-workspace.md +3 -3
  326. package/docs/content/locales/ja-JP/multi-app-workspace.md +3 -3
  327. package/docs/content/locales/ko-KR/multi-app-workspace.md +3 -3
  328. package/docs/content/locales/pt-BR/multi-app-workspace.md +3 -3
  329. package/docs/content/locales/zh-CN/multi-app-workspace.md +3 -3
  330. package/docs/content/locales/zh-TW/multi-app-workspace.md +3 -3
  331. package/docs/content/multi-app-workspace.md +3 -3
  332. package/docs/content/template-clips.md +14 -5
  333. package/package.json +1 -1
  334. package/src/templates/workspace-root/AGENTS.md +3 -2
  335. package/src/templates/workspace-root/README.md +1 -1
  336. package/src/templates/workspace-root/scripts/repair-workspace-org.ts +29 -90
  337. package/corpus/core/src/server/env-var-writes.ts +0 -16
  338. package/corpus/templates/analytics/app/pages/Team.tsx +0 -9
  339. package/corpus/templates/calendar/app/pages/Team.tsx +0 -12
  340. package/corpus/templates/mail/app/pages/Team.tsx +0 -17
  341. package/dist/server/env-var-writes.d.ts +0 -10
  342. package/dist/server/env-var-writes.d.ts.map +0 -1
  343. package/dist/server/env-var-writes.js +0 -18
  344. package/dist/server/env-var-writes.js.map +0 -1
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Email transport for system emails (password resets, invitations, notifications).
3
3
  *
4
- * Providers are selected by env var:
4
+ * Providers are selected by scoped secrets:
5
5
  * RESEND_API_KEY — https://resend.com
6
6
  * SENDGRID_API_KEY — https://sendgrid.com
7
7
  * EMAIL_FROM — "Name <addr@domain>" (optional; defaults to Resend's sandbox)
@@ -10,6 +10,8 @@
10
10
  * so the reset-password flow still works end-to-end for local development.
11
11
  */
12
12
 
13
+ import { resolveSecret } from "./credential-provider.js";
14
+
13
15
  export type EmailProvider = "resend" | "sendgrid" | "dev";
14
16
 
15
17
  export interface EmailAttachment {
@@ -33,32 +35,65 @@ export interface SendEmailArgs {
33
35
  attachments?: EmailAttachment[];
34
36
  }
35
37
 
36
- export function isEmailConfigured(): boolean {
37
- return !!(process.env.RESEND_API_KEY || process.env.SENDGRID_API_KEY);
38
+ interface EmailTransportConfig {
39
+ provider: EmailProvider;
40
+ resendApiKey?: string;
41
+ sendgridApiKey?: string;
42
+ from?: string;
38
43
  }
39
44
 
40
- export function getEmailProvider(): EmailProvider {
41
- if (process.env.RESEND_API_KEY) return "resend";
42
- if (process.env.SENDGRID_API_KEY) return "sendgrid";
43
- return "dev";
45
+ async function resolveEmailTransport(): Promise<EmailTransportConfig> {
46
+ const [resendApiKey, sendgridApiKey, from] = await Promise.all([
47
+ resolveSecret("RESEND_API_KEY"),
48
+ resolveSecret("SENDGRID_API_KEY"),
49
+ resolveSecret("EMAIL_FROM"),
50
+ ]);
51
+ const resolvedFrom = from ?? undefined;
52
+ if (resendApiKey) {
53
+ return {
54
+ provider: "resend",
55
+ resendApiKey,
56
+ from: resolvedFrom,
57
+ };
58
+ }
59
+ if (sendgridApiKey) {
60
+ return {
61
+ provider: "sendgrid",
62
+ sendgridApiKey,
63
+ from: resolvedFrom,
64
+ };
65
+ }
66
+ return { provider: "dev", from: resolvedFrom };
44
67
  }
45
68
 
46
- function getFromAddress(override?: string, provider?: EmailProvider): string {
47
- const explicit = override || process.env.EMAIL_FROM;
69
+ export async function isEmailConfigured(): Promise<boolean> {
70
+ return (await resolveEmailTransport()).provider !== "dev";
71
+ }
72
+
73
+ export async function getEmailProvider(): Promise<EmailProvider> {
74
+ return (await resolveEmailTransport()).provider;
75
+ }
76
+
77
+ function getFromAddress(
78
+ config: EmailTransportConfig,
79
+ override?: string,
80
+ ): string {
81
+ const explicit = override || config.from;
48
82
  if (explicit) return explicit;
49
83
  // Resend lets unverified accounts send from its sandbox domain; SendGrid
50
84
  // does not, so falling back there would cause silent 403s at runtime.
51
- if (provider === "sendgrid") {
85
+ if (config.provider === "sendgrid") {
52
86
  throw new Error(
53
- "EMAIL_FROM is required when using SendGrid — set it to a verified sender address.",
87
+ "EMAIL_FROM is required when using SendGrid — save it as a verified sender address.",
54
88
  );
55
89
  }
56
90
  return "Agent Native <onboarding@resend.dev>";
57
91
  }
58
92
 
59
93
  export async function sendEmail(args: SendEmailArgs): Promise<void> {
60
- const provider = getEmailProvider();
61
- const from = getFromAddress(args.from, provider);
94
+ const config = await resolveEmailTransport();
95
+ const provider = config.provider;
96
+ const from = getFromAddress(config, args.from);
62
97
 
63
98
  if (provider === "resend") {
64
99
  const payload: Record<string, unknown> = {
@@ -89,7 +124,7 @@ export async function sendEmail(args: SendEmailArgs): Promise<void> {
89
124
  const res = await fetch("https://api.resend.com/emails", {
90
125
  method: "POST",
91
126
  headers: {
92
- Authorization: `Bearer ${process.env.RESEND_API_KEY}`,
127
+ Authorization: `Bearer ${config.resendApiKey}`,
93
128
  "Content-Type": "application/json",
94
129
  },
95
130
  body: JSON.stringify(payload),
@@ -140,7 +175,7 @@ export async function sendEmail(args: SendEmailArgs): Promise<void> {
140
175
  const res = await fetch("https://api.sendgrid.com/v3/mail/send", {
141
176
  method: "POST",
142
177
  headers: {
143
- Authorization: `Bearer ${process.env.SENDGRID_API_KEY}`,
178
+ Authorization: `Bearer ${config.sendgridApiKey}`,
144
179
  "Content-Type": "application/json",
145
180
  },
146
181
  body: JSON.stringify(sgPayload),
@@ -157,12 +192,12 @@ export async function sendEmail(args: SendEmailArgs): Promise<void> {
157
192
  // to send rather than silently leaking secrets to logs.
158
193
  if (process.env.NODE_ENV === "production") {
159
194
  throw new Error(
160
- "No email provider configured. Set RESEND_API_KEY or SENDGRID_API_KEY.",
195
+ "No email provider configured. Save RESEND_API_KEY or SENDGRID_API_KEY in settings.",
161
196
  );
162
197
  }
163
198
  console.log(
164
199
  `\n[agent-native:email] No email provider configured. ` +
165
- `Set RESEND_API_KEY or SENDGRID_API_KEY to send real emails.\n` +
200
+ `Save RESEND_API_KEY or SENDGRID_API_KEY in settings to send real emails.\n` +
166
201
  `---\nTo: ${args.to}\nFrom: ${from}\nSubject: ${args.subject}\n\n` +
167
202
  `${args.text || stripHtml(args.html)}\n---\n`,
168
203
  );
@@ -1,6 +1,5 @@
1
1
  export {
2
2
  createServer,
3
- upsertEnvFile,
4
3
  type CreateServerOptions,
5
4
  type EnvKeyConfig,
6
5
  } from "./create-server.js";
@@ -325,6 +324,7 @@ export {
325
324
  unregisterFileUploadProvider,
326
325
  listFileUploadProviders,
327
326
  getActiveFileUploadProvider,
327
+ getActiveFileUploadProviderForRequest,
328
328
  uploadFile,
329
329
  builderFileUploadProvider,
330
330
  type FileUploadInput,
@@ -381,6 +381,7 @@ export {
381
381
  resolveHasCompleteBuilderConnection,
382
382
  resolveBuilderCredentials,
383
383
  resolveBuilderCredential,
384
+ readDeployCredentialEnv,
384
385
  writeBuilderCredentials,
385
386
  deleteBuilderCredentials,
386
387
  resolveSecret,
@@ -0,0 +1,223 @@
1
+ import type { H3Event } from "h3";
2
+
3
+ import { getOrgContext } from "../org/context.js";
4
+ import {
5
+ getRequiredSecret,
6
+ type RegisteredSecret,
7
+ type SecretScope,
8
+ } from "../secrets/register.js";
9
+ import { writeAppSecret } from "../secrets/storage.js";
10
+ import { getSession } from "./auth.js";
11
+
12
+ const KEY_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
13
+
14
+ export type ScopedKeySaveRequestScope =
15
+ | "app"
16
+ | "auto"
17
+ | "org"
18
+ | "user"
19
+ | "workspace"
20
+ | undefined;
21
+
22
+ export interface ScopedKeyValue {
23
+ key: string;
24
+ value: string;
25
+ }
26
+
27
+ export interface ScopedKeySaveRow {
28
+ key: string;
29
+ scope: SecretScope;
30
+ scopeId: string;
31
+ }
32
+
33
+ export class ScopedKeyStorageError extends Error {
34
+ constructor(
35
+ readonly statusCode: number,
36
+ message: string,
37
+ ) {
38
+ super(message);
39
+ this.name = "ScopedKeyStorageError";
40
+ }
41
+ }
42
+
43
+ export function findUnsupportedScopedKeyNames(
44
+ vars: unknown,
45
+ allowedKeys: Iterable<string>,
46
+ ): string[] {
47
+ if (!Array.isArray(vars)) return [];
48
+
49
+ const allowed = new Set(allowedKeys);
50
+ const unsupported = new Set<string>();
51
+ for (const entry of vars) {
52
+ if (!entry || typeof entry !== "object") continue;
53
+ const key = (entry as { key?: unknown }).key;
54
+ const normalizedKey = typeof key === "string" ? key.trim() : "";
55
+ if (normalizedKey && !allowed.has(normalizedKey)) {
56
+ unsupported.add(normalizedKey);
57
+ }
58
+ }
59
+ return [...unsupported];
60
+ }
61
+
62
+ function redactSecretFromMessage(message: string, secretValue: string): string {
63
+ if (!message || !secretValue) return message;
64
+ return message.split(secretValue).join("[redacted]");
65
+ }
66
+
67
+ function normalizeKeyValueVars(vars: unknown): ScopedKeyValue[] {
68
+ if (!Array.isArray(vars) || vars.length === 0) {
69
+ throw new ScopedKeyStorageError(400, "vars array required");
70
+ }
71
+
72
+ const out: ScopedKeyValue[] = [];
73
+ for (const entry of vars) {
74
+ if (!entry || typeof entry !== "object") {
75
+ throw new ScopedKeyStorageError(400, "Each var must be an object");
76
+ }
77
+ const { key, value } = entry as { key?: unknown; value?: unknown };
78
+ const normalizedKey = typeof key === "string" ? key.trim() : "";
79
+ if (!normalizedKey || !KEY_NAME_RE.test(normalizedKey)) {
80
+ throw new ScopedKeyStorageError(
81
+ 400,
82
+ normalizedKey
83
+ ? `Invalid key name "${normalizedKey}"`
84
+ : "Each var requires a key",
85
+ );
86
+ }
87
+ const normalizedValue = typeof value === "string" ? value.trim() : "";
88
+ if (!normalizedValue) {
89
+ throw new ScopedKeyStorageError(
90
+ 400,
91
+ `Value for ${normalizedKey} must be non-empty`,
92
+ );
93
+ }
94
+ out.push({ key: normalizedKey, value: normalizedValue });
95
+ }
96
+ return out;
97
+ }
98
+
99
+ function resolveTargetScope(
100
+ secret: RegisteredSecret | undefined,
101
+ requestedScope: ScopedKeySaveRequestScope,
102
+ ): SecretScope {
103
+ if (secret?.kind === "api-key") return secret.scope;
104
+ if (requestedScope === "org") return "org";
105
+ if (requestedScope === "workspace" || requestedScope === "app") {
106
+ return "workspace";
107
+ }
108
+ return "user";
109
+ }
110
+
111
+ async function resolveScopeId(
112
+ event: H3Event,
113
+ scope: SecretScope,
114
+ ): Promise<{
115
+ scopeId: string;
116
+ orgRole: string | null;
117
+ orgId: string | null;
118
+ }> {
119
+ const session = await getSession(event).catch(() => null);
120
+ const email = session?.email ?? null;
121
+
122
+ if (scope === "user") {
123
+ if (!email) {
124
+ throw new ScopedKeyStorageError(401, "Sign in to save keys");
125
+ }
126
+ return { scopeId: email, orgRole: null, orgId: null };
127
+ }
128
+
129
+ const orgCtx = await getOrgContext(event).catch(() => null);
130
+ const orgId = orgCtx?.orgId ?? null;
131
+ const orgRole = orgCtx?.role ?? null;
132
+
133
+ if (scope === "org") {
134
+ if (!orgId) {
135
+ throw new ScopedKeyStorageError(401, "No active organization");
136
+ }
137
+ return { scopeId: orgId, orgRole, orgId };
138
+ }
139
+
140
+ if (orgId) {
141
+ return { scopeId: orgId, orgRole, orgId };
142
+ }
143
+ if (!email) {
144
+ throw new ScopedKeyStorageError(401, "Sign in to save workspace keys");
145
+ }
146
+ return { scopeId: `solo:${email}`, orgRole: null, orgId: null };
147
+ }
148
+
149
+ function assertCanMutateScope(
150
+ scope: SecretScope,
151
+ scopeId: string,
152
+ orgRole: string | null,
153
+ ): void {
154
+ if (scope === "user") return;
155
+ if (scope === "workspace" && scopeId.startsWith("solo:")) return;
156
+ if (orgRole === "owner" || orgRole === "admin") return;
157
+ throw new ScopedKeyStorageError(
158
+ 403,
159
+ scope === "org"
160
+ ? "Only organization owners and admins can set org-scoped keys"
161
+ : "Only organization owners and admins can set workspace-scoped keys",
162
+ );
163
+ }
164
+
165
+ async function validateRegisteredSecret(
166
+ secret: RegisteredSecret | undefined,
167
+ value: string,
168
+ ): Promise<void> {
169
+ if (!secret) return;
170
+ if (secret.kind === "oauth") {
171
+ throw new ScopedKeyStorageError(
172
+ 400,
173
+ `"${secret.key}" is an OAuth-kind secret and must be connected via OAuth`,
174
+ );
175
+ }
176
+ if (!secret.validator) return;
177
+ try {
178
+ const result = await secret.validator(value);
179
+ const ok = typeof result === "boolean" ? result : result?.ok === true;
180
+ if (ok) return;
181
+ const error =
182
+ typeof result === "object" && result && result.error
183
+ ? String(result.error)
184
+ : "Validator rejected the value";
185
+ throw new ScopedKeyStorageError(400, redactSecretFromMessage(error, value));
186
+ } catch (err) {
187
+ if (err instanceof ScopedKeyStorageError) throw err;
188
+ const message =
189
+ err instanceof Error
190
+ ? `Validator threw: ${err.message}`
191
+ : "Validator threw";
192
+ throw new ScopedKeyStorageError(
193
+ 400,
194
+ redactSecretFromMessage(message, value),
195
+ );
196
+ }
197
+ }
198
+
199
+ export async function saveKeyValuesToScopedSecrets(
200
+ event: H3Event,
201
+ vars: unknown,
202
+ requestedScope?: ScopedKeySaveRequestScope,
203
+ ): Promise<{ saved: string[]; rows: ScopedKeySaveRow[] }> {
204
+ const normalized = normalizeKeyValueVars(vars);
205
+ const rows: ScopedKeySaveRow[] = [];
206
+
207
+ for (const entry of normalized) {
208
+ const secret = getRequiredSecret(entry.key);
209
+ const scope = resolveTargetScope(secret, requestedScope);
210
+ const { scopeId, orgRole } = await resolveScopeId(event, scope);
211
+ assertCanMutateScope(scope, scopeId, orgRole);
212
+ await validateRegisteredSecret(secret, entry.value);
213
+ await writeAppSecret({
214
+ key: entry.key,
215
+ value: entry.value,
216
+ scope,
217
+ scopeId,
218
+ });
219
+ rows.push({ key: entry.key, scope, scopeId });
220
+ }
221
+
222
+ return { saved: rows.map((row) => row.key), rows };
223
+ }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Isomorphic Agent Env Utility
2
+ * Isomorphic Agent Key Utility
3
3
  *
4
4
  * Works in both browser and Node.js contexts:
5
5
  * - Browser: sends via postMessage to the parent window
@@ -18,7 +18,7 @@ const isBrowser =
18
18
  typeof window !== "undefined" && typeof window.postMessage === "function";
19
19
 
20
20
  /**
21
- * Send env vars to the host (Builder cloud or Claude frame).
21
+ * Send key/value settings to the host for scoped secret persistence.
22
22
  * Automatically detects environment (browser vs Node.js) and uses the right transport.
23
23
  */
24
24
  function setVars(vars: EnvVar[]): void {
@@ -41,6 +41,6 @@ function setVars(vars: EnvVar[]): void {
41
41
  }
42
42
 
43
43
  export const agentEnv = {
44
- /** Send environment variables to the host for persistence */
44
+ /** Send key/value settings to the host for scoped secret persistence. */
45
45
  setVars,
46
46
  };
@@ -262,7 +262,7 @@ export default defineAction({
262
262
  if (
263
263
  args.notify !== false &&
264
264
  args.principalType === "user" &&
265
- isEmailConfigured() &&
265
+ (await isEmailConfigured()) &&
266
266
  !isSyntheticQaEmail(principalId)
267
267
  ) {
268
268
  try {
@@ -55,6 +55,8 @@
55
55
  --agent-native-lower-surface: hsl(
56
56
  var(--sidebar-background, var(--background))
57
57
  );
58
+ --agent-native-raised-surface: hsl(var(--background));
59
+ --agent-native-card-surface: hsl(var(--card));
58
60
  --agent-native-raised-border: hsl(var(--border));
59
61
  --agent-native-raised-radius: 8px;
60
62
  --agent-native-raised-shadow-left: -1px 0 3px rgb(0 0 0 / 0.018);
@@ -86,6 +88,16 @@
86
88
  hsl(var(--sidebar-background, var(--background))) 94%,
87
89
  black
88
90
  );
91
+ --agent-native-raised-surface: color-mix(
92
+ in srgb,
93
+ hsl(var(--background)) 78%,
94
+ hsl(var(--muted)) 22%
95
+ );
96
+ --agent-native-card-surface: color-mix(
97
+ in srgb,
98
+ var(--agent-native-raised-surface) 88%,
99
+ hsl(var(--muted)) 12%
100
+ );
89
101
  }
90
102
  }
91
103
 
@@ -107,6 +119,13 @@
107
119
  border-inline-end-color: transparent !important;
108
120
  }
109
121
 
122
+ .agent-layout-shell
123
+ .agent-layout-left-drawer
124
+ > :where(.border-e, .border-r):first-child {
125
+ border-inline-end-color: transparent !important;
126
+ border-right-color: transparent !important;
127
+ }
128
+
110
129
  .agent-sidebar-panel > .agent-sidebar-panel-inner {
111
130
  background: inherit;
112
131
  }
@@ -119,26 +138,59 @@
119
138
  .agent-sidebar-main-surface {
120
139
  position: relative;
121
140
  z-index: 1;
122
- background: hsl(var(--background));
141
+ background: var(--agent-native-raised-surface);
123
142
  transition:
124
143
  border-radius 260ms cubic-bezier(0.32, 0.72, 0, 1),
144
+ border-color 260ms cubic-bezier(0.32, 0.72, 0, 1),
125
145
  box-shadow 260ms cubic-bezier(0.32, 0.72, 0, 1);
126
146
  }
127
147
 
128
148
  .agent-layout-shell
129
149
  :where(.agent-layout-main-surface, .agent-sidebar-main-surface)
130
150
  > :first-child
131
- > :where(header, div).border-b:first-child,
151
+ > :where(header, div).border-b,
132
152
  .agent-layout-shell
133
153
  :where(.agent-layout-main-surface, .agent-sidebar-main-surface)
134
- > :where(header, div).border-b:first-child,
154
+ > :where(header, div).border-b,
135
155
  .agent-layout-shell
136
156
  .agent-layout-left-drawer
137
157
  > :where(header, div).border-b:first-child,
158
+ .agent-layout-shell
159
+ .agent-layout-left-drawer
160
+ > :first-child
161
+ > :where(header, div).border-b,
138
162
  .agent-layout-shell .agent-native-shell-topbar {
139
163
  border-bottom-color: transparent !important;
140
164
  }
141
165
 
166
+ .agent-layout-shell
167
+ :where(.agent-layout-main-surface, .agent-sidebar-main-surface)
168
+ > :first-child
169
+ > :where(header, div).border-b,
170
+ .agent-layout-shell
171
+ :where(.agent-layout-main-surface, .agent-sidebar-main-surface)
172
+ > :where(header, div).border-b {
173
+ background-color: var(--agent-native-raised-surface) !important;
174
+ }
175
+
176
+ .agent-layout-shell
177
+ :where(.agent-layout-main-surface, .agent-sidebar-main-surface)
178
+ > :first-child
179
+ > :where(header, div).border-b.h-12,
180
+ .agent-layout-shell
181
+ :where(.agent-layout-main-surface, .agent-sidebar-main-surface)
182
+ > :where(header, div).border-b.h-12 {
183
+ min-height: 4rem;
184
+ height: 4rem;
185
+ }
186
+
187
+ .dark
188
+ .agent-layout-shell
189
+ :where(.agent-layout-main-surface, .agent-sidebar-main-surface)
190
+ :where(.bg-card) {
191
+ background-color: var(--agent-native-card-surface) !important;
192
+ }
193
+
142
194
  @media (min-width: 768px) {
143
195
  .agent-layout-main-surface,
144
196
  .agent-layout-shell > .agent-sidebar-shell > .agent-sidebar-main-surface {
@@ -170,7 +170,8 @@ Use the workspace root `.env` for shared identity and cross-app trust settings:
170
170
  - `WORKSPACE_OWNER_EMAIL` — initial owner/admin email for repairs and
171
171
  integration defaults.
172
172
  - `A2A_SECRET` — shared secret for cross-app A2A signing. Generate with
173
- `openssl rand -hex 32` or `pnpm repair:workspace-org -- --name ...`.
173
+ `openssl rand -hex 32` and configure through your deployment/scoped secret
174
+ manager.
174
175
 
175
176
  `DISPATCH_DEFAULT_OWNER_EMAIL` is optional. Set it only for trusted,
176
177
  single-workspace deployments where unlinked integration requests should run as
@@ -183,7 +184,7 @@ When asked to repair workspace org or A2A configuration:
183
184
  1. Read `.env` first. Do not infer the organization, domain, owner email, or
184
185
  secret from old examples.
185
186
  2. Run `pnpm repair:workspace-org -- --name "<org>" --domain example.com --owner-email owner@example.com`
186
- to create or update generic workspace identity values.
187
+ to validate generic workspace identity values without writing `.env`.
187
188
  3. Prefer the app's organization settings UI or authenticated org routes for
188
189
  changing `allowed_domain` and `a2a_secret`.
189
190
  4. If direct SQL is unavoidable, inspect the live schema first and use only
@@ -97,7 +97,7 @@ cross-app trust:
97
97
  - `A2A_SECRET` — shared signing secret for cross-app A2A calls.
98
98
 
99
99
  Run `pnpm repair:workspace-org -- --name "<org>" --domain example.com --owner-email owner@example.com`
100
- to fill or validate those values without committing secrets. Existing
100
+ to validate those values without writing env files. Existing
101
101
  organization rows should still be repaired through the app's org settings UI or
102
102
  authenticated org routes whenever possible.
103
103