@agent-native/core 0.164.4 → 0.164.12

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 (268) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/calendar/.agents/skills/event-management/SKILL.md +84 -0
  3. package/corpus/templates/calendar/AGENTS.md +5 -0
  4. package/corpus/templates/calendar/actions/delete-event.ts +1 -1
  5. package/corpus/templates/calendar/actions/delete-events.ts +508 -0
  6. package/corpus/templates/calendar/actions/event-action-helpers.ts +1 -1
  7. package/corpus/templates/calendar/actions/list-events.ts +53 -0
  8. package/corpus/templates/calendar/app/components/calendar/CreateEventDialog.tsx +36 -47
  9. package/corpus/templates/calendar/app/components/calendar/DayView.tsx +3 -0
  10. package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +18 -1
  11. package/corpus/templates/calendar/app/components/calendar/InlineEventPickers.tsx +256 -38
  12. package/corpus/templates/calendar/app/hooks/use-google-auth.ts +43 -3
  13. package/corpus/templates/calendar/app/i18n-data.ts +120 -0
  14. package/corpus/templates/calendar/app/lib/event-form-utils.ts +113 -0
  15. package/corpus/templates/calendar/changelog/2026-08-18-the-agent-can-now-remove-many-meetings-at-once-such-as-every.md +6 -0
  16. package/corpus/templates/calendar/server/handlers/google-auth.ts +119 -3
  17. package/corpus/templates/calendar/server/lib/event-weekday.ts +112 -0
  18. package/corpus/templates/calendar/server/routes/[base]/_agent-native/google/add-account/auth-url.post.ts +1 -0
  19. package/corpus/templates/calendar/server/routes/[base]/_agent-native/google/auth-url.post.ts +1 -0
  20. package/corpus/templates/calendar/server/routes/_agent-native/google/add-account/auth-url.post.ts +1 -0
  21. package/corpus/templates/calendar/server/routes/_agent-native/google/auth-url.post.ts +1 -0
  22. package/corpus/templates/clips/app/components/player/video-player.tsx +12 -0
  23. package/corpus/templates/clips/app/routes/_app.dictate.tsx +18 -4
  24. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +114 -20
  25. package/corpus/templates/clips/app/routes/share.$shareId.tsx +83 -78
  26. package/corpus/templates/clips/changelog/2026-08-19-clips-nightly-builds-are-available-for-trying-the-latest-upd.md +6 -0
  27. package/corpus/templates/clips/changelog/2026-08-19-social-preview-video-frames.md +1 -0
  28. package/corpus/templates/clips/desktop/README.md +19 -4
  29. package/corpus/templates/clips/desktop/src/app.tsx +78 -16
  30. package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +3 -2
  31. package/corpus/templates/clips/desktop/src-tauri/tauri.conf.json +1 -0
  32. package/corpus/templates/clips/server/routes/[base]/_agent-native/google/auth-url.post.ts +1 -0
  33. package/corpus/templates/clips/server/routes/_agent-native/google/auth-url.get.ts +41 -3
  34. package/corpus/templates/clips/server/routes/_agent-native/google/auth-url.post.ts +1 -0
  35. package/corpus/templates/clips/server/routes/_agent-native/google/callback.get.ts +22 -1
  36. package/corpus/templates/clips/server/routes/api/clips-updater.json.get.ts +41 -22
  37. package/corpus/templates/factory/AGENTS.md +3 -2
  38. package/corpus/templates/factory/actions/get-factory-graph-version.ts +69 -0
  39. package/corpus/templates/factory/actions/list-factory-automations.ts +4 -0
  40. package/corpus/templates/factory/actions/list-factory-graph-versions.ts +82 -0
  41. package/corpus/templates/factory/actions/restore-factory-graph-version.ts +163 -0
  42. package/corpus/templates/factory/actions/save-factory-graph.ts +93 -60
  43. package/corpus/templates/factory/actions/start-builder-for-item.ts +19 -17
  44. package/corpus/templates/factory/app/components/factory/FactoryAuditView.tsx +100 -36
  45. package/corpus/templates/factory/app/components/factory/FactoryHistoryView.tsx +709 -0
  46. package/corpus/templates/factory/app/components/factory/FactoryInspector.tsx +62 -2
  47. package/corpus/templates/factory/app/components/ui/alert-dialog.tsx +1 -0
  48. package/corpus/templates/factory/app/i18n/en-US.ts +47 -0
  49. package/corpus/templates/factory/app/routes/factory.tsx +324 -61
  50. package/corpus/templates/factory/server/connectors/slack.ts +44 -2
  51. package/corpus/templates/factory/server/plugins/agent-chat.ts +12 -8
  52. package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +13 -0
  53. package/corpus/templates/factory/server/triage/slack-client.ts +5 -0
  54. package/corpus/templates/factory/server/triage/slack-poller.ts +72 -4
  55. package/corpus/templates/mail/actions/view-screen.ts +1 -1
  56. package/corpus/templates/mail/app/components/GoogleConnectBanner.tsx +100 -18
  57. package/corpus/templates/mail/server/handlers/google-auth.ts +125 -24
  58. package/corpus/templates/mail/server/lib/gmail-query.ts +5 -2
  59. package/corpus/templates/mail/server/routes/[base]/_agent-native/google/add-account/auth-url.post.ts +1 -0
  60. package/corpus/templates/mail/server/routes/[base]/_agent-native/google/auth-url.post.ts +1 -0
  61. package/corpus/templates/mail/server/routes/_agent-native/google/add-account/auth-url.post.ts +1 -0
  62. package/corpus/templates/mail/server/routes/_agent-native/google/auth-url.post.ts +1 -0
  63. package/corpus/templates/plan/app/pages/PlansPage.tsx +0 -12
  64. package/corpus/templates/plan/changelog/2026-08-19-plan-prompts-now-guide-you-to-connect-ai-before-sending-and-.md +6 -0
  65. package/corpus/templates/slides/actions/approve-deck-access-request.ts +234 -0
  66. package/corpus/templates/slides/actions/get-deck-access-status.ts +35 -2
  67. package/corpus/templates/slides/actions/request-deck-access.ts +263 -64
  68. package/corpus/templates/slides/app/components/editor/MissingDeckAccessPane.tsx +196 -0
  69. package/corpus/templates/slides/app/components/editor/RequestDeckAccessDialog.tsx +101 -0
  70. package/corpus/templates/slides/app/hooks/use-deck-access.ts +7 -4
  71. package/corpus/templates/slides/app/i18n/en-US.ts +29 -6
  72. package/corpus/templates/slides/app/pages/DeckEditor.tsx +147 -169
  73. package/corpus/templates/slides/app/routes/access-request.approve.tsx +250 -0
  74. package/corpus/templates/slides/server/db/schema.ts +8 -0
  75. package/corpus/templates/slides/server/lib/access-request-email.ts +36 -0
  76. package/corpus/templates/slides/server/lib/emails.ts +26 -0
  77. package/corpus/templates/slides/server/plugins/agent-chat.ts +7 -0
  78. package/corpus/templates/slides/server/plugins/db.ts +50 -0
  79. package/corpus/templates/slides/shared/deck-access.ts +31 -0
  80. package/dist/a2a/task-store.d.ts +1 -0
  81. package/dist/a2a/task-store.js +1 -1
  82. package/dist/agent/observational-memory/store.d.ts +1 -0
  83. package/dist/agent/observational-memory/store.js +1 -1
  84. package/dist/agent/run-store.d.ts +1 -0
  85. package/dist/agent/run-store.js +1 -1
  86. package/dist/agent/tool-approval-store.d.ts +1 -0
  87. package/dist/agent/tool-approval-store.js +1 -1
  88. package/dist/application-state/store.d.ts +1 -0
  89. package/dist/application-state/store.js +1 -1
  90. package/dist/browser-sessions/store.d.ts +1 -0
  91. package/dist/browser-sessions/store.js +1 -1
  92. package/dist/checkpoints/store.d.ts +1 -0
  93. package/dist/checkpoints/store.js +1 -1
  94. package/dist/cli/code-agent-schedules.d.ts +11 -0
  95. package/dist/cli/code-agent-schedules.js +44 -5
  96. package/dist/client/AgentPanel.d.ts +5 -1
  97. package/dist/client/AgentPanel.js +2 -2
  98. package/dist/client/AssistantChat.d.ts +5 -1
  99. package/dist/client/AssistantChat.js +40 -6
  100. package/dist/client/EnvironmentBadge.d.ts +7 -13
  101. package/dist/client/EnvironmentBadge.js +43 -92
  102. package/dist/client/agent-chat/index.d.ts +1 -0
  103. package/dist/client/agent-chat/index.js +1 -0
  104. package/dist/client/agent-chat-adapter.js +76 -50
  105. package/dist/client/app-providers.js +4 -4
  106. package/dist/client/chat/message-components.d.ts +4 -0
  107. package/dist/client/chat/message-components.js +28 -1
  108. package/dist/client/chat/run-recovery.js +26 -0
  109. package/dist/client/chat-first/apps-rail.d.ts +1 -0
  110. package/dist/client/chat-first/apps-rail.js +28 -2
  111. package/dist/client/sse-event-processor.js +13 -8
  112. package/dist/client/use-active-agent-chat-run.d.ts +2 -0
  113. package/dist/client/use-active-agent-chat-run.js +22 -0
  114. package/dist/coding-tools/sandbox/executions-store.d.ts +1 -0
  115. package/dist/coding-tools/sandbox/executions-store.js +1 -1
  116. package/dist/collab/awareness-store.d.ts +1 -0
  117. package/dist/collab/awareness-store.js +1 -1
  118. package/dist/collab/routes.d.ts +1 -1
  119. package/dist/collab/storage.d.ts +1 -0
  120. package/dist/collab/storage.js +1 -1
  121. package/dist/collab/struct-routes.d.ts +1 -1
  122. package/dist/db/client.js +3 -3
  123. package/dist/db/ddl-guard.js +8 -0
  124. package/dist/db/migration-runtime.d.ts +23 -0
  125. package/dist/db/migration-runtime.js +41 -0
  126. package/dist/db/migrations.d.ts +1 -2
  127. package/dist/db/migrations.js +2 -24
  128. package/dist/email-catalog/log.d.ts +1 -0
  129. package/dist/email-catalog/log.js +1 -1
  130. package/dist/guards/index.d.ts +1 -0
  131. package/dist/guards/index.js +1 -0
  132. package/dist/guards/release-schema-complete.d.ts +22 -0
  133. package/dist/guards/release-schema-complete.js +144 -0
  134. package/dist/integrations/a2a-continuations-store.d.ts +1 -0
  135. package/dist/integrations/a2a-continuations-store.js +1 -1
  136. package/dist/integrations/awaiting-input-store.d.ts +1 -0
  137. package/dist/integrations/awaiting-input-store.js +1 -1
  138. package/dist/integrations/config-store.d.ts +1 -0
  139. package/dist/integrations/config-store.js +1 -1
  140. package/dist/integrations/controls-store.d.ts +1 -0
  141. package/dist/integrations/controls-store.js +1 -1
  142. package/dist/integrations/identity-links-store.d.ts +1 -0
  143. package/dist/integrations/identity-links-store.js +1 -1
  144. package/dist/integrations/installations-store.d.ts +1 -0
  145. package/dist/integrations/installations-store.js +1 -1
  146. package/dist/integrations/remote-commands-store.d.ts +1 -0
  147. package/dist/integrations/remote-commands-store.js +1 -1
  148. package/dist/integrations/remote-devices-store.d.ts +1 -0
  149. package/dist/integrations/remote-devices-store.js +1 -1
  150. package/dist/integrations/remote-push-store.d.ts +1 -0
  151. package/dist/integrations/remote-push-store.js +1 -1
  152. package/dist/integrations/remote-run-events-store.d.ts +1 -0
  153. package/dist/integrations/remote-run-events-store.js +1 -1
  154. package/dist/integrations/scope-store.d.ts +1 -0
  155. package/dist/integrations/scope-store.js +1 -1
  156. package/dist/integrations/thread-mapping-store.d.ts +1 -0
  157. package/dist/integrations/thread-mapping-store.js +1 -1
  158. package/dist/integrations/usage-budget-store.d.ts +1 -0
  159. package/dist/integrations/usage-budget-store.js +1 -1
  160. package/dist/jobs/background-automation-runner.js +111 -9
  161. package/dist/jobs/run-history.d.ts +1 -0
  162. package/dist/jobs/run-history.js +1 -1
  163. package/dist/jobs/scheduler-health.d.ts +1 -0
  164. package/dist/jobs/scheduler-health.js +1 -1
  165. package/dist/mcp/approval-store.d.ts +1 -0
  166. package/dist/mcp/approval-store.js +1 -1
  167. package/dist/mcp/connect-store.d.ts +1 -0
  168. package/dist/mcp/connect-store.js +1 -1
  169. package/dist/mcp/oauth-store.d.ts +1 -0
  170. package/dist/mcp/oauth-store.js +1 -1
  171. package/dist/notifications/store.d.ts +1 -0
  172. package/dist/notifications/store.js +1 -1
  173. package/dist/oauth-tokens/store.d.ts +1 -0
  174. package/dist/oauth-tokens/store.js +1 -1
  175. package/dist/observability/routes.d.ts +5 -5
  176. package/dist/progress/routes.d.ts +1 -1
  177. package/dist/progress/store.d.ts +1 -0
  178. package/dist/progress/store.js +1 -1
  179. package/dist/provider-api/actions/custom-provider-registration.d.ts +5 -5
  180. package/dist/provider-api/actions/provider-api.d.ts +4 -4
  181. package/dist/provider-api/corpus-jobs-store.d.ts +1 -0
  182. package/dist/provider-api/corpus-jobs-store.js +1 -1
  183. package/dist/provider-api/custom-registry.d.ts +1 -0
  184. package/dist/provider-api/custom-registry.js +1 -1
  185. package/dist/provider-api/quota-governor.d.ts +1 -0
  186. package/dist/provider-api/quota-governor.js +1 -1
  187. package/dist/provider-api/staged-datasets-store.d.ts +1 -0
  188. package/dist/provider-api/staged-datasets-store.js +1 -1
  189. package/dist/resources/handlers.d.ts +3 -3
  190. package/dist/resources/store.d.ts +1 -0
  191. package/dist/resources/store.js +1 -1
  192. package/dist/scripts/dev/index.js +15 -1
  193. package/dist/search/index.js +3 -0
  194. package/dist/secrets/routes.d.ts +9 -9
  195. package/dist/secrets/storage.d.ts +1 -0
  196. package/dist/secrets/storage.js +1 -1
  197. package/dist/server/agent-chat-plugin.js +38 -9
  198. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  199. package/dist/server/agent-teams-run-queue.d.ts +1 -0
  200. package/dist/server/agent-teams-run-queue.js +1 -1
  201. package/dist/server/auth-marketing.js +3 -1
  202. package/dist/server/auth.d.ts +18 -1
  203. package/dist/server/auth.js +370 -154
  204. package/dist/server/embed-session.d.ts +1 -0
  205. package/dist/server/embed-session.js +1 -1
  206. package/dist/server/google-auth-plugin.js +3 -1
  207. package/dist/server/google-oauth.d.ts +10 -0
  208. package/dist/server/google-oauth.js +25 -1
  209. package/dist/server/identity-sso-store.d.ts +1 -0
  210. package/dist/server/identity-sso-store.js +1 -1
  211. package/dist/server/index.d.ts +1 -1
  212. package/dist/server/index.js +1 -1
  213. package/dist/server/onboarding-html.js +200 -31
  214. package/dist/server/poll.d.ts +2 -0
  215. package/dist/server/poll.js +19 -1
  216. package/dist/server/realtime-token.d.ts +1 -1
  217. package/dist/server/release-migrations.js +5 -0
  218. package/dist/server/release-schema.d.ts +46 -0
  219. package/dist/server/release-schema.js +307 -0
  220. package/dist/settings/store.d.ts +1 -0
  221. package/dist/settings/store.js +1 -1
  222. package/dist/shared/environment-lanes.d.ts +28 -0
  223. package/dist/shared/environment-lanes.js +61 -0
  224. package/dist/sharing/actions/share-resource.js +22 -2
  225. package/dist/styles/agent-native.css +17 -15
  226. package/dist/triggers/routes.d.ts +11 -0
  227. package/dist/triggers/routes.js +10 -0
  228. package/dist/usage/alerts-store.d.ts +1 -0
  229. package/dist/usage/alerts-store.js +1 -1
  230. package/dist/usage/store.d.ts +1 -0
  231. package/dist/usage/store.js +1 -1
  232. package/docs/content/actions-access-control.mdx +136 -2
  233. package/docs/content/actions-agent-tools.mdx +101 -0
  234. package/docs/content/actions-defining.mdx +2 -2
  235. package/docs/content/audit-log.mdx +1 -1
  236. package/docs/content/authentication.mdx +1 -1
  237. package/docs/content/cloudflare.mdx +43 -0
  238. package/docs/content/creating-templates.mdx +1 -1
  239. package/docs/content/deploy-an-app.mdx +109 -0
  240. package/docs/content/deployment-environment-variables.mdx +101 -0
  241. package/docs/content/deployment.mdx +125 -792
  242. package/docs/content/docs-components.mdx +2 -2
  243. package/docs/content/environment-variables.mdx +41 -41
  244. package/docs/content/file-uploads.mdx +74 -40
  245. package/docs/content/harness-agents.mdx +2 -2
  246. package/docs/content/internationalization.mdx +61 -65
  247. package/docs/content/key-concepts.mdx +3 -3
  248. package/docs/content/multi-app-workspace.mdx +2 -2
  249. package/docs/content/netlify.mdx +47 -0
  250. package/docs/content/node-docker.mdx +138 -0
  251. package/docs/content/organizations-teams-permissions.mdx +5 -5
  252. package/docs/content/other-platforms.mdx +27 -0
  253. package/docs/content/ssr-caching.mdx +45 -0
  254. package/docs/content/template-assets-developers.mdx +2 -2
  255. package/docs/content/template-chat-developers.mdx +2 -2
  256. package/docs/content/template-content-developers.mdx +2 -2
  257. package/docs/content/{local-file-mode.mdx → template-content-local-files.mdx} +2 -1
  258. package/docs/content/template-content-sync.mdx +2 -2
  259. package/docs/content/toolkit-agent-ux.mdx +1 -1
  260. package/docs/content/toolkit-resources.mdx +2 -2
  261. package/docs/content/updating-ui-in-production.mdx +35 -0
  262. package/docs/content/vercel.mdx +38 -0
  263. package/docs/content/what-is-agent-native.mdx +1 -1
  264. package/docs/content/workspace-deployment.mdx +350 -0
  265. package/package.json +2 -2
  266. package/docs/content/agents.mdx +0 -9
  267. package/docs/content/database.mdx +0 -317
  268. package/docs/content/human-approval.mdx +0 -156
@@ -151,7 +151,7 @@ Each step is a `###` heading followed by the body content. Steps work best for 3
151
151
 
152
152
  Typed operations callable from the agent, UI, CLI, and HTTP. Define once, call from anywhere.
153
153
 
154
- ### [Database](/docs/database)
154
+ ### [Database](/docs/server-database)
155
155
 
156
156
  SQL persistence with automatic migrations. SQLite locally, Postgres/Turso in production.
157
157
 
@@ -172,7 +172,7 @@ Plain-text instruction files that give the agent domain knowledge and task-speci
172
172
 
173
173
  Typed operations callable from the agent, UI, CLI, and HTTP. Define once, call from anywhere.
174
174
 
175
- ### [Database](/docs/database)
175
+ ### [Database](/docs/server-database)
176
176
 
177
177
  SQL persistence with automatic migrations. SQLite locally, Postgres/Turso in production.
178
178
 
@@ -12,7 +12,7 @@ deployment system in this repository. Template-only values stay in the
12
12
  maintainer inventory; the setup tables below focus on the shared configuration
13
13
  most apps need.
14
14
 
15
- For a normal app, start with [Deployment](/docs/deployment#environment-variables)
15
+ For a normal app, start with [Deployment: Environment Variables](/docs/deployment-environment-variables)
16
16
  and [Authentication](/docs/authentication). Keep user-, organization-, and
17
17
  workspace-scoped credentials in the database-backed secret or connection store;
18
18
  use environment variables for deploy-level configuration.
@@ -24,46 +24,46 @@ deployment-specific values in the environment or scoped secret store.
24
24
 
25
25
  ## Common application and deployment variables
26
26
 
27
- | Variable | What it controls | Supported values or format |
28
- | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
29
- | `DATABASE_URL` | Primary SQL connection. Local development falls back to SQLite when it is unset. Production also accepts `<APP_NAME>_DATABASE_URL` or Netlify's `NETLIFY_DATABASE_URL`. | A provider-specific SQL URL, or unset for local SQLite. |
30
- | `DATABASE_AUTH_TOKEN` | Separate database token when the database provider requires one. | An opaque provider token, or unset when the URL includes authentication. |
31
- | `APP_URL` | Optional canonical public origin used for auth, OAuth, A2A, webhooks, and generated links. Netlify and Vercel metadata are inferred when it is unset. | An absolute public `http(s)` origin. |
32
- | `BETTER_AUTH_URL` | Optional Better Auth origin override. Known template or request context, `APP_URL`, and platform metadata such as Netlify or Vercel are used when it is unset. | An absolute public `http(s)` origin. |
33
- | `APP_BASE_PATH` | Mounts an app under a path such as `/mail`. | Unset for a standalone app, or a slash-prefixed path. |
34
- | `PORT` | Local Node/Nitro server port. | A decimal TCP port. |
35
- | `NITRO_PRESET` | Build and deployment adapter. | A preset supported by the target host, such as `node`, `netlify`, `vercel`, or `cloudflare_pages`. |
36
- | `BETTER_AUTH_SECRET` | Stable Better Auth session signing secret for standalone production apps. Workspace deploys can derive it from `A2A_SECRET`. | A fresh random value of at least 32 characters. |
37
- | `OAUTH_STATE_SECRET` | Dedicated signing key for OAuth state envelopes. Falls back to `BETTER_AUTH_SECRET` when unset. | A fresh random value of at least 32 characters. |
38
- | `A2A_SECRET` | Shared HMAC for trusted cross-app A2A calls and signed handoffs. | One shared random value across trusted apps. |
39
- | `SECRETS_ENCRYPTION_KEY` | Legacy app-local/shared encryption fallback. | A stable encryption key; prefer the workspace key for new shared vaults. |
40
- | `WORKSPACE_SECRETS_ENCRYPTION_KEY` | Stable encryption key for a workspace-shared secrets vault. | The same stable key in every app that reads the vault. |
41
- | `WORKSPACE_SECRETS_ENCRYPTION_KEY_PREVIOUS` | Previous workspace key during rotation. | The old key only; remove it after migration. |
42
- | `ANTHROPIC_API_KEY` | Optional deploy-level fallback for the embedded production agent. | An API key; prefer scoped credentials for multi-tenant apps. |
43
- | `AGENT_ENGINE` | Explicitly selects the agent engine instead of auto-detecting from provider keys. | A registered engine name such as `anthropic`, `ai-sdk:openai`, `builder`, or `codex-cli`. |
44
- | `AGENT_ENGINE_PREFER_BYO_KEY` | Prefers a provider key you set over the managed Builder gateway during auto-detection. | `true` or `1`; Builder still applies as the fallback when no provider key is set. |
45
- | `AUTH_MODE` | Selects the local authentication behavior used by CLI and agent flows. | Unset or `local`; this is not a browser login bypass. |
46
- | `AGENT_NATIVE_ALLOW_BUILDER_PREVIEW_LOCAL_DEV` | Explicitly enables the existing local-dev sign-in button on approved Builder preview hosts during development. | `1` or `true`; requires development mode and must stay off public or production deployments. |
47
- | `AUTH_DISABLED` | Disables auth for local or preview-only work. Unset already means false. | `true` or `1`; never use on a public production app. |
48
- | `AUTH_MAGIC_LINK` | Controls the password-first versus magic-link sign-in path. | `0` keeps password-first sign-in; otherwise a configured email transport can enable magic links. |
49
- | `AUTH_SKIP_EMAIL_VERIFICATION` | Skips signup email verification for local QA or previews. | `1`; never use it to weaken production auth. |
50
- | `ACCESS_TOKEN` / `ACCESS_TOKENS` | Static bearer fallback for MCP and Connect clients. | One token or a delimited token list; these are not browser auth. |
51
- | `AGENT_PROD_CODE_EXECUTION` | Production code-execution policy. | `off`, `sandboxed`, or `trusted`. See [Production Code Execution](/docs/deployment#production-code-execution). |
52
- | `AGENT_NATIVE_SSR_CACHE` | Deployment-wide public SSR shell cache policy. | Unset/`on`, `off`, or a duration such as `30s` or `5m`. See [SSR Caching](/docs/deployment#ssr-caching). |
53
- | `AGENT_NATIVE_ENABLE_KEEP_WARM` | Opts into the Netlify keep-warm scheduled function; unset by default. | `1`; see [Keep-warm](/docs/deployment#netlify-keep-warm). |
54
- | `AGENT_NATIVE_DISABLE_KEEP_WARM` | Compatibility kill switch for the Netlify keep-warm scheduled function. | `1`; see [Keep-warm](/docs/deployment#netlify-keep-warm). |
55
- | `AGENT_NATIVE_KEEP_WARM_SCHEDULE` | Keep-warm cadence override when enabled. | A 5-field cron expression such as `*/5 * * * *`; an unparseable value fails the build. |
56
- | `AGENT_NATIVE_DISABLE_KEEP_WARM_BACKGROUND` | Drops only the background-function warm and keeps the server warm when keep-warm is enabled. | `1`; see [Keep-warm](/docs/deployment#netlify-keep-warm). |
57
- | `AGENT_NATIVE_DISABLE_INPROCESS_SWEEPS` | Turns off the in-process backstop sweep timers where a durable scheduler drives the same work. | `1`; queued work is not retried without another driver. |
58
- | `AGENT_NATIVE_SKIP_ENSURE_TABLES` | Skips on-demand schema DDL for an already-migrated database. | `1`; see [On-demand schema DDL](/docs/deployment#skip-ensure-tables). You own migrations when this is set. |
59
- | `COOKIE_DOMAIN` | Shares auth cookies across same-database subdomains when explicitly configured. | A cookie domain. |
60
- | `CORS_ALLOWED_ORIGINS` | Cross-origin request allowlist. | A comma-separated list of exact origins. |
61
- | `WEBHOOK_BASE_URL` | Optional public base URL for self-callback and webhook targets. | An absolute public `http(s)` origin. |
62
- | `APP_NAME` | App identity used by workspace and app-scoped configuration. | A short app name, such as `mail`. |
63
- | `APP_ID` / `APP_TEMPLATE` | Optional app identity and generated-template metadata. | App-owned strings. |
64
- | `NODE_ENV` | Node runtime mode. | Normally `development`, `test`, or `production`. |
65
- | `CI` | Marks CI-driven test and build behavior. | A CI-provided truthy value. |
66
- | `DEBUG` | Enables resolver-specific debug logging. | A resolver-supported truthy or namespace value. |
27
+ | Variable | What it controls | Supported values or format |
28
+ | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
29
+ | `DATABASE_URL` | Primary SQL connection. Local development falls back to SQLite when it is unset. Production also accepts `<APP_NAME>_DATABASE_URL` or Netlify's `NETLIFY_DATABASE_URL`. | A provider-specific SQL URL, or unset for local SQLite. |
30
+ | `DATABASE_AUTH_TOKEN` | Separate database token when the database provider requires one. | An opaque provider token, or unset when the URL includes authentication. |
31
+ | `APP_URL` | Optional canonical public origin used for auth, OAuth, A2A, webhooks, and generated links. Netlify and Vercel metadata are inferred when it is unset. | An absolute public `http(s)` origin. |
32
+ | `BETTER_AUTH_URL` | Optional Better Auth origin override. Known template or request context, `APP_URL`, and platform metadata such as Netlify or Vercel are used when it is unset. | An absolute public `http(s)` origin. |
33
+ | `APP_BASE_PATH` | Mounts an app under a path such as `/mail`. | Unset for a standalone app, or a slash-prefixed path. |
34
+ | `PORT` | Local Node/Nitro server port. | A decimal TCP port. |
35
+ | `NITRO_PRESET` | Build and deployment adapter. | A preset supported by the target host, such as `node`, `netlify`, `vercel`, or `cloudflare_pages`. |
36
+ | `BETTER_AUTH_SECRET` | Stable Better Auth session signing secret for standalone production apps. Workspace deploys can derive it from `A2A_SECRET`. | A fresh random value of at least 32 characters. |
37
+ | `OAUTH_STATE_SECRET` | Dedicated signing key for OAuth state envelopes. Falls back to `BETTER_AUTH_SECRET` when unset. | A fresh random value of at least 32 characters. |
38
+ | `A2A_SECRET` | Shared HMAC for trusted cross-app A2A calls and signed handoffs. | One shared random value across trusted apps. |
39
+ | `SECRETS_ENCRYPTION_KEY` | Legacy app-local/shared encryption fallback. | A stable encryption key; prefer the workspace key for new shared vaults. |
40
+ | `WORKSPACE_SECRETS_ENCRYPTION_KEY` | Stable encryption key for a workspace-shared secrets vault. | The same stable key in every app that reads the vault. |
41
+ | `WORKSPACE_SECRETS_ENCRYPTION_KEY_PREVIOUS` | Previous workspace key during rotation. | The old key only; remove it after migration. |
42
+ | `ANTHROPIC_API_KEY` | Optional deploy-level fallback for the embedded production agent. | An API key; prefer scoped credentials for multi-tenant apps. |
43
+ | `AGENT_ENGINE` | Explicitly selects the agent engine instead of auto-detecting from provider keys. | A registered engine name such as `anthropic`, `ai-sdk:openai`, `builder`, or `codex-cli`. |
44
+ | `AGENT_ENGINE_PREFER_BYO_KEY` | Prefers a provider key you set over the managed Builder gateway during auto-detection. | `true` or `1`; Builder still applies as the fallback when no provider key is set. |
45
+ | `AUTH_MODE` | Selects the local authentication behavior used by CLI and agent flows. | Unset or `local`; this is not a browser login bypass. |
46
+ | `AGENT_NATIVE_ALLOW_BUILDER_PREVIEW_LOCAL_DEV` | Explicitly enables the existing local-dev sign-in button on approved Builder preview hosts during development. | `1` or `true`; requires development mode and must stay off public or production deployments. |
47
+ | `AUTH_DISABLED` | Disables auth for local or preview-only work. Unset already means false. | `true` or `1`; never use on a public production app. |
48
+ | `AUTH_MAGIC_LINK` | Controls the password-first versus magic-link sign-in path. | `0` keeps password-first sign-in; otherwise a configured email transport can enable magic links. |
49
+ | `AUTH_SKIP_EMAIL_VERIFICATION` | Skips signup email verification for local QA or previews. | `1`; never use it to weaken production auth. |
50
+ | `ACCESS_TOKEN` / `ACCESS_TOKENS` | Static bearer fallback for MCP and Connect clients. | One token or a delimited token list; these are not browser auth. |
51
+ | `AGENT_PROD_CODE_EXECUTION` | Production code-execution policy. | `off`, `sandboxed`, or `trusted`. See [Production Code Execution](/docs/actions-agent-tools#production-code-execution). |
52
+ | `AGENT_NATIVE_SSR_CACHE` | Deployment-wide public SSR shell cache policy. | Unset/`on`, `off`, or a duration such as `30s` or `5m`. See [SSR Caching](/docs/ssr-caching). |
53
+ | `AGENT_NATIVE_ENABLE_KEEP_WARM` | Opts into the Netlify keep-warm scheduled function; unset by default. | `1`; see [Keep-warm](/docs/netlify#netlify-keep-warm). |
54
+ | `AGENT_NATIVE_DISABLE_KEEP_WARM` | Compatibility kill switch for the Netlify keep-warm scheduled function. | `1`; see [Keep-warm](/docs/netlify#netlify-keep-warm). |
55
+ | `AGENT_NATIVE_KEEP_WARM_SCHEDULE` | Keep-warm cadence override when enabled. | A 5-field cron expression such as `*/5 * * * *`; an unparseable value fails the build. |
56
+ | `AGENT_NATIVE_DISABLE_KEEP_WARM_BACKGROUND` | Drops only the background-function warm and keeps the server warm when keep-warm is enabled. | `1`; see [Keep-warm](/docs/netlify#netlify-keep-warm). |
57
+ | `AGENT_NATIVE_DISABLE_INPROCESS_SWEEPS` | Turns off the in-process backstop sweep timers where a durable scheduler drives the same work. | `1`; queued work is not retried without another driver. |
58
+ | `AGENT_NATIVE_SKIP_ENSURE_TABLES` | Skips on-demand schema DDL for an already-migrated database. | `1`; see [On-demand schema DDL](/docs/deployment#skip-ensure-tables). You own migrations when this is set. |
59
+ | `COOKIE_DOMAIN` | Shares auth cookies across same-database subdomains when explicitly configured. | A cookie domain. |
60
+ | `CORS_ALLOWED_ORIGINS` | Cross-origin request allowlist. | A comma-separated list of exact origins. |
61
+ | `WEBHOOK_BASE_URL` | Optional public base URL for self-callback and webhook targets. | An absolute public `http(s)` origin. |
62
+ | `APP_NAME` | App identity used by workspace and app-scoped configuration. | A short app name, such as `mail`. |
63
+ | `APP_ID` / `APP_TEMPLATE` | Optional app identity and generated-template metadata. | App-owned strings. |
64
+ | `NODE_ENV` | Node runtime mode. | Normally `development`, `test`, or `production`. |
65
+ | `CI` | Marks CI-driven test and build behavior. | A CI-provided truthy value. |
66
+ | `DEBUG` | Enables resolver-specific debug logging. | A resolver-supported truthy or namespace value. |
67
67
 
68
68
  Generate strong secrets with:
69
69
 
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  title: "File Uploads"
3
- description: "Configure durable file upload storage — Builder.io or custom object storage for production."
3
+ description: "Configure durable file upload storage with Builder.io or a custom object storage provider for production."
4
4
  ---
5
5
 
6
6
  # File Uploads
7
7
 
8
- The framework provides a file upload abstraction that routes uploads through a configurable provider. Templates call `uploadFile()` and get back a URL — the storage backend is swappable without changing application code.
8
+ The framework provides a file upload abstraction that routes uploads through a configurable provider. Templates call `uploadFile()` and get back a URL. The storage backend is swappable without changing application code.
9
9
 
10
10
  ## How It Works {#how-it-works}
11
11
 
@@ -13,9 +13,21 @@ Upload requests go to `POST /_agent-native/file-upload`, which dispatches to the
13
13
 
14
14
  The provider resolution order is:
15
15
 
16
- 1. **User-registered providers** — custom providers registered via `registerFileUploadProvider()`
17
- 2. **Builder.io provider** — built-in, activates automatically when Builder.io is connected
18
- 3. **No provider** — the upload is rejected and the chat renders a storage setup CTA; binary data is never persisted in SQL
16
+ 1. **User-registered providers**: custom providers registered via `registerFileUploadProvider()`.
17
+ 2. **Builder.io provider**: built-in, and it activates automatically when Builder.io is connected.
18
+ 3. **No provider**: the upload is rejected and the chat renders a storage setup CTA. Binary data is never persisted in SQL.
19
+
20
+ Among user-registered providers, the first one registered that reports
21
+ itself configured wins. `registerFileUploadProvider()` is idempotent per
22
+ `id`. Registering under an id that is already in use replaces the existing
23
+ provider.
24
+
25
+ The UI decides whether to show a storage-setup prompt using only the
26
+ synchronous `isConfigured()` check, before an upload is attempted. The
27
+ actual upload checks both `isConfigured()` and `isConfiguredForRequest()`.
28
+ A provider that only reports itself configured through
29
+ `isConfiguredForRequest()` stays invisible to the setup prompt even though
30
+ uploads through it would succeed.
19
31
 
20
32
  <Diagram id="doc-block-hq5uvx" title="Provider resolution order" summary="uploadFile() picks the first configured provider in order. Without one, the upload fails closed so binary data is never persisted in SQL.">
21
33
 
@@ -32,7 +44,7 @@ The provider resolution order is:
32
44
  <span class="diagram-pill accent">1</span>
33
45
  <div class="diagram-node">
34
46
  User-registered<br /><small class="diagram-muted"
35
- >registerFileUploadProvider() — S3, R2, GCS…</small
47
+ >registerFileUploadProvider() for S3, R2, GCS…</small
36
48
  >
37
49
  </div>
38
50
  </div>
@@ -40,7 +52,7 @@ The provider resolution order is:
40
52
  <span class="diagram-pill">2</span>
41
53
  <div class="diagram-node">
42
54
  Builder.io<br /><small class="diagram-muted"
43
- >auto when connected — CDN-served</small
55
+ >auto when connected, CDN-served</small
44
56
  >
45
57
  </div>
46
58
  </div>
@@ -48,7 +60,7 @@ The provider resolution order is:
48
60
  <span class="diagram-pill warn">3</span>
49
61
  <div class="diagram-node">
50
62
  No provider<br /><small class="diagram-muted"
51
- >setup CTA — no binary persistence</small
63
+ >setup CTA, no binary persistence</small
52
64
  >
53
65
  </div>
54
66
  </div>
@@ -85,8 +97,24 @@ The provider resolution order is:
85
97
  "contentType": "multipart/form-data"
86
98
  }} responses={[
87
99
  {
88
- "status": "200",
89
- "description": "{ url, id?, provider } — the public URL and which provider handled it."
100
+ "status": "201",
101
+ "description": "`{ url, id?, provider }`: the public URL and which provider handled it."
102
+ },
103
+ {
104
+ "status": "401",
105
+ "description": "No authenticated session."
106
+ },
107
+ {
108
+ "status": "413",
109
+ "description": "File exceeds the 25 MB upload ceiling."
110
+ },
111
+ {
112
+ "status": "415",
113
+ "description": "Blocked MIME type, such as an executable or script."
114
+ },
115
+ {
116
+ "status": "503",
117
+ "description": "No file upload provider is configured."
90
118
  }
91
119
  ]}>
92
120
 
@@ -104,42 +132,47 @@ When your app is connected to Builder.io, file uploads are automatically routed
104
132
 
105
133
  ## Custom Providers {#custom-providers}
106
134
 
107
- Register a custom provider in a server plugin to use any storage backend (S3, Cloudflare R2, GCS, etc.):
135
+ The framework already ships a built-in provider for S3-compatible storage
136
+ (AWS S3, Cloudflare R2, MinIO, and similar). Connect it with environment
137
+ variables or through the sidebar onboarding checklist. No code is required.
138
+ See [Onboarding](/docs/onboarding).
139
+
140
+ Register a custom provider only for a different kind of backend. This
141
+ example uploads through a generic HTTP API using `fetch()`:
108
142
 
109
143
  ```ts filename="server/plugins/file-upload.ts"
110
- import { S3 } from "@aws-sdk/client-s3";
111
144
  import { registerFileUploadProvider } from "@agent-native/core/file-upload";
112
- import { defineNitroPlugin, resolveSecret } from "@agent-native/core/server";
113
-
114
- const s3Client = new S3({ region: process.env.AWS_REGION });
145
+ import { defineNitroPlugin } from "@agent-native/core/server";
115
146
 
116
147
  export default defineNitroPlugin(() => {
117
- const readBucket = () => resolveSecret("S3_BUCKET");
118
-
119
148
  registerFileUploadProvider({
120
- id: "s3",
121
- name: "Amazon S3",
122
- isConfigured: () => false,
123
- isConfiguredForRequest: async () => !!(await readBucket()),
149
+ id: "my-storage",
150
+ name: "My Storage",
151
+ isConfigured: () => !!process.env.UPLOAD_ENDPOINT,
124
152
  upload: async ({ data, filename, mimeType }) => {
125
- const bucket = await readBucket();
126
- if (!bucket) throw new Error("S3 storage is not configured");
127
- const key = `uploads/${Date.now()}-${filename}`;
128
- await s3Client.putObject({
129
- Bucket: bucket,
130
- Key: key,
131
- Body: data,
132
- ContentType: mimeType,
133
- });
134
- return {
135
- url: `https://${bucket}.s3.amazonaws.com/${key}`,
136
- provider: "s3",
137
- };
153
+ const endpoint = process.env.UPLOAD_ENDPOINT!;
154
+ const body = new FormData();
155
+ body.append("file", new Blob([data], { type: mimeType }), filename);
156
+
157
+ // This example assumes an upload API that accepts a multipart file
158
+ // and returns { url }. Adjust the request and response handling to
159
+ // match your own provider's actual contract.
160
+ const response = await fetch(endpoint, { method: "POST", body });
161
+ if (!response.ok) {
162
+ throw new Error(`Upload failed with status ${response.status}`);
163
+ }
164
+
165
+ const { url } = await response.json();
166
+ return { url, provider: "my-storage" };
138
167
  },
139
168
  });
140
169
  });
141
170
  ```
142
171
 
172
+ Use `resolveSecret()` from `@agent-native/core/server` instead of an
173
+ environment variable when the provider needs a real credential, such as an
174
+ API key. See [Security — Secrets Management](/docs/security#secrets).
175
+
143
176
  ## Upload API {#upload-api}
144
177
 
145
178
  The `FileUploadProvider` interface:
@@ -158,6 +191,8 @@ interface FileUploadInput {
158
191
  filename?: string; // Original filename
159
192
  mimeType?: string; // MIME type, e.g. "image/png"
160
193
  ownerEmail?: string; // For request-scoped provider credentials
194
+ stableUrl?: boolean; // Builder.io hint: one stable URL while compression finishes
195
+ recordAsset?: boolean; // Builder.io hint: set false to skip the asset library
161
196
  }
162
197
 
163
198
  interface FileUploadResult {
@@ -179,15 +214,15 @@ const result = await uploadFile({
179
214
  });
180
215
 
181
216
  if (result) {
182
- // Provider handled it — result.url is the public URL
217
+ // Provider handled it. result.url is the public URL.
183
218
  } else {
184
- // No provider configured — show the storage setup CTA, or skip
219
+ // No provider configured. Show the storage setup CTA, or skip.
185
220
  }
186
221
  ```
187
222
 
188
223
  ## Resumable / Streaming Uploads {#resumable}
189
224
 
190
- A provider can optionally implement a `resumable` block on `FileUploadProvider` for uploads that need to stream to storage as data arrives instead of buffering the whole file first — the Clips template uses this to relay a recording to storage chunk-by-chunk while it is still being recorded, rather than assembling the full blob after the recorder stops.
225
+ A provider can optionally implement a `resumable` block on `FileUploadProvider` for uploads that need to stream to storage as data arrives instead of buffering the whole file first. The Clips template uses this to relay a recording to storage chunk-by-chunk while it is still being recorded, rather than assembling the full blob after the recorder stops.
191
226
 
192
227
  ```ts
193
228
  interface FileUploadProvider {
@@ -227,11 +262,10 @@ interface ResumableChunkResult {
227
262
  }
228
263
  ```
229
264
 
230
- When `resumable` is present, callers that stream data in (like a recorder) call `startSession` once, `relayChunk` repeatedly as bytes arrive, and `completeSession` when the stream ends — instead of the single buffered `upload()` call. A provider with no `resumable` block only ever sees the buffered path; implement it only when your storage backend has a native chunked/resumable upload API (S3 multipart, GCS resumable uploads, etc.) worth exposing.
265
+ When `resumable` is present, callers that stream data in (like a recorder) call `startSession` once, `relayChunk` repeatedly as bytes arrive, and `completeSession` when the stream ends. This replaces the single buffered `upload()` call. A provider with no `resumable` block only ever sees the buffered path. Implement it only when your storage backend has a native chunked/resumable upload API (S3 multipart, GCS resumable uploads, etc.) worth exposing.
231
266
 
232
267
  ## What's next
233
268
 
234
- - [**Database**](/docs/database) — why binary blobs stay out of SQL and go through this provider abstraction instead
269
+ - [**Database**](/docs/server-database) — the `getDb()`/schema pattern for persisting the URL `uploadFile()` returns
235
270
  - [**Security — Secrets Management**](/docs/security#secrets) — how `resolveSecret()` and the credential vault encrypt provider keys at rest
236
271
  - [**Onboarding**](/docs/onboarding) — registering a custom provider's setup step in the sidebar checklist
237
- - [**Deployment**](/docs/deployment) — connecting Builder.io or a custom provider in production
@@ -329,7 +329,7 @@ you do.
329
329
  When a harness pauses for approval it emits an `approval-request` event and the
330
330
  session is marked `idle` with the pending approval recorded, so the UI can
331
331
  surface it and resume on the user's decision. See
332
- [Human Approval](/docs/human-approval) for the approval surface.
332
+ [Human Approval](/docs/actions-access-control#needs-approval) for the approval surface.
333
333
 
334
334
  ## Events {#events}
335
335
 
@@ -419,4 +419,4 @@ one implementation of this contract, not the public abstraction.
419
419
  - [Agent-Native Code UI](/docs/code-agents-ui) — the reusable coding workspace surface.
420
420
  - [Custom Agents & Teams](/docs/agent-teams) — background runs and sub-agent delegation.
421
421
  - [Sandbox Adapters](/docs/sandbox-adapters) — pluggable execution backends for coding harnesses.
422
- - [Human Approval](/docs/human-approval) — the approval surface harness runs use.
422
+ - [Human Approval](/docs/actions-access-control#needs-approval) — the approval surface harness runs use.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: "Internationalization"
3
- description: "Localize Agent Native apps with shared locale catalogs, a language picker, browser-language fallback, and locale-aware docs content."
3
+ description: "Localize Agent Native apps with shared locale catalogs, a language picker, and browser-language fallback."
4
4
  ---
5
5
 
6
6
  # Internationalization
@@ -41,88 +41,78 @@ resolved locale/catalog into that script to avoid hydration mismatches.
41
41
  Each localized template keeps catalogs under `app/i18n/`:
42
42
 
43
43
  ```ts filename="app/i18n/index.ts"
44
+ import { createAgentNativeI18nCatalog } from "@agent-native/core/client/i18n";
44
45
  import enUS from "./en-US";
45
- import type { AgentNativeI18nCatalog } from "@agent-native/core/client/i18n";
46
- export const i18nCatalog = {
47
- sourceLocale: "en-US",
46
+
47
+ export const i18nCatalog = createAgentNativeI18nCatalog({
48
48
  messages: enUS,
49
- loadMessages: async (locale) => {
50
- switch (locale) {
51
- case "zh-CN":
52
- return (await import("./zh-CN")).default;
53
- default:
54
- return null;
55
- }
49
+ localeLoaders: {
50
+ "zh-CN": () => import("./zh-CN"),
51
+ "zh-TW": () => import("./zh-TW"),
52
+ "es-ES": () => import("./es-ES"),
53
+ "fr-FR": () => import("./fr-FR"),
54
+ "de-DE": () => import("./de-DE"),
55
+ "ja-JP": () => import("./ja-JP"),
56
+ "ko-KR": () => import("./ko-KR"),
57
+ "pt-BR": () => import("./pt-BR"),
58
+ "hi-IN": () => import("./hi-IN"),
59
+ "ar-SA": () => import("./ar-SA"),
56
60
  },
57
- } satisfies AgentNativeI18nCatalog;
61
+ });
58
62
  ```
59
63
 
60
- Always bundle `en-US`. Dynamic-import non-English catalogs so users only
61
- download the active locale. The supported locale codes are `en-US`, `zh-CN`,
62
- `zh-TW`, `es-ES`, `fr-FR`, `de-DE`, `ja-JP`, `ko-KR`, `pt-BR`, `hi-IN`, and
63
- `ar-SA`.
64
+ `messages` bundles `en-US` directly so it is always available before any
65
+ locale loads. `localeLoaders` dynamic-imports every other catalog so users
66
+ only download the active locale. The supported locale codes are `en-US`,
67
+ `zh-CN`, `zh-TW`, `es-ES`, `fr-FR`, `de-DE`, `ja-JP`, `ko-KR`, `pt-BR`,
68
+ `hi-IN`, and `ar-SA`.
69
+
70
+ This list is fixed by the framework. It is not just what this example
71
+ happens to bundle. `LocaleCode` is a TypeScript union of exactly these
72
+ codes, and `set-localization-preference` rejects anything else at runtime.
73
+ Each locale also needs framework-curated metadata, such as text direction
74
+ for right-to-left languages. Adding a new locale means extending the
75
+ framework itself, not adding a catalog file to your app.
76
+
77
+ `createAgentNativeI18nCatalog` also accepts an optional `sourceLocale`,
78
+ which defaults to `en-US`, and an optional `supportedLocales` array. Set
79
+ `supportedLocales` when an app ships translations for only some of the
80
+ framework's locales instead of all ten. It defaults to every locale the
81
+ framework supports. `LanguagePicker` only lists locales in this set, and any
82
+ detected or requested locale outside it falls back to `sourceLocale`.
64
83
 
65
84
  ## UI
66
85
 
67
- Use `useT()` for interface strings and put `<LanguagePicker />` on the app's
68
- `/settings` page. Sidebar apps should expose **Settings** in the app sidebar;
69
- the header language icon is only a shortcut.
86
+ Use `useT()` to translate interface strings:
70
87
 
71
88
  ```tsx
72
- import { LanguagePicker, useT } from "@agent-native/core/client/i18n";
73
- import { openAgentSettings } from "@agent-native/core/client/navigation";
74
- function SettingsPage() {
89
+ import { useT } from "@agent-native/core/client/i18n";
90
+
91
+ function Greeting({ name }: { name: string }) {
75
92
  const t = useT();
76
- return (
77
- <>
78
- <h2>{t("settings.languageTitle")}</h2>
79
- <LanguagePicker label={t("settings.languageLabel")} />
80
-
81
- <h2>{t("settings.agentTitle")}</h2>
82
- <p>{t("settings.agentDescription")}</p>
83
- <button type="button" onClick={() => openAgentSettings()}>
84
- {t("settings.openAgentSettings")}
85
- </button>
86
- </>
87
- );
93
+ return <p>{t("greeting.hello", { name })}</p>;
88
94
  }
89
95
  ```
90
96
 
91
- The "Agent settings" control should open the right agent sidebar's Settings tab
92
- for model, API key, automation, voice, and other framework-level controls.
93
- Apps may duplicate high-value framework settings in their own settings page
94
- when the setting is central to the app, but the sidebar settings tab remains the
95
- source of truth.
96
-
97
97
  Use `useFormatters()` for dates, numbers, relative time, and lists. Do not put
98
98
  locale-sensitive date/number formatting inside translation strings.
99
99
 
100
- ## Docs Site Content {#docs-site-content}
101
-
102
- Public docs pages use the same core provider, but with
103
- `persistPreference={false}` so anonymous docs traffic uses localStorage and the
104
- browser language instead of SQL settings actions. The English source remains in
105
- `packages/core/docs/content/*.mdx`. Localized page overrides live next to it under
106
- `packages/core/docs/content/locales/<locale>/<slug>.mdx`.
107
-
108
- Use the same BCP-47 locale codes as app catalogs. Keep the same slug as the
109
- English source, preserve stable anchors with `{#anchor}` on translated headings,
110
- and leave routes, action names, protocol fields, env vars, and provider names
111
- untranslated. If a locale has no translated Markdown for a page, the docs site
112
- falls back to English for that page while still localizing navigation and chrome.
113
-
114
- Docs Markdown may include structured `an-*` visual blocks. Translate their
115
- user-facing prose fields where it makes sense, such as file-tree titles and
116
- `entries[].note`, callout bodies, tab labels, and annotated-code labels/notes.
117
- Keep stable identifiers unchanged: filenames, paths, env vars, route strings,
118
- action names, language tags, code snippets, JSON keys, and protocol names.
100
+ Put `<LanguagePicker />` wherever the app lets a user change their language.
101
+ See [Toolkit: Settings](/docs/toolkit-settings) for the standard settings
102
+ page pattern, including where `openAgentSettings()` fits in.
119
103
 
120
104
  ## Actions And Persistence
121
105
 
122
106
  Every app inherits:
123
107
 
124
- - `get-localization-preference` — read the current user's `{ locale }`
125
- - `set-localization-preference` — set `"system"` or a supported locale
108
+ - `get-localization-preference` — read the current user's `{ locale, timezone }`
109
+ - `set-localization-preference` — set `locale` and/or `timezone`, each optional
110
+
111
+ `locale` is `"system"` or a supported BCP-47 locale. `timezone` is `"system"`
112
+ or an IANA zone such as `America/New_York`. It exists so scheduled and
113
+ automation work runs in the user's zone instead of the host's. Setting only
114
+ one field leaves the other unchanged, because `set-localization-preference`
115
+ merges onto the existing stored value instead of overwriting it.
126
116
 
127
117
  The durable value lives in user-scoped SQL settings under `localization`.
128
118
  `localStorage` is only used for pre-hydration and anonymous fallback. The active
@@ -137,10 +127,16 @@ Run:
137
127
  pnpm guard:i18n-catalogs
138
128
  ```
139
129
 
140
- The guard verifies supported locale filenames, key parity, placeholder parity,
141
- stale keys, and CLDR plural categories through `Intl.PluralRules`. It checks
142
- structure, not translation quality; high-visibility strings still need human
143
- review.
130
+ For app and template catalogs, the guard checks:
131
+
132
+ - Locale filenames, key parity, placeholder parity, and stale keys
133
+ - Duplicate keys and leftover development-only markers
134
+ - Wrong-script contamination, for example Chinese text inside an Arabic catalog
135
+ - CLDR plural categories through `Intl.PluralRules`
136
+ - `t()` calls in app source whose key is missing from the English catalog
137
+
138
+ The guard checks structure, not translation quality. High-visibility strings
139
+ still need human review.
144
140
 
145
141
  Do not translate stable identifiers such as action names, routes, enum values,
146
142
  app-state keys, database values, protocol fields, env var names, or provider
@@ -170,7 +170,7 @@ Adopting the framework is valuable mostly because of what you stop having to bui
170
170
 
171
171
  ## Data in SQL {#data-in-sql}
172
172
 
173
- All application state lives in a SQL database via Drizzle ORM. Schemas are provider-agnostic; the supported databases, `DATABASE_URL` config, and portability rules live in [Database](/docs/database).
173
+ All application state lives in a SQL database via Drizzle ORM. Schemas are provider-agnostic; the supported databases, `DATABASE_URL` config, and portability rules live in [Database](/docs/server-database).
174
174
 
175
175
  Core SQL stores are auto-created and available in every template:
176
176
 
@@ -295,7 +295,7 @@ should also expose scoped `db-exec` / `db-patch`; set `database: "off"` /
295
295
  sharing, review comments, version history, feature flags, localization, audit,
296
296
  context X-Ray, profile, automations, docs, resources, web, cross-app delegation,
297
297
  chat, and email. See
298
- [Production Agent Tools](/docs/deployment#production-agent-tools) for the full
298
+ [Production Agent Tools](/docs/actions-agent-tools#production-agent-tools) for the full
299
299
  list, the `"minimal"` preset, and why disabling a group leaves its HTTP routes
300
300
  mounted.
301
301
 
@@ -484,7 +484,7 @@ without source changes, use [Extensions](/docs/extensions).
484
484
 
485
485
  Two architectural rules keep apps portable across databases and hosts:
486
486
 
487
- - **Database-agnostic.** Write schemas with `@agent-native/core/db/schema` and reads/writes with Drizzle's portable query DSL so the same code runs on any supported provider. Use raw SQL only for additive migrations or one-off maintenance, kept parameterized and dialect-agnostic. See [Database](/docs/database).
487
+ - **Database-agnostic.** Write schemas with `@agent-native/core/db/schema` and reads/writes with Drizzle's portable query DSL so the same code runs on any supported provider. Use raw SQL only for additive migrations or one-off maintenance, kept parameterized and dialect-agnostic. See [Database](/docs/server-database).
488
488
  - **Hosting-agnostic.** The server runs on Nitro and compiles to any deployment target. Never use Node-specific APIs (`fs`, `child_process`, `path`) in server routes or plugins, and never assume a persistent server process. Serverless and edge are stateless, so keep all state in SQL. See [Deployment](/docs/deployment).
489
489
 
490
490
  ## Agent Resources {#workspace}
@@ -286,10 +286,10 @@ Brand colors, typography, spacing scales, and any shared component classes can l
286
286
 
287
287
  ## Deployment {#deployment}
288
288
 
289
- You have two options: **unified deploy** (the default for workspaces) or per-app independent deploy. [Deployment — Workspace Deploy](/docs/deployment#workspace-deploy) covers the full command, per-preset details (Cloudflare, Netlify, Vercel), and a diagram of the shape; the tradeoff:
289
+ You have two options: **unified deploy** (the default for workspaces) or per-app independent deploy. [Workspace Deployment — One Origin, Many Apps](/docs/workspace-deployment#workspace-deploy) covers the full command, per-preset details (Cloudflare, Netlify, Vercel), and a diagram of the shape; the tradeoff:
290
290
 
291
291
  - **Unified deploy (recommended)** — `npx @agent-native/core@latest deploy` builds every app in the workspace and ships them behind a single origin, one path per app (`your-agents.com/mail/*`, `/calendar/*`, ...). Being on the same origin is where the real payoff lives: a shared login session (log into any app, every app is logged in), zero-config cross-app A2A (`@mail` tagging `@calendar` is a same-origin fetch — no CORS, no JWT signing between siblings), and one DNS record, cert, and CDN cache to manage.
292
- - **Per-app independent deploy** — prefer each app on its own domain (`mail.company.com`, `calendar.company.com`)? Every app in the workspace is still an independent deployable — `cd apps/mail && npx @agent-native/core@latest build` behaves exactly like a standalone scaffold. Cross-app A2A then goes through the standard JWT-signed path with a shared `A2A_SECRET`. Cross-domain SSO between separately-deployed apps is handled by identity federation with Dispatch as the hub — see [Cross-App SSO](/docs/cross-app-sso); the unified single-origin deploy avoids needing it. For a self-hosted VPS or Docker Compose setup on one origin instead, see [Deployment — Self-hosted workspace with Docker Compose](/docs/deployment#workspace-docker-compose).
292
+ - **Per-app independent deploy** — prefer each app on its own domain (`mail.company.com`, `calendar.company.com`)? Every app in the workspace is still an independent deployable — `cd apps/mail && npx @agent-native/core@latest build` behaves exactly like a standalone scaffold. Cross-app A2A then goes through the standard JWT-signed path with a shared `A2A_SECRET`. Cross-domain SSO between separately-deployed apps is handled by identity federation with Dispatch as the hub — see [Cross-App SSO](/docs/cross-app-sso); the unified single-origin deploy avoids needing it. For a self-hosted VPS or Docker Compose setup on one origin instead, see [Workspace Deployment — Self-hosted Workspace with Docker Compose](/docs/workspace-deployment#workspace-docker-compose).
293
293
 
294
294
  Whichever you pick, point every app at the same `DATABASE_URL` for cross-app state out of the box: one set of user accounts, one set of organizations, one set of shared settings. The shared package itself is never deployed standalone — pnpm symlinks it into each app's `node_modules/` at build time.
295
295