@agent-native/core 0.7.18 → 0.7.20
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/README.md +1 -1
- package/dist/agent/engine/builder-engine.d.ts.map +1 -1
- package/dist/agent/engine/builder-engine.js +60 -5
- package/dist/agent/engine/builder-engine.js.map +1 -1
- package/dist/agent/loop-settings.d.ts +37 -0
- package/dist/agent/loop-settings.d.ts.map +1 -0
- package/dist/agent/loop-settings.js +127 -0
- package/dist/agent/loop-settings.js.map +1 -0
- package/dist/agent/production-agent.d.ts +8 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +268 -29
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +76 -3
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/run-store.d.ts +1 -1
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +65 -2
- package/dist/agent/run-store.js.map +1 -1
- package/dist/agent/thread-data-builder.d.ts +3 -0
- package/dist/agent/thread-data-builder.d.ts.map +1 -1
- package/dist/agent/thread-data-builder.js +52 -10
- package/dist/agent/thread-data-builder.js.map +1 -1
- package/dist/agent/tool-search.d.ts +37 -0
- package/dist/agent/tool-search.d.ts.map +1 -0
- package/dist/agent/tool-search.js +201 -0
- package/dist/agent/tool-search.js.map +1 -0
- package/dist/agent/types.d.ts +8 -1
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +57 -11
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/workspacify.d.ts +2 -0
- package/dist/cli/workspacify.d.ts.map +1 -1
- package/dist/cli/workspacify.js +34 -1
- package/dist/cli/workspacify.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +303 -14
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/ConnectBuilderCard.d.ts.map +1 -1
- package/dist/client/ConnectBuilderCard.js +1 -1
- package/dist/client/ConnectBuilderCard.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +16 -24
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/NewWorkspaceAppFlow.d.ts +14 -0
- package/dist/client/NewWorkspaceAppFlow.d.ts.map +1 -0
- package/dist/client/NewWorkspaceAppFlow.js +200 -0
- package/dist/client/NewWorkspaceAppFlow.js.map +1 -0
- package/dist/client/PoweredByBadge.d.ts +10 -1
- package/dist/client/PoweredByBadge.d.ts.map +1 -1
- package/dist/client/PoweredByBadge.js +120 -8
- package/dist/client/PoweredByBadge.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts +8 -0
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +32 -5
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/agent-chat.d.ts.map +1 -1
- package/dist/client/agent-chat.js +15 -3
- package/dist/client/agent-chat.js.map +1 -1
- package/dist/client/analytics.d.ts +1 -1
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +141 -1
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/builder-frame.d.ts +10 -0
- package/dist/client/builder-frame.d.ts.map +1 -0
- package/dist/client/builder-frame.js +94 -0
- package/dist/client/builder-frame.js.map +1 -0
- package/dist/client/composer/MentionPopover.d.ts.map +1 -1
- package/dist/client/composer/MentionPopover.js +5 -1
- package/dist/client/composer/MentionPopover.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +11 -6
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/error-format.d.ts +20 -1
- package/dist/client/error-format.d.ts.map +1 -1
- package/dist/client/error-format.js +53 -5
- package/dist/client/error-format.js.map +1 -1
- package/dist/client/index.d.ts +3 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +3 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/onboarding/OnboardingPanel.d.ts.map +1 -1
- package/dist/client/onboarding/OnboardingPanel.js +88 -6
- package/dist/client/onboarding/OnboardingPanel.js.map +1 -1
- package/dist/client/org/TeamPage.d.ts.map +1 -1
- package/dist/client/org/TeamPage.js +14 -2
- package/dist/client/org/TeamPage.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +145 -9
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/settings/useBuilderStatus.d.ts +13 -0
- package/dist/client/settings/useBuilderStatus.d.ts.map +1 -1
- package/dist/client/settings/useBuilderStatus.js +50 -9
- package/dist/client/settings/useBuilderStatus.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts +9 -1
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +95 -8
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/client/tools/ToolsListPage.d.ts.map +1 -1
- package/dist/client/tools/ToolsListPage.js +16 -1
- package/dist/client/tools/ToolsListPage.js.map +1 -1
- package/dist/client/tools/ToolsSidebarSection.d.ts.map +1 -1
- package/dist/client/tools/ToolsSidebarSection.js +63 -8
- package/dist/client/tools/ToolsSidebarSection.js.map +1 -1
- package/dist/client/tools/tool-order.d.ts +7 -0
- package/dist/client/tools/tool-order.d.ts.map +1 -0
- package/dist/client/tools/tool-order.js +47 -0
- package/dist/client/tools/tool-order.js.map +1 -0
- package/dist/client/transcription/BuilderTranscriptionCta.d.ts.map +1 -1
- package/dist/client/transcription/BuilderTranscriptionCta.js +71 -6
- package/dist/client/transcription/BuilderTranscriptionCta.js.map +1 -1
- package/dist/client/use-send-to-agent-chat.d.ts.map +1 -1
- package/dist/client/use-send-to-agent-chat.js +11 -3
- package/dist/client/use-send-to-agent-chat.js.map +1 -1
- package/dist/client/useProductionAgent.d.ts.map +1 -1
- package/dist/client/useProductionAgent.js +1 -1
- package/dist/client/useProductionAgent.js.map +1 -1
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +5 -1
- package/dist/db/client.js.map +1 -1
- package/dist/deploy/build.d.ts +1 -0
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +4 -1
- package/dist/deploy/build.js.map +1 -1
- package/dist/integrations/pending-tasks-retry-job.d.ts.map +1 -1
- package/dist/integrations/pending-tasks-retry-job.js +1 -1
- package/dist/integrations/pending-tasks-retry-job.js.map +1 -1
- package/dist/oauth-tokens/index.d.ts +1 -1
- package/dist/oauth-tokens/index.d.ts.map +1 -1
- package/dist/oauth-tokens/index.js +1 -1
- package/dist/oauth-tokens/index.js.map +1 -1
- package/dist/oauth-tokens/store.d.ts.map +1 -1
- package/dist/oauth-tokens/store.js +6 -0
- package/dist/oauth-tokens/store.js.map +1 -1
- package/dist/observability/store.d.ts.map +1 -1
- package/dist/observability/store.js +19 -19
- package/dist/observability/store.js.map +1 -1
- package/dist/onboarding/default-steps.d.ts.map +1 -1
- package/dist/onboarding/default-steps.js +95 -61
- package/dist/onboarding/default-steps.js.map +1 -1
- package/dist/onboarding/plugin.d.ts.map +1 -1
- package/dist/onboarding/plugin.js +17 -8
- package/dist/onboarding/plugin.js.map +1 -1
- package/dist/org/migrations.js +2 -2
- package/dist/org/migrations.js.map +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.d.ts.map +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.js +2 -3
- package/dist/scripts/agent-engines/list-agent-engines.js.map +1 -1
- package/dist/scripts/db/exec.d.ts +2 -1
- package/dist/scripts/db/exec.d.ts.map +1 -1
- package/dist/scripts/db/exec.js +264 -61
- package/dist/scripts/db/exec.js.map +1 -1
- package/dist/scripts/db/schema.d.ts.map +1 -1
- package/dist/scripts/db/schema.js +16 -4
- package/dist/scripts/db/schema.js.map +1 -1
- package/dist/scripts/dev/index.d.ts.map +1 -1
- package/dist/scripts/dev/index.js +36 -11
- package/dist/scripts/dev/index.js.map +1 -1
- package/dist/scripts/manage-agent-loop-settings.d.ts +7 -0
- package/dist/scripts/manage-agent-loop-settings.d.ts.map +1 -0
- package/dist/scripts/manage-agent-loop-settings.js +63 -0
- package/dist/scripts/manage-agent-loop-settings.js.map +1 -0
- package/dist/scripts/runner.d.ts.map +1 -1
- package/dist/scripts/runner.js +11 -0
- package/dist/scripts/runner.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +60 -18
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/app-url.d.ts +5 -4
- package/dist/server/app-url.d.ts.map +1 -1
- package/dist/server/app-url.js +8 -4
- package/dist/server/app-url.js.map +1 -1
- package/dist/server/auth.d.ts +37 -0
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +114 -35
- package/dist/server/auth.js.map +1 -1
- package/dist/server/better-auth-instance.d.ts +15 -0
- package/dist/server/better-auth-instance.d.ts.map +1 -1
- package/dist/server/better-auth-instance.js +131 -5
- package/dist/server/better-auth-instance.js.map +1 -1
- package/dist/server/builder-browser.d.ts +12 -0
- package/dist/server/builder-browser.d.ts.map +1 -1
- package/dist/server/builder-browser.js +36 -4
- package/dist/server/builder-browser.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +350 -53
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/credential-provider.d.ts +21 -3
- package/dist/server/credential-provider.d.ts.map +1 -1
- package/dist/server/credential-provider.js +51 -21
- package/dist/server/credential-provider.js.map +1 -1
- package/dist/server/google-oauth.d.ts +3 -0
- package/dist/server/google-oauth.d.ts.map +1 -1
- package/dist/server/google-oauth.js +35 -18
- package/dist/server/google-oauth.js.map +1 -1
- package/dist/server/index.d.ts +4 -3
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +4 -3
- package/dist/server/index.js.map +1 -1
- package/dist/server/schema-prompt.d.ts.map +1 -1
- package/dist/server/schema-prompt.js +2 -1
- package/dist/server/schema-prompt.js.map +1 -1
- package/dist/server/security-headers.d.ts +3 -0
- package/dist/server/security-headers.d.ts.map +1 -1
- package/dist/server/security-headers.js +7 -1
- package/dist/server/security-headers.js.map +1 -1
- package/dist/server/ssr-handler.d.ts.map +1 -1
- package/dist/server/ssr-handler.js +24 -4
- package/dist/server/ssr-handler.js.map +1 -1
- package/dist/server/voice-providers-status.d.ts +7 -0
- package/dist/server/voice-providers-status.d.ts.map +1 -1
- package/dist/server/voice-providers-status.js +1 -0
- package/dist/server/voice-providers-status.js.map +1 -1
- package/dist/templates/default/_gitignore +5 -1
- package/dist/templates/default/app/root.tsx +1 -0
- package/dist/templates/default/public/favicon.svg +3 -3
- package/dist/templates/default/public/icon-180.svg +3 -3
- package/dist/templates/default/public/icon-192.svg +3 -3
- package/dist/templates/default/public/icon-512.svg +3 -3
- package/dist/templates/workspace-core/AGENTS.md +23 -7
- package/dist/templates/workspace-core/package.json +2 -1
- package/dist/templates/workspace-core/src/credentials.ts +22 -11
- package/dist/templates/workspace-root/.env.example +7 -0
- package/dist/templates/workspace-root/README.md +6 -3
- package/dist/templates/workspace-root/_gitignore +3 -0
- package/dist/templates/workspace-root/package.json +3 -1
- package/dist/templates/workspace-root/scripts/workspace-dev.ts +410 -0
- package/dist/tools/actions.d.ts.map +1 -1
- package/dist/tools/actions.js +2 -0
- package/dist/tools/actions.js.map +1 -1
- package/dist/tools/html-shell.d.ts.map +1 -1
- package/dist/tools/html-shell.js +13 -1
- package/dist/tools/html-shell.js.map +1 -1
- package/dist/tools/store.d.ts.map +1 -1
- package/dist/tools/store.js +16 -11
- package/dist/tools/store.js.map +1 -1
- package/dist/tracking/providers.d.ts +1 -0
- package/dist/tracking/providers.d.ts.map +1 -1
- package/dist/tracking/providers.js +72 -0
- package/dist/tracking/providers.js.map +1 -1
- package/dist/vite/action-types-plugin.d.ts.map +1 -1
- package/dist/vite/action-types-plugin.js +106 -9
- package/dist/vite/action-types-plugin.js.map +1 -1
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +67 -2
- package/dist/vite/client.js.map +1 -1
- package/docs/content/authentication.md +17 -13
- package/docs/content/deployment.md +11 -11
- package/docs/content/mcp-clients.md +2 -2
- package/docs/content/onboarding.md +32 -30
- package/docs/content/security.md +1 -1
- package/docs/content/tools.md +4 -0
- package/package.json +2 -2
- package/src/templates/default/_gitignore +5 -1
- package/src/templates/default/app/root.tsx +1 -0
- package/src/templates/default/public/favicon.svg +3 -3
- package/src/templates/default/public/icon-180.svg +3 -3
- package/src/templates/default/public/icon-192.svg +3 -3
- package/src/templates/default/public/icon-512.svg +3 -3
- package/src/templates/workspace-core/AGENTS.md +23 -7
- package/src/templates/workspace-core/package.json +2 -1
- package/src/templates/workspace-core/src/credentials.ts +22 -11
- package/src/templates/workspace-root/.env.example +7 -0
- package/src/templates/workspace-root/README.md +6 -3
- package/src/templates/workspace-root/_gitignore +3 -0
- package/src/templates/workspace-root/package.json +3 -1
- package/src/templates/workspace-root/scripts/workspace-dev.ts +410 -0
package/dist/server/app-url.d.ts
CHANGED
|
@@ -6,15 +6,16 @@
|
|
|
6
6
|
* Resolution order:
|
|
7
7
|
* 1. `APP_URL` env var — explicit override
|
|
8
8
|
* 2. `BETTER_AUTH_URL` env var — Better Auth's canonical URL
|
|
9
|
-
* 3.
|
|
9
|
+
* 3. `WORKSPACE_GATEWAY_URL` — local multi-app workspace gateway
|
|
10
|
+
* 4. First-party template `prodUrl` from the registry (matched by
|
|
10
11
|
* package.json name) — lets deployed first-party apps (mail,
|
|
11
12
|
* calendar, analytics, …) use e.g. `analytics.agent-native.com`
|
|
12
13
|
* instead of their Netlify preview hostname.
|
|
13
|
-
*
|
|
14
|
-
*
|
|
14
|
+
* 5. Incoming request's origin (when an H3Event is available)
|
|
15
|
+
* 6. Platform-injected URL (Netlify `URL`, Vercel `VERCEL_URL`) —
|
|
15
16
|
* automatically set by the hosting platform, so user-deployed apps
|
|
16
17
|
* get a real hostname in emails without needing to set `APP_URL`.
|
|
17
|
-
*
|
|
18
|
+
* 7. `http://localhost:3000`
|
|
18
19
|
*/
|
|
19
20
|
import { type H3Event } from "h3";
|
|
20
21
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-url.d.ts","sourceRoot":"","sources":["../../src/server/app-url.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"app-url.d.ts","sourceRoot":"","sources":["../../src/server/app-url.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAiB,KAAK,OAAO,EAAE,MAAM,IAAI,CAAC;AAkCjD;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,GAAG,SAAS,CAKzD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CA4C3D"}
|
package/dist/server/app-url.js
CHANGED
|
@@ -6,15 +6,16 @@
|
|
|
6
6
|
* Resolution order:
|
|
7
7
|
* 1. `APP_URL` env var — explicit override
|
|
8
8
|
* 2. `BETTER_AUTH_URL` env var — Better Auth's canonical URL
|
|
9
|
-
* 3.
|
|
9
|
+
* 3. `WORKSPACE_GATEWAY_URL` — local multi-app workspace gateway
|
|
10
|
+
* 4. First-party template `prodUrl` from the registry (matched by
|
|
10
11
|
* package.json name) — lets deployed first-party apps (mail,
|
|
11
12
|
* calendar, analytics, …) use e.g. `analytics.agent-native.com`
|
|
12
13
|
* instead of their Netlify preview hostname.
|
|
13
|
-
*
|
|
14
|
-
*
|
|
14
|
+
* 5. Incoming request's origin (when an H3Event is available)
|
|
15
|
+
* 6. Platform-injected URL (Netlify `URL`, Vercel `VERCEL_URL`) —
|
|
15
16
|
* automatically set by the hosting platform, so user-deployed apps
|
|
16
17
|
* get a real hostname in emails without needing to set `APP_URL`.
|
|
17
|
-
*
|
|
18
|
+
* 7. `http://localhost:3000`
|
|
18
19
|
*/
|
|
19
20
|
import { getRequestURL } from "h3";
|
|
20
21
|
import path from "node:path";
|
|
@@ -64,6 +65,9 @@ export function getAppProductionUrl(event) {
|
|
|
64
65
|
const envUrl = process.env.APP_URL || process.env.BETTER_AUTH_URL;
|
|
65
66
|
if (envUrl)
|
|
66
67
|
return stripTrailingSlash(envUrl);
|
|
68
|
+
if (process.env.WORKSPACE_GATEWAY_URL) {
|
|
69
|
+
return stripTrailingSlash(process.env.WORKSPACE_GATEWAY_URL);
|
|
70
|
+
}
|
|
67
71
|
// Prefer the incoming request's origin when we have one — for local dev
|
|
68
72
|
// this is `http://localhost:3000`, which keeps Better Auth from setting
|
|
69
73
|
// `Secure` cookies on plain-HTTP dev servers.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-url.js","sourceRoot":"","sources":["../../src/server/app-url.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"app-url.js","sourceRoot":"","sources":["../../src/server/app-url.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Resolve the canonical URL of this app — used in transactional emails,\n * invite links, and anywhere we need an absolute URL that remains valid\n * outside the current request context.\n *\n * Resolution order:\n * 1. `APP_URL` env var — explicit override\n * 2. `BETTER_AUTH_URL` env var — Better Auth's canonical URL\n * 3. `WORKSPACE_GATEWAY_URL` — local multi-app workspace gateway\n * 4. First-party template `prodUrl` from the registry (matched by\n * package.json name) — lets deployed first-party apps (mail,\n * calendar, analytics, …) use e.g. `analytics.agent-native.com`\n * instead of their Netlify preview hostname.\n * 5. Incoming request's origin (when an H3Event is available)\n * 6. Platform-injected URL (Netlify `URL`, Vercel `VERCEL_URL`) —\n * automatically set by the hosting platform, so user-deployed apps\n * get a real hostname in emails without needing to set `APP_URL`.\n * 7. `http://localhost:3000`\n */\nimport { getRequestURL, type H3Event } from \"h3\";\nimport path from \"node:path\";\nimport fs from \"node:fs\";\nimport { TEMPLATES } from \"../cli/templates-meta.js\";\nimport { isLocalDatabase } from \"../db/client.js\";\n\nlet cachedPkgName: string | undefined | null = null;\n\n/**\n * Read the app's package name, validated against the first-party template\n * registry. On serverless runtimes (Netlify Functions, Cloudflare Workers),\n * `process.cwd()` may point at a bundler-generated package.json with a\n * bogus name (e.g. Nitro's \"traced-node-modules\"). Only trust the name if\n * it matches a known template.\n */\nfunction readPackageName(): string | undefined {\n if (cachedPkgName !== null) return cachedPkgName ?? undefined;\n try {\n const pkgPath = path.join(process.cwd(), \"package.json\");\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf8\"));\n const name = typeof pkg?.name === \"string\" ? pkg.name : undefined;\n const isKnown = name && TEMPLATES.some((t) => t.name === name);\n cachedPkgName = isKnown ? name : undefined;\n } catch {\n cachedPkgName = undefined;\n }\n return cachedPkgName ?? undefined;\n}\n\n/** Strip trailing slashes for consistent URL concatenation. */\nfunction stripTrailingSlash(u: string): string {\n return u.replace(/\\/+$/, \"\");\n}\n\n/**\n * Look up the first-party template `prodUrl` for the current app based on\n * its `package.json` name. Returns undefined if the app isn't a known\n * first-party template or the template has no `prodUrl`.\n */\nexport function getFirstPartyProdUrl(): string | undefined {\n const name = readPackageName();\n if (!name) return undefined;\n const t = TEMPLATES.find((t) => t.name === name);\n return t?.prodUrl;\n}\n\nexport function getAppProductionUrl(event?: H3Event): string {\n const envUrl = process.env.APP_URL || process.env.BETTER_AUTH_URL;\n if (envUrl) return stripTrailingSlash(envUrl);\n\n if (process.env.WORKSPACE_GATEWAY_URL) {\n return stripTrailingSlash(process.env.WORKSPACE_GATEWAY_URL);\n }\n\n // Prefer the incoming request's origin when we have one — for local dev\n // this is `http://localhost:3000`, which keeps Better Auth from setting\n // `Secure` cookies on plain-HTTP dev servers.\n if (event) {\n try {\n const url = getRequestURL(event);\n return `${url.protocol}//${url.host}`;\n } catch {\n // fall through\n }\n }\n\n // Fall back to a first-party template's hard-coded prod URL when we're\n // running in production OR on a remote database (Neon/Postgres/Turso).\n // A remote DB means we're deployed even if NODE_ENV isn't explicitly\n // \"production\" (e.g. Netlify Functions). In local dev with SQLite, skip\n // this — the hard-coded URL breaks auth via Secure cookies on HTTP.\n if (process.env.NODE_ENV === \"production\" || !isLocalDatabase()) {\n const firstParty = getFirstPartyProdUrl();\n if (firstParty) return stripTrailingSlash(firstParty);\n\n // Netlify injects `URL` (main site URL, always https) and `DEPLOY_URL`\n // (deploy-specific URL). Prefer `URL` so emails always link to the\n // primary domain rather than a preview branch URL.\n const netlifyUrl = process.env.URL || process.env.DEPLOY_URL;\n if (netlifyUrl) return stripTrailingSlash(netlifyUrl);\n\n // Vercel injects `VERCEL_PROJECT_PRODUCTION_URL` (custom/primary domain,\n // no protocol) and `VERCEL_URL` (ephemeral deployment hostname). Prefer\n // the production URL so emails use the real domain, not *.vercel.app.\n const vercelUrl =\n process.env.VERCEL_PROJECT_PRODUCTION_URL || process.env.VERCEL_URL;\n if (vercelUrl) return `https://${stripTrailingSlash(vercelUrl)}`;\n }\n\n return \"http://localhost:3000\";\n}\n"]}
|
package/dist/server/auth.d.ts
CHANGED
|
@@ -45,6 +45,35 @@ export interface AuthOptions {
|
|
|
45
45
|
* is provided.
|
|
46
46
|
*/
|
|
47
47
|
googleOnly?: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Mount the framework's generic Google sign-in routes.
|
|
50
|
+
*
|
|
51
|
+
* Set this to false when a template owns `/_agent-native/google/auth-url`
|
|
52
|
+
* and `/_agent-native/google/callback` itself because it needs broader
|
|
53
|
+
* product scopes and persisted API tokens, not just identity sign-in.
|
|
54
|
+
*/
|
|
55
|
+
mountGoogleOAuthRoutes?: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Additional Google OAuth scopes to request beyond the default identity
|
|
58
|
+
* scopes (`openid`, `email`, `profile`). When set, Better Auth's Google
|
|
59
|
+
* social provider asks for these up front, requests a refresh token
|
|
60
|
+
* (`access_type=offline`), and forces the consent screen so the refresh
|
|
61
|
+
* token is reissued on every sign-in.
|
|
62
|
+
*
|
|
63
|
+
* Tokens land in Better Auth's `account` table, and a database hook
|
|
64
|
+
* mirrors them into `oauth_tokens` so template code (mail's Gmail client,
|
|
65
|
+
* calendar's events fetcher, etc.) can pick them up without a separate
|
|
66
|
+
* "Connect Google" round-trip.
|
|
67
|
+
*
|
|
68
|
+
* Example for the mail template:
|
|
69
|
+
* ```ts
|
|
70
|
+
* googleScopes: [
|
|
71
|
+
* "https://www.googleapis.com/auth/gmail.readonly",
|
|
72
|
+
* "https://www.googleapis.com/auth/gmail.send",
|
|
73
|
+
* ],
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
googleScopes?: string[];
|
|
48
77
|
/**
|
|
49
78
|
* Product marketing content shown alongside the sign-in form.
|
|
50
79
|
* When provided, the page uses a split layout: marketing on the left,
|
|
@@ -92,7 +121,15 @@ export declare function removeSession(token: string): Promise<void>;
|
|
|
92
121
|
* Returns null if the session doesn't exist, is expired, or has no email.
|
|
93
122
|
*/
|
|
94
123
|
export declare function getSessionEmail(token: string): Promise<string | null>;
|
|
124
|
+
export interface DesktopExchangeErrorPayload {
|
|
125
|
+
message: string;
|
|
126
|
+
code?: string;
|
|
127
|
+
accountId?: string;
|
|
128
|
+
existingOwner?: string;
|
|
129
|
+
attemptedOwner?: string;
|
|
130
|
+
}
|
|
95
131
|
export declare function setDesktopExchange(flowId: string, token: string, email: string): void;
|
|
132
|
+
export declare function setDesktopExchangeError(flowId: string, error: DesktopExchangeErrorPayload): void;
|
|
96
133
|
/**
|
|
97
134
|
* Run the auth guard on an event. Returns a Response/object to block the
|
|
98
135
|
* request (login page or 401), or undefined to allow it through.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/server/auth.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAsChE,KAAK,KAAK,GAAG,SAAS,CAAC;AASvB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAuBlE;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAMD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mFAAmF;IACnF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC7D;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,SAAS,CAAC,EAAE;QACV,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;IACF;;OAEG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B;AAqBD,eAAO,MAAM,WAAW,QAER,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/server/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/server/auth.js
CHANGED
|
@@ -79,6 +79,16 @@ const APP_NAME_SLUG = (process.env.APP_NAME || "")
|
|
|
79
79
|
export const COOKIE_NAME = APP_NAME_SLUG
|
|
80
80
|
? `an_session_${APP_NAME_SLUG}`
|
|
81
81
|
: "an_session";
|
|
82
|
+
function getOAuthStateAppId() {
|
|
83
|
+
const raw = process.env.APP_NAME || process.env.npm_package_name;
|
|
84
|
+
if (!raw)
|
|
85
|
+
return undefined;
|
|
86
|
+
const slug = raw
|
|
87
|
+
.toLowerCase()
|
|
88
|
+
.replace(/[^a-z0-9-]+/g, "-")
|
|
89
|
+
.replace(/^-+|-+$/g, "");
|
|
90
|
+
return slug || undefined;
|
|
91
|
+
}
|
|
82
92
|
const DEFAULT_MAX_AGE = 60 * 60 * 24 * 30; // 30 days
|
|
83
93
|
const LOCAL_MODE_MARKER_PATH = path.resolve(process.cwd(), ".agent-native", "auth-mode");
|
|
84
94
|
// ---------------------------------------------------------------------------
|
|
@@ -359,16 +369,17 @@ export async function getSessionEmail(token) {
|
|
|
359
369
|
let customGetSession = null;
|
|
360
370
|
let authDisabledMode = false;
|
|
361
371
|
let _authGuardConfig = null;
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
372
|
+
const _genericGoogleOAuthRoutesEnabled = new WeakMap();
|
|
373
|
+
function setGenericGoogleOAuthRoutesEnabled(app, enabled) {
|
|
374
|
+
if (app && typeof app === "object") {
|
|
375
|
+
_genericGoogleOAuthRoutesEnabled.set(app, enabled);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
function areGenericGoogleOAuthRoutesEnabled(app) {
|
|
379
|
+
return _genericGoogleOAuthRoutesEnabled.get(app) !== false;
|
|
380
|
+
}
|
|
371
381
|
const _desktopExchanges = new Map();
|
|
382
|
+
const DESKTOP_EXCHANGE_ERROR_PREFIX = "__error__::";
|
|
372
383
|
// 5-minute TTL for exchange entries (short — single-use tokens).
|
|
373
384
|
const DESKTOP_EXCHANGE_TTL_MS = 5 * 60 * 1000;
|
|
374
385
|
export function setDesktopExchange(flowId, token, email) {
|
|
@@ -382,6 +393,13 @@ export function setDesktopExchange(flowId, token, email) {
|
|
|
382
393
|
// callback path).
|
|
383
394
|
void persistDesktopExchangeToDB(flowId, token, email);
|
|
384
395
|
}
|
|
396
|
+
export function setDesktopExchangeError(flowId, error) {
|
|
397
|
+
_desktopExchanges.set(flowId, {
|
|
398
|
+
error,
|
|
399
|
+
expiresAt: Date.now() + DESKTOP_EXCHANGE_TTL_MS,
|
|
400
|
+
});
|
|
401
|
+
void persistDesktopExchangeErrorToDB(flowId, error);
|
|
402
|
+
}
|
|
385
403
|
/**
|
|
386
404
|
* Persist a desktop exchange entry to the sessions table so it survives
|
|
387
405
|
* cross-instance routing (e.g. Cloudflare Workers). Stored under a synthetic
|
|
@@ -398,6 +416,15 @@ async function persistDesktopExchangeToDB(flowId, token, email) {
|
|
|
398
416
|
// non-fatal — in-memory Map is the primary path
|
|
399
417
|
}
|
|
400
418
|
}
|
|
419
|
+
async function persistDesktopExchangeErrorToDB(flowId, error) {
|
|
420
|
+
try {
|
|
421
|
+
const payload = Buffer.from(JSON.stringify(error)).toString("base64url");
|
|
422
|
+
await addSession(`dex:${flowId}`, `${DESKTOP_EXCHANGE_ERROR_PREFIX}${payload}`);
|
|
423
|
+
}
|
|
424
|
+
catch {
|
|
425
|
+
// non-fatal — in-memory Map is the primary path
|
|
426
|
+
}
|
|
427
|
+
}
|
|
401
428
|
/**
|
|
402
429
|
* Retrieve and consume a desktop exchange entry from the DB fallback.
|
|
403
430
|
* Returns null if not found or already consumed.
|
|
@@ -420,6 +447,12 @@ async function consumeDesktopExchangeFromDB(flowId) {
|
|
|
420
447
|
const packed = (rows[0].email ?? rows[0][0]);
|
|
421
448
|
if (!packed)
|
|
422
449
|
return null;
|
|
450
|
+
if (packed.startsWith(DESKTOP_EXCHANGE_ERROR_PREFIX)) {
|
|
451
|
+
const raw = packed.slice(DESKTOP_EXCHANGE_ERROR_PREFIX.length);
|
|
452
|
+
return {
|
|
453
|
+
error: JSON.parse(Buffer.from(raw, "base64url").toString()),
|
|
454
|
+
};
|
|
455
|
+
}
|
|
423
456
|
const sepIdx = packed.indexOf("::");
|
|
424
457
|
if (sepIdx === -1)
|
|
425
458
|
return null;
|
|
@@ -696,6 +729,9 @@ export async function getSession(event) {
|
|
|
696
729
|
catch {
|
|
697
730
|
// Better Auth not initialized yet
|
|
698
731
|
}
|
|
732
|
+
const querySession = await promoteQuerySession(event);
|
|
733
|
+
if (querySession)
|
|
734
|
+
return querySession;
|
|
699
735
|
return LOCAL_SESSION;
|
|
700
736
|
}
|
|
701
737
|
// 2. ACCESS_TOKEN check (programmatic/agent access)
|
|
@@ -767,20 +803,9 @@ export async function getSession(event) {
|
|
|
767
803
|
}
|
|
768
804
|
}
|
|
769
805
|
// 6. Mobile WebView bridge — _session query param
|
|
770
|
-
const
|
|
771
|
-
if (
|
|
772
|
-
|
|
773
|
-
if (email) {
|
|
774
|
-
setCookie(event, COOKIE_NAME, qToken, {
|
|
775
|
-
httpOnly: true,
|
|
776
|
-
...crossSiteCookieAttrs(event),
|
|
777
|
-
path: "/",
|
|
778
|
-
maxAge: sessionMaxAge,
|
|
779
|
-
});
|
|
780
|
-
setResponseHeader(event, "Referrer-Policy", "no-referrer");
|
|
781
|
-
return { email, token: qToken };
|
|
782
|
-
}
|
|
783
|
-
}
|
|
806
|
+
const querySession = await promoteQuerySession(event);
|
|
807
|
+
if (querySession)
|
|
808
|
+
return querySession;
|
|
784
809
|
// 7. Dev-mode safety net — in development on a local SQLite database, fall
|
|
785
810
|
// back to local@localhost so the app is usable without any auth configuration.
|
|
786
811
|
// This prevents 401 errors when Better Auth isn't configured, the marker file
|
|
@@ -809,6 +834,17 @@ export async function getSession(event) {
|
|
|
809
834
|
}
|
|
810
835
|
return null;
|
|
811
836
|
}
|
|
837
|
+
async function promoteQuerySession(event) {
|
|
838
|
+
const qToken = getQuery(event)?._session;
|
|
839
|
+
if (!qToken)
|
|
840
|
+
return null;
|
|
841
|
+
const email = await getSessionEmail(qToken);
|
|
842
|
+
if (!email)
|
|
843
|
+
return null;
|
|
844
|
+
setFrameworkSessionCookie(event, qToken);
|
|
845
|
+
setResponseHeader(event, "Referrer-Policy", "no-referrer");
|
|
846
|
+
return { email, token: qToken };
|
|
847
|
+
}
|
|
812
848
|
/**
|
|
813
849
|
* Cookie set by POST /_agent-native/auth/exit-local-mode so we know the user
|
|
814
850
|
* is in the middle of upgrading from local@localhost to a real account.
|
|
@@ -862,6 +898,14 @@ function crossSiteCookieAttrs(event) {
|
|
|
862
898
|
? { sameSite: "none", secure: true }
|
|
863
899
|
: { sameSite: "lax", secure: false };
|
|
864
900
|
}
|
|
901
|
+
function setFrameworkSessionCookie(event, token) {
|
|
902
|
+
setCookie(event, COOKIE_NAME, token, {
|
|
903
|
+
httpOnly: true,
|
|
904
|
+
...crossSiteCookieAttrs(event),
|
|
905
|
+
path: "/",
|
|
906
|
+
maxAge: sessionMaxAge,
|
|
907
|
+
});
|
|
908
|
+
}
|
|
865
909
|
function isHttpsRequest(event) {
|
|
866
910
|
try {
|
|
867
911
|
const req = event.req ?? event.node?.req;
|
|
@@ -1089,10 +1133,13 @@ async function mountBetterAuthRoutes(app, options) {
|
|
|
1089
1133
|
if (!publicPaths.includes(pp))
|
|
1090
1134
|
publicPaths.push(pp);
|
|
1091
1135
|
}
|
|
1092
|
-
// Auto-add Google OAuth routes when credentials are configured.
|
|
1093
|
-
//
|
|
1094
|
-
//
|
|
1095
|
-
if (process.env.GOOGLE_CLIENT_ID &&
|
|
1136
|
+
// Auto-add Google OAuth routes when credentials are configured. Templates
|
|
1137
|
+
// that need broader product scopes (mail/calendar) opt out and provide
|
|
1138
|
+
// their own Nitro routes at these paths.
|
|
1139
|
+
if (process.env.GOOGLE_CLIENT_ID &&
|
|
1140
|
+
process.env.GOOGLE_CLIENT_SECRET &&
|
|
1141
|
+
options.mountGoogleOAuthRoutes !== false) {
|
|
1142
|
+
setGenericGoogleOAuthRoutesEnabled(app, true);
|
|
1096
1143
|
for (const gp of [
|
|
1097
1144
|
"/_agent-native/google/callback",
|
|
1098
1145
|
"/_agent-native/google/auth-url",
|
|
@@ -1106,6 +1153,8 @@ async function mountBetterAuthRoutes(app, options) {
|
|
|
1106
1153
|
"https://www.googleapis.com/auth/userinfo.profile",
|
|
1107
1154
|
].join(" ");
|
|
1108
1155
|
app.use("/_agent-native/google/auth-url", defineEventHandler((event) => {
|
|
1156
|
+
if (!areGenericGoogleOAuthRoutesEnabled(app))
|
|
1157
|
+
return undefined;
|
|
1109
1158
|
if (getMethod(event) !== "GET") {
|
|
1110
1159
|
setResponseStatus(event, 405);
|
|
1111
1160
|
return { error: "Method not allowed" };
|
|
@@ -1130,7 +1179,14 @@ async function mountBetterAuthRoutes(app, options) {
|
|
|
1130
1179
|
const returnQuery = q.return;
|
|
1131
1180
|
const validated = typeof returnQuery === "string" ? safeReturnPath(returnQuery) : "/";
|
|
1132
1181
|
const returnUrl = validated !== "/" ? validated : undefined;
|
|
1133
|
-
const state = encodeOAuthState(
|
|
1182
|
+
const state = encodeOAuthState({
|
|
1183
|
+
redirectUri,
|
|
1184
|
+
desktop,
|
|
1185
|
+
addAccount: false,
|
|
1186
|
+
app: getOAuthStateAppId(),
|
|
1187
|
+
returnUrl,
|
|
1188
|
+
flowId,
|
|
1189
|
+
});
|
|
1134
1190
|
const params = new URLSearchParams({
|
|
1135
1191
|
client_id: process.env.GOOGLE_CLIENT_ID,
|
|
1136
1192
|
redirect_uri: redirectUri,
|
|
@@ -1147,6 +1203,8 @@ async function mountBetterAuthRoutes(app, options) {
|
|
|
1147
1203
|
return { url: authUrl };
|
|
1148
1204
|
}));
|
|
1149
1205
|
app.use("/_agent-native/google/callback", defineEventHandler(async (event) => {
|
|
1206
|
+
if (!areGenericGoogleOAuthRoutesEnabled(app))
|
|
1207
|
+
return undefined;
|
|
1150
1208
|
if (getMethod(event) !== "GET") {
|
|
1151
1209
|
setResponseStatus(event, 405);
|
|
1152
1210
|
return { error: "Method not allowed" };
|
|
@@ -1253,21 +1311,39 @@ async function mountBetterAuthRoutes(app, options) {
|
|
|
1253
1311
|
if (!fromDb) {
|
|
1254
1312
|
return { pending: true };
|
|
1255
1313
|
}
|
|
1256
|
-
entry =
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1314
|
+
entry =
|
|
1315
|
+
"error" in fromDb
|
|
1316
|
+
? { error: fromDb.error, expiresAt: Date.now() + 1 }
|
|
1317
|
+
: {
|
|
1318
|
+
token: fromDb.token,
|
|
1319
|
+
email: fromDb.email,
|
|
1320
|
+
expiresAt: Date.now() + 1,
|
|
1321
|
+
};
|
|
1261
1322
|
}
|
|
1262
1323
|
_desktopExchanges.delete(flowId);
|
|
1263
1324
|
// Also wipe the DB-persisted entry so it cannot be replayed via the
|
|
1264
1325
|
// DB fallback path after in-memory consumption.
|
|
1265
1326
|
void removeSession(`dex:${flowId}`);
|
|
1327
|
+
if ("error" in entry) {
|
|
1328
|
+
return { error: entry.error.message, ...entry.error };
|
|
1329
|
+
}
|
|
1330
|
+
// Make the exchange itself establish the app session. Older clients
|
|
1331
|
+
// still make a follow-up /auth/session?_session=... request, but the
|
|
1332
|
+
// OAuth handoff should not depend on that second request succeeding.
|
|
1333
|
+
setFrameworkSessionCookie(event, entry.token);
|
|
1334
|
+
setResponseHeader(event, "Referrer-Policy", "no-referrer");
|
|
1266
1335
|
return { token: entry.token, email: entry.email };
|
|
1267
1336
|
}));
|
|
1268
1337
|
const accessTokens = getAccessTokens();
|
|
1269
|
-
// Initialize Better Auth
|
|
1270
|
-
|
|
1338
|
+
// Initialize Better Auth. Forward `googleScopes` into the BetterAuthConfig
|
|
1339
|
+
// so the social provider requests the broader product scopes (Gmail,
|
|
1340
|
+
// Calendar, etc.) up front during the primary sign-in — eliminating the
|
|
1341
|
+
// need for a separate "Connect Google" page.
|
|
1342
|
+
const betterAuthConfig = {
|
|
1343
|
+
...(options.betterAuth ?? {}),
|
|
1344
|
+
...(options.googleScopes ? { googleScopes: options.googleScopes } : {}),
|
|
1345
|
+
};
|
|
1346
|
+
const auth = await getBetterAuth(betterAuthConfig);
|
|
1271
1347
|
// Mount Better Auth catch-all handler at /_agent-native/auth/ba/*
|
|
1272
1348
|
app.use("/_agent-native/auth/ba", defineEventHandler(async (event) => {
|
|
1273
1349
|
const reqPath = event.url?.pathname ?? event.path ?? "";
|
|
@@ -1924,6 +2000,9 @@ export async function autoMountAuth(app, options = {}) {
|
|
|
1924
2000
|
// H3 app, empty middleware) would short-circuit here and end up with no
|
|
1925
2001
|
// auth routes mounted at all.
|
|
1926
2002
|
if (_authGuardFn && _mountedApp === app) {
|
|
2003
|
+
if (options.mountGoogleOAuthRoutes === false) {
|
|
2004
|
+
setGenericGoogleOAuthRoutesEnabled(app, false);
|
|
2005
|
+
}
|
|
1927
2006
|
// A custom getSession always wins — even if the default auth plugin
|
|
1928
2007
|
// mounted first (which happens in production where bootstrapDefaultPlugins
|
|
1929
2008
|
// can't see the template's server/plugins/ dir and auto-mounts defaults).
|