@agent-native/core 0.167.1 → 0.168.0

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 (117) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/agent-native-docs/SKILL.md +11 -0
  3. package/corpus/templates/assets/.agents/skills/agent-native-docs/SKILL.md +11 -0
  4. package/corpus/templates/brain/.agents/skills/agent-native-docs/SKILL.md +11 -0
  5. package/corpus/templates/brain/actions/list-sources.ts +17 -7
  6. package/corpus/templates/brain/app/components/brain/Surface.tsx +4 -2
  7. package/corpus/templates/brain/app/lib/brain.ts +13 -3
  8. package/corpus/templates/brain/server/lib/brain-health.ts +5 -8
  9. package/corpus/templates/brain/server/lib/brain.ts +1 -0
  10. package/corpus/templates/brain/server/lib/capture-sanitization.ts +5 -0
  11. package/corpus/templates/brain/server/routes/api/brain/queue/run.post.ts +3 -2
  12. package/corpus/templates/calendar/.agents/skills/agent-native-docs/SKILL.md +11 -0
  13. package/corpus/templates/chat/.agents/skills/agent-native-docs/SKILL.md +11 -0
  14. package/corpus/templates/clips/.agents/skills/agent-native-docs/SKILL.md +11 -0
  15. package/corpus/templates/clips/app/routes/download.tsx +78 -131
  16. package/corpus/templates/clips/desktop/src/app.tsx +11 -10
  17. package/corpus/templates/clips/desktop/src/lib/desktop-oauth-window.ts +23 -0
  18. package/corpus/templates/content/.agents/skills/agent-native-docs/SKILL.md +11 -0
  19. package/corpus/templates/crm/.agents/skills/agent-native-docs/SKILL.md +11 -0
  20. package/corpus/templates/design/.agents/skills/agent-native-docs/SKILL.md +11 -0
  21. package/corpus/templates/dispatch/.agents/skills/agent-native-docs/SKILL.md +11 -0
  22. package/corpus/templates/factory/.agents/skills/agent-native-docs/SKILL.md +11 -0
  23. package/corpus/templates/forms/.agents/skills/agent-native-docs/SKILL.md +11 -0
  24. package/corpus/templates/macros/.agents/skills/agent-native-docs/SKILL.md +11 -0
  25. package/corpus/templates/mail/.agents/skills/agent-native-docs/SKILL.md +11 -0
  26. package/corpus/templates/plan/.agents/skills/agent-native-docs/SKILL.md +11 -0
  27. package/corpus/templates/slides/.agents/skills/agent-native-docs/SKILL.md +11 -0
  28. package/corpus/templates/tasks/.agents/skills/agent-native-docs/SKILL.md +11 -0
  29. package/dist/chat-threads/store.d.ts +7 -0
  30. package/dist/chat-threads/store.js +15 -0
  31. package/dist/client/AboutAgentNativeDialog.d.ts +5 -0
  32. package/dist/client/AboutAgentNativeDialog.js +56 -0
  33. package/dist/client/AgentPanel.d.ts +5 -1
  34. package/dist/client/AgentPanel.js +8 -8
  35. package/dist/client/AssistantChat.d.ts +3 -1
  36. package/dist/client/AssistantChat.js +22 -6
  37. package/dist/client/CommandMenu.d.ts +6 -1
  38. package/dist/client/CommandMenu.js +46 -3
  39. package/dist/client/EnvironmentBadge.js +4 -1
  40. package/dist/client/MultiTabAssistantChat.d.ts +3 -1
  41. package/dist/client/MultiTabAssistantChat.js +5 -4
  42. package/dist/client/agent-native-version.d.ts +12 -0
  43. package/dist/client/agent-native-version.js +36 -0
  44. package/dist/client/agent-page/AgentJobsTab.js +39 -6
  45. package/dist/client/agent-page/AutomationScheduleDialog.d.ts +10 -1
  46. package/dist/client/agent-page/AutomationScheduleDialog.js +3 -2
  47. package/dist/client/agent-page/ScheduledTriggerNotice.d.ts +22 -0
  48. package/dist/client/agent-page/ScheduledTriggerNotice.js +84 -0
  49. package/dist/client/agent-page/scheduled-trigger-state.d.ts +28 -0
  50. package/dist/client/agent-page/scheduled-trigger-state.js +10 -0
  51. package/dist/client/agent-page/use-jobs.d.ts +7 -0
  52. package/dist/client/agent-page/use-jobs.js +14 -0
  53. package/dist/client/blocks/library/diagram.config.d.ts +4 -1
  54. package/dist/client/blocks/library/diagram.js +1 -1
  55. package/dist/client/chat/run-recovery.js +15 -7
  56. package/dist/client/use-chat-threads.d.ts +7 -0
  57. package/dist/client/use-chat-threads.js +144 -40
  58. package/dist/collab/routes.d.ts +1 -1
  59. package/dist/config.d.ts +3 -1
  60. package/dist/config.js +14 -9
  61. package/dist/deploy/build.d.ts +5 -0
  62. package/dist/deploy/build.js +12 -1
  63. package/dist/framework-tools.js +1 -0
  64. package/dist/jobs/actions/get-scheduled-trigger-status.d.ts +13 -0
  65. package/dist/jobs/actions/get-scheduled-trigger-status.js +21 -0
  66. package/dist/localization/core-messages/ar-SA.js +6 -0
  67. package/dist/localization/core-messages/de-DE.js +6 -0
  68. package/dist/localization/core-messages/en-US.d.ts +6 -0
  69. package/dist/localization/core-messages/en-US.js +6 -0
  70. package/dist/localization/core-messages/es-ES.js +6 -0
  71. package/dist/localization/core-messages/fr-FR.js +6 -0
  72. package/dist/localization/core-messages/hi-IN.js +6 -0
  73. package/dist/localization/core-messages/ja-JP.js +6 -0
  74. package/dist/localization/core-messages/ko-KR.js +6 -0
  75. package/dist/localization/core-messages/pt-BR.js +6 -0
  76. package/dist/localization/core-messages/zh-CN.js +6 -0
  77. package/dist/localization/core-messages/zh-TW.js +6 -0
  78. package/dist/localization/core-messages.d.ts +6 -0
  79. package/dist/localization/default-messages.d.ts +14 -0
  80. package/dist/localization/default-messages.js +14 -0
  81. package/dist/mcp/screen-memory-stdio.d.ts +7 -7
  82. package/dist/notifications/routes.d.ts +1 -1
  83. package/dist/observability/routes.d.ts +3 -3
  84. package/dist/provider-api/actions/custom-provider-registration.d.ts +1 -1
  85. package/dist/provider-api/actions/provider-api.d.ts +12 -12
  86. package/dist/resources/handlers.d.ts +2 -2
  87. package/dist/server/action-discovery.js +4 -0
  88. package/dist/server/agent-chat/recurring-jobs-runtime.d.ts +42 -1
  89. package/dist/server/agent-chat/recurring-jobs-runtime.js +102 -9
  90. package/dist/server/agent-chat-plugin.d.ts +3 -1
  91. package/dist/server/agent-chat-plugin.js +115 -24
  92. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  93. package/dist/server/attribution.d.ts +29 -0
  94. package/dist/server/attribution.js +68 -0
  95. package/dist/server/auth.js +58 -15
  96. package/dist/server/better-auth-instance.js +16 -4
  97. package/dist/server/identity-sso.js +14 -2
  98. package/dist/server/realtime-token.d.ts +1 -1
  99. package/dist/server/request-context.d.ts +8 -0
  100. package/dist/server/request-context.js +4 -0
  101. package/dist/templates/chat/.agents/skills/agent-native-docs/SKILL.md +11 -0
  102. package/dist/templates/default/.agents/skills/agent-native-docs/SKILL.md +11 -0
  103. package/dist/templates/headless/.agents/skills/agent-native-docs/SKILL.md +11 -0
  104. package/dist/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +11 -0
  105. package/dist/vite/agent-native-config-loader.js +1 -1
  106. package/dist/vite/client.js +19 -8
  107. package/dist/vite/package-versions.d.ts +1 -0
  108. package/dist/vite/package-versions.js +97 -0
  109. package/docs/content/agent-native-config.mdx +55 -31
  110. package/docs/content/deployment.mdx +3 -1
  111. package/docs/content/environment-variables.mdx +51 -14
  112. package/docs/content/recurring-jobs.mdx +6 -0
  113. package/package.json +2 -2
  114. package/src/templates/chat/.agents/skills/agent-native-docs/SKILL.md +11 -0
  115. package/src/templates/default/.agents/skills/agent-native-docs/SKILL.md +11 -0
  116. package/src/templates/headless/.agents/skills/agent-native-docs/SKILL.md +11 -0
  117. package/src/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +11 -0
@@ -58,7 +58,7 @@ import { isValidWorkspaceAppIdFormat } from "../shared/workspace-app-id.js";
58
58
  import { injectAnalyticsIntoHtml } from "./analytics.js";
59
59
  import { getConfiguredAppBasePath } from "./app-base-path.js";
60
60
  import { getAppProductionUrl } from "./app-url.js";
61
- import { readAnalyticsAnonymousId, readFirstTouchAttribution, signupAttributionFromCookieHeader, } from "./attribution.js";
61
+ import { addSignupAttributionHeader, readAnalyticsAnonymousId, readFirstTouchAttribution, signupAttributionContextFromCookieHeader, signupAttributionFromCookieHeader, } from "./attribution.js";
62
62
  import { getAuthLoginMode } from "./auth-login-mode.js";
63
63
  import { injectBetaOptOutPersistence } from "./beta-opt-out-html.js";
64
64
  import { createBetterAuthSessionForEmail, ensureGoogleAuthIdentity, getAuthSecret, getBetterAuth, getBetterAuthSync, isDeployPreview, } from "./better-auth-instance.js";
@@ -73,6 +73,7 @@ import { ensureCanonicalUserForLegacySession } from "./legacy-auth-migration.js"
73
73
  import { encodeMagicLinkSignupAttribution, MAGIC_LINK_ATTRIBUTION_PARAM, } from "./magic-link-attribution.js";
74
74
  import { safeOAuthReturnUrl } from "./oauth-return-url.js";
75
75
  import { getOnboardingHtml, getResetPasswordHtml, } from "./onboarding-html.js";
76
+ import { getRequestContext, hasContinuationLocalRequestContext, runWithRequestContext, } from "./request-context.js";
76
77
  import { captureAuthError } from "./sentry.js";
77
78
  import { forgetCachedSessionEmail, getCachedSessionEmail, invalidateSessionEmailCache, setCachedSessionEmail, } from "./session-email-cache.js";
78
79
  import { isWorkspaceOAuthCallbackRelayEnabled } from "./workspace-oauth.js";
@@ -83,6 +84,23 @@ import { isWorkspaceOAuthCallbackRelayEnabled } from "./workspace-oauth.js";
83
84
  export function getSessionMaxAge() {
84
85
  return sessionMaxAge;
85
86
  }
87
+ function withSignupAttributionContext(cookieHeader, fn) {
88
+ const signupAttribution = signupAttributionContextFromCookieHeader(cookieHeader);
89
+ if (!hasContinuationLocalRequestContext())
90
+ return fn();
91
+ return runWithRequestContext({
92
+ ...(getRequestContext() ?? {}),
93
+ signupAttribution,
94
+ }, fn);
95
+ }
96
+ function requestWithSignupAttribution(request, signupAttribution) {
97
+ return new Request(request, {
98
+ headers: addSignupAttributionHeader(request.headers, signupAttribution),
99
+ });
100
+ }
101
+ function headersWithSignupAttribution(headers, cookieHeader) {
102
+ return addSignupAttributionHeader(headers, signupAttributionContextFromCookieHeader(cookieHeader));
103
+ }
86
104
  // ---------------------------------------------------------------------------
87
105
  // Constants
88
106
  // ---------------------------------------------------------------------------
@@ -416,6 +434,9 @@ async function readDesktopSsoSafely(event) {
416
434
  return null;
417
435
  return await readDesktopSso();
418
436
  }
437
+ function isDesktopSessionCookieOnlyCheck(event) {
438
+ return getHeader(event, "x-agent-native-session-check") === "cookie-only";
439
+ }
419
440
  /**
420
441
  * Extract the framework session token from a Better Auth response's
421
442
  * Set-Cookie headers, if any. Used by the password-reset path to skip
@@ -2688,6 +2709,7 @@ export async function getSession(event) {
2688
2709
  })());
2689
2710
  }
2690
2711
  async function resolveSessionUncached(event) {
2712
+ const cookieOnlyDesktopCheck = isDesktopSessionCookieOnlyCheck(event);
2691
2713
  // 1. MCP App embed session. This is a short-lived browser session minted
2692
2714
  // from a one-time ticket that was scoped to the authenticated MCP caller.
2693
2715
  // It lets an inline MCP App iframe load the real app without reusing the
@@ -2724,9 +2746,11 @@ async function resolveSessionUncached(event) {
2724
2746
  // templates too. Gated on `readDesktopSsoSafely` so a non-loopback
2725
2747
  // request that spoofs `User-Agent: ... Electron/...` cannot read the
2726
2748
  // home-dir broker file (and so production builds never consult it).
2727
- const sso = await readDesktopSsoSafely(event);
2728
- if (sso?.email)
2729
- return { email: sso.email, token: sso.token };
2749
+ if (!cookieOnlyDesktopCheck) {
2750
+ const sso = await readDesktopSsoSafely(event);
2751
+ if (sso?.email)
2752
+ return { email: sso.email, token: sso.token };
2753
+ }
2730
2754
  // Fall through to mobile _session check
2731
2755
  }
2732
2756
  else {
@@ -2765,9 +2789,11 @@ async function resolveSessionUncached(event) {
2765
2789
  // a loopback (127.0.0.1 / ::1) source IP, and a non-production NODE_ENV
2766
2790
  // — anything else is rejected so a hostile network request cannot
2767
2791
  // impersonate whichever email last signed into the desktop app.
2768
- const sso = await readDesktopSsoSafely(event);
2769
- if (sso?.email) {
2770
- return { email: sso.email, token: sso.token };
2792
+ if (!cookieOnlyDesktopCheck) {
2793
+ const sso = await readDesktopSsoSafely(event);
2794
+ if (sso?.email) {
2795
+ return { email: sso.email, token: sso.token };
2796
+ }
2771
2797
  }
2772
2798
  }
2773
2799
  // 8. Mobile WebView bridge — _session query param
@@ -3699,11 +3725,18 @@ async function mountBetterAuthRoutes(app, options) {
3699
3725
  getMethod(event) === "POST";
3700
3726
  const isMagicLinkRequest = reqPath.includes("/sign-in/magic-link") && getMethod(event) === "POST";
3701
3727
  const isMagicLinkVerification = reqPath.includes("/magic-link/verify") && getMethod(event) === "GET";
3728
+ const isEmailSignup = reqPath.includes("/sign-up/email") && getMethod(event) === "POST";
3702
3729
  const isSignOut = reqPath.includes("sign-out") && getMethod(event) === "POST";
3703
3730
  if (isSignOut)
3704
3731
  optOutOfAuthDisabledSession(event);
3705
3732
  const authRequest = toWebRequest(event);
3706
3733
  let requestForAuth = authRequest;
3734
+ const signupCookieHeader = isEmailSignup
3735
+ ? authRequest.headers.get("cookie")
3736
+ : undefined;
3737
+ const signupAttribution = isEmailSignup
3738
+ ? signupAttributionContextFromCookieHeader(signupCookieHeader)
3739
+ : undefined;
3707
3740
  let magicLinkPreConsume;
3708
3741
  if (isMagicLinkVerification) {
3709
3742
  const verificationURL = new URL(authRequest.url);
@@ -3820,9 +3853,14 @@ async function mountBetterAuthRoutes(app, options) {
3820
3853
  // validation error.
3821
3854
  }
3822
3855
  }
3856
+ if (signupAttribution) {
3857
+ requestForAuth = requestWithSignupAttribution(requestForAuth, signupAttribution);
3858
+ }
3823
3859
  let response;
3824
3860
  try {
3825
- response = await auth.handler(requestForAuth);
3861
+ response = await (isEmailSignup
3862
+ ? withSignupAttributionContext(signupCookieHeader, () => auth.handler(requestForAuth))
3863
+ : auth.handler(requestForAuth));
3826
3864
  }
3827
3865
  catch (error) {
3828
3866
  if (isMagicLinkVerification) {
@@ -4127,10 +4165,15 @@ async function mountBetterAuthRoutes(app, options) {
4127
4165
  return { error: GOOGLE_AUTH_REQUIRED_MESSAGE };
4128
4166
  }
4129
4167
  try {
4130
- await auth.api.signUpEmail({
4131
- body: { email, password, name: email.split("@")[0], callbackURL },
4132
- headers: event.headers,
4133
- });
4168
+ await withSignupAttributionContext(getHeader(event, "cookie") ?? null, () => auth.api.signUpEmail({
4169
+ body: {
4170
+ email,
4171
+ password,
4172
+ name: email.split("@")[0],
4173
+ callbackURL,
4174
+ },
4175
+ headers: headersWithSignupAttribution(event.headers, getHeader(event, "cookie") ?? null),
4176
+ }));
4134
4177
  setFirstRunOnboardingCookie(event);
4135
4178
  return { ok: true };
4136
4179
  }
@@ -4384,10 +4427,10 @@ function mountAuthFallbackRoutes(app) {
4384
4427
  }
4385
4428
  try {
4386
4429
  const auth = await getBetterAuth();
4387
- await auth.api.signUpEmail({
4430
+ await withSignupAttributionContext(getHeader(event, "cookie") ?? null, () => auth.api.signUpEmail({
4388
4431
  body: { email, password, name: email.split("@")[0] },
4389
- headers: event.headers,
4390
- });
4432
+ headers: headersWithSignupAttribution(event.headers, getHeader(event, "cookie") ?? null),
4433
+ }));
4391
4434
  setFirstRunOnboardingCookie(event);
4392
4435
  return { ok: true };
4393
4436
  }
@@ -26,13 +26,14 @@ import { PASSWORD_MAX_LENGTH, PASSWORD_MIN_LENGTH, } from "../shared/password-po
26
26
  import { formatRuntimeConfigReport, getRuntimeConfigReport, } from "../shared/runtime-config.js";
27
27
  import { flushTracking, identify, track } from "../tracking/index.js";
28
28
  import { getAppProductionUrl } from "./app-url.js";
29
- import { readAnalyticsAnonymousId, signupAttributionFromCookieHeader, } from "./attribution.js";
29
+ import { signupAttributionContextFromCookieHeader, signupAttributionContextFromHeaders, } from "./attribution.js";
30
30
  import { resolveAuthCookieNamespace } from "./cookie-namespace.js";
31
31
  import { getWorkspaceA2ADerivedSecret } from "./derived-secret.js";
32
32
  import { renderMagicLinkEmail, renderResetPasswordEmail, renderVerifySignupEmail, } from "./email-templates.js";
33
33
  import { getEmailReadiness, sendEmail } from "./email.js";
34
34
  import { resolveGoogleSignInCredentials } from "./google-oauth-credentials.js";
35
35
  import { readMagicLinkSignupAttribution } from "./magic-link-attribution.js";
36
+ import { getRequestContext, hasContinuationLocalRequestContext, } from "./request-context.js";
36
37
  export { getAuthLoginMode, resolveAuthLoginMode, resolveAuthLoginModeFromReadiness, } from "./auth-login-mode.js";
37
38
  async function flushSignupTracking() {
38
39
  try {
@@ -1045,14 +1046,25 @@ async function createBetterAuthInstance(config) {
1045
1046
  const cookieHeader = context?.headers?.get("cookie") ??
1046
1047
  context?.request?.headers?.get("cookie") ??
1047
1048
  null;
1049
+ const scopedSignupAttribution = hasContinuationLocalRequestContext()
1050
+ ? getRequestContext()?.signupAttribution
1051
+ : undefined;
1052
+ const requestSignupAttribution = signupAttributionContextFromCookieHeader(cookieHeader);
1053
+ const headerSignupAttribution = signupAttributionContextFromHeaders(context?.headers) ??
1054
+ signupAttributionContextFromHeaders(context?.request?.headers);
1048
1055
  const magicLinkAttribution = context?.request?.url?.includes("newUserCallbackURL")
1049
1056
  ? readMagicLinkSignupAttribution(context.request.url, getAuthSecret())
1050
1057
  : undefined;
1051
- attribution = signupAttributionFromCookieHeader(cookieHeader);
1052
- attribution = magicLinkAttribution?.attribution ?? attribution;
1058
+ attribution =
1059
+ magicLinkAttribution?.attribution ??
1060
+ scopedSignupAttribution?.attribution ??
1061
+ headerSignupAttribution?.attribution ??
1062
+ requestSignupAttribution.attribution;
1053
1063
  anonymousId =
1054
1064
  magicLinkAttribution?.anonymousId ??
1055
- readAnalyticsAnonymousId(cookieHeader);
1065
+ scopedSignupAttribution?.anonymousId ??
1066
+ headerSignupAttribution?.anonymousId ??
1067
+ requestSignupAttribution.anonymousId;
1056
1068
  }
1057
1069
  catch (err) {
1058
1070
  console.error("[auth] failed to derive signup attribution", err);
@@ -19,10 +19,12 @@ import { getAppConfig } from "../app-config/index.js";
19
19
  import { GOOGLE_AUTH_REQUIRED_MESSAGE, isGoogleSignInRequiredForEmail, } from "../org/auth-policy.js";
20
20
  import { SIGN_IN_ENTRY_PATH } from "../shared/sign-in-journey.js";
21
21
  import { getAppName } from "./app-name.js";
22
+ import { addSignupAttributionHeader, signupAttributionContextFromCookieHeader, } from "./attribution.js";
22
23
  import { getSession, isExpectedAuthFailure, safeReturnPath } from "./auth.js";
23
24
  import { getBetterAuth, getBetterAuthInternalAdapter, } from "./better-auth-instance.js";
24
25
  import { createOAuthSession, getOrigin } from "./google-oauth.js";
25
26
  import { consumeSsoState, createSsoState, CANONICAL_IDENTITY_SSO_HUB_URL, getIdentityHubUrl, identitySsoLoginButtonHtml, isCanonicalIdentitySsoClientRequest, isDesktopSsoUserAgent, isIdentitySsoExplicitlyEnabled, isIdentitySsoEnabled, isJtiReplayed, SSO_STATE_TTL_MS, } from "./identity-sso-store.js";
27
+ import { getRequestContext, hasContinuationLocalRequestContext, runWithRequestContext, } from "./request-context.js";
26
28
  export { getIdentityHubUrl, identitySsoLoginButtonHtml, isIdentitySsoEnabled };
27
29
  export const IDENTITY_SSO_PROVIDER_ID = "agent-native";
28
30
  export const IDENTITY_SSO_SCOPE = "identity";
@@ -269,7 +271,7 @@ async function exchangeIdentityCode(hub, binding, input) {
269
271
  return null;
270
272
  }
271
273
  }
272
- async function jitLinkIdentity(identity) {
274
+ async function jitLinkIdentity(identity, signupHeaders) {
273
275
  const adapter = await getBetterAuthInternalAdapter();
274
276
  let existing = adapter
275
277
  ? await adapter
@@ -288,6 +290,7 @@ async function jitLinkIdentity(identity) {
288
290
  password: createUnusableSsoCredential(),
289
291
  name: identity.name || identity.email.split("@")[0] || "User",
290
292
  },
293
+ ...(signupHeaders ? { headers: signupHeaders } : {}),
291
294
  });
292
295
  }
293
296
  catch (error) {
@@ -463,7 +466,16 @@ export async function handleIdentitySso(event, subpath) {
463
466
  return errorPage(GOOGLE_AUTH_REQUIRED_MESSAGE, loginPath);
464
467
  }
465
468
  try {
466
- await jitLinkIdentity(identity);
469
+ const signupCookieHeader = getHeader(event, "cookie") ?? null;
470
+ const signupAttribution = signupAttributionContextFromCookieHeader(signupCookieHeader);
471
+ const signupHeaders = addSignupAttributionHeader(event.headers, signupAttribution);
472
+ const linkIdentity = () => jitLinkIdentity(identity, signupHeaders);
473
+ await (hasContinuationLocalRequestContext()
474
+ ? runWithRequestContext({
475
+ ...(getRequestContext() ?? {}),
476
+ signupAttribution,
477
+ }, linkIdentity)
478
+ : linkIdentity());
467
479
  }
468
480
  catch {
469
481
  return errorPage("Could not finish linking your account. Please try again.", loginPath);
@@ -26,8 +26,8 @@ export declare function createRealtimeTokenHandler(): import("h3").EventHandlerW
26
26
  expiresAt?: undefined;
27
27
  ttlSeconds?: undefined;
28
28
  } | {
29
- error?: undefined;
30
29
  token: string;
31
30
  expiresAt: string;
32
31
  ttlSeconds: number;
32
+ error?: undefined;
33
33
  }>>;
@@ -15,6 +15,7 @@
15
15
  * process.env so existing `AGENT_USER_EMAIL=x pnpm action foo` invocations
16
16
  * continue to work.
17
17
  */
18
+ import type { SignupAttributionContext } from "./attribution.js";
18
19
  /**
19
20
  * Per-request agent-run state. Lives on `RequestContext.run` so the
20
21
  * agent-chat plugin can populate fields as the run progresses (owner,
@@ -109,6 +110,11 @@ export interface RequestContext {
109
110
  * replay; never used for authorization.
110
111
  */
111
112
  browserSessionId?: string;
113
+ /**
114
+ * Browser attribution captured before a Better Auth signup crosses into its
115
+ * async user-create hook. Analytics-only; never used for authorization.
116
+ */
117
+ signupAttribution?: SignupAttributionContext;
112
118
  /** Canonical client surface for analytics attribution. */
113
119
  clientPlatform?: import("../shared/analytics-platform.js").AnalyticsClientPlatform;
114
120
  /**
@@ -188,6 +194,8 @@ type RequestContextObserver = (ctx: RequestContext) => void;
188
194
  * overlapping async requests are only isolated by native AsyncLocalStorage.
189
195
  */
190
196
  export declare function assertRequestActionSurfaceIsolation(): void;
197
+ /** Whether request context values are isolated across overlapping promises. */
198
+ export declare function hasContinuationLocalRequestContext(): boolean;
191
199
  /**
192
200
  * Register a callback fired every time `runWithRequestContext` enters a new
193
201
  * scope. The hook runs INSIDE the AsyncLocalStorage scope, so observability
@@ -80,6 +80,10 @@ export function assertRequestActionSurfaceIsolation() {
80
80
  throw new Error("Request-scoped action surfaces require continuation-local request context storage; " +
81
81
  "this runtime only provides the non-isolated fallback.");
82
82
  }
83
+ /** Whether request context values are isolated across overlapping promises. */
84
+ export function hasContinuationLocalRequestContext() {
85
+ return globalRef[CONTINUATION_LOCAL_KEY] === true;
86
+ }
83
87
  /**
84
88
  * Register a callback fired every time `runWithRequestContext` enters a new
85
89
  * scope. The hook runs INSIDE the AsyncLocalStorage scope, so observability
@@ -134,3 +134,14 @@ hand-duplicating framework logic.
134
134
  `agent-surfaces`.
135
135
  - Do not copy framework runtime internals when a public API or narrow UI copy
136
136
  will do; read `customizing-agent-native` for the supported override ladder.
137
+
138
+ ## Authoring visual docs blocks
139
+
140
+ Treat the shared `Diagram` block as a renderer, not as a reason to style every
141
+ docs UI as a sketch. Use the hand-drawn font and Rough.js only for actual
142
+ diagrams or wireframes that communicate structure, flow, or a design draft.
143
+ For polished UI-like content - cards, logo walls, tables, controls, or product
144
+ shells — set `renderMode="design"` (and usually `frame="hide"` when the block
145
+ is the content itself). Design mode preserves normal docs typography and
146
+ disables the Rough.js overlay. Keep `data-rough` only on elements intentionally
147
+ sketched inside a real diagram.
@@ -134,3 +134,14 @@ hand-duplicating framework logic.
134
134
  `agent-surfaces`.
135
135
  - Do not copy framework runtime internals when a public API or narrow UI copy
136
136
  will do; read `customizing-agent-native` for the supported override ladder.
137
+
138
+ ## Authoring visual docs blocks
139
+
140
+ Treat the shared `Diagram` block as a renderer, not as a reason to style every
141
+ docs UI as a sketch. Use the hand-drawn font and Rough.js only for actual
142
+ diagrams or wireframes that communicate structure, flow, or a design draft.
143
+ For polished UI-like content - cards, logo walls, tables, controls, or product
144
+ shells — set `renderMode="design"` (and usually `frame="hide"` when the block
145
+ is the content itself). Design mode preserves normal docs typography and
146
+ disables the Rough.js overlay. Keep `data-rough` only on elements intentionally
147
+ sketched inside a real diagram.
@@ -134,3 +134,14 @@ hand-duplicating framework logic.
134
134
  `agent-surfaces`.
135
135
  - Do not copy framework runtime internals when a public API or narrow UI copy
136
136
  will do; read `customizing-agent-native` for the supported override ladder.
137
+
138
+ ## Authoring visual docs blocks
139
+
140
+ Treat the shared `Diagram` block as a renderer, not as a reason to style every
141
+ docs UI as a sketch. Use the hand-drawn font and Rough.js only for actual
142
+ diagrams or wireframes that communicate structure, flow, or a design draft.
143
+ For polished UI-like content - cards, logo walls, tables, controls, or product
144
+ shells — set `renderMode="design"` (and usually `frame="hide"` when the block
145
+ is the content itself). Design mode preserves normal docs typography and
146
+ disables the Rough.js overlay. Keep `data-rough` only on elements intentionally
147
+ sketched inside a real diagram.
@@ -134,3 +134,14 @@ hand-duplicating framework logic.
134
134
  `agent-surfaces`.
135
135
  - Do not copy framework runtime internals when a public API or narrow UI copy
136
136
  will do; read `customizing-agent-native` for the supported override ladder.
137
+
138
+ ## Authoring visual docs blocks
139
+
140
+ Treat the shared `Diagram` block as a renderer, not as a reason to style every
141
+ docs UI as a sketch. Use the hand-drawn font and Rough.js only for actual
142
+ diagrams or wireframes that communicate structure, flow, or a design draft.
143
+ For polished UI-like content - cards, logo walls, tables, controls, or product
144
+ shells — set `renderMode="design"` (and usually `frame="hide"` when the block
145
+ is the content itself). Design mode preserves normal docs typography and
146
+ disables the Rough.js overlay. Keep `data-rough` only on elements intentionally
147
+ sketched inside a real diagram.
@@ -81,7 +81,7 @@ export async function loadResolvedAgentNativeConfig(cwd, context, options = {})
81
81
  : await loadAgentNativeConfigFile(cwd));
82
82
  return resolveAgentNativeConfig(mergeAgentNativeConfigs(mergeAgentNativeConfigs(mergeAgentNativeConfigs(workspaceConfig
83
83
  ? resolveAgentNativeConfig(workspaceConfig, context)
84
- : {}, readAgentNativeJsonConfig(cwd)), readAgentNativeConfigEnv(options.environment ?? process.env)), projectConfig ? resolveAgentNativeConfig(projectConfig, context) : {}), context);
84
+ : {}, readAgentNativeJsonConfig(cwd)), projectConfig ? resolveAgentNativeConfig(projectConfig, context) : {}), readAgentNativeConfigEnv(options.environment ?? process.env), { arrayStrategy: "replace" }), context);
85
85
  }
86
86
  function findConfigPath(cwd) {
87
87
  return AGENT_NATIVE_CONFIG_FILE_CANDIDATES.map((filename) => path.join(cwd, filename)).find((candidate) => fs.existsSync(candidate));
@@ -10,6 +10,7 @@ import { getViteDevRecoveryScript } from "../client/vite-dev-recovery-script.js"
10
10
  import { inferAgentNativeDeploymentEnvironment, mergeAgentNativeConfigs, readAgentNativeConfigEnv, resolveAgentNativeConfig, } from "../config.js";
11
11
  import { writeAgentNativeNitroPresetMarker } from "../deploy/nitro-preset.js";
12
12
  import { findWorkspaceRoot } from "../scripts/utils.js";
13
+ import { RECURRING_JOBS_BUILD_MARKER_ENV_VAR, resolveRecurringJobsBuildMarker, } from "../server/agent-chat/recurring-jobs-runtime.js";
13
14
  import { verifyEmbedSessionToken } from "../server/embed-session.js";
14
15
  import { EMBED_SESSION_COOKIE, EMBED_TOKEN_QUERY_PARAM, MCP_APP_CHAT_BRIDGE_QUERY_PARAM, } from "../shared/embed-auth.js";
15
16
  import { isMcpEmbedCorsOrigin, MCP_EMBED_CORS_ALLOW_HEADERS, MCP_EMBED_STATIC_ASSET_HEADERS, mcpEmbedStaticAssetRouteRules, shouldAllowMcpEmbedCredentials, } from "../shared/mcp-embed-headers.js";
@@ -19,6 +20,7 @@ import { formatRuntimeConfigReport, getRuntimeConfigReport, isTruthyRuntimeValue
19
20
  import { actionTypesPlugin } from "./action-types-plugin.js";
20
21
  import { createAgentNativeConfigContext, loadAgentNativeConfigFile, loadWorkspaceAgentNativeConfigFile, readAgentNativeJsonConfig, } from "./agent-native-config-loader.js";
21
22
  import { agentsBundlePlugin } from "./agents-bundle-plugin.js";
23
+ import { resolveAgentNativePackageVersions } from "./package-versions.js";
22
24
  const require = createRequire(import.meta.url);
23
25
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
24
26
  let nitroFsWatchGuardInstalled = false;
@@ -2561,6 +2563,10 @@ function createNitroDevPlugin(options, appBasePath) {
2561
2563
  // injected into deployed Functions. Nitro is a separate server build,
2562
2564
  // so it needs the release ownership decision in its own replacement map.
2563
2565
  "process.env.AGENT_NATIVE_RELEASE_MIGRATIONS": JSON.stringify(process.env.AGENT_NATIVE_RELEASE_MIGRATIONS?.trim() || ""),
2566
+ // Same reason as the release owner above: the recurring-jobs decision
2567
+ // belongs to the build env, and Nitro is a separate server build with its
2568
+ // own replacement map.
2569
+ [`process.env.${RECURRING_JOBS_BUILD_MARKER_ENV_VAR}`]: JSON.stringify(resolveRecurringJobsBuildMarker(process.env)),
2564
2570
  },
2565
2571
  // Never auto-load test files as server handlers/plugins/middleware.
2566
2572
  // Nitro scans server/{plugins,middleware,routes,api}/*; a co-located
@@ -2801,7 +2807,7 @@ function reportRuntimeConfigDiagnostics(appConfig, context, mode, env = process.
2801
2807
  }
2802
2808
  console.warn(message);
2803
2809
  }
2804
- function createAgentNativeConfig(options = {}, command, userConfig = {}, mode = process.env.NODE_ENV === "production" ? "production" : "development", projectConfig) {
2810
+ function createAgentNativeConfig(options = {}, command, userConfig = {}, mode = process.env.NODE_ENV === "production" ? "production" : "development", projectConfig, workspaceConfig) {
2805
2811
  const cwd = process.cwd();
2806
2812
  const configContext = createAgentNativeConfigContext(command, mode);
2807
2813
  const projectConfigInput = projectConfig ?? options.agentNativeConfig;
@@ -2817,9 +2823,11 @@ function createAgentNativeConfig(options = {}, command, userConfig = {}, mode =
2817
2823
  ...loadEnv(mode, cwd, ""),
2818
2824
  ...process.env,
2819
2825
  };
2820
- const appConfig = resolveAgentNativeConfig(mergeAgentNativeConfigs(mergeAgentNativeConfigs(readAgentNativeJsonConfig(cwd), readAgentNativeConfigEnv(runtimeEnv)), projectConfigInput
2826
+ const appConfig = resolveAgentNativeConfig(mergeAgentNativeConfigs(mergeAgentNativeConfigs(mergeAgentNativeConfigs(workspaceConfig
2827
+ ? resolveAgentNativeConfig(workspaceConfig, configContext)
2828
+ : {}, readAgentNativeJsonConfig(cwd)), projectConfigInput
2821
2829
  ? resolveAgentNativeConfig(projectConfigInput, configContext)
2822
- : {}), configContext);
2830
+ : {}), readAgentNativeConfigEnv(runtimeEnv), { arrayStrategy: "replace" }), configContext);
2823
2831
  const inferredDeploymentEnvironment = appConfig.deployment?.environment ??
2824
2832
  inferAgentNativeDeploymentEnvironment(process.env, mode);
2825
2833
  const resolvedAppConfig = appConfig.deployment?.environment === undefined &&
@@ -2835,6 +2843,7 @@ function createAgentNativeConfig(options = {}, command, userConfig = {}, mode =
2835
2843
  process.env.CF_PAGES_COMMIT_SHA?.trim() ||
2836
2844
  process.env.AGENT_NATIVE_BUILD_SHA?.trim() ||
2837
2845
  "development";
2846
+ const packageVersions = resolveAgentNativePackageVersions(cwd);
2838
2847
  // Preload workspace-root .env into process.env so Nitro server code sees
2839
2848
  // shared keys during dev (Nitro reads process.env, not vite's envDir).
2840
2849
  if (workspaceRoot && workspaceRoot !== cwd) {
@@ -2905,6 +2914,7 @@ function createAgentNativeConfig(options = {}, command, userConfig = {}, mode =
2905
2914
  ...(userConfig.define ?? {}),
2906
2915
  ...(options.define ?? {}),
2907
2916
  __AGENT_NATIVE_BUILD_ID__: JSON.stringify(buildId),
2917
+ __AGENT_NATIVE_PACKAGE_VERSIONS__: JSON.stringify(packageVersions),
2908
2918
  __AGENT_NATIVE_CLIENT_COMPATIBILITY_VERSION__: JSON.stringify(options.clientCompatibilityVersion?.trim() || ""),
2909
2919
  __AGENT_NATIVE_APP_CONFIG__: JSON.stringify(resolvedAppConfig),
2910
2920
  __AGENT_NATIVE_BUILD_GA_MEASUREMENT_ID__: JSON.stringify(process.env.GA_MEASUREMENT_ID?.trim() || ""),
@@ -2913,6 +2923,11 @@ function createAgentNativeConfig(options = {}, command, userConfig = {}, mode =
2913
2923
  // netlify.toml environment is available to the build but not injected
2914
2924
  // into deployed Functions, so embed the decision in the server bundle.
2915
2925
  "process.env.AGENT_NATIVE_RELEASE_MIGRATIONS": JSON.stringify(process.env.AGENT_NATIVE_RELEASE_MIGRATIONS?.trim() || ""),
2926
+ // Recurring jobs are turned off (and their platform scheduled trigger
2927
+ // omitted) by the BUILD environment, which a deployed serverless runtime
2928
+ // never sees. Embed the decision so the Automations page reports what
2929
+ // will actually fire instead of inferring it from runtime-only markers.
2930
+ [`process.env.${RECURRING_JOBS_BUILD_MARKER_ENV_VAR}`]: JSON.stringify(resolveRecurringJobsBuildMarker(process.env)),
2916
2931
  ...(resolvedAppConfig.deployment?.environment
2917
2932
  ? {
2918
2933
  "process.env.AGENT_NATIVE_DEPLOYMENT_ENVIRONMENT": JSON.stringify(resolvedAppConfig.deployment.environment),
@@ -3129,14 +3144,10 @@ function createAgentNativeConfigPlugin(options) {
3129
3144
  name: "agent-native-config",
3130
3145
  enforce: "pre",
3131
3146
  async config(config, env) {
3132
- const context = createAgentNativeConfigContext(env.command, env.mode);
3133
3147
  const workspaceConfig = await loadWorkspaceAgentNativeConfigFile(process.cwd());
3134
3148
  const projectConfig = options.agentNativeConfig ??
3135
3149
  (await loadAgentNativeConfigFile(process.cwd()));
3136
- const resolvedConfig = mergeAgentNativeConfigs(workspaceConfig
3137
- ? resolveAgentNativeConfig(workspaceConfig, context)
3138
- : {}, projectConfig ? resolveAgentNativeConfig(projectConfig, context) : {});
3139
- return createAgentNativeConfig(options, env.command, config, env.mode, resolvedConfig);
3150
+ return createAgentNativeConfig(options, env.command, config, env.mode, projectConfig, workspaceConfig);
3140
3151
  },
3141
3152
  };
3142
3153
  }
@@ -0,0 +1 @@
1
+ export declare function resolveAgentNativePackageVersions(cwd: string): Record<string, string>;
@@ -0,0 +1,97 @@
1
+ import fs from "fs";
2
+ import { createRequire } from "module";
3
+ import path from "path";
4
+ import { fileURLToPath } from "url";
5
+ const AGENT_NATIVE_PACKAGE_PREFIX = "@agent-native/";
6
+ function readPackageManifest(manifestPath) {
7
+ try {
8
+ const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
9
+ return manifest && typeof manifest === "object"
10
+ ? manifest
11
+ : null;
12
+ }
13
+ catch {
14
+ // coercion-ok: missing or malformed manifests are typed absence from the optional version inventory.
15
+ return null;
16
+ }
17
+ }
18
+ function dependencyNames(manifest, includeDevDependencies = false) {
19
+ if (!manifest) {
20
+ return [];
21
+ }
22
+ return [
23
+ ...Object.keys(manifest.dependencies ?? {}),
24
+ ...Object.keys(manifest.optionalDependencies ?? {}),
25
+ ...Object.keys(manifest.peerDependencies ?? {}),
26
+ ...(includeDevDependencies
27
+ ? Object.keys(manifest.devDependencies ?? {})
28
+ : []),
29
+ ];
30
+ }
31
+ function resolvePackageManifest(packageName, resolutionBase) {
32
+ let entryPath;
33
+ const packageRequire = createRequire(path.join(resolutionBase, "package.json"));
34
+ try {
35
+ entryPath = packageRequire.resolve(packageName);
36
+ }
37
+ catch {
38
+ if (packageName !== "@agent-native/core") {
39
+ return null;
40
+ }
41
+ const coreManifestPath = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../package.json");
42
+ const coreManifest = readPackageManifest(coreManifestPath);
43
+ return coreManifest?.name === packageName
44
+ ? { manifest: coreManifest, manifestPath: coreManifestPath }
45
+ : null;
46
+ }
47
+ let directory = path.dirname(entryPath);
48
+ for (let depth = 0; depth < 20; depth += 1) {
49
+ const manifestPath = path.join(directory, "package.json");
50
+ const manifest = readPackageManifest(manifestPath);
51
+ if (manifest?.name === packageName) {
52
+ return { manifest, manifestPath };
53
+ }
54
+ const parent = path.dirname(directory);
55
+ if (parent === directory) {
56
+ break;
57
+ }
58
+ directory = parent;
59
+ }
60
+ return null;
61
+ }
62
+ export function resolveAgentNativePackageVersions(cwd) {
63
+ const appManifest = readPackageManifest(path.join(cwd, "package.json"));
64
+ const packageNames = new Set([
65
+ "@agent-native/core",
66
+ ...dependencyNames(appManifest, true).filter((name) => name.startsWith(AGENT_NATIVE_PACKAGE_PREFIX)),
67
+ ]);
68
+ const resolvedVersions = new Map();
69
+ const queuedPackages = [...packageNames].map((packageName) => ({
70
+ packageName,
71
+ resolutionBase: cwd,
72
+ }));
73
+ while (queuedPackages.length > 0) {
74
+ const queuedPackage = queuedPackages.shift();
75
+ if (!queuedPackage)
76
+ continue;
77
+ const resolvedPackage = resolvePackageManifest(queuedPackage.packageName, queuedPackage.resolutionBase);
78
+ if (!resolvedPackage) {
79
+ continue;
80
+ }
81
+ const { manifest } = resolvedPackage;
82
+ if (typeof manifest.version === "string" && manifest.version.trim()) {
83
+ resolvedVersions.set(queuedPackage.packageName, manifest.version.trim());
84
+ }
85
+ for (const dependencyName of dependencyNames(manifest)) {
86
+ if (dependencyName.startsWith(AGENT_NATIVE_PACKAGE_PREFIX) &&
87
+ !packageNames.has(dependencyName)) {
88
+ packageNames.add(dependencyName);
89
+ queuedPackages.push({
90
+ packageName: dependencyName,
91
+ resolutionBase: path.dirname(resolvedPackage.manifestPath),
92
+ });
93
+ }
94
+ }
95
+ }
96
+ return Object.fromEntries([...resolvedVersions.entries()].sort(([left], [right]) => left.localeCompare(right)));
97
+ }