@agent-native/core 0.168.1 → 0.168.3

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 (62) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/netlify.toml +4 -4
  3. package/corpus/templates/analytics/server/lib/dashboards-store.ts +32 -5
  4. package/corpus/templates/analytics/server/lib/scoped-settings.ts +2 -3
  5. package/corpus/templates/assets/netlify.toml +4 -1
  6. package/corpus/templates/brain/netlify.toml +4 -1
  7. package/corpus/templates/calendar/app/root.tsx +2 -0
  8. package/corpus/templates/calendar/netlify.toml +4 -1
  9. package/corpus/templates/chat/netlify.toml +4 -1
  10. package/corpus/templates/clips/desktop/src/app.tsx +4 -8
  11. package/corpus/templates/clips/netlify.toml +4 -1
  12. package/corpus/templates/clips/server/routes/_agent-native/google/auth-url.get.ts +17 -11
  13. package/corpus/templates/clips/server/routes/_agent-native/google/callback.get.ts +6 -5
  14. package/corpus/templates/content/netlify.toml +4 -1
  15. package/corpus/templates/crm/netlify.toml +6 -1
  16. package/corpus/templates/design/app/root.tsx +5 -1
  17. package/corpus/templates/design/netlify.toml +4 -1
  18. package/corpus/templates/dispatch/netlify.toml +4 -1
  19. package/corpus/templates/factory/netlify.toml +4 -1
  20. package/corpus/templates/forms/netlify.toml +4 -1
  21. package/corpus/templates/macros/netlify.toml +3 -3
  22. package/corpus/templates/mail/actions/view-screen.ts +80 -8
  23. package/corpus/templates/mail/app/components/email/EmailList.tsx +3 -1
  24. package/corpus/templates/mail/app/components/email/EmailListItem.tsx +1 -35
  25. package/corpus/templates/mail/app/components/email/EmailThread.tsx +16 -8
  26. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +146 -87
  27. package/corpus/templates/mail/app/global.css +21 -0
  28. package/corpus/templates/mail/app/hooks/use-emails.ts +6 -0
  29. package/corpus/templates/mail/app/hooks/use-navigation-state.ts +2 -0
  30. package/corpus/templates/mail/app/lib/inbox-tabs.ts +5 -0
  31. package/corpus/templates/mail/app/lib/label-colors.ts +47 -0
  32. package/corpus/templates/mail/app/pages/InboxPage.tsx +25 -8
  33. package/corpus/templates/mail/netlify.toml +4 -1
  34. package/corpus/templates/mail/server/handlers/emails.ts +27 -2
  35. package/corpus/templates/plan/netlify.toml +4 -1
  36. package/corpus/templates/slides/netlify.toml +4 -1
  37. package/corpus/templates/tasks/netlify.toml +6 -1
  38. package/dist/app-config/migration.d.ts +5 -0
  39. package/dist/app-config/migration.js +11 -0
  40. package/dist/app-config/schema.d.ts +4 -0
  41. package/dist/app-config/schema.js +2 -0
  42. package/dist/app-config/store.d.ts +8 -0
  43. package/dist/app-config/store.js +19 -1
  44. package/dist/collab/awareness.d.ts +2 -2
  45. package/dist/collab/routes.d.ts +1 -1
  46. package/dist/collab/struct-routes.d.ts +1 -1
  47. package/dist/db/migrations.js +10 -2
  48. package/dist/deploy/build.js +6 -0
  49. package/dist/deploy/netlify-static-headers.d.ts +3 -0
  50. package/dist/deploy/netlify-static-headers.js +60 -0
  51. package/dist/notifications/routes.d.ts +3 -3
  52. package/dist/observability/routes.d.ts +3 -3
  53. package/dist/provider-api/actions/custom-provider-registration.d.ts +16 -16
  54. package/dist/provider-api/actions/provider-api.d.ts +17 -17
  55. package/dist/server/transcribe-voice.d.ts +1 -1
  56. package/dist/settings/index.d.ts +1 -1
  57. package/dist/settings/index.js +1 -1
  58. package/dist/settings/org-settings.js +7 -3
  59. package/dist/templates/chat/netlify.toml +4 -1
  60. package/dist/vite/client.js +2 -0
  61. package/package.json +2 -1
  62. package/src/templates/chat/netlify.toml +4 -1
package/corpus/README.md CHANGED
@@ -31,4 +31,4 @@ rg -n "defineAction|useActionQuery" node_modules/@agent-native/core/corpus
31
31
 
32
32
  ## Generated Counts
33
33
 
34
- - template files: 8491
34
+ - template files: 8492
@@ -4,7 +4,7 @@ ignore = "node ./scripts/netlify-ignore-build.mjs analytics"
4
4
  # core explicitly here so a cached Netlify install cannot bundle an older agent
5
5
  # loop into Analytics' server functions (including A2A/MCP final-response
6
6
  # guards).
7
- command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && pnpm --filter @agent-native/core build && NITRO_PRESET=netlify pnpm --filter analytics build && if [ \"${CONTEXT:-}\" = \"production\" ]; then pnpm --filter analytics migrate:production; fi"
7
+ command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && pnpm --filter @agent-native/core build && NITRO_PRESET=netlify pnpm --filter analytics build && if [ \"${CONTEXT:-}\" = \"production\" ] || [ \"${AGENT_NATIVE_RUN_RELEASE_MIGRATIONS:-}\" = \"1\" ]; then pnpm --filter analytics migrate:production; fi"
8
8
  publish = "templates/analytics/dist"
9
9
  functions = "templates/analytics/.netlify/functions-internal"
10
10
 
@@ -27,9 +27,9 @@ AGENT_NATIVE_DISABLE_KEEP_WARM_BACKGROUND = "1"
27
27
  # its loading screen while those chunks return 404.
28
28
  AGENT_NATIVE_SSR_CACHE = "30s"
29
29
  # Analytics owns its schema at release time (`migrate:production` above), so
30
- # production request functions skip migrations. Preview functions still run
31
- # request-path migrations because previews do not run the production release
32
- # migration step.
30
+ # production request functions skip migrations. Ordinary deploy previews still
31
+ # run request-path migrations; the beta prebuilt lane explicitly supplies the
32
+ # release owner even though it builds with branch-deploy context.
33
33
  AGENT_NATIVE_RELEASE_MIGRATIONS = "1"
34
34
 
35
35
  # A2A delegation calls run a full agent loop (LLM + tool calls + DB queries).
@@ -15,11 +15,11 @@
15
15
  import { isPostgres } from "@agent-native/core/db";
16
16
  import { recordChange } from "@agent-native/core/server";
17
17
  import {
18
- getAllSettings,
19
18
  getOrgSetting,
20
19
  getUserSetting,
21
20
  deleteOrgSetting,
22
21
  deleteUserSetting,
22
+ listSettingsByPrefix,
23
23
  } from "@agent-native/core/settings";
24
24
  import {
25
25
  accessFilter,
@@ -167,6 +167,33 @@ interface AccessCtx {
167
167
  orgId: string | null;
168
168
  }
169
169
 
170
+ /**
171
+ * Legacy KV rows are only ever reachable under `o:<orgId>:` or `u:<email>:`,
172
+ * so a caller can match nothing else. Reading them with `getAllSettings()`
173
+ * pulled and JSON-parsed every tenant's settings row into the Lambda to
174
+ * string-match those two prefixes, putting the whole deployment's settings
175
+ * table on the critical path of every dashboard and analysis list read.
176
+ */
177
+ async function getScopedLegacySettings(
178
+ ctx: Pick<AccessCtx, "email" | "orgId">,
179
+ ): Promise<Record<string, Record<string, unknown>>> {
180
+ // User scope first, then org: callers append these to the SQL rows in
181
+ // iteration order and never re-sort, so the order is user-visible. The
182
+ // previous full-table read inherited whatever order the settings table
183
+ // returned, which no query pinned.
184
+ const prefixes: string[] = [];
185
+ if (ctx.email) prefixes.push(`u:${ctx.email}:`);
186
+ if (ctx.orgId) prefixes.push(`o:${ctx.orgId}:`);
187
+ if (prefixes.length === 0) return {};
188
+ const scoped: Record<string, Record<string, unknown>> = {};
189
+ for (const entries of await Promise.all(
190
+ prefixes.map((prefix) => listSettingsByPrefix(prefix)),
191
+ )) {
192
+ for (const { key, value } of entries) scoped[key] = value;
193
+ }
194
+ return scoped;
195
+ }
196
+
170
197
  const SQL_PREFIX = "sql-dashboard-";
171
198
  const EXPLORER_PREFIX = "dashboard-";
172
199
 
@@ -666,7 +693,7 @@ export async function listDashboards(
666
693
  // entirely when the caller wants archived-only or hidden-only records.
667
694
  if (archived === "archived" || hidden === "hidden") return out;
668
695
  try {
669
- const all = await getAllSettings();
696
+ const all = await getScopedLegacySettings(ctx);
670
697
  for (const [key, value] of Object.entries(all)) {
671
698
  let id: string | null = null;
672
699
  let kind: DashboardKind | null = null;
@@ -814,7 +841,7 @@ export async function listDashboardSummaries(
814
841
 
815
842
  if (archived === "archived" || hidden === "hidden") return out;
816
843
  try {
817
- const all = await getAllSettings();
844
+ const all = await getScopedLegacySettings(ctx);
818
845
  for (const [key, value] of Object.entries(all)) {
819
846
  let id: string | null = null;
820
847
  let kind: DashboardKind | null = null;
@@ -962,7 +989,7 @@ export async function searchDashboardReferences(
962
989
  const seen = new Set(
963
990
  ranked.map(({ record }) => `${record.kind}:${record.id}`),
964
991
  );
965
- const allSettings = await getAllSettings();
992
+ const allSettings = await getScopedLegacySettings(ctx);
966
993
  for (const [key, value] of Object.entries(allSettings)) {
967
994
  const scope = legacyDashboardReferenceScope(key, ctx);
968
995
  if (
@@ -2040,7 +2067,7 @@ export async function listAnalyses(
2040
2067
  // the legacy scan entirely.
2041
2068
  if (hidden === "hidden") return out;
2042
2069
  try {
2043
- const all = await getAllSettings();
2070
+ const all = await getScopedLegacySettings(ctx);
2044
2071
  for (const [key, value] of Object.entries(all)) {
2045
2072
  let id: string | null = null;
2046
2073
  let ownerEmail = ctx.email;
@@ -11,6 +11,7 @@ import {
11
11
  getOrgSetting,
12
12
  getUserSetting,
13
13
  listOrgSettings,
14
+ listSettingsByPrefix,
14
15
  putOrgSetting,
15
16
  putUserSetting,
16
17
  } from "@agent-native/core/settings";
@@ -35,11 +36,9 @@ async function listUserSettings(
35
36
  email: string,
36
37
  prefix: string,
37
38
  ): Promise<Record<string, Record<string, unknown>>> {
38
- const all = await getAllSettings();
39
39
  const scopedPrefix = `${userPrefix(email)}${prefix}`;
40
40
  const out: Record<string, Record<string, unknown>> = {};
41
- for (const [key, value] of Object.entries(all)) {
42
- if (!key.startsWith(scopedPrefix)) continue;
41
+ for (const { key, value } of await listSettingsByPrefix(scopedPrefix)) {
43
42
  out[key.slice(userPrefix(email).length)] = value;
44
43
  }
45
44
  return out;
@@ -1,6 +1,6 @@
1
1
  [build]
2
2
  ignore = "node ./scripts/netlify-ignore-build.mjs assets"
3
- command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && NITRO_PRESET=netlify pnpm --filter assets build && if [ \"${CONTEXT:-}\" = \"production\" ]; then pnpm --filter assets migrate:production; fi"
3
+ command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && NITRO_PRESET=netlify pnpm --filter assets build && if [ \"${CONTEXT:-}\" = \"production\" ] || [ \"${AGENT_NATIVE_RUN_RELEASE_MIGRATIONS:-}\" = \"1\" ]; then pnpm --filter assets migrate:production; fi"
4
4
  publish = "templates/assets/dist"
5
5
  functions = "templates/assets/.netlify/functions-internal"
6
6
 
@@ -15,6 +15,9 @@ AGENT_CHAT_DURABLE_BACKGROUND = "true"
15
15
  AGENT_NATIVE_HOSTED_HARNESS = "true"
16
16
  AGENT_NATIVE_ENABLE_KEEP_WARM = "1"
17
17
  AGENT_NATIVE_DISABLE_KEEP_WARM_BACKGROUND = "1"
18
+ # Production release migrations own schema setup; request functions must skip
19
+ # migration probes on every serverless invocation.
20
+ AGENT_NATIVE_RELEASE_MIGRATIONS = "1"
18
21
 
19
22
  # Emit the Netlify background function used by Assets' durable agent-chat opt-in.
20
23
  # The normal server timeout still protects non-agent image/video HTTP handlers.
@@ -1,6 +1,6 @@
1
1
  [build]
2
2
  ignore = "node ./scripts/netlify-ignore-build.mjs brain"
3
- command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && NITRO_PRESET=netlify pnpm --filter brain build && pnpm exec tsx templates/brain/jobs/emit-netlify-brain-queue-cron.ts && if [ \"${CONTEXT:-}\" = \"production\" ]; then pnpm --filter brain migrate:production; fi"
3
+ command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && NITRO_PRESET=netlify pnpm --filter brain build && pnpm exec tsx templates/brain/jobs/emit-netlify-brain-queue-cron.ts && if [ \"${CONTEXT:-}\" = \"production\" ] || [ \"${AGENT_NATIVE_RUN_RELEASE_MIGRATIONS:-}\" = \"1\" ]; then pnpm --filter brain migrate:production; fi"
4
4
  publish = "templates/brain/dist"
5
5
  functions = "templates/brain/.netlify/functions-internal"
6
6
 
@@ -14,6 +14,9 @@ NPM_CONFIG_PRODUCTION = "false"
14
14
  AGENT_NATIVE_HOSTED_HARNESS = "true"
15
15
  AGENT_NATIVE_ENABLE_KEEP_WARM = "1"
16
16
  AGENT_NATIVE_DISABLE_KEEP_WARM_BACKGROUND = "1"
17
+ # Production release migrations own schema setup; request functions must skip
18
+ # migration probes on every serverless invocation.
19
+ AGENT_NATIVE_RELEASE_MIGRATIONS = "1"
17
20
 
18
21
  # A2A delegation calls run a full agent loop (LLM + tool calls + DB queries).
19
22
  # The framework does not impose a default agent-run timeout; if a template sets
@@ -5,6 +5,7 @@ import {
5
5
  createAgentNativeQueryClient,
6
6
  useDbSync,
7
7
  } from "@agent-native/core/client/hooks";
8
+ import { isEmbedAuthActive } from "@agent-native/core/client/host";
8
9
  import {
9
10
  getLocaleInitScript,
10
11
  type LocaleCode,
@@ -278,6 +279,7 @@ export default function Root() {
278
279
  <AppProviders
279
280
  queryClient={queryClient}
280
281
  isPublicPath={isPublicPath}
282
+ sessionBypass={isEmbedAuthActive()}
281
283
  clientOnlyFallback={<DefaultSpinner />}
282
284
  toaster={<Toaster richColors position="bottom-center" />}
283
285
  i18n={{
@@ -1,6 +1,6 @@
1
1
  [build]
2
2
  ignore = "node ./scripts/netlify-ignore-build.mjs calendar"
3
- command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && DATABASE_URL=${NETLIFY_DATABASE_URL_UNPOOLED:-$DATABASE_URL} NITRO_PRESET=netlify pnpm --filter calendar build && if [ \"${CONTEXT:-}\" = \"production\" ]; then DATABASE_URL=${NETLIFY_DATABASE_URL_UNPOOLED:-$DATABASE_URL} pnpm --filter calendar migrate:production; fi"
3
+ command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && DATABASE_URL=${NETLIFY_DATABASE_URL_UNPOOLED:-$DATABASE_URL} NITRO_PRESET=netlify pnpm --filter calendar build && if [ \"${CONTEXT:-}\" = \"production\" ] || [ \"${AGENT_NATIVE_RUN_RELEASE_MIGRATIONS:-}\" = \"1\" ]; then DATABASE_URL=${NETLIFY_DATABASE_URL_UNPOOLED:-$DATABASE_URL} pnpm --filter calendar migrate:production; fi"
4
4
  publish = "templates/calendar/dist"
5
5
  functions = "templates/calendar/.netlify/functions-internal"
6
6
 
@@ -14,6 +14,9 @@ NPM_CONFIG_PRODUCTION = "false"
14
14
  AGENT_NATIVE_HOSTED_HARNESS = "true"
15
15
  AGENT_NATIVE_ENABLE_KEEP_WARM = "1"
16
16
  AGENT_NATIVE_DISABLE_KEEP_WARM_BACKGROUND = "1"
17
+ # Production release migrations own schema setup; request functions must skip
18
+ # migration probes on every serverless invocation.
19
+ AGENT_NATIVE_RELEASE_MIGRATIONS = "1"
17
20
 
18
21
  # A2A delegation calls run a full agent loop (LLM + tool calls + DB queries).
19
22
  # The framework does not impose a default agent-run timeout; if a template sets
@@ -1,6 +1,6 @@
1
1
  [build]
2
2
  ignore = "node ./scripts/netlify-ignore-build.mjs chat"
3
- command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && NITRO_PRESET=netlify pnpm --filter chat build && if [ \"${CONTEXT:-}\" = \"production\" ]; then pnpm --filter chat migrate:production; fi"
3
+ command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && NITRO_PRESET=netlify pnpm --filter chat build && if [ \"${CONTEXT:-}\" = \"production\" ] || [ \"${AGENT_NATIVE_RUN_RELEASE_MIGRATIONS:-}\" = \"1\" ]; then pnpm --filter chat migrate:production; fi"
4
4
  publish = "templates/chat/dist"
5
5
  functions = "templates/chat/.netlify/functions-internal"
6
6
 
@@ -14,3 +14,6 @@ NPM_CONFIG_PRODUCTION = "false"
14
14
  AGENT_NATIVE_HOSTED_HARNESS = "true"
15
15
  AGENT_NATIVE_ENABLE_KEEP_WARM = "1"
16
16
  AGENT_NATIVE_DISABLE_KEEP_WARM_BACKGROUND = "1"
17
+ # Production release migrations own schema setup; request functions must skip
18
+ # migration probes on every serverless invocation.
19
+ AGENT_NATIVE_RELEASE_MIGRATIONS = "1"
@@ -67,7 +67,6 @@ import {
67
67
  startBubbleWebrtc,
68
68
  type BubbleWebrtcHandle,
69
69
  } from "./lib/bubble-webrtc";
70
- import { openBoundOAuthWindow } from "./lib/desktop-oauth-window";
71
70
  import {
72
71
  getCameraStreamWithFallback,
73
72
  isMediaConstraintFailure,
@@ -2127,17 +2126,15 @@ export function App() {
2127
2126
  void tick();
2128
2127
  }
2129
2128
 
2130
- // Google verification stays in a child of the bound Tauri WebView so the
2131
- // callback sees the same browser-binding cookie. Magic-link verification
2132
- // still completes in the system browser through its own exchange flow.
2129
+ // Google verification opens in the system browser so the user's Google
2130
+ // cookies are available. The client-held verifier still gates the exchange
2131
+ // back into this Tauri app.
2133
2132
  async function signInExternal() {
2134
2133
  if (signInInflightRef.current) return;
2135
2134
  signInInflightRef.current = true;
2136
- let oauthWindow: ReturnType<typeof openBoundOAuthWindow> | null = null;
2137
2135
 
2138
2136
  try {
2139
2137
  setSignInError(null);
2140
- oauthWindow = openBoundOAuthWindow();
2141
2138
  const flowId = crypto.randomUUID?.() ?? null;
2142
2139
  const verifier = (() => {
2143
2140
  const randomUuid = crypto.randomUUID;
@@ -2196,12 +2193,11 @@ export function App() {
2196
2193
  : "Could not start Google sign-in.";
2197
2194
  throw new Error(message);
2198
2195
  }
2199
- oauthWindow.location.href = authPayload.url;
2196
+ await openExternal(authPayload.url);
2200
2197
  setSignInPending("google");
2201
2198
  startDesktopAuthExchange(flowId, "google", verifier);
2202
2199
  } catch (err) {
2203
2200
  console.error("[clips-tray] signInExternal failed:", err);
2204
- oauthWindow?.close();
2205
2201
  signInInflightRef.current = false;
2206
2202
  setSignInPending(null);
2207
2203
  setSignInError(
@@ -1,6 +1,6 @@
1
1
  [build]
2
2
  ignore = "node ./scripts/netlify-ignore-build.mjs clips"
3
- command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && if [ \"${agentNativePrebuiltBuild:-}\" = \"true\" ]; then export DATABASE_URL=\"${agentNativePrebuiltDatabaseUrl:?}\" BETTER_AUTH_SECRET=\"${agentNativePrebuiltAuthSecret:?}\"; fi && pnpm install && NITRO_PRESET=netlify pnpm --filter clips build && pnpm exec tsx templates/clips/jobs/emit-netlify-brain-export-cron.ts && if [ \"${CONTEXT:-}\" = \"production\" ] && [ \"${agentNativePrebuiltBuild:-}\" != \"true\" ]; then pnpm --filter clips migrate:production; fi"
3
+ command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && if [ \"${agentNativePrebuiltBuild:-}\" = \"true\" ]; then export DATABASE_URL=\"${agentNativePrebuiltDatabaseUrl:?}\" BETTER_AUTH_SECRET=\"${agentNativePrebuiltAuthSecret:?}\"; fi && pnpm install && NITRO_PRESET=netlify pnpm --filter clips build && pnpm exec tsx templates/clips/jobs/emit-netlify-brain-export-cron.ts && if { [ \"${CONTEXT:-}\" = \"production\" ] || [ \"${AGENT_NATIVE_RUN_RELEASE_MIGRATIONS:-}\" = \"1\" ]; } && [ \"${agentNativePrebuiltBuild:-}\" != \"true\" ]; then pnpm --filter clips migrate:production; fi"
4
4
  publish = "templates/clips/dist"
5
5
  functions = "templates/clips/.netlify/functions-internal"
6
6
 
@@ -18,6 +18,9 @@ AGENT_CHAT_DURABLE_BACKGROUND = "true"
18
18
  AGENT_NATIVE_HOSTED_HARNESS = "true"
19
19
  AGENT_NATIVE_ENABLE_KEEP_WARM = "1"
20
20
  AGENT_NATIVE_DISABLE_KEEP_WARM_BACKGROUND = "1"
21
+ # Production release migrations own schema setup; request functions must skip
22
+ # migration probes on every serverless invocation.
23
+ AGENT_NATIVE_RELEASE_MIGRATIONS = "1"
21
24
 
22
25
  # Netlify Functions run on linux/x64 (AWS Lambda). This tells the deploy build
23
26
  # to bundle the matching ffmpeg-static binary into the server bundle so frame
@@ -64,6 +64,7 @@ export default defineEventHandler(async (event: H3Event) => {
64
64
  }
65
65
  const calendarConnect =
66
66
  q.calendar === "1" || q.calendar === "true" || q.product === "calendar";
67
+ const desktopWebview = desktop && q.webview === "1" && !calendarConnect;
67
68
  let desktopVerifierHash: string | undefined;
68
69
  let desktopBrowserBindingHash: string | undefined;
69
70
  if (flowId && !calendarConnect) {
@@ -77,12 +78,20 @@ export default defineEventHandler(async (event: H3Event) => {
77
78
  return { error: "Invalid desktop exchange challenge." };
78
79
  }
79
80
  try {
80
- desktopBrowserBindingHash = prepareDesktopOAuthBrowserBinding(event);
81
- desktopVerifierHash = await registerDesktopExchange(
82
- flowId,
83
- verifier,
84
- desktopBrowserBindingHash,
85
- );
81
+ // The system-browser flow deliberately uses the user's existing
82
+ // Google cookies. The client-held verifier still gates the exchange
83
+ // token returned to the initiating Tauri app. Only an in-app WebView
84
+ // needs the additional browser-partition binding.
85
+ if (desktopWebview) {
86
+ desktopBrowserBindingHash = prepareDesktopOAuthBrowserBinding(event);
87
+ desktopVerifierHash = await registerDesktopExchange(
88
+ flowId,
89
+ verifier,
90
+ desktopBrowserBindingHash,
91
+ );
92
+ } else {
93
+ desktopVerifierHash = await registerDesktopExchange(flowId, verifier);
94
+ }
86
95
  } catch {
87
96
  setResponseStatus(event, 400);
88
97
  return { error: "Invalid desktop exchange challenge." };
@@ -116,13 +125,10 @@ export default defineEventHandler(async (event: H3Event) => {
116
125
  redirectUri,
117
126
  owner,
118
127
  desktop,
119
- desktopWebview: desktop && q.webview === "1" && !calendarConnect,
128
+ desktopWebview,
120
129
  addAccount: calendarConnect,
121
130
  app: CLIPS_GOOGLE_OAUTH_APP_ID,
122
- returnUrl:
123
- desktop && q.webview === "1" && !calendarConnect
124
- ? "/?desktop_auth=complete"
125
- : returnUrl,
131
+ returnUrl: desktopWebview ? "/?desktop_auth=complete" : returnUrl,
126
132
  flowId: calendarConnect ? undefined : flowId,
127
133
  desktopVerifierHash,
128
134
  desktopBrowserBindingHash,
@@ -35,11 +35,12 @@ async function handleGoogleSignInCallback(
35
35
  if (
36
36
  flowId &&
37
37
  (!state.desktopVerifierHash ||
38
- !state.desktopBrowserBindingHash ||
39
- !matchesDesktopOAuthBrowserBinding(
40
- event,
41
- state.desktopBrowserBindingHash,
42
- ))
38
+ (state.desktopWebview &&
39
+ (!state.desktopBrowserBindingHash ||
40
+ !matchesDesktopOAuthBrowserBinding(
41
+ event,
42
+ state.desktopBrowserBindingHash,
43
+ ))))
43
44
  ) {
44
45
  return oauthErrorPage("Desktop OAuth browser binding is invalid.");
45
46
  }
@@ -1,6 +1,6 @@
1
1
  [build]
2
2
  ignore = "node ./scripts/netlify-ignore-build.mjs content"
3
- command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && NITRO_PRESET=netlify pnpm --filter content build && if [ \"${CONTEXT:-}\" = \"production\" ]; then pnpm --filter content migrate:production; fi"
3
+ command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && NITRO_PRESET=netlify pnpm --filter content build && if [ \"${CONTEXT:-}\" = \"production\" ] || [ \"${AGENT_NATIVE_RUN_RELEASE_MIGRATIONS:-}\" = \"1\" ]; then pnpm --filter content migrate:production; fi"
4
4
  publish = "templates/content/dist"
5
5
  functions = "templates/content/.netlify/functions-internal"
6
6
 
@@ -18,6 +18,9 @@ AGENT_CHAT_DURABLE_BACKGROUND = "true"
18
18
  AGENT_NATIVE_HOSTED_HARNESS = "true"
19
19
  AGENT_NATIVE_ENABLE_KEEP_WARM = "1"
20
20
  AGENT_NATIVE_DISABLE_KEEP_WARM_BACKGROUND = "1"
21
+ # Production release migrations own schema setup; request functions must skip
22
+ # migration probes on every serverless invocation.
23
+ AGENT_NATIVE_RELEASE_MIGRATIONS = "1"
21
24
 
22
25
  # A2A delegation calls run a full agent loop (LLM + tool calls + DB queries).
23
26
  # The framework does not impose a default agent-run timeout; if a template sets
@@ -1,6 +1,6 @@
1
1
  [build]
2
2
  ignore = "node ./scripts/netlify-ignore-build.mjs crm"
3
- command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && NITRO_PRESET=netlify pnpm --filter crm build && if [ \"${CONTEXT:-}\" = \"production\" ]; then pnpm --filter crm migrate:production; fi"
3
+ command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && NITRO_PRESET=netlify pnpm --filter crm build && if [ \"${CONTEXT:-}\" = \"production\" ] || [ \"${AGENT_NATIVE_RUN_RELEASE_MIGRATIONS:-}\" = \"1\" ]; then pnpm --filter crm migrate:production; fi"
4
4
  publish = "templates/crm/dist"
5
5
  functions = "templates/crm/.netlify/functions-internal"
6
6
 
@@ -9,3 +9,8 @@ GA_MEASUREMENT_ID = "G-ESF7FYXGN9"
9
9
  GTM_CONTAINER_ID = "GTM-N3WSTXZ"
10
10
  NITRO_PRESET = "netlify"
11
11
  NPM_CONFIG_PRODUCTION = "false"
12
+
13
+ [context.production.environment]
14
+ # Production release migrations own schema setup; request functions must skip
15
+ # migration probes on every serverless invocation.
16
+ AGENT_NATIVE_RELEASE_MIGRATIONS = "1"
@@ -7,7 +7,10 @@ import {
7
7
  getBrowserTabId,
8
8
  useSession,
9
9
  } from "@agent-native/core/client/hooks";
10
- import { setAgentNativeApiDisabled } from "@agent-native/core/client/host";
10
+ import {
11
+ isEmbedAuthActive,
12
+ setAgentNativeApiDisabled,
13
+ } from "@agent-native/core/client/host";
11
14
  import { getLocaleInitScript, useT } from "@agent-native/core/client/i18n";
12
15
  import {
13
16
  CommandMenu,
@@ -230,6 +233,7 @@ export default function Root() {
230
233
  <AppProviders
231
234
  queryClient={queryClient}
232
235
  isPublicPath={isPublicPath}
236
+ sessionBypass={isEmbedAuthActive()}
233
237
  i18n={{ catalog: i18nCatalog, persistPreference: !isPublicPath }}
234
238
  toaster={<DesignToaster />}
235
239
  >
@@ -1,6 +1,6 @@
1
1
  [build]
2
2
  ignore = "node ./scripts/netlify-ignore-build.mjs design"
3
- command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && NITRO_PRESET=netlify pnpm --filter design build && if [ \"${CONTEXT:-}\" = \"production\" ]; then pnpm --filter design migrate:production; fi"
3
+ command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && NITRO_PRESET=netlify pnpm --filter design build && if [ \"${CONTEXT:-}\" = \"production\" ] || [ \"${AGENT_NATIVE_RUN_RELEASE_MIGRATIONS:-}\" = \"1\" ]; then pnpm --filter design migrate:production; fi"
4
4
  publish = "templates/design/dist"
5
5
  functions = "templates/design/.netlify/functions-internal"
6
6
 
@@ -15,6 +15,9 @@ AGENT_CHAT_DURABLE_BACKGROUND = "true"
15
15
  AGENT_NATIVE_HOSTED_HARNESS = "true"
16
16
  AGENT_NATIVE_ENABLE_KEEP_WARM = "1"
17
17
  AGENT_NATIVE_DISABLE_KEEP_WARM_BACKGROUND = "1"
18
+ # Production release migrations own schema setup; request functions must skip
19
+ # migration probes on every serverless invocation.
20
+ AGENT_NATIVE_RELEASE_MIGRATIONS = "1"
18
21
 
19
22
  # Emit the Netlify background function used by Design's durable agent-chat opt-in.
20
23
  # The normal server timeout still protects non-background HTTP handlers.
@@ -1,6 +1,6 @@
1
1
  [build]
2
2
  ignore = "node ./scripts/netlify-ignore-build.mjs dispatch"
3
- command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && NITRO_PRESET=netlify pnpm --filter dispatch build && if [ \"${CONTEXT:-}\" = \"production\" ]; then pnpm --filter dispatch migrate:production; fi"
3
+ command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && NITRO_PRESET=netlify pnpm --filter dispatch build && if [ \"${CONTEXT:-}\" = \"production\" ] || [ \"${AGENT_NATIVE_RUN_RELEASE_MIGRATIONS:-}\" = \"1\" ]; then pnpm --filter dispatch migrate:production; fi"
4
4
  publish = "templates/dispatch/dist"
5
5
  functions = "templates/dispatch/.netlify/functions-internal"
6
6
 
@@ -17,6 +17,9 @@ AGENT_CHAT_DURABLE_BACKGROUND = "true"
17
17
  AGENT_NATIVE_HOSTED_HARNESS = "true"
18
18
  AGENT_NATIVE_ENABLE_KEEP_WARM = "1"
19
19
  AGENT_NATIVE_DISABLE_KEEP_WARM_BACKGROUND = "1"
20
+ # Production release migrations own schema setup; request functions must skip
21
+ # migration probes on every serverless invocation.
22
+ AGENT_NATIVE_RELEASE_MIGRATIONS = "1"
20
23
 
21
24
  # A2A delegation calls run a full agent loop (LLM + tool calls + DB queries).
22
25
  # The framework does not impose a default agent-run timeout; if a template sets
@@ -1,5 +1,5 @@
1
1
  [build]
2
- command = "export DATABASE_URL=\"${NETLIFY_DATABASE_URL:-$DATABASE_URL}\" && pnpm install && DATABASE_URL=\"${NETLIFY_DATABASE_URL_UNPOOLED:-$DATABASE_URL}\" NITRO_PRESET=netlify pnpm --filter factory build && if [ \"${CONTEXT:-}\" = \"production\" ]; then DATABASE_URL=\"${NETLIFY_DATABASE_URL_UNPOOLED:-$DATABASE_URL}\" pnpm --filter factory migrate:production; fi"
2
+ command = "export DATABASE_URL=\"${NETLIFY_DATABASE_URL:-$DATABASE_URL}\" && pnpm install && DATABASE_URL=\"${NETLIFY_DATABASE_URL_UNPOOLED:-$DATABASE_URL}\" NITRO_PRESET=netlify pnpm --filter factory build && if [ \"${CONTEXT:-}\" = \"production\" ] || [ \"${AGENT_NATIVE_RUN_RELEASE_MIGRATIONS:-}\" = \"1\" ]; then DATABASE_URL=\"${NETLIFY_DATABASE_URL_UNPOOLED:-$DATABASE_URL}\" pnpm --filter factory migrate:production; fi"
3
3
  publish = "dist"
4
4
  functions = ".netlify/functions-internal"
5
5
 
@@ -11,3 +11,6 @@ NPM_CONFIG_PRODUCTION = "false"
11
11
 
12
12
  [context.production.environment]
13
13
  AGENT_NATIVE_HOSTED_HARNESS = "true"
14
+ # Production release migrations own schema setup; request functions must skip
15
+ # migration probes on every serverless invocation.
16
+ AGENT_NATIVE_RELEASE_MIGRATIONS = "1"
@@ -1,6 +1,6 @@
1
1
  [build]
2
2
  ignore = "node ./scripts/netlify-ignore-build.mjs forms"
3
- command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && DATABASE_URL=${NETLIFY_DATABASE_URL_UNPOOLED:-$DATABASE_URL} NITRO_PRESET=netlify pnpm --filter forms build && if [ \"${CONTEXT:-}\" = \"production\" ]; then DATABASE_URL=${NETLIFY_DATABASE_URL_UNPOOLED:-$DATABASE_URL} pnpm --filter forms migrate:production; fi"
3
+ command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && DATABASE_URL=${NETLIFY_DATABASE_URL_UNPOOLED:-$DATABASE_URL} NITRO_PRESET=netlify pnpm --filter forms build && if [ \"${CONTEXT:-}\" = \"production\" ] || [ \"${AGENT_NATIVE_RUN_RELEASE_MIGRATIONS:-}\" = \"1\" ]; then DATABASE_URL=${NETLIFY_DATABASE_URL_UNPOOLED:-$DATABASE_URL} pnpm --filter forms migrate:production; fi"
4
4
  publish = "templates/forms/dist"
5
5
  functions = "templates/forms/.netlify/functions-internal"
6
6
 
@@ -14,6 +14,9 @@ NPM_CONFIG_PRODUCTION = "false"
14
14
  AGENT_NATIVE_HOSTED_HARNESS = "true"
15
15
  AGENT_NATIVE_ENABLE_KEEP_WARM = "1"
16
16
  AGENT_NATIVE_DISABLE_KEEP_WARM_BACKGROUND = "1"
17
+ # Production release migrations own schema setup; request functions must skip
18
+ # migration probes on every serverless invocation.
19
+ AGENT_NATIVE_RELEASE_MIGRATIONS = "1"
17
20
 
18
21
  # A2A delegation calls run a full agent loop (LLM + tool calls + DB queries).
19
22
  # The framework does not impose a default agent-run timeout; if a template sets
@@ -1,6 +1,6 @@
1
1
  [build]
2
2
  ignore = "node ./scripts/netlify-ignore-build.mjs macros"
3
- command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && DATABASE_URL=${NETLIFY_DATABASE_URL_UNPOOLED:-$DATABASE_URL} NITRO_PRESET=netlify pnpm --filter macros build && if [ \"${CONTEXT:-}\" = \"production\" ]; then DATABASE_URL=${NETLIFY_DATABASE_URL_UNPOOLED:-$DATABASE_URL} pnpm --filter macros migrate:production; fi"
3
+ command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && DATABASE_URL=${NETLIFY_DATABASE_URL_UNPOOLED:-$DATABASE_URL} NITRO_PRESET=netlify pnpm --filter macros build && if [ \"${CONTEXT:-}\" = \"production\" ] || [ \"${AGENT_NATIVE_RUN_RELEASE_MIGRATIONS:-}\" = \"1\" ]; then DATABASE_URL=${NETLIFY_DATABASE_URL_UNPOOLED:-$DATABASE_URL} pnpm --filter macros migrate:production; fi"
4
4
  publish = "templates/macros/dist"
5
5
  functions = "templates/macros/.netlify/functions-internal"
6
6
 
@@ -16,6 +16,6 @@ AGENT_NATIVE_ENABLE_KEEP_WARM = "1"
16
16
  AGENT_NATIVE_DISABLE_KEEP_WARM_BACKGROUND = "1"
17
17
  # Macros owns its schema at release time (`migrate:production` above), so
18
18
  # production request functions must not probe the database for migrations.
19
- # Preview functions still run request-path migrations because previews do not
20
- # run the production release migration step.
19
+ # Ordinary deploy previews still run request-path migrations; the beta
20
+ # prebuilt lane explicitly supplies the release owner.
21
21
  AGENT_NATIVE_RELEASE_MIGRATIONS = "1"