@agent-native/core 0.164.11 → 0.164.15
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.
- package/corpus/README.md +1 -1
- package/corpus/templates/calendar/.agents/skills/event-management/SKILL.md +84 -0
- package/corpus/templates/calendar/AGENTS.md +5 -0
- package/corpus/templates/calendar/actions/delete-event.ts +1 -1
- package/corpus/templates/calendar/actions/delete-events.ts +508 -0
- package/corpus/templates/calendar/actions/event-action-helpers.ts +1 -1
- package/corpus/templates/calendar/actions/list-events.ts +53 -0
- package/corpus/templates/calendar/changelog/2026-08-18-the-agent-can-now-remove-many-meetings-at-once-such-as-every.md +6 -0
- package/corpus/templates/calendar/server/lib/event-weekday.ts +112 -0
- package/corpus/templates/content/actions/_database-source-utils.ts +25 -2
- package/corpus/templates/content/actions/_database-utils.ts +2 -0
- package/corpus/templates/content/actions/_local-folder-source.ts +186 -2
- package/corpus/templates/content/actions/connect-local-folder-source.ts +23 -8
- package/corpus/templates/content/actions/disconnect-local-folder-source.ts +3 -3
- package/corpus/templates/content/actions/resolve-local-folder-conflict.ts +2 -2
- package/corpus/templates/content/actions/sync-local-folder-source.ts +130 -12
- package/corpus/templates/content/app/components/LocalFolderLiveSync.tsx +77 -0
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +354 -8
- package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +23 -1
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +78 -1
- package/corpus/templates/content/app/components/editor/database/sidebar.tsx +36 -0
- package/corpus/templates/content/app/components/editor/local-source-write-state.ts +52 -0
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +244 -6
- package/corpus/templates/content/app/components/sidebar/local-source-hierarchy.ts +189 -0
- package/corpus/templates/content/app/hooks/use-create-page.ts +26 -4
- package/corpus/templates/content/app/hooks/use-documents.ts +83 -0
- package/corpus/templates/content/app/i18n-data.ts +79 -0
- package/corpus/templates/content/app/lib/desktop-content-files.ts +57 -1
- package/corpus/templates/content/app/lib/local-content-source-files.ts +210 -34
- package/corpus/templates/content/app/lib/local-folder-live-sync.ts +191 -0
- package/corpus/templates/content/app/root.tsx +2 -1
- package/corpus/templates/content/app/routes/_app.local-files.tsx +103 -38
- package/corpus/templates/content/docs/product/capabilities/content.source.file-folder.md +2 -2
- package/corpus/templates/content/docs/product/features/content.feature.bring-your-local-work.md +3 -3
- package/corpus/templates/content/docs/product/roadmap.md +2 -2
- package/corpus/templates/content/docs/solutions/2026-08-18-content-navigation-coherence-shape.md +482 -0
- package/corpus/templates/content/shared/api.ts +25 -0
- package/corpus/templates/factory/AGENTS.md +2 -1
- package/corpus/templates/factory/actions/get-factory-graph-version.ts +69 -0
- package/corpus/templates/factory/actions/list-factory-graph-versions.ts +82 -0
- package/corpus/templates/factory/actions/restore-factory-graph-version.ts +163 -0
- package/corpus/templates/factory/actions/save-factory-graph.ts +93 -60
- package/corpus/templates/factory/app/components/factory/FactoryHistoryView.tsx +709 -0
- package/corpus/templates/factory/app/components/factory/FactoryInspector.tsx +62 -2
- package/corpus/templates/factory/app/components/ui/alert-dialog.tsx +1 -0
- package/corpus/templates/factory/app/i18n/en-US.ts +43 -0
- package/corpus/templates/factory/app/routes/factory.tsx +115 -15
- package/corpus/templates/factory/server/plugins/agent-chat.ts +3 -1
- package/dist/app-config/auth.d.ts +4 -0
- package/dist/app-config/auth.js +7 -0
- package/dist/app-config/schema.d.ts +3 -0
- package/dist/app-config/schema.js +2 -0
- package/dist/cli/code-agent-executor.js +6 -1
- package/dist/cli/code-agent-mcp-config.d.ts +2 -2
- package/dist/cli/code-agent-mcp-config.js +34 -9
- package/dist/client/org/OrgSwitcher.js +8 -4
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/mcp-client/config.d.ts +11 -0
- package/dist/mcp-client/config.js +33 -26
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +3 -3
- package/dist/progress/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +2 -2
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/auth.js +15 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/docs/content/actions-access-control.mdx +136 -2
- package/docs/content/actions-agent-tools.mdx +101 -0
- package/docs/content/actions-defining.mdx +2 -2
- package/docs/content/audit-log.mdx +1 -1
- package/docs/content/authentication.mdx +1 -1
- package/docs/content/cloudflare.mdx +43 -0
- package/docs/content/creating-templates.mdx +1 -1
- package/docs/content/deploy-an-app.mdx +109 -0
- package/docs/content/deployment-environment-variables.mdx +101 -0
- package/docs/content/deployment.mdx +125 -792
- package/docs/content/docs-components.mdx +2 -2
- package/docs/content/environment-variables.mdx +41 -41
- package/docs/content/file-uploads.mdx +74 -40
- package/docs/content/harness-agents.mdx +2 -2
- package/docs/content/internationalization.mdx +61 -65
- package/docs/content/key-concepts.mdx +3 -3
- package/docs/content/multi-app-workspace.mdx +2 -2
- package/docs/content/netlify.mdx +47 -0
- package/docs/content/node-docker.mdx +138 -0
- package/docs/content/organizations-teams-permissions.mdx +5 -5
- package/docs/content/other-platforms.mdx +27 -0
- package/docs/content/ssr-caching.mdx +45 -0
- package/docs/content/template-assets-developers.mdx +2 -2
- package/docs/content/template-chat-developers.mdx +2 -2
- package/docs/content/template-content-developers.mdx +2 -2
- package/docs/content/{local-file-mode.mdx → template-content-local-files.mdx} +2 -1
- package/docs/content/template-content-sync.mdx +2 -2
- package/docs/content/toolkit-agent-ux.mdx +1 -1
- package/docs/content/toolkit-resources.mdx +2 -2
- package/docs/content/updating-ui-in-production.mdx +35 -0
- package/docs/content/vercel.mdx +38 -0
- package/docs/content/what-is-agent-native.mdx +1 -1
- package/docs/content/workspace-deployment.mdx +350 -0
- package/package.json +1 -1
- package/docs/content/agents.mdx +0 -9
- package/docs/content/database.mdx +0 -317
- 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
|
|
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/
|
|
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/
|
|
53
|
-
| `AGENT_NATIVE_ENABLE_KEEP_WARM` | Opts into the Netlify keep-warm scheduled function; unset by default. | `1`; see [Keep-warm](/docs/
|
|
54
|
-
| `AGENT_NATIVE_DISABLE_KEEP_WARM` | Compatibility kill switch for the Netlify keep-warm scheduled function. | `1`; see [Keep-warm](/docs/
|
|
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/
|
|
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
|
|
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
|
|
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
|
|
17
|
-
2. **Builder.io provider
|
|
18
|
-
3. **No provider
|
|
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()
|
|
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
|
|
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
|
|
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": "
|
|
89
|
-
"description": "{ url, id?, provider }
|
|
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
|
-
|
|
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
|
|
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: "
|
|
121
|
-
name: "
|
|
122
|
-
isConfigured: () =>
|
|
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
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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
|
|
217
|
+
// Provider handled it. result.url is the public URL.
|
|
183
218
|
} else {
|
|
184
|
-
// No provider configured
|
|
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
|
|
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
|
|
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) —
|
|
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/
|
|
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/
|
|
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
|
|
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
|
-
|
|
46
|
-
export const i18nCatalog = {
|
|
47
|
-
sourceLocale: "en-US",
|
|
46
|
+
|
|
47
|
+
export const i18nCatalog = createAgentNativeI18nCatalog({
|
|
48
48
|
messages: enUS,
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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
|
-
}
|
|
61
|
+
});
|
|
58
62
|
```
|
|
59
63
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
`
|
|
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()`
|
|
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 {
|
|
73
|
-
|
|
74
|
-
function
|
|
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
|
-
|
|
101
|
-
|
|
102
|
-
|
|
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 `
|
|
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
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
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/
|
|
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 —
|
|
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
|
|
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
|
|