@agent-native/core 0.164.4 → 0.164.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (268) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/calendar/.agents/skills/event-management/SKILL.md +84 -0
  3. package/corpus/templates/calendar/AGENTS.md +5 -0
  4. package/corpus/templates/calendar/actions/delete-event.ts +1 -1
  5. package/corpus/templates/calendar/actions/delete-events.ts +508 -0
  6. package/corpus/templates/calendar/actions/event-action-helpers.ts +1 -1
  7. package/corpus/templates/calendar/actions/list-events.ts +53 -0
  8. package/corpus/templates/calendar/app/components/calendar/CreateEventDialog.tsx +36 -47
  9. package/corpus/templates/calendar/app/components/calendar/DayView.tsx +3 -0
  10. package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +18 -1
  11. package/corpus/templates/calendar/app/components/calendar/InlineEventPickers.tsx +256 -38
  12. package/corpus/templates/calendar/app/hooks/use-google-auth.ts +43 -3
  13. package/corpus/templates/calendar/app/i18n-data.ts +120 -0
  14. package/corpus/templates/calendar/app/lib/event-form-utils.ts +113 -0
  15. package/corpus/templates/calendar/changelog/2026-08-18-the-agent-can-now-remove-many-meetings-at-once-such-as-every.md +6 -0
  16. package/corpus/templates/calendar/server/handlers/google-auth.ts +119 -3
  17. package/corpus/templates/calendar/server/lib/event-weekday.ts +112 -0
  18. package/corpus/templates/calendar/server/routes/[base]/_agent-native/google/add-account/auth-url.post.ts +1 -0
  19. package/corpus/templates/calendar/server/routes/[base]/_agent-native/google/auth-url.post.ts +1 -0
  20. package/corpus/templates/calendar/server/routes/_agent-native/google/add-account/auth-url.post.ts +1 -0
  21. package/corpus/templates/calendar/server/routes/_agent-native/google/auth-url.post.ts +1 -0
  22. package/corpus/templates/clips/app/components/player/video-player.tsx +12 -0
  23. package/corpus/templates/clips/app/routes/_app.dictate.tsx +18 -4
  24. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +114 -20
  25. package/corpus/templates/clips/app/routes/share.$shareId.tsx +83 -78
  26. package/corpus/templates/clips/changelog/2026-08-19-clips-nightly-builds-are-available-for-trying-the-latest-upd.md +6 -0
  27. package/corpus/templates/clips/changelog/2026-08-19-social-preview-video-frames.md +1 -0
  28. package/corpus/templates/clips/desktop/README.md +19 -4
  29. package/corpus/templates/clips/desktop/src/app.tsx +78 -16
  30. package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +3 -2
  31. package/corpus/templates/clips/desktop/src-tauri/tauri.conf.json +1 -0
  32. package/corpus/templates/clips/server/routes/[base]/_agent-native/google/auth-url.post.ts +1 -0
  33. package/corpus/templates/clips/server/routes/_agent-native/google/auth-url.get.ts +41 -3
  34. package/corpus/templates/clips/server/routes/_agent-native/google/auth-url.post.ts +1 -0
  35. package/corpus/templates/clips/server/routes/_agent-native/google/callback.get.ts +22 -1
  36. package/corpus/templates/clips/server/routes/api/clips-updater.json.get.ts +41 -22
  37. package/corpus/templates/factory/AGENTS.md +3 -2
  38. package/corpus/templates/factory/actions/get-factory-graph-version.ts +69 -0
  39. package/corpus/templates/factory/actions/list-factory-automations.ts +4 -0
  40. package/corpus/templates/factory/actions/list-factory-graph-versions.ts +82 -0
  41. package/corpus/templates/factory/actions/restore-factory-graph-version.ts +163 -0
  42. package/corpus/templates/factory/actions/save-factory-graph.ts +93 -60
  43. package/corpus/templates/factory/actions/start-builder-for-item.ts +19 -17
  44. package/corpus/templates/factory/app/components/factory/FactoryAuditView.tsx +100 -36
  45. package/corpus/templates/factory/app/components/factory/FactoryHistoryView.tsx +709 -0
  46. package/corpus/templates/factory/app/components/factory/FactoryInspector.tsx +62 -2
  47. package/corpus/templates/factory/app/components/ui/alert-dialog.tsx +1 -0
  48. package/corpus/templates/factory/app/i18n/en-US.ts +47 -0
  49. package/corpus/templates/factory/app/routes/factory.tsx +324 -61
  50. package/corpus/templates/factory/server/connectors/slack.ts +44 -2
  51. package/corpus/templates/factory/server/plugins/agent-chat.ts +12 -8
  52. package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +13 -0
  53. package/corpus/templates/factory/server/triage/slack-client.ts +5 -0
  54. package/corpus/templates/factory/server/triage/slack-poller.ts +72 -4
  55. package/corpus/templates/mail/actions/view-screen.ts +1 -1
  56. package/corpus/templates/mail/app/components/GoogleConnectBanner.tsx +100 -18
  57. package/corpus/templates/mail/server/handlers/google-auth.ts +125 -24
  58. package/corpus/templates/mail/server/lib/gmail-query.ts +5 -2
  59. package/corpus/templates/mail/server/routes/[base]/_agent-native/google/add-account/auth-url.post.ts +1 -0
  60. package/corpus/templates/mail/server/routes/[base]/_agent-native/google/auth-url.post.ts +1 -0
  61. package/corpus/templates/mail/server/routes/_agent-native/google/add-account/auth-url.post.ts +1 -0
  62. package/corpus/templates/mail/server/routes/_agent-native/google/auth-url.post.ts +1 -0
  63. package/corpus/templates/plan/app/pages/PlansPage.tsx +0 -12
  64. package/corpus/templates/plan/changelog/2026-08-19-plan-prompts-now-guide-you-to-connect-ai-before-sending-and-.md +6 -0
  65. package/corpus/templates/slides/actions/approve-deck-access-request.ts +234 -0
  66. package/corpus/templates/slides/actions/get-deck-access-status.ts +35 -2
  67. package/corpus/templates/slides/actions/request-deck-access.ts +263 -64
  68. package/corpus/templates/slides/app/components/editor/MissingDeckAccessPane.tsx +196 -0
  69. package/corpus/templates/slides/app/components/editor/RequestDeckAccessDialog.tsx +101 -0
  70. package/corpus/templates/slides/app/hooks/use-deck-access.ts +7 -4
  71. package/corpus/templates/slides/app/i18n/en-US.ts +29 -6
  72. package/corpus/templates/slides/app/pages/DeckEditor.tsx +147 -169
  73. package/corpus/templates/slides/app/routes/access-request.approve.tsx +250 -0
  74. package/corpus/templates/slides/server/db/schema.ts +8 -0
  75. package/corpus/templates/slides/server/lib/access-request-email.ts +36 -0
  76. package/corpus/templates/slides/server/lib/emails.ts +26 -0
  77. package/corpus/templates/slides/server/plugins/agent-chat.ts +7 -0
  78. package/corpus/templates/slides/server/plugins/db.ts +50 -0
  79. package/corpus/templates/slides/shared/deck-access.ts +31 -0
  80. package/dist/a2a/task-store.d.ts +1 -0
  81. package/dist/a2a/task-store.js +1 -1
  82. package/dist/agent/observational-memory/store.d.ts +1 -0
  83. package/dist/agent/observational-memory/store.js +1 -1
  84. package/dist/agent/run-store.d.ts +1 -0
  85. package/dist/agent/run-store.js +1 -1
  86. package/dist/agent/tool-approval-store.d.ts +1 -0
  87. package/dist/agent/tool-approval-store.js +1 -1
  88. package/dist/application-state/store.d.ts +1 -0
  89. package/dist/application-state/store.js +1 -1
  90. package/dist/browser-sessions/store.d.ts +1 -0
  91. package/dist/browser-sessions/store.js +1 -1
  92. package/dist/checkpoints/store.d.ts +1 -0
  93. package/dist/checkpoints/store.js +1 -1
  94. package/dist/cli/code-agent-schedules.d.ts +11 -0
  95. package/dist/cli/code-agent-schedules.js +44 -5
  96. package/dist/client/AgentPanel.d.ts +5 -1
  97. package/dist/client/AgentPanel.js +2 -2
  98. package/dist/client/AssistantChat.d.ts +5 -1
  99. package/dist/client/AssistantChat.js +40 -6
  100. package/dist/client/EnvironmentBadge.d.ts +7 -13
  101. package/dist/client/EnvironmentBadge.js +43 -92
  102. package/dist/client/agent-chat/index.d.ts +1 -0
  103. package/dist/client/agent-chat/index.js +1 -0
  104. package/dist/client/agent-chat-adapter.js +76 -50
  105. package/dist/client/app-providers.js +4 -4
  106. package/dist/client/chat/message-components.d.ts +4 -0
  107. package/dist/client/chat/message-components.js +28 -1
  108. package/dist/client/chat/run-recovery.js +26 -0
  109. package/dist/client/chat-first/apps-rail.d.ts +1 -0
  110. package/dist/client/chat-first/apps-rail.js +28 -2
  111. package/dist/client/sse-event-processor.js +13 -8
  112. package/dist/client/use-active-agent-chat-run.d.ts +2 -0
  113. package/dist/client/use-active-agent-chat-run.js +22 -0
  114. package/dist/coding-tools/sandbox/executions-store.d.ts +1 -0
  115. package/dist/coding-tools/sandbox/executions-store.js +1 -1
  116. package/dist/collab/awareness-store.d.ts +1 -0
  117. package/dist/collab/awareness-store.js +1 -1
  118. package/dist/collab/routes.d.ts +1 -1
  119. package/dist/collab/storage.d.ts +1 -0
  120. package/dist/collab/storage.js +1 -1
  121. package/dist/collab/struct-routes.d.ts +1 -1
  122. package/dist/db/client.js +3 -3
  123. package/dist/db/ddl-guard.js +8 -0
  124. package/dist/db/migration-runtime.d.ts +23 -0
  125. package/dist/db/migration-runtime.js +41 -0
  126. package/dist/db/migrations.d.ts +1 -2
  127. package/dist/db/migrations.js +2 -24
  128. package/dist/email-catalog/log.d.ts +1 -0
  129. package/dist/email-catalog/log.js +1 -1
  130. package/dist/guards/index.d.ts +1 -0
  131. package/dist/guards/index.js +1 -0
  132. package/dist/guards/release-schema-complete.d.ts +22 -0
  133. package/dist/guards/release-schema-complete.js +144 -0
  134. package/dist/integrations/a2a-continuations-store.d.ts +1 -0
  135. package/dist/integrations/a2a-continuations-store.js +1 -1
  136. package/dist/integrations/awaiting-input-store.d.ts +1 -0
  137. package/dist/integrations/awaiting-input-store.js +1 -1
  138. package/dist/integrations/config-store.d.ts +1 -0
  139. package/dist/integrations/config-store.js +1 -1
  140. package/dist/integrations/controls-store.d.ts +1 -0
  141. package/dist/integrations/controls-store.js +1 -1
  142. package/dist/integrations/identity-links-store.d.ts +1 -0
  143. package/dist/integrations/identity-links-store.js +1 -1
  144. package/dist/integrations/installations-store.d.ts +1 -0
  145. package/dist/integrations/installations-store.js +1 -1
  146. package/dist/integrations/remote-commands-store.d.ts +1 -0
  147. package/dist/integrations/remote-commands-store.js +1 -1
  148. package/dist/integrations/remote-devices-store.d.ts +1 -0
  149. package/dist/integrations/remote-devices-store.js +1 -1
  150. package/dist/integrations/remote-push-store.d.ts +1 -0
  151. package/dist/integrations/remote-push-store.js +1 -1
  152. package/dist/integrations/remote-run-events-store.d.ts +1 -0
  153. package/dist/integrations/remote-run-events-store.js +1 -1
  154. package/dist/integrations/scope-store.d.ts +1 -0
  155. package/dist/integrations/scope-store.js +1 -1
  156. package/dist/integrations/thread-mapping-store.d.ts +1 -0
  157. package/dist/integrations/thread-mapping-store.js +1 -1
  158. package/dist/integrations/usage-budget-store.d.ts +1 -0
  159. package/dist/integrations/usage-budget-store.js +1 -1
  160. package/dist/jobs/background-automation-runner.js +111 -9
  161. package/dist/jobs/run-history.d.ts +1 -0
  162. package/dist/jobs/run-history.js +1 -1
  163. package/dist/jobs/scheduler-health.d.ts +1 -0
  164. package/dist/jobs/scheduler-health.js +1 -1
  165. package/dist/mcp/approval-store.d.ts +1 -0
  166. package/dist/mcp/approval-store.js +1 -1
  167. package/dist/mcp/connect-store.d.ts +1 -0
  168. package/dist/mcp/connect-store.js +1 -1
  169. package/dist/mcp/oauth-store.d.ts +1 -0
  170. package/dist/mcp/oauth-store.js +1 -1
  171. package/dist/notifications/store.d.ts +1 -0
  172. package/dist/notifications/store.js +1 -1
  173. package/dist/oauth-tokens/store.d.ts +1 -0
  174. package/dist/oauth-tokens/store.js +1 -1
  175. package/dist/observability/routes.d.ts +5 -5
  176. package/dist/progress/routes.d.ts +1 -1
  177. package/dist/progress/store.d.ts +1 -0
  178. package/dist/progress/store.js +1 -1
  179. package/dist/provider-api/actions/custom-provider-registration.d.ts +5 -5
  180. package/dist/provider-api/actions/provider-api.d.ts +4 -4
  181. package/dist/provider-api/corpus-jobs-store.d.ts +1 -0
  182. package/dist/provider-api/corpus-jobs-store.js +1 -1
  183. package/dist/provider-api/custom-registry.d.ts +1 -0
  184. package/dist/provider-api/custom-registry.js +1 -1
  185. package/dist/provider-api/quota-governor.d.ts +1 -0
  186. package/dist/provider-api/quota-governor.js +1 -1
  187. package/dist/provider-api/staged-datasets-store.d.ts +1 -0
  188. package/dist/provider-api/staged-datasets-store.js +1 -1
  189. package/dist/resources/handlers.d.ts +3 -3
  190. package/dist/resources/store.d.ts +1 -0
  191. package/dist/resources/store.js +1 -1
  192. package/dist/scripts/dev/index.js +15 -1
  193. package/dist/search/index.js +3 -0
  194. package/dist/secrets/routes.d.ts +9 -9
  195. package/dist/secrets/storage.d.ts +1 -0
  196. package/dist/secrets/storage.js +1 -1
  197. package/dist/server/agent-chat-plugin.js +38 -9
  198. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  199. package/dist/server/agent-teams-run-queue.d.ts +1 -0
  200. package/dist/server/agent-teams-run-queue.js +1 -1
  201. package/dist/server/auth-marketing.js +3 -1
  202. package/dist/server/auth.d.ts +18 -1
  203. package/dist/server/auth.js +370 -154
  204. package/dist/server/embed-session.d.ts +1 -0
  205. package/dist/server/embed-session.js +1 -1
  206. package/dist/server/google-auth-plugin.js +3 -1
  207. package/dist/server/google-oauth.d.ts +10 -0
  208. package/dist/server/google-oauth.js +25 -1
  209. package/dist/server/identity-sso-store.d.ts +1 -0
  210. package/dist/server/identity-sso-store.js +1 -1
  211. package/dist/server/index.d.ts +1 -1
  212. package/dist/server/index.js +1 -1
  213. package/dist/server/onboarding-html.js +200 -31
  214. package/dist/server/poll.d.ts +2 -0
  215. package/dist/server/poll.js +19 -1
  216. package/dist/server/realtime-token.d.ts +1 -1
  217. package/dist/server/release-migrations.js +5 -0
  218. package/dist/server/release-schema.d.ts +46 -0
  219. package/dist/server/release-schema.js +307 -0
  220. package/dist/settings/store.d.ts +1 -0
  221. package/dist/settings/store.js +1 -1
  222. package/dist/shared/environment-lanes.d.ts +28 -0
  223. package/dist/shared/environment-lanes.js +61 -0
  224. package/dist/sharing/actions/share-resource.js +22 -2
  225. package/dist/styles/agent-native.css +17 -15
  226. package/dist/triggers/routes.d.ts +11 -0
  227. package/dist/triggers/routes.js +10 -0
  228. package/dist/usage/alerts-store.d.ts +1 -0
  229. package/dist/usage/alerts-store.js +1 -1
  230. package/dist/usage/store.d.ts +1 -0
  231. package/dist/usage/store.js +1 -1
  232. package/docs/content/actions-access-control.mdx +136 -2
  233. package/docs/content/actions-agent-tools.mdx +101 -0
  234. package/docs/content/actions-defining.mdx +2 -2
  235. package/docs/content/audit-log.mdx +1 -1
  236. package/docs/content/authentication.mdx +1 -1
  237. package/docs/content/cloudflare.mdx +43 -0
  238. package/docs/content/creating-templates.mdx +1 -1
  239. package/docs/content/deploy-an-app.mdx +109 -0
  240. package/docs/content/deployment-environment-variables.mdx +101 -0
  241. package/docs/content/deployment.mdx +125 -792
  242. package/docs/content/docs-components.mdx +2 -2
  243. package/docs/content/environment-variables.mdx +41 -41
  244. package/docs/content/file-uploads.mdx +74 -40
  245. package/docs/content/harness-agents.mdx +2 -2
  246. package/docs/content/internationalization.mdx +61 -65
  247. package/docs/content/key-concepts.mdx +3 -3
  248. package/docs/content/multi-app-workspace.mdx +2 -2
  249. package/docs/content/netlify.mdx +47 -0
  250. package/docs/content/node-docker.mdx +138 -0
  251. package/docs/content/organizations-teams-permissions.mdx +5 -5
  252. package/docs/content/other-platforms.mdx +27 -0
  253. package/docs/content/ssr-caching.mdx +45 -0
  254. package/docs/content/template-assets-developers.mdx +2 -2
  255. package/docs/content/template-chat-developers.mdx +2 -2
  256. package/docs/content/template-content-developers.mdx +2 -2
  257. package/docs/content/{local-file-mode.mdx → template-content-local-files.mdx} +2 -1
  258. package/docs/content/template-content-sync.mdx +2 -2
  259. package/docs/content/toolkit-agent-ux.mdx +1 -1
  260. package/docs/content/toolkit-resources.mdx +2 -2
  261. package/docs/content/updating-ui-in-production.mdx +35 -0
  262. package/docs/content/vercel.mdx +38 -0
  263. package/docs/content/what-is-agent-native.mdx +1 -1
  264. package/docs/content/workspace-deployment.mdx +350 -0
  265. package/package.json +2 -2
  266. package/docs/content/agents.mdx +0 -9
  267. package/docs/content/database.mdx +0 -317
  268. package/docs/content/human-approval.mdx +0 -156
@@ -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())
@@ -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";
@@ -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
- try {
2676
- var qp = new URLSearchParams(window.location.search).get('authMode');
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
- if (verifier) exchangeParams += '&verifier=' + encodeURIComponent(verifier);
2800
- var res = await fetch(__anPath('/_agent-native/auth/desktop-exchange') + exchangeParams, { credentials: 'include' });
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 __anStartPopupOAuth(ret, btn, err) {
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.set('redirect', '1');
2849
- var url = __anGoogleAuthUrlPath() + '?' + params.toString();
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
- var popup = window.open('', '_blank', 'width=640,height=760');
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
- __anWaitForOAuthExchange(flowId, ret, btn, err);
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 params = new URLSearchParams();
2876
- if (ret) params.set('return', ret);
2877
- params.set('desktop', '1');
2878
- params.set('flow_id', flowId);
2879
- params.set('redirect', '1');
2880
- var url = __anGoogleAuthUrlPath() + '?' + params.toString();
2881
- __anSetOAuthDebug('Opening Google sign-in in system browser', flowId);
2882
- __anOpenOAuthUrl(url);
2883
- __anWaitForOAuthExchange(flowId, ret, btn, err);
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) {}
@@ -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
@@ -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
- await client.execute(SEED_SYNC_VERSION_SQL).catch(() => { });
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 {};