@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.
- 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/app/components/calendar/CreateEventDialog.tsx +36 -47
- package/corpus/templates/calendar/app/components/calendar/DayView.tsx +3 -0
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +18 -1
- package/corpus/templates/calendar/app/components/calendar/InlineEventPickers.tsx +256 -38
- package/corpus/templates/calendar/app/hooks/use-google-auth.ts +43 -3
- package/corpus/templates/calendar/app/i18n-data.ts +120 -0
- package/corpus/templates/calendar/app/lib/event-form-utils.ts +113 -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/handlers/google-auth.ts +119 -3
- package/corpus/templates/calendar/server/lib/event-weekday.ts +112 -0
- package/corpus/templates/calendar/server/routes/[base]/_agent-native/google/add-account/auth-url.post.ts +1 -0
- package/corpus/templates/calendar/server/routes/[base]/_agent-native/google/auth-url.post.ts +1 -0
- package/corpus/templates/calendar/server/routes/_agent-native/google/add-account/auth-url.post.ts +1 -0
- package/corpus/templates/calendar/server/routes/_agent-native/google/auth-url.post.ts +1 -0
- package/corpus/templates/clips/app/components/player/video-player.tsx +12 -0
- package/corpus/templates/clips/app/routes/_app.dictate.tsx +18 -4
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +114 -20
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +83 -78
- package/corpus/templates/clips/changelog/2026-08-19-clips-nightly-builds-are-available-for-trying-the-latest-upd.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-19-social-preview-video-frames.md +1 -0
- package/corpus/templates/clips/desktop/README.md +19 -4
- package/corpus/templates/clips/desktop/src/app.tsx +78 -16
- package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +3 -2
- package/corpus/templates/clips/desktop/src-tauri/tauri.conf.json +1 -0
- package/corpus/templates/clips/server/routes/[base]/_agent-native/google/auth-url.post.ts +1 -0
- package/corpus/templates/clips/server/routes/_agent-native/google/auth-url.get.ts +41 -3
- package/corpus/templates/clips/server/routes/_agent-native/google/auth-url.post.ts +1 -0
- package/corpus/templates/clips/server/routes/_agent-native/google/callback.get.ts +22 -1
- package/corpus/templates/clips/server/routes/api/clips-updater.json.get.ts +41 -22
- package/corpus/templates/factory/AGENTS.md +3 -2
- package/corpus/templates/factory/actions/get-factory-graph-version.ts +69 -0
- package/corpus/templates/factory/actions/list-factory-automations.ts +4 -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/actions/start-builder-for-item.ts +19 -17
- package/corpus/templates/factory/app/components/factory/FactoryAuditView.tsx +100 -36
- 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 +47 -0
- package/corpus/templates/factory/app/routes/factory.tsx +324 -61
- package/corpus/templates/factory/server/connectors/slack.ts +44 -2
- package/corpus/templates/factory/server/plugins/agent-chat.ts +12 -8
- package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +13 -0
- package/corpus/templates/factory/server/triage/slack-client.ts +5 -0
- package/corpus/templates/factory/server/triage/slack-poller.ts +72 -4
- package/corpus/templates/mail/actions/view-screen.ts +1 -1
- package/corpus/templates/mail/app/components/GoogleConnectBanner.tsx +100 -18
- package/corpus/templates/mail/server/handlers/google-auth.ts +125 -24
- package/corpus/templates/mail/server/lib/gmail-query.ts +5 -2
- package/corpus/templates/mail/server/routes/[base]/_agent-native/google/add-account/auth-url.post.ts +1 -0
- package/corpus/templates/mail/server/routes/[base]/_agent-native/google/auth-url.post.ts +1 -0
- package/corpus/templates/mail/server/routes/_agent-native/google/add-account/auth-url.post.ts +1 -0
- package/corpus/templates/mail/server/routes/_agent-native/google/auth-url.post.ts +1 -0
- package/corpus/templates/plan/app/pages/PlansPage.tsx +0 -12
- package/corpus/templates/plan/changelog/2026-08-19-plan-prompts-now-guide-you-to-connect-ai-before-sending-and-.md +6 -0
- package/corpus/templates/slides/actions/approve-deck-access-request.ts +234 -0
- package/corpus/templates/slides/actions/get-deck-access-status.ts +35 -2
- package/corpus/templates/slides/actions/request-deck-access.ts +263 -64
- package/corpus/templates/slides/app/components/editor/MissingDeckAccessPane.tsx +196 -0
- package/corpus/templates/slides/app/components/editor/RequestDeckAccessDialog.tsx +101 -0
- package/corpus/templates/slides/app/hooks/use-deck-access.ts +7 -4
- package/corpus/templates/slides/app/i18n/en-US.ts +29 -6
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +147 -169
- package/corpus/templates/slides/app/routes/access-request.approve.tsx +250 -0
- package/corpus/templates/slides/server/db/schema.ts +8 -0
- package/corpus/templates/slides/server/lib/access-request-email.ts +36 -0
- package/corpus/templates/slides/server/lib/emails.ts +26 -0
- package/corpus/templates/slides/server/plugins/agent-chat.ts +7 -0
- package/corpus/templates/slides/server/plugins/db.ts +50 -0
- package/corpus/templates/slides/shared/deck-access.ts +31 -0
- package/dist/a2a/task-store.d.ts +1 -0
- package/dist/a2a/task-store.js +1 -1
- package/dist/agent/observational-memory/store.d.ts +1 -0
- package/dist/agent/observational-memory/store.js +1 -1
- package/dist/agent/run-store.d.ts +1 -0
- package/dist/agent/run-store.js +1 -1
- package/dist/agent/tool-approval-store.d.ts +1 -0
- package/dist/agent/tool-approval-store.js +1 -1
- package/dist/application-state/store.d.ts +1 -0
- package/dist/application-state/store.js +1 -1
- package/dist/browser-sessions/store.d.ts +1 -0
- package/dist/browser-sessions/store.js +1 -1
- package/dist/checkpoints/store.d.ts +1 -0
- package/dist/checkpoints/store.js +1 -1
- package/dist/cli/code-agent-schedules.d.ts +11 -0
- package/dist/cli/code-agent-schedules.js +44 -5
- package/dist/client/AgentPanel.d.ts +5 -1
- package/dist/client/AgentPanel.js +2 -2
- package/dist/client/AssistantChat.d.ts +5 -1
- package/dist/client/AssistantChat.js +40 -6
- package/dist/client/EnvironmentBadge.d.ts +7 -13
- package/dist/client/EnvironmentBadge.js +43 -92
- package/dist/client/agent-chat/index.d.ts +1 -0
- package/dist/client/agent-chat/index.js +1 -0
- package/dist/client/agent-chat-adapter.js +76 -50
- package/dist/client/app-providers.js +4 -4
- package/dist/client/chat/message-components.d.ts +4 -0
- package/dist/client/chat/message-components.js +28 -1
- package/dist/client/chat/run-recovery.js +26 -0
- package/dist/client/chat-first/apps-rail.d.ts +1 -0
- package/dist/client/chat-first/apps-rail.js +28 -2
- package/dist/client/sse-event-processor.js +13 -8
- package/dist/client/use-active-agent-chat-run.d.ts +2 -0
- package/dist/client/use-active-agent-chat-run.js +22 -0
- package/dist/coding-tools/sandbox/executions-store.d.ts +1 -0
- package/dist/coding-tools/sandbox/executions-store.js +1 -1
- package/dist/collab/awareness-store.d.ts +1 -0
- package/dist/collab/awareness-store.js +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/storage.d.ts +1 -0
- package/dist/collab/storage.js +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/db/client.js +3 -3
- package/dist/db/ddl-guard.js +8 -0
- package/dist/db/migration-runtime.d.ts +23 -0
- package/dist/db/migration-runtime.js +41 -0
- package/dist/db/migrations.d.ts +1 -2
- package/dist/db/migrations.js +2 -24
- package/dist/email-catalog/log.d.ts +1 -0
- package/dist/email-catalog/log.js +1 -1
- package/dist/guards/index.d.ts +1 -0
- package/dist/guards/index.js +1 -0
- package/dist/guards/release-schema-complete.d.ts +22 -0
- package/dist/guards/release-schema-complete.js +144 -0
- package/dist/integrations/a2a-continuations-store.d.ts +1 -0
- package/dist/integrations/a2a-continuations-store.js +1 -1
- package/dist/integrations/awaiting-input-store.d.ts +1 -0
- package/dist/integrations/awaiting-input-store.js +1 -1
- package/dist/integrations/config-store.d.ts +1 -0
- package/dist/integrations/config-store.js +1 -1
- package/dist/integrations/controls-store.d.ts +1 -0
- package/dist/integrations/controls-store.js +1 -1
- package/dist/integrations/identity-links-store.d.ts +1 -0
- package/dist/integrations/identity-links-store.js +1 -1
- package/dist/integrations/installations-store.d.ts +1 -0
- package/dist/integrations/installations-store.js +1 -1
- package/dist/integrations/remote-commands-store.d.ts +1 -0
- package/dist/integrations/remote-commands-store.js +1 -1
- package/dist/integrations/remote-devices-store.d.ts +1 -0
- package/dist/integrations/remote-devices-store.js +1 -1
- package/dist/integrations/remote-push-store.d.ts +1 -0
- package/dist/integrations/remote-push-store.js +1 -1
- package/dist/integrations/remote-run-events-store.d.ts +1 -0
- package/dist/integrations/remote-run-events-store.js +1 -1
- package/dist/integrations/scope-store.d.ts +1 -0
- package/dist/integrations/scope-store.js +1 -1
- package/dist/integrations/thread-mapping-store.d.ts +1 -0
- package/dist/integrations/thread-mapping-store.js +1 -1
- package/dist/integrations/usage-budget-store.d.ts +1 -0
- package/dist/integrations/usage-budget-store.js +1 -1
- package/dist/jobs/background-automation-runner.js +111 -9
- package/dist/jobs/run-history.d.ts +1 -0
- package/dist/jobs/run-history.js +1 -1
- package/dist/jobs/scheduler-health.d.ts +1 -0
- package/dist/jobs/scheduler-health.js +1 -1
- package/dist/mcp/approval-store.d.ts +1 -0
- package/dist/mcp/approval-store.js +1 -1
- package/dist/mcp/connect-store.d.ts +1 -0
- package/dist/mcp/connect-store.js +1 -1
- package/dist/mcp/oauth-store.d.ts +1 -0
- package/dist/mcp/oauth-store.js +1 -1
- package/dist/notifications/store.d.ts +1 -0
- package/dist/notifications/store.js +1 -1
- package/dist/oauth-tokens/store.d.ts +1 -0
- package/dist/oauth-tokens/store.js +1 -1
- package/dist/observability/routes.d.ts +5 -5
- package/dist/progress/routes.d.ts +1 -1
- package/dist/progress/store.d.ts +1 -0
- package/dist/progress/store.js +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +5 -5
- package/dist/provider-api/actions/provider-api.d.ts +4 -4
- package/dist/provider-api/corpus-jobs-store.d.ts +1 -0
- package/dist/provider-api/corpus-jobs-store.js +1 -1
- package/dist/provider-api/custom-registry.d.ts +1 -0
- package/dist/provider-api/custom-registry.js +1 -1
- package/dist/provider-api/quota-governor.d.ts +1 -0
- package/dist/provider-api/quota-governor.js +1 -1
- package/dist/provider-api/staged-datasets-store.d.ts +1 -0
- package/dist/provider-api/staged-datasets-store.js +1 -1
- package/dist/resources/handlers.d.ts +3 -3
- package/dist/resources/store.d.ts +1 -0
- package/dist/resources/store.js +1 -1
- package/dist/scripts/dev/index.js +15 -1
- package/dist/search/index.js +3 -0
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/secrets/storage.d.ts +1 -0
- package/dist/secrets/storage.js +1 -1
- package/dist/server/agent-chat-plugin.js +38 -9
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-teams-run-queue.d.ts +1 -0
- package/dist/server/agent-teams-run-queue.js +1 -1
- package/dist/server/auth-marketing.js +3 -1
- package/dist/server/auth.d.ts +18 -1
- package/dist/server/auth.js +370 -154
- package/dist/server/embed-session.d.ts +1 -0
- package/dist/server/embed-session.js +1 -1
- package/dist/server/google-auth-plugin.js +3 -1
- package/dist/server/google-oauth.d.ts +10 -0
- package/dist/server/google-oauth.js +25 -1
- package/dist/server/identity-sso-store.d.ts +1 -0
- package/dist/server/identity-sso-store.js +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/onboarding-html.js +200 -31
- package/dist/server/poll.d.ts +2 -0
- package/dist/server/poll.js +19 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/release-migrations.js +5 -0
- package/dist/server/release-schema.d.ts +46 -0
- package/dist/server/release-schema.js +307 -0
- package/dist/settings/store.d.ts +1 -0
- package/dist/settings/store.js +1 -1
- package/dist/shared/environment-lanes.d.ts +28 -0
- package/dist/shared/environment-lanes.js +61 -0
- package/dist/sharing/actions/share-resource.js +22 -2
- package/dist/styles/agent-native.css +17 -15
- package/dist/triggers/routes.d.ts +11 -0
- package/dist/triggers/routes.js +10 -0
- package/dist/usage/alerts-store.d.ts +1 -0
- package/dist/usage/alerts-store.js +1 -1
- package/dist/usage/store.d.ts +1 -0
- package/dist/usage/store.js +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 +2 -2
- package/docs/content/agents.mdx +0 -9
- package/docs/content/database.mdx +0 -317
- package/docs/content/human-approval.mdx +0 -156
|
@@ -66,6 +66,7 @@ export type ResolvedEmbedSession = {
|
|
|
66
66
|
*/
|
|
67
67
|
export declare function isEmbedCapabilityScope(scope: string | undefined | null): boolean;
|
|
68
68
|
export declare function resolvedEmbedCapabilityScope(session: ResolvedEmbedSession | null): string | undefined;
|
|
69
|
+
export declare function ensureTable(): Promise<void>;
|
|
69
70
|
export declare function requestMatchesEmbedTarget(event: H3Event, targetPath: string): boolean;
|
|
70
71
|
export declare function normalizeEmbedTargetPath(raw: string | undefined | null, requestOrigin?: string): string | null;
|
|
71
72
|
export declare function createEmbedSessionTicket(input: EmbedSessionTicketInput): Promise<EmbedSessionTicket>;
|
|
@@ -69,7 +69,7 @@ export function resolvedEmbedCapabilityScope(session) {
|
|
|
69
69
|
}
|
|
70
70
|
return scope;
|
|
71
71
|
}
|
|
72
|
-
async function ensureTable() {
|
|
72
|
+
export async function ensureTable() {
|
|
73
73
|
if (!_initPromise) {
|
|
74
74
|
_initPromise = (async () => {
|
|
75
75
|
// Build the CREATE SQL here (not at module scope) so intType() runs at
|
|
@@ -32,7 +32,9 @@ export function createGoogleAuthPlugin(options) {
|
|
|
32
32
|
// `window.location.href = ret || '/'` where `ret` was the sign-in page
|
|
33
33
|
// itself — sign in, land back on the sign-in page, click sign in again.
|
|
34
34
|
// Every anti-loop fix ever shipped landed on whichever copy the ticket
|
|
35
|
-
// named. Do not reintroduce a second producer of `loginHtml`.
|
|
35
|
+
// named. Do not reintroduce a second producer of `loginHtml`. Keeping this
|
|
36
|
+
// producer shared also keeps the verifier-bound desktop OAuth POST
|
|
37
|
+
// bootstrap in Google-only plugin pages.
|
|
36
38
|
loginHtml: getOnboardingHtml({
|
|
37
39
|
googleOnly: true,
|
|
38
40
|
googleAuthMode: options?.googleAuthMode,
|
|
@@ -106,6 +106,12 @@ export interface OAuthStatePayload {
|
|
|
106
106
|
*/
|
|
107
107
|
returnUrl?: string;
|
|
108
108
|
flowId?: string;
|
|
109
|
+
/** Hash of the client-held verifier binding a desktop exchange to its initiator. */
|
|
110
|
+
desktopVerifierHash?: string;
|
|
111
|
+
/** Hash of the initiating browser binding for a desktop OAuth exchange. */
|
|
112
|
+
desktopBrowserBindingHash?: string;
|
|
113
|
+
/** Complete the callback in the already-bound native WebView. */
|
|
114
|
+
desktopWebview?: boolean;
|
|
109
115
|
signupAttribution?: Record<string, string | undefined>;
|
|
110
116
|
signupAnonymousId?: string;
|
|
111
117
|
}
|
|
@@ -125,6 +131,9 @@ export interface EncodeOAuthStateOptions {
|
|
|
125
131
|
app?: string;
|
|
126
132
|
returnUrl?: string;
|
|
127
133
|
flowId?: string;
|
|
134
|
+
desktopVerifierHash?: string;
|
|
135
|
+
desktopBrowserBindingHash?: string;
|
|
136
|
+
desktopWebview?: boolean;
|
|
128
137
|
signupAttribution?: Record<string, string | undefined>;
|
|
129
138
|
signupAnonymousId?: string;
|
|
130
139
|
}
|
|
@@ -202,6 +211,7 @@ export declare function oauthCallbackResponse(event: H3Event, email: string, opt
|
|
|
202
211
|
returnUrl?: string;
|
|
203
212
|
flowId?: string;
|
|
204
213
|
appName?: string;
|
|
214
|
+
desktopWebview?: boolean;
|
|
205
215
|
}): Response | string | unknown | Promise<Response | string | unknown>;
|
|
206
216
|
/** HTML error page for OAuth failures. The message is HTML-escaped — most
|
|
207
217
|
* callers pass `error.message` from a token-exchange or userinfo failure,
|
|
@@ -12,7 +12,7 @@ import { normalizeAnalyticsAnonymousId } from "../shared/analytics-anonymous-id.
|
|
|
12
12
|
import { getAppBasePathFromViteEnv } from "./app-base-path.js";
|
|
13
13
|
import { getAppName } from "./app-name.js";
|
|
14
14
|
import { readAnalyticsAnonymousId, signupAttributionFromCookieHeader, } from "./attribution.js";
|
|
15
|
-
import { addSession, getSession, getSessionMaxAge, hasLegacySessionForEmail, setFrameworkSessionCookie, } from "./auth.js";
|
|
15
|
+
import { addSession, getSession, getSessionMaxAge, hasLegacySessionForEmail, safeReturnPath, setFrameworkSessionCookie, } from "./auth.js";
|
|
16
16
|
import { hasBetterAuthUserEmail, trackSignupEvent, } from "./better-auth-instance.js";
|
|
17
17
|
import { getWorkspaceA2ADerivedSecret } from "./derived-secret.js";
|
|
18
18
|
import { writeDesktopSso } from "./desktop-sso.js";
|
|
@@ -463,6 +463,12 @@ export function encodeOAuthState(redirectUriOrOpts, owner, desktop, addAccount,
|
|
|
463
463
|
payload.r2 = opts.returnUrl;
|
|
464
464
|
if (opts.flowId)
|
|
465
465
|
payload.f = opts.flowId;
|
|
466
|
+
if (opts.desktopVerifierHash)
|
|
467
|
+
payload.vh = opts.desktopVerifierHash;
|
|
468
|
+
if (opts.desktopBrowserBindingHash)
|
|
469
|
+
payload.bh = opts.desktopBrowserBindingHash;
|
|
470
|
+
if (opts.desktopWebview)
|
|
471
|
+
payload.dw = true;
|
|
466
472
|
if (opts.signupAttribution)
|
|
467
473
|
payload.ft = opts.signupAttribution;
|
|
468
474
|
const signupAnonymousId = normalizeAnalyticsAnonymousId(opts.signupAnonymousId);
|
|
@@ -511,6 +517,9 @@ export function decodeOAuthState(stateParam, fallbackUri) {
|
|
|
511
517
|
// depth in case the signing key ever leaks.
|
|
512
518
|
returnUrl: typeof parsed.r2 === "string" ? parsed.r2 : undefined,
|
|
513
519
|
flowId: parsed.f || undefined,
|
|
520
|
+
desktopVerifierHash: typeof parsed.vh === "string" ? parsed.vh : undefined,
|
|
521
|
+
desktopBrowserBindingHash: typeof parsed.bh === "string" ? parsed.bh : undefined,
|
|
522
|
+
desktopWebview: parsed.dw === true,
|
|
514
523
|
signupAttribution: sanitizeStateAttribution(parsed.ft),
|
|
515
524
|
signupAnonymousId: sanitizeStateAnonymousId(parsed.ai),
|
|
516
525
|
};
|
|
@@ -628,6 +637,21 @@ export function oauthCallbackResponse(event, email, opts) {
|
|
|
628
637
|
if (opts.desktop && opts.flowId && isElectron(event) && opts.sessionToken) {
|
|
629
638
|
return desktopSuccessPage(event, email, opts.sessionToken, callbackState);
|
|
630
639
|
}
|
|
640
|
+
// A Tauri WebView cannot share cookies with the system browser or another
|
|
641
|
+
// Tauri WebviewWindow. When the callback stays in the initiating WebView,
|
|
642
|
+
// createOAuthSession has already staged its session cookie on this event;
|
|
643
|
+
// carry that cookie onto the HTML response before returning to the app.
|
|
644
|
+
if (opts.desktop && opts.flowId && opts.desktopWebview) {
|
|
645
|
+
const returnPath = safeReturnPath(opts.returnUrl);
|
|
646
|
+
const headers = new Headers({
|
|
647
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
648
|
+
"Referrer-Policy": "no-referrer",
|
|
649
|
+
});
|
|
650
|
+
for (const cookie of event.res?.headers?.getSetCookie?.() ?? []) {
|
|
651
|
+
headers.append("set-cookie", cookie);
|
|
652
|
+
}
|
|
653
|
+
return new Response(`<!DOCTYPE html><html><head><meta charset="utf-8"><title>Connected</title></head><body style="background:Canvas;color:CanvasText;font-family:system-ui;display:flex;align-items:center;justify-content:center;height:100vh;margin:0"><p>Connected! Returning to Clips…</p><script>setTimeout(function(){window.location.replace(${JSON.stringify(returnPath)})},50)</script></body></html>`, { status: 200, headers });
|
|
654
|
+
}
|
|
631
655
|
// Desktop exchange flow (non-Electron tray app): the tray app polls the
|
|
632
656
|
// desktop-exchange endpoint for the token — no deep link needed.
|
|
633
657
|
if (opts.desktop && opts.flowId) {
|
|
@@ -54,6 +54,7 @@ export interface SsoStateConsumeResult {
|
|
|
54
54
|
ok: boolean;
|
|
55
55
|
returnPath: string | null;
|
|
56
56
|
}
|
|
57
|
+
export declare function ensureTable(): Promise<void>;
|
|
57
58
|
/** Mint and persist a bound, crypto-random state value. */
|
|
58
59
|
export declare function createSsoState(input: CreateSsoStateInput): Promise<string>;
|
|
59
60
|
/**
|
|
@@ -188,7 +188,7 @@ function buildIdentitySsoJtiCreateSql() {
|
|
|
188
188
|
)
|
|
189
189
|
`;
|
|
190
190
|
}
|
|
191
|
-
async function ensureTable() {
|
|
191
|
+
export async function ensureTable() {
|
|
192
192
|
// Release migrations own schema in production serverless functions. A
|
|
193
193
|
// request must not turn a missing migration into request-time DDL.
|
|
194
194
|
if (isProductionServerlessFunctionRuntime())
|
package/dist/server/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export { createOpenRouteHandler, type OpenRouteOptions } from "./open-route.js";
|
|
|
8
8
|
export { createEmbedStartRouteHandler, buildEmbedStartPath, type EmbedStartRouteOptions, } from "./embed-route.js";
|
|
9
9
|
export { createEmbedSessionTicket, consumeEmbedSessionTicket, normalizeEmbedTargetPath, requestHasEmbedAuthMarker, resolveEmbedSessionFromRequest, setEmbedSessionCookie, signEmbedSessionToken, verifyEmbedSessionToken, type ConsumedEmbedSessionTicket, type ConsumeEmbedSessionTicketOptions, type EmbedSessionTicket, type EmbedSessionTicketInput, type EmbedSessionTokenClaims, type ResolvedEmbedSession, type VerifyEmbedSessionTokenResult, } from "./embed-session.js";
|
|
10
10
|
export { createSSEHandler, type SSEHandlerOptions } from "./sse.js";
|
|
11
|
-
export { mountAuthMiddleware, autoMountAuth, registerAuthPublicPaths, getSession, COOKIE_NAME, addSession, removeSession, getSessionEmail, getFrameworkSessionCookieValues, setFrameworkSessionCookie, clearFrameworkSessionCookies, runAuthGuard, setDesktopExchange, setDesktopExchangeError, safeReturnPath, type DesktopExchangeErrorPayload, type AuthSession, type AuthOptions, } from "./auth.js";
|
|
11
|
+
export { mountAuthMiddleware, autoMountAuth, registerAuthPublicPaths, getSession, COOKIE_NAME, addSession, removeSession, getSessionEmail, getFrameworkSessionCookieValues, setFrameworkSessionCookie, clearFrameworkSessionCookies, runAuthGuard, registerDesktopExchange, prepareDesktopOAuthBrowserBinding, matchesDesktopOAuthBrowserBinding, DESKTOP_OAUTH_BROWSER_BINDING_COOKIE, setDesktopExchange, setDesktopExchangeError, safeReturnPath, type DesktopExchangeErrorPayload, type AuthSession, type AuthOptions, } from "./auth.js";
|
|
12
12
|
export { handleIdentitySso, getIdentityHubUrl, isIdentitySsoEnabled, isIdentitySsoBypassPath, identitySsoLoginButtonHtml, IDENTITY_SSO_PROVIDER_ID, IDENTITY_SSO_SCOPE, IDENTITY_SSO_DESKTOP_COMPLETE_PATH, } from "./identity-sso.js";
|
|
13
13
|
export { hasGoogleAuthIdentity } from "./better-auth-instance.js";
|
|
14
14
|
export { requireEnvKey, type MissingKeyResponse } from "./missing-key.js";
|
package/dist/server/index.js
CHANGED
|
@@ -8,7 +8,7 @@ export { createOpenRouteHandler } from "./open-route.js";
|
|
|
8
8
|
export { createEmbedStartRouteHandler, buildEmbedStartPath, } from "./embed-route.js";
|
|
9
9
|
export { createEmbedSessionTicket, consumeEmbedSessionTicket, normalizeEmbedTargetPath, requestHasEmbedAuthMarker, resolveEmbedSessionFromRequest, setEmbedSessionCookie, signEmbedSessionToken, verifyEmbedSessionToken, } from "./embed-session.js";
|
|
10
10
|
export { createSSEHandler } from "./sse.js";
|
|
11
|
-
export { mountAuthMiddleware, autoMountAuth, registerAuthPublicPaths, getSession, COOKIE_NAME, addSession, removeSession, getSessionEmail, getFrameworkSessionCookieValues, setFrameworkSessionCookie, clearFrameworkSessionCookies, runAuthGuard, setDesktopExchange, setDesktopExchangeError, safeReturnPath, } from "./auth.js";
|
|
11
|
+
export { mountAuthMiddleware, autoMountAuth, registerAuthPublicPaths, getSession, COOKIE_NAME, addSession, removeSession, getSessionEmail, getFrameworkSessionCookieValues, setFrameworkSessionCookie, clearFrameworkSessionCookies, runAuthGuard, registerDesktopExchange, prepareDesktopOAuthBrowserBinding, matchesDesktopOAuthBrowserBinding, DESKTOP_OAUTH_BROWSER_BINDING_COOKIE, setDesktopExchange, setDesktopExchangeError, safeReturnPath, } from "./auth.js";
|
|
12
12
|
export { handleIdentitySso, getIdentityHubUrl, isIdentitySsoEnabled, isIdentitySsoBypassPath, identitySsoLoginButtonHtml, IDENTITY_SSO_PROVIDER_ID, IDENTITY_SSO_SCOPE, IDENTITY_SSO_DESKTOP_COMPLETE_PATH, } from "./identity-sso.js";
|
|
13
13
|
export { hasGoogleAuthIdentity } from "./better-auth-instance.js";
|
|
14
14
|
export { requireEnvKey } from "./missing-key.js";
|
|
@@ -11,6 +11,7 @@ import { getLocaleInitScript } from "../localization/server.js";
|
|
|
11
11
|
import { DEFAULT_LOCALE, LOCALE_METADATA, LOCALE_STORAGE_KEY, SUPPORTED_LOCALES, localeDisplayName, } from "../localization/shared.js";
|
|
12
12
|
import { NATIVE_AUTH_COPY } from "../shared/auth-copy.js";
|
|
13
13
|
import { docsUrl } from "../shared/docs-url.js";
|
|
14
|
+
import { BETA_OPT_OUT_DURATION_MS, BETA_OPT_OUT_QUERY_PARAM, ENVIRONMENT_BETA_HOSTS, } from "../shared/environment-lanes.js";
|
|
14
15
|
import { PASSWORD_MAX_LENGTH, PASSWORD_MIN_LENGTH, } from "../shared/password-policy.js";
|
|
15
16
|
import { signInJourneyInlineScript } from "../shared/sign-in-journey.js";
|
|
16
17
|
import { AGENT_NATIVE_SOCIAL_IMAGE_ALT, AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT, AGENT_NATIVE_SOCIAL_IMAGE_PATH, AGENT_NATIVE_SOCIAL_IMAGE_TYPE, AGENT_NATIVE_SOCIAL_IMAGE_WIDTH, withAgentNativeSocialImageCacheBuster, } from "../shared/social-meta.js";
|
|
@@ -1026,6 +1027,15 @@ export function getOnboardingHtml(opts = {}) {
|
|
|
1026
1027
|
<div class="locale-menu" id="auth-locale-menu" role="menu" aria-labelledby="auth-locale-trigger" hidden>
|
|
1027
1028
|
${localeMenuItemsHtml}
|
|
1028
1029
|
</div>
|
|
1030
|
+
</div>`;
|
|
1031
|
+
const environmentBadgeHtml = `
|
|
1032
|
+
<div class="environment-switcher" id="environment-switcher" hidden>
|
|
1033
|
+
<button type="button" class="environment-badge" id="environment-badge" aria-expanded="false" aria-controls="environment-popover">beta</button>
|
|
1034
|
+
<div class="environment-popover" id="environment-popover" role="dialog" aria-labelledby="environment-popover-title" hidden>
|
|
1035
|
+
<div class="environment-popover-title" id="environment-popover-title">You're on Agent Native Beta</div>
|
|
1036
|
+
<div class="environment-popover-copy">Choose where you want to continue.</div>
|
|
1037
|
+
<a class="environment-production-link" id="environment-production-link" href="">Switch to production</a>
|
|
1038
|
+
</div>
|
|
1029
1039
|
</div>`;
|
|
1030
1040
|
const hostedSignupLegalNotice = opts.signupLegalNotice === undefined &&
|
|
1031
1041
|
isAgentNativeHostedHost(opts.requestHost)
|
|
@@ -1412,8 +1422,53 @@ ${marketing.description ? ` <p class="app-desc" data-marketing-field="descr
|
|
|
1412
1422
|
}
|
|
1413
1423
|
}
|
|
1414
1424
|
if (!reducedMotion) startAnimation();
|
|
1415
|
-
|
|
1425
|
+
})();`
|
|
1416
1426
|
: "";
|
|
1427
|
+
const environmentBadgeScript = `
|
|
1428
|
+
(function __anInitEnvironmentBadge() {
|
|
1429
|
+
var switcher = document.getElementById('environment-switcher');
|
|
1430
|
+
var button = document.getElementById('environment-badge');
|
|
1431
|
+
var popover = document.getElementById('environment-popover');
|
|
1432
|
+
var productionLink = document.getElementById('environment-production-link');
|
|
1433
|
+
if (!switcher || !button || !popover || !productionLink) return;
|
|
1434
|
+
if (window.parent !== window) return;
|
|
1435
|
+
|
|
1436
|
+
var betaHosts = ${JSON.stringify(ENVIRONMENT_BETA_HOSTS)};
|
|
1437
|
+
var hostname = (window.location.hostname || '').toLowerCase().replace(/\\.$/, '');
|
|
1438
|
+
var productionHost = hostname.indexOf('beta.') === 0 ? hostname.slice(5) : '';
|
|
1439
|
+
if (!productionHost || betaHosts[productionHost] !== hostname) return;
|
|
1440
|
+
|
|
1441
|
+
try {
|
|
1442
|
+
var productionUrl = new URL(window.location.href);
|
|
1443
|
+
productionUrl.protocol = 'https:';
|
|
1444
|
+
productionUrl.hostname = productionHost;
|
|
1445
|
+
productionUrl.port = '';
|
|
1446
|
+
productionUrl.searchParams.set(
|
|
1447
|
+
${JSON.stringify(BETA_OPT_OUT_QUERY_PARAM)},
|
|
1448
|
+
String(Date.now() + ${BETA_OPT_OUT_DURATION_MS}),
|
|
1449
|
+
);
|
|
1450
|
+
productionLink.href = productionUrl.toString();
|
|
1451
|
+
} catch (error) {
|
|
1452
|
+
void error;
|
|
1453
|
+
return;
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
function setOpen(open) {
|
|
1457
|
+
popover.hidden = !open;
|
|
1458
|
+
button.setAttribute('aria-expanded', String(open));
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
switcher.hidden = false;
|
|
1462
|
+
button.addEventListener('click', function() {
|
|
1463
|
+
setOpen(popover.hidden);
|
|
1464
|
+
});
|
|
1465
|
+
document.addEventListener('click', function(event) {
|
|
1466
|
+
if (!switcher.contains(event.target)) setOpen(false);
|
|
1467
|
+
});
|
|
1468
|
+
document.addEventListener('keydown', function(event) {
|
|
1469
|
+
if (event.key === 'Escape') setOpen(false);
|
|
1470
|
+
});
|
|
1471
|
+
})();`;
|
|
1417
1472
|
return `<!DOCTYPE html>
|
|
1418
1473
|
<html lang="${DEFAULT_LOCALE}" dir="ltr">
|
|
1419
1474
|
<head>
|
|
@@ -1553,6 +1608,69 @@ ${hasMarketing
|
|
|
1553
1608
|
.locale-menu-item[aria-checked="true"] .locale-menu-check {
|
|
1554
1609
|
opacity: 1;
|
|
1555
1610
|
}
|
|
1611
|
+
/* guard:allow-raw-color - standalone auth HTML has no app theme token layer */
|
|
1612
|
+
.environment-switcher {
|
|
1613
|
+
position: fixed;
|
|
1614
|
+
right: max(0.75rem, env(safe-area-inset-right));
|
|
1615
|
+
bottom: max(0.75rem, env(safe-area-inset-bottom));
|
|
1616
|
+
z-index: 100;
|
|
1617
|
+
}
|
|
1618
|
+
.environment-switcher[hidden],
|
|
1619
|
+
.environment-popover[hidden] { display: none; }
|
|
1620
|
+
.environment-badge {
|
|
1621
|
+
display: inline-flex;
|
|
1622
|
+
align-items: center;
|
|
1623
|
+
justify-content: center;
|
|
1624
|
+
height: 1.5rem;
|
|
1625
|
+
min-width: 0;
|
|
1626
|
+
padding: 0 0.5rem;
|
|
1627
|
+
background: #3a3a3a;
|
|
1628
|
+
color: #fff;
|
|
1629
|
+
border: 1px solid rgba(255,255,255,0.16);
|
|
1630
|
+
border-radius: 0.75rem;
|
|
1631
|
+
box-shadow: 0 2px 8px rgba(0,0,0,0.25);
|
|
1632
|
+
font: inherit;
|
|
1633
|
+
font-size: 0.6875rem;
|
|
1634
|
+
font-weight: 600;
|
|
1635
|
+
letter-spacing: 0.03125rem;
|
|
1636
|
+
line-height: 1;
|
|
1637
|
+
text-transform: uppercase;
|
|
1638
|
+
cursor: pointer;
|
|
1639
|
+
}
|
|
1640
|
+
.environment-badge:hover,
|
|
1641
|
+
.environment-badge[aria-expanded="true"] { background: #4a4a4a; }
|
|
1642
|
+
.environment-badge:focus-visible,
|
|
1643
|
+
.environment-production-link:focus-visible {
|
|
1644
|
+
outline: 2px solid #33c4ff;
|
|
1645
|
+
outline-offset: 2px;
|
|
1646
|
+
}
|
|
1647
|
+
.environment-popover {
|
|
1648
|
+
position: absolute;
|
|
1649
|
+
right: 0;
|
|
1650
|
+
bottom: calc(100% + 0.5rem);
|
|
1651
|
+
width: min(17.5rem, calc(100vw - 1.5rem));
|
|
1652
|
+
padding: 1.25rem;
|
|
1653
|
+
background: #141414;
|
|
1654
|
+
color: #fff;
|
|
1655
|
+
border: 1px solid rgba(255,255,255,0.12);
|
|
1656
|
+
border-radius: 0.75rem;
|
|
1657
|
+
box-shadow: 0 18px 50px rgba(0,0,0,0.42);
|
|
1658
|
+
}
|
|
1659
|
+
.environment-popover-title { margin-bottom: 0.25rem; font-size: 0.875rem; font-weight: 600; line-height: 1.25rem; }
|
|
1660
|
+
.environment-popover-copy { margin-bottom: 1rem; color: #888; font-size: 0.875rem; line-height: 1.25rem; }
|
|
1661
|
+
.environment-production-link {
|
|
1662
|
+
display: flex;
|
|
1663
|
+
align-items: center;
|
|
1664
|
+
justify-content: center;
|
|
1665
|
+
min-height: 2rem;
|
|
1666
|
+
padding: 0.375rem 0.75rem;
|
|
1667
|
+
color: #e5e5e5;
|
|
1668
|
+
border: 1px solid rgba(255,255,255,0.16);
|
|
1669
|
+
border-radius: 0.375rem;
|
|
1670
|
+
font-size: 0.8125rem;
|
|
1671
|
+
text-decoration: none;
|
|
1672
|
+
}
|
|
1673
|
+
.environment-production-link:hover { background: #242424; }
|
|
1556
1674
|
.card {
|
|
1557
1675
|
width: 100%;
|
|
1558
1676
|
max-width: 400px;
|
|
@@ -1972,6 +2090,7 @@ ${embeddedAuthCss}
|
|
|
1972
2090
|
</head>
|
|
1973
2091
|
<body${simplifiedAuth ? ' class="simplified-auth"' : hasMarketing ? ' class="has-marketing"' : ""}>
|
|
1974
2092
|
${localePickerHtml}
|
|
2093
|
+
${environmentBadgeHtml}
|
|
1975
2094
|
${marketingPanelHtml}
|
|
1976
2095
|
<div class="card">
|
|
1977
2096
|
<h1 id="heading"${i18nAttr(googleOnly ? "signInTitle" : "welcomeTitle")}>${esc(t(googleOnly ? "signInTitle" : "welcomeTitle"))}</h1>
|
|
@@ -2065,6 +2184,7 @@ ${signupLocalModeNoteHtml}
|
|
|
2065
2184
|
<span${i18nAttr("localNotePrefix")}>${esc(t("localNotePrefix"))}</span> (<strong>${getConnectionLabel()}</strong>)<span${i18nAttr("localNoteSuffix")}>${esc(t("localNoteSuffix"))}</span>
|
|
2066
2185
|
</p>${marketingCloseHtml}
|
|
2067
2186
|
<script>
|
|
2187
|
+
${environmentBadgeScript}
|
|
2068
2188
|
function __anBasePath() {
|
|
2069
2189
|
var configured = ${JSON.stringify(appBasePath)};
|
|
2070
2190
|
if (configured) return configured;
|
|
@@ -2672,10 +2792,8 @@ ${identitySsoScript}
|
|
|
2672
2792
|
if (__anIsBuilderPreview()) return __anIsInFrame() ? 'popup' : 'redirect';
|
|
2673
2793
|
// Per-session override for ad-hoc testing outside Builder: append
|
|
2674
2794
|
// ?authMode=popup or ?authMode=redirect to the sign-in URL.
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
if (qp === 'popup' || qp === 'redirect') return qp;
|
|
2678
|
-
} catch(e) {}
|
|
2795
|
+
var qp = new URLSearchParams(window.location.search).get('authMode');
|
|
2796
|
+
if (qp === 'popup' || qp === 'redirect') return qp;
|
|
2679
2797
|
var mode = __AN_GOOGLE_AUTH_MODE || 'auto';
|
|
2680
2798
|
if (mode === 'popup') return 'popup';
|
|
2681
2799
|
if (mode === 'redirect') return 'redirect';
|
|
@@ -2694,6 +2812,22 @@ ${identitySsoScript}
|
|
|
2694
2812
|
} catch(e) {}
|
|
2695
2813
|
return 'builder-' + Date.now().toString(36) + '-' + Math.random().toString(36).slice(2);
|
|
2696
2814
|
}
|
|
2815
|
+
function __anNewOAuthVerifier() {
|
|
2816
|
+
try {
|
|
2817
|
+
if (window.crypto && typeof window.crypto.randomUUID === 'function') {
|
|
2818
|
+
return window.crypto.randomUUID() + window.crypto.randomUUID();
|
|
2819
|
+
}
|
|
2820
|
+
if (window.crypto && typeof window.crypto.getRandomValues === 'function') {
|
|
2821
|
+
var bytes = new Uint8Array(32);
|
|
2822
|
+
window.crypto.getRandomValues(bytes);
|
|
2823
|
+
var binary = '';
|
|
2824
|
+
for (var i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);
|
|
2825
|
+
return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');
|
|
2826
|
+
}
|
|
2827
|
+
} catch(e) { // coercion-ok: callers reject the empty verifier fallback.
|
|
2828
|
+
}
|
|
2829
|
+
return '';
|
|
2830
|
+
}
|
|
2697
2831
|
function __anFlowDebugId(flowId) {
|
|
2698
2832
|
return flowId ? String(flowId).slice(-10) : '';
|
|
2699
2833
|
}
|
|
@@ -2796,8 +2930,11 @@ ${identitySsoScript}
|
|
|
2796
2930
|
__anOAuthPollCount++;
|
|
2797
2931
|
try {
|
|
2798
2932
|
var exchangeParams = '?flow_id=' + encodeURIComponent(flowId);
|
|
2799
|
-
|
|
2800
|
-
|
|
2933
|
+
var exchangeOptions = { credentials: 'include' };
|
|
2934
|
+
if (verifier) {
|
|
2935
|
+
exchangeOptions.headers = { 'X-Agent-Native-Desktop-Verifier': verifier };
|
|
2936
|
+
}
|
|
2937
|
+
var res = await fetch(__anPath('/_agent-native/auth/desktop-exchange') + exchangeParams, exchangeOptions);
|
|
2801
2938
|
var data = await res.json().catch(function() { return {}; });
|
|
2802
2939
|
if (data && (data.email || data.token)) {
|
|
2803
2940
|
if (__anOAuthPollTimer) clearInterval(__anOAuthPollTimer);
|
|
@@ -2838,49 +2975,81 @@ ${identitySsoScript}
|
|
|
2838
2975
|
__anOAuthPollTimer = setInterval(check, 1000);
|
|
2839
2976
|
setTimeout(check, 500);
|
|
2840
2977
|
}
|
|
2841
|
-
function
|
|
2842
|
-
var flowId = __anNewOAuthFlowId();
|
|
2843
|
-
var oauthReturn = __anIsBuilderPreview() ? __anOAuthReturnTarget(ret) : ret;
|
|
2978
|
+
async function __anRequestDesktopOAuthUrl(flowId, verifier, oauthReturn) {
|
|
2844
2979
|
var params = new URLSearchParams();
|
|
2845
2980
|
if (oauthReturn) params.set('return', oauthReturn);
|
|
2846
2981
|
params.set('desktop', '1');
|
|
2847
2982
|
params.set('flow_id', flowId);
|
|
2848
|
-
params.
|
|
2849
|
-
|
|
2983
|
+
var res = await fetch(__anGoogleAuthUrlPath() + '?' + params.toString(), {
|
|
2984
|
+
method: 'POST',
|
|
2985
|
+
credentials: 'include',
|
|
2986
|
+
headers: {
|
|
2987
|
+
'Accept': 'application/json',
|
|
2988
|
+
'X-Agent-Native-Desktop-Verifier': verifier
|
|
2989
|
+
}
|
|
2990
|
+
});
|
|
2991
|
+
var data;
|
|
2992
|
+
try {
|
|
2993
|
+
data = await res.json();
|
|
2994
|
+
} catch(e) {
|
|
2995
|
+
throw new Error(__anT('failedToConnect'));
|
|
2996
|
+
}
|
|
2997
|
+
if (!res.ok || !data || typeof data.url !== 'string' || !data.url) {
|
|
2998
|
+
throw new Error(__anAuthErrorText(data, __anT('failedToConnect')));
|
|
2999
|
+
}
|
|
3000
|
+
return data.url;
|
|
3001
|
+
}
|
|
3002
|
+
function __anStartPopupOAuth(ret, btn, err) {
|
|
3003
|
+
var flowId = __anNewOAuthFlowId();
|
|
3004
|
+
var verifier = __anNewOAuthVerifier();
|
|
3005
|
+
if (!verifier) {
|
|
3006
|
+
__anShowOAuthError(err, btn, __anT('failedToConnect'));
|
|
3007
|
+
return;
|
|
3008
|
+
}
|
|
3009
|
+
var oauthReturn = __anIsBuilderPreview() ? __anOAuthReturnTarget(ret) : ret;
|
|
2850
3010
|
try { sessionStorage.setItem('__an_signin', '1'); } catch(e) {}
|
|
2851
3011
|
__anSetOAuthDebug('Opening Google sign-in popup', flowId);
|
|
3012
|
+
var popup;
|
|
2852
3013
|
try {
|
|
2853
|
-
|
|
3014
|
+
popup = window.open('', '_blank', 'width=640,height=760');
|
|
2854
3015
|
if (!popup) {
|
|
2855
3016
|
__anHandlePopupOAuthFailure(ret, btn, err, flowId, 'Google popup was blocked; falling back to redirect', 'Google popup was blocked.');
|
|
2856
3017
|
return;
|
|
2857
3018
|
}
|
|
2858
3019
|
try { popup.opener = null; } catch(e) {}
|
|
2859
|
-
try {
|
|
2860
|
-
popup.location.href = url;
|
|
2861
|
-
} catch(e) {
|
|
2862
|
-
try { popup.close(); } catch(closeErr) {}
|
|
2863
|
-
__anHandlePopupOAuthFailure(ret, btn, err, flowId, 'Could not navigate Google popup; falling back to redirect', 'Could not navigate Google popup.');
|
|
2864
|
-
return;
|
|
2865
|
-
}
|
|
2866
|
-
__anSetOAuthDebug('Google popup opened; waiting for callback', flowId);
|
|
2867
3020
|
} catch(e) {
|
|
2868
3021
|
__anHandlePopupOAuthFailure(ret, btn, err, flowId, 'Could not open Google popup; falling back to redirect', 'Could not open Google popup.');
|
|
2869
3022
|
return;
|
|
2870
3023
|
}
|
|
2871
|
-
|
|
3024
|
+
__anRequestDesktopOAuthUrl(flowId, verifier, oauthReturn).then(function(url) {
|
|
3025
|
+
try {
|
|
3026
|
+
popup.location.href = url;
|
|
3027
|
+
__anSetOAuthDebug('Google popup opened; waiting for callback', flowId);
|
|
3028
|
+
__anWaitForOAuthExchange(flowId, ret, btn, err, 'google', verifier);
|
|
3029
|
+
} catch(e) {
|
|
3030
|
+
throw e;
|
|
3031
|
+
}
|
|
3032
|
+
}).catch(function(e) {
|
|
3033
|
+
try { popup.close(); } catch(closeErr) {}
|
|
3034
|
+
__anShowOAuthError(err, btn, e && e.message ? e.message : __anT('failedToConnect'));
|
|
3035
|
+
});
|
|
2872
3036
|
}
|
|
2873
3037
|
function __anStartNativeDesktopOAuth(ret, btn, err) {
|
|
2874
3038
|
var flowId = __anNewOAuthFlowId();
|
|
2875
|
-
var
|
|
2876
|
-
if (
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
var
|
|
2881
|
-
__anSetOAuthDebug('
|
|
2882
|
-
|
|
2883
|
-
|
|
3039
|
+
var verifier = __anNewOAuthVerifier();
|
|
3040
|
+
if (!verifier) {
|
|
3041
|
+
__anShowOAuthError(err, btn, __anT('failedToConnect'));
|
|
3042
|
+
return;
|
|
3043
|
+
}
|
|
3044
|
+
var oauthReturn = ret;
|
|
3045
|
+
__anSetOAuthDebug('Preparing Google sign-in in system browser', flowId);
|
|
3046
|
+
__anRequestDesktopOAuthUrl(flowId, verifier, oauthReturn).then(function(url) {
|
|
3047
|
+
__anSetOAuthDebug('Opening Google sign-in in system browser', flowId);
|
|
3048
|
+
__anOpenOAuthUrl(url);
|
|
3049
|
+
__anWaitForOAuthExchange(flowId, ret, btn, err, 'google', verifier);
|
|
3050
|
+
}).catch(function(e) {
|
|
3051
|
+
__anShowOAuthError(err, btn, e && e.message ? e.message : __anT('failedToConnect'));
|
|
3052
|
+
});
|
|
2884
3053
|
}
|
|
2885
3054
|
function __anOpenOAuthUrl(url) {
|
|
2886
3055
|
try { sessionStorage.setItem('__an_signin', '1'); } catch(e) {}
|
package/dist/server/poll.d.ts
CHANGED
|
@@ -158,6 +158,7 @@ export declare class AppSyncState {
|
|
|
158
158
|
private lastDurablePrune;
|
|
159
159
|
private durablePruneFailures;
|
|
160
160
|
private durableWriteFailures;
|
|
161
|
+
private allocatorReseedFailures;
|
|
161
162
|
/**
|
|
162
163
|
* Whether we've seeded `version` from the DB. In serverless (Netlify,
|
|
163
164
|
* Vercel, etc.) each invocation starts fresh — without seeding, `version`
|
|
@@ -252,6 +253,7 @@ export declare class AppSyncState {
|
|
|
252
253
|
*/
|
|
253
254
|
private pruneDurableEvents;
|
|
254
255
|
private reportDurableWriteFailure;
|
|
256
|
+
private reportAllocatorReseedFailure;
|
|
255
257
|
persistSyncEvent(event: ChangeEvent, dedupeKey?: string, presetId?: string): Promise<void>;
|
|
256
258
|
/**
|
|
257
259
|
* Persist with a DB-allocated version (see ALLOCATING_INSERT_SQL). Returns
|
package/dist/server/poll.js
CHANGED
|
@@ -302,6 +302,7 @@ export class AppSyncState {
|
|
|
302
302
|
lastDurablePrune = Date.now();
|
|
303
303
|
durablePruneFailures = 0;
|
|
304
304
|
durableWriteFailures = 0;
|
|
305
|
+
allocatorReseedFailures = 0;
|
|
305
306
|
/**
|
|
306
307
|
* Whether we've seeded `version` from the DB. In serverless (Netlify,
|
|
307
308
|
* Vercel, etc.) each invocation starts fresh — without seeding, `version`
|
|
@@ -566,6 +567,12 @@ export class AppSyncState {
|
|
|
566
567
|
console.warn(`[agent-native] sync_events write failed for ${event.source}/${event.type}${event.key ? `/${event.key}` : ""}; durable replay is unavailable until the database recovers:`, error instanceof Error ? error.message : String(error));
|
|
567
568
|
}
|
|
568
569
|
}
|
|
570
|
+
reportAllocatorReseedFailure(error) {
|
|
571
|
+
this.allocatorReseedFailures++;
|
|
572
|
+
if (this.allocatorReseedFailures === 1) {
|
|
573
|
+
console.warn("[agent-native] sync version allocator reseed failed; retrying allocation:", error instanceof Error ? error.message : String(error));
|
|
574
|
+
}
|
|
575
|
+
}
|
|
569
576
|
async persistSyncEvent(event, dedupeKey, presetId) {
|
|
570
577
|
if (!(await this.ensureSyncEventsTable()))
|
|
571
578
|
return;
|
|
@@ -628,9 +635,20 @@ export class AppSyncState {
|
|
|
628
635
|
let result = await client.execute({ sql: ALLOCATING_INSERT_SQL, args });
|
|
629
636
|
if (result.rows.length === 0) {
|
|
630
637
|
// Allocator row missing (e.g. wiped after ensure): reseed, retry once.
|
|
631
|
-
|
|
638
|
+
try {
|
|
639
|
+
await client.execute(SEED_SYNC_VERSION_SQL);
|
|
640
|
+
this.allocatorReseedFailures = 0;
|
|
641
|
+
}
|
|
642
|
+
catch (error) {
|
|
643
|
+
// Keep the retry/fallback behavior, but do not hide the reason the
|
|
644
|
+
// allocator was unavailable. A missing warning here makes a broken
|
|
645
|
+
// allocator look like a normal retry until version ordering drifts.
|
|
646
|
+
this.reportAllocatorReseedFailure(error);
|
|
647
|
+
}
|
|
632
648
|
result = await client.execute({ sql: ALLOCATING_INSERT_SQL, args });
|
|
633
649
|
}
|
|
650
|
+
if (result.rows.length > 0)
|
|
651
|
+
this.allocatorReseedFailures = 0;
|
|
634
652
|
const version = timestampValue(result.rows[0]?.version);
|
|
635
653
|
await this.pruneDurableEvents(client);
|
|
636
654
|
return version > 0 ? version : null;
|
|
@@ -26,8 +26,8 @@ export declare function createRealtimeTokenHandler(): import("h3").EventHandlerW
|
|
|
26
26
|
expiresAt?: undefined;
|
|
27
27
|
ttlSeconds?: undefined;
|
|
28
28
|
} | {
|
|
29
|
+
error?: undefined;
|
|
29
30
|
token: string;
|
|
30
31
|
expiresAt: string;
|
|
31
32
|
ttlSeconds: number;
|
|
32
|
-
error?: undefined;
|
|
33
33
|
}>>;
|
|
@@ -14,6 +14,7 @@ import { USAGE_ALERT_MIGRATIONS, USAGE_ALERT_MIGRATIONS_TABLE, } from "../usage/
|
|
|
14
14
|
import { WORKSPACE_CONNECTIONS_MIGRATIONS, WORKSPACE_CONNECTIONS_MIGRATIONS_TABLE, } from "../workspace-connections/migrations.js";
|
|
15
15
|
import { runBetterAuthMigrations } from "./better-auth-migrations.js";
|
|
16
16
|
import { IDENTITY_SSO_MIGRATIONS } from "./identity-sso-migrations.js";
|
|
17
|
+
import { runFrameworkSchemaEnsures } from "./release-schema.js";
|
|
17
18
|
/**
|
|
18
19
|
* Apply framework-owned schema in one explicit release step.
|
|
19
20
|
*
|
|
@@ -22,6 +23,10 @@ import { IDENTITY_SSO_MIGRATIONS } from "./identity-sso-migrations.js";
|
|
|
22
23
|
* private schema from being silently coupled to every framework deployment.
|
|
23
24
|
*/
|
|
24
25
|
export async function runFrameworkReleaseMigrations(nitroApp) {
|
|
26
|
+
// First: the versioned migration lists below only cover the tables that have
|
|
27
|
+
// one. Most framework tables are defined by their store's `ensureTable()`,
|
|
28
|
+
// which production serverless can never run — see `./release-schema.ts`.
|
|
29
|
+
await runFrameworkSchemaEnsures();
|
|
25
30
|
await runBetterAuthMigrations(nitroApp);
|
|
26
31
|
await runMigrations(AGENT_TOOL_APPROVAL_MIGRATIONS, {
|
|
27
32
|
table: AGENT_TOOL_APPROVAL_MIGRATIONS_TABLE,
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Release-time creation of every framework-owned table that a store would
|
|
3
|
+
* otherwise create on first use.
|
|
4
|
+
*
|
|
5
|
+
* `ensureTable()` is the framework's schema definition: the DDL lives next to
|
|
6
|
+
* the store that owns it, and there is no second copy in a migration list. On a
|
|
7
|
+
* long-lived server that works, because the first request creates what is
|
|
8
|
+
* missing. On production serverless it does NOT: `schemaEnsureDisabled()` turns
|
|
9
|
+
* every probe into "already present" so a cold start never pays for ~390
|
|
10
|
+
* probes, which means nothing on the request path can create a table.
|
|
11
|
+
*
|
|
12
|
+
* So the release step has to run the same paths, and this module is the list
|
|
13
|
+
* that makes it complete. It is deliberately explicit rather than a
|
|
14
|
+
* side-effect-import registry: `package.json#sideEffects` is a narrow
|
|
15
|
+
* allow-list, so an import kept only for its registration is exactly what a
|
|
16
|
+
* bundler is entitled to drop — and the symptom would be a missing table in
|
|
17
|
+
* production, months later.
|
|
18
|
+
*
|
|
19
|
+
* The imports are dynamic on purpose. `server/index.ts` and `server/edge.ts`
|
|
20
|
+
* re-export `runFrameworkReleaseMigrations`, so a static list here would pull
|
|
21
|
+
* all 60 store modules into the graph of every server boot to serve a path
|
|
22
|
+
* that runs once, at release. Loading them inside the step keeps request cold
|
|
23
|
+
* starts unchanged.
|
|
24
|
+
*
|
|
25
|
+
* `guard:release-schema-complete` fails the build when a module defines schema
|
|
26
|
+
* and is not listed here.
|
|
27
|
+
*/
|
|
28
|
+
type SchemaEnsure = readonly [name: string, run: () => Promise<void>];
|
|
29
|
+
/** Store names in release order. Exported for the guard and its tests. */
|
|
30
|
+
export declare function frameworkSchemaEnsureNames(): string[];
|
|
31
|
+
/**
|
|
32
|
+
* Create every framework-owned table, in one pass, before the app serves
|
|
33
|
+
* traffic. Callers must already hold migration duty via `withMigrationRuntime`;
|
|
34
|
+
* without it `schemaEnsureDisabled()` reports every table present and this
|
|
35
|
+
* whole pass silently creates nothing.
|
|
36
|
+
*
|
|
37
|
+
* Sequential on purpose: these run against one database at release time, where
|
|
38
|
+
* total wall clock does not matter and concurrent `CREATE TABLE` on a shared
|
|
39
|
+
* Neon instance contends for `ACCESS EXCLUSIVE` locks.
|
|
40
|
+
*
|
|
41
|
+
* A failure aborts the release rather than being collected and reported at the
|
|
42
|
+
* end. A half-created schema that reports success is the failure mode this
|
|
43
|
+
* module exists to remove.
|
|
44
|
+
*/
|
|
45
|
+
export declare function runFrameworkSchemaEnsures(ensures?: readonly SchemaEnsure[]): Promise<void>;
|
|
46
|
+
export {};
|