@agent-native/core 0.204.1-nightly-20261008153353 → 0.205.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 (45) hide show
  1. package/dist/a2a/caller-auth.d.ts +1 -0
  2. package/dist/a2a/caller-auth.js +9 -3
  3. package/dist/a2a/client.d.ts +1 -0
  4. package/dist/a2a/client.js +1 -1
  5. package/dist/a2a/index.d.ts +2 -1
  6. package/dist/a2a/index.js +2 -1
  7. package/dist/agent/engine/ai-sdk-engine.js +3 -8
  8. package/dist/agent/engine/builder-engine.d.ts +1 -1
  9. package/dist/agent/engine/openrouter-tool-fetch.d.ts +1 -0
  10. package/dist/agent/engine/openrouter-tool-fetch.js +20 -0
  11. package/dist/agent/engine/translate-ai-sdk.d.ts +1 -1
  12. package/dist/agent/engine/translate-ai-sdk.js +3 -2
  13. package/dist/agent/model-config.d.ts +2 -2
  14. package/dist/agent/model-config.js +2 -0
  15. package/dist/app-config/observability.js +8 -1
  16. package/dist/client/analytics-session.js +25 -7
  17. package/dist/client/chat/agentkit-protocol.js +13 -2
  18. package/dist/client/url-scrub.js +5 -2
  19. package/dist/deploy/build.js +11 -0
  20. package/dist/file-upload/actions/upload-image.d.ts +3 -3
  21. package/dist/jobs/background-automation-runner.js +13 -2
  22. package/dist/mcp/build-server.js +7 -4
  23. package/dist/mcp/connect-route.js +16 -11
  24. package/dist/notifications/routes.d.ts +2 -2
  25. package/dist/observability/routes.d.ts +6 -6
  26. package/dist/observability/sentiment.d.ts +1 -1
  27. package/dist/observability/sentiment.js +30 -6
  28. package/dist/org/index.d.ts +1 -1
  29. package/dist/progress/routes.d.ts +1 -1
  30. package/dist/secrets/routes.d.ts +11 -11
  31. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  32. package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
  33. package/dist/server/attribution.d.ts +4 -6
  34. package/dist/server/attribution.js +20 -6
  35. package/dist/server/better-auth-instance.d.ts +2 -1
  36. package/dist/server/better-auth-instance.js +5 -1
  37. package/dist/server/magic-link-attribution.d.ts +1 -0
  38. package/dist/server/magic-link-attribution.js +5 -0
  39. package/dist/shared/analytics-session-id.d.ts +5 -0
  40. package/dist/shared/analytics-session-id.js +21 -0
  41. package/dist/triggers/actions/manage-automation.d.ts +3 -3
  42. package/dist/vite/sentry-source-maps.d.ts +1 -0
  43. package/dist/vite/sentry-source-maps.js +48 -22
  44. package/docs/content/actions-access-control.mdx +67 -21
  45. package/package.json +4 -4
@@ -27,43 +27,43 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
27
27
  thumbsUpRate: number;
28
28
  avgEvalScore: number;
29
29
  } | {
30
+ ok?: undefined;
30
31
  error: string;
31
32
  message: string;
32
33
  summary?: undefined;
33
34
  spans?: undefined;
34
- ok?: undefined;
35
35
  } | {
36
+ ok?: undefined;
36
37
  message?: undefined;
37
38
  summary: import("./types.js").TraceSummary;
38
39
  spans: import("./types.js").TraceSpan[];
39
40
  error?: undefined;
40
- ok?: undefined;
41
41
  } | {
42
+ ok?: undefined;
42
43
  message?: undefined;
43
44
  summary?: undefined;
44
45
  spans?: undefined;
45
46
  traceMissing: true;
46
47
  id: string;
47
48
  error?: undefined;
48
- ok?: undefined;
49
49
  } | {
50
+ ok?: undefined;
50
51
  message?: undefined;
51
52
  summary?: undefined;
52
53
  spans?: undefined;
53
54
  traceMissing?: undefined;
54
55
  id: string;
55
56
  error?: undefined;
56
- ok?: undefined;
57
57
  } | {
58
+ ok?: undefined;
58
59
  message?: undefined;
59
60
  summary?: undefined;
60
61
  spans?: undefined;
61
62
  error: any;
62
- ok?: undefined;
63
63
  } | {
64
64
  message?: undefined;
65
65
  summary?: undefined;
66
66
  spans?: undefined;
67
- error?: undefined;
68
67
  ok: boolean;
68
+ error?: undefined;
69
69
  }>>;
@@ -15,7 +15,7 @@ export declare function shouldInferSentimentForTurn(args: {
15
15
  hasUserText: boolean;
16
16
  }): boolean;
17
17
  export declare function parseInferredSentiment(output: string): InferredSentiment | null;
18
- export declare const INFERRED_SENTIMENT_FAILURE_REASONS: readonly ["engine_unavailable", "timeout", "parse_failed", "empty"];
18
+ export declare const INFERRED_SENTIMENT_FAILURE_REASONS: readonly ["engine_unavailable", "model_unsupported", "timeout", "parse_failed", "empty"];
19
19
  export type InferredSentimentFailureReason = (typeof INFERRED_SENTIMENT_FAILURE_REASONS)[number];
20
20
  export declare function inferAndTrackSentiment(args: {
21
21
  /** Explicit engine override; wins over `runEngine`. */
@@ -101,6 +101,7 @@ function truncateInput(text) {
101
101
  }
102
102
  export const INFERRED_SENTIMENT_FAILURE_REASONS = [
103
103
  "engine_unavailable",
104
+ "model_unsupported",
104
105
  "timeout",
105
106
  "parse_failed",
106
107
  "empty",
@@ -110,9 +111,32 @@ function engineCanRun(engine, model) {
110
111
  engine.supportedModels.length === 0 ||
111
112
  engine.supportedModels.includes(model));
112
113
  }
114
+ // Codes an engine puts on a stop event or EngineError when the gateway or
115
+ // provider refuses the model itself. `builder_model_unauthorized` is
116
+ // BUILDER_MODEL_UNAUTHORIZED_ERROR_CODE; builder-engine is imported lazily here.
117
+ const MODEL_REJECTION_ERROR_CODES = new Set([
118
+ "builder_model_unauthorized",
119
+ "model_not_found",
120
+ "not_found_error",
121
+ ]);
122
+ // A rejected model is a configuration error to fix, not an outage to retry, so
123
+ // it must not be counted as `engine_unavailable`.
124
+ function engineFailureReason(errorCode) {
125
+ return typeof errorCode === "string" &&
126
+ MODEL_REJECTION_ERROR_CODES.has(errorCode.trim().toLowerCase())
127
+ ? "model_unsupported"
128
+ : "engine_unavailable";
129
+ }
130
+ function thrownErrorCode(error) {
131
+ return typeof error === "object" && error !== null && "errorCode" in error
132
+ ? error.errorCode
133
+ : undefined;
134
+ }
113
135
  async function classifySentiment(args) {
136
+ // The engine is up but does not list the model: a configuration error, not
137
+ // an outage, so it must not read as `engine_unavailable`.
114
138
  if (!engineCanRun(args.engine, args.model)) {
115
- return { failure: "engine_unavailable" };
139
+ return { failure: "model_unsupported" };
116
140
  }
117
141
  const input = truncateInput(args.text);
118
142
  if (!input)
@@ -125,8 +149,8 @@ async function classifySentiment(args) {
125
149
  }, INFERRED_SENTIMENT_TIMEOUT_MS);
126
150
  let output = "";
127
151
  let finalOutput = "";
128
- const interrupted = () => ({
129
- failure: timedOut ? "timeout" : "engine_unavailable",
152
+ const interrupted = (errorCode) => ({
153
+ failure: timedOut ? "timeout" : engineFailureReason(errorCode),
130
154
  });
131
155
  try {
132
156
  for await (const event of args.engine.stream({
@@ -149,12 +173,12 @@ async function classifySentiment(args) {
149
173
  .join("");
150
174
  }
151
175
  if (typedEvent.type === "stop" && typedEvent.reason === "error") {
152
- return interrupted();
176
+ return interrupted(typedEvent.errorCode);
153
177
  }
154
178
  }
155
179
  }
156
- catch {
157
- return interrupted();
180
+ catch (error) {
181
+ return interrupted(thrownErrorCode(error));
158
182
  }
159
183
  finally {
160
184
  clearTimeout(timeout);
@@ -177,9 +177,9 @@ export declare const getMyOrgHandler: import("h3").EventHandlerWithFetch<import(
177
177
  soloDeploymentAdmin: boolean | undefined;
178
178
  }>>;
179
179
  export declare const createOrgHandler: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
180
- id?: undefined;
181
180
  name?: undefined;
182
181
  success: boolean;
182
+ id?: undefined;
183
183
  role?: undefined;
184
184
  } | {
185
185
  success?: undefined;
@@ -2,6 +2,6 @@ export declare function createProgressHandler(): import("h3").EventHandlerWithFe
2
2
  error: string;
3
3
  ok?: undefined;
4
4
  } | {
5
- error?: undefined;
6
5
  ok: boolean;
6
+ error?: undefined;
7
7
  }>>;
@@ -58,47 +58,47 @@ export declare function createWriteSecretHandler(): import("h3").EventHandlerWit
58
58
  error: string;
59
59
  errorCode?: undefined;
60
60
  retryable?: undefined;
61
- status?: undefined;
62
61
  ok?: undefined;
62
+ status?: undefined;
63
63
  } | {
64
64
  error: string;
65
65
  errorCode: string;
66
66
  retryable?: undefined;
67
- status?: undefined;
68
67
  ok?: undefined;
68
+ status?: undefined;
69
69
  } | {
70
70
  error: string;
71
71
  errorCode: string;
72
72
  retryable: boolean;
73
- status?: undefined;
74
73
  ok?: undefined;
74
+ status?: undefined;
75
75
  } | {
76
+ error?: undefined;
76
77
  errorCode?: undefined;
77
78
  retryable?: undefined;
78
79
  ok: boolean;
79
80
  status: string;
80
- error?: undefined;
81
81
  } | {
82
+ ok?: undefined;
82
83
  error: string;
83
84
  removed?: undefined;
84
- ok?: undefined;
85
85
  } | {
86
+ error?: undefined;
86
87
  ok: boolean;
87
88
  removed: boolean;
88
- error?: undefined;
89
89
  }>>;
90
90
  export declare function createTestSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
91
+ ok?: undefined;
91
92
  error: string;
92
93
  note?: undefined;
93
- ok?: undefined;
94
94
  } | {
95
+ error?: undefined;
95
96
  ok: boolean;
96
97
  note?: undefined;
97
- error?: undefined;
98
98
  } | {
99
+ error?: undefined;
99
100
  ok: boolean;
100
101
  note: string;
101
- error?: undefined;
102
102
  } | {
103
103
  note?: undefined;
104
104
  ok: boolean;
@@ -126,11 +126,11 @@ export declare function createAdHocSecretHandler(): import("h3").EventHandlerWit
126
126
  } | {
127
127
  error: string;
128
128
  } | {
129
+ error?: undefined;
129
130
  ok: boolean;
130
131
  key: string;
131
- error?: undefined;
132
132
  } | {
133
+ error?: undefined;
133
134
  ok: boolean;
134
135
  removed: boolean;
135
- error?: undefined;
136
136
  }>>;
@@ -66,12 +66,12 @@ export declare function createAgentEngineApiKeyHandler(): import("h3").EventHand
66
66
  code: any;
67
67
  } | {
68
68
  errorCode?: undefined;
69
- error?: undefined;
70
69
  code?: undefined;
71
70
  ok: boolean;
72
71
  key: string;
73
72
  baseUrlKey?: string;
74
73
  scope: AgentEngineApiKeyScope;
75
74
  defaultModel?: import("./agent-engine-default-model-route.js").SavedKeyDefaultModelOutcome;
75
+ error?: undefined;
76
76
  }>>;
77
77
  export {};
@@ -1,6 +1,6 @@
1
1
  export declare function createAgentEngineOllamaModelsHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
2
- error: string;
3
2
  ok?: undefined;
3
+ error: string;
4
4
  models?: undefined;
5
5
  } | {
6
6
  error?: undefined;
@@ -68,6 +68,7 @@ export type SignupOrigin = "browser_signup"
68
68
  export interface SignupAttributionContext {
69
69
  attribution: Record<string, string>;
70
70
  anonymousId?: string;
71
+ sessionId?: string;
71
72
  }
72
73
  export declare const SIGNUP_ATTRIBUTION_HEADER_NAME = "x-agent-native-signup-attribution";
73
74
  export declare const FIRST_TOUCH_COOKIE_NAME = "an_ft";
@@ -90,6 +91,7 @@ export declare function readFirstTouchAttribution(cookieHeader: string | null |
90
91
  */
91
92
  export declare function readLastTouchAttribution(cookieHeader: string | null | undefined): LastTouchAttribution | null;
92
93
  export declare function readAnalyticsAnonymousId(cookieHeader: string | null | undefined): string | undefined;
94
+ export declare function readAnalyticsSessionId(cookieHeader: string | null | undefined): string | undefined;
93
95
  export declare function deriveReferralSource(ft: FirstTouchAttribution | LastTouchAttribution | null): string;
94
96
  export declare function deriveSignupAttribution(ft: FirstTouchAttribution | null): Record<string, string>;
95
97
  export declare function deriveLastTouchAttribution(lt: LastTouchAttribution | null): Record<string, string>;
@@ -104,12 +106,8 @@ export declare function signupAttributionFromCookieHeader(cookieHeader: string |
104
106
  * Keep this as one boundary helper so every signup entry point carries the
105
107
  * same values into Better Auth's user-create hook.
106
108
  *
107
- * Returns `undefined` when the request carried neither cookie. A browser that
108
- * ran our client script always has `an_ft`, so "no cookies at all" means no
109
- * browser — a server-side backfill or provisioning call. Reporting that as
110
- * `referral_source: "direct"` is the coercion that made this metric unusable:
111
- * it renders "we never saw a visitor" identical to "a visitor arrived with no
112
- * campaign", and only the second one is direct traffic.
109
+ * Returns `undefined` when no attribution or anonymous ID identifies a signup
110
+ * context. A session ID alone cannot establish direct traffic.
113
111
  */
114
112
  export declare function signupAttributionContextFromCookieHeader(cookieHeader: string | null | undefined): SignupAttributionContext | undefined;
115
113
  export declare function encodeSignupAttributionContext(context: SignupAttributionContext): string;
@@ -1,4 +1,5 @@
1
1
  import { ANALYTICS_ANONYMOUS_ID_COOKIE_NAME, ANALYTICS_ANONYMOUS_ID_MAX_LENGTH, normalizeAnalyticsAnonymousId, } from "../shared/analytics-anonymous-id.js";
2
+ import { ANALYTICS_SESSION_ID_COOKIE_NAME, normalizeAnalyticsSessionId, } from "../shared/analytics-session-id.js";
2
3
  import { isSourceReferrerHost, shareLandingSource, } from "../shared/attribution-source.js";
3
4
  export const SIGNUP_ATTRIBUTION_HEADER_NAME = "x-agent-native-signup-attribution";
4
5
  const SIGNUP_ATTRIBUTION_HEADER_MAX_LENGTH = 4096;
@@ -127,6 +128,19 @@ export function readAnalyticsAnonymousId(cookieHeader) {
127
128
  return normalizeAnalyticsAnonymousId(parseCookieHeader(cookieHeader)[ANALYTICS_ANONYMOUS_ID_COOKIE_NAME]);
128
129
  }
129
130
  catch {
131
+ // coercion-ok: malformed anonymous id cookies are absent analytics context.
132
+ return undefined;
133
+ }
134
+ }
135
+ export function readAnalyticsSessionId(cookieHeader) {
136
+ try {
137
+ const value = parseCookieHeader(cookieHeader)[ANALYTICS_SESSION_ID_COOKIE_NAME];
138
+ if (!value)
139
+ return undefined;
140
+ return normalizeAnalyticsSessionId(decodeURIComponent(value));
141
+ }
142
+ catch {
143
+ // coercion-ok: malformed session cookie input is absent analytics context.
130
144
  return undefined;
131
145
  }
132
146
  }
@@ -238,22 +252,20 @@ export function signupAttributionFromCookieHeader(cookieHeader) {
238
252
  * Keep this as one boundary helper so every signup entry point carries the
239
253
  * same values into Better Auth's user-create hook.
240
254
  *
241
- * Returns `undefined` when the request carried neither cookie. A browser that
242
- * ran our client script always has `an_ft`, so "no cookies at all" means no
243
- * browser — a server-side backfill or provisioning call. Reporting that as
244
- * `referral_source: "direct"` is the coercion that made this metric unusable:
245
- * it renders "we never saw a visitor" identical to "a visitor arrived with no
246
- * campaign", and only the second one is direct traffic.
255
+ * Returns `undefined` when no attribution or anonymous ID identifies a signup
256
+ * context. A session ID alone cannot establish direct traffic.
247
257
  */
248
258
  export function signupAttributionContextFromCookieHeader(cookieHeader) {
249
259
  const firstTouch = readFirstTouchAttribution(cookieHeader);
250
260
  const lastTouch = readLastTouchAttribution(cookieHeader);
251
261
  const anonymousId = readAnalyticsAnonymousId(cookieHeader);
262
+ const sessionId = readAnalyticsSessionId(cookieHeader);
252
263
  if (!firstTouch && !lastTouch && !anonymousId)
253
264
  return undefined;
254
265
  return {
255
266
  attribution: withLastTouchAttribution(deriveSignupAttribution(firstTouch), lastTouch),
256
267
  ...(anonymousId ? { anonymousId } : {}),
268
+ ...(sessionId ? { sessionId } : {}),
257
269
  };
258
270
  }
259
271
  export function encodeSignupAttributionContext(context) {
@@ -283,9 +295,11 @@ export function decodeSignupAttributionContext(value) {
283
295
  if (Object.keys(attribution).length === 0)
284
296
  return undefined;
285
297
  const anonymousId = normalizeAnalyticsAnonymousId(parsed?.anonymousId);
298
+ const sessionId = normalizeAnalyticsSessionId(parsed?.sessionId);
286
299
  return {
287
300
  attribution,
288
301
  ...(anonymousId ? { anonymousId } : {}),
302
+ ...(sessionId ? { sessionId } : {}),
289
303
  };
290
304
  }
291
305
  catch (error) {
@@ -27,7 +27,7 @@ export declare function emitSignupEventForCreatedUser(user: {
27
27
  name?: string | null;
28
28
  }, context?: BetterAuthUserCreateContext | null): Promise<void>;
29
29
  export declare function hasGoogleAuthIdentity(email: string): Promise<boolean | undefined>;
30
- export declare function trackSignupEvent({ authProvider, origin, signupMethod, authUserId, email, name, attribution, anonymousId, }: {
30
+ export declare function trackSignupEvent({ authProvider, origin, signupMethod, authUserId, email, name, attribution, anonymousId, sessionId, }: {
31
31
  authProvider: string;
32
32
  origin: SignupOrigin;
33
33
  signupMethod?: "google" | "magic_link" | "password";
@@ -45,6 +45,7 @@ export declare function trackSignupEvent({ authProvider, origin, signupMethod, a
45
45
  */
46
46
  attribution?: Record<string, string | undefined>;
47
47
  anonymousId?: string;
48
+ sessionId?: string;
48
49
  }): Promise<void>;
49
50
  export declare const DEV_AUTH_SECRET_PATH: string;
50
51
  /**
@@ -136,6 +136,7 @@ export async function emitSignupEventForCreatedUser(user, context) {
136
136
  : undefined;
137
137
  let attribution;
138
138
  let anonymousId;
139
+ let sessionId;
139
140
  try {
140
141
  const browser = (context?.request?.url?.includes("newUserCallbackURL")
141
142
  ? readMagicLinkSignupAttribution(context.request.url, getAuthSecret())
@@ -145,6 +146,7 @@ export async function emitSignupEventForCreatedUser(user, context) {
145
146
  signupAttributionContextFromCookieHeader(requestHeaders.get("cookie"));
146
147
  attribution = browser?.attribution;
147
148
  anonymousId = browser?.anonymousId;
149
+ sessionId = browser?.sessionId;
148
150
  }
149
151
  catch (err) {
150
152
  console.error("[auth] failed to derive signup attribution", err);
@@ -177,6 +179,7 @@ export async function emitSignupEventForCreatedUser(user, context) {
177
179
  name: user.name,
178
180
  attribution,
179
181
  anonymousId,
182
+ sessionId,
180
183
  });
181
184
  }
182
185
  export async function hasGoogleAuthIdentity(email) {
@@ -189,7 +192,7 @@ export async function hasGoogleAuthIdentity(email) {
189
192
  return (existing?.accounts.some((account) => account.providerId === "google") ??
190
193
  false);
191
194
  }
192
- export async function trackSignupEvent({ authProvider, origin, signupMethod, authUserId, email, name, attribution, anonymousId, }) {
195
+ export async function trackSignupEvent({ authProvider, origin, signupMethod, authUserId, email, name, attribution, anonymousId, sessionId, }) {
193
196
  identify(email, {
194
197
  email,
195
198
  name: name ?? undefined,
@@ -214,6 +217,7 @@ export async function trackSignupEvent({ authProvider, origin, signupMethod, aut
214
217
  userId: email,
215
218
  authUserId,
216
219
  ...(anonymousId ? { anonymousId } : {}),
220
+ ...(sessionId ? { sessionId } : {}),
217
221
  });
218
222
  await flushSignupTracking();
219
223
  }
@@ -2,6 +2,7 @@ export declare const MAGIC_LINK_ATTRIBUTION_PARAM = "signup_attribution";
2
2
  export interface MagicLinkSignupAttribution {
3
3
  attribution?: Record<string, string>;
4
4
  anonymousId?: string;
5
+ sessionId?: string;
5
6
  }
6
7
  /**
7
8
  * Sign the attribution captured when a magic link is requested. The token is
@@ -1,5 +1,6 @@
1
1
  import crypto from "node:crypto";
2
2
  import { normalizeAnalyticsAnonymousId } from "../shared/analytics-anonymous-id.js";
3
+ import { normalizeAnalyticsSessionId } from "../shared/analytics-session-id.js";
3
4
  export const MAGIC_LINK_ATTRIBUTION_PARAM = "signup_attribution";
4
5
  const MAGIC_LINK_ATTRIBUTION_TTL_SECONDS = 10 * 60;
5
6
  // A signup carries up to 17 first-touch and 16 last-touch properties.
@@ -33,12 +34,14 @@ export function encodeMagicLinkSignupAttribution(value, secret, now = Date.now()
33
34
  return undefined;
34
35
  const attribution = sanitizeAttribution(value.attribution);
35
36
  const anonymousId = normalizeAnalyticsAnonymousId(value.anonymousId);
37
+ const sessionId = normalizeAnalyticsSessionId(value.sessionId);
36
38
  if (!attribution && !anonymousId)
37
39
  return undefined;
38
40
  const payload = {
39
41
  exp: Math.floor(now / 1000) + MAGIC_LINK_ATTRIBUTION_TTL_SECONDS,
40
42
  ...(attribution ? { attribution } : {}),
41
43
  ...(anonymousId ? { anonymousId } : {}),
44
+ ...(sessionId ? { sessionId } : {}),
42
45
  };
43
46
  const data = encodePayload(payload);
44
47
  const signature = crypto
@@ -73,11 +76,13 @@ export function decodeMagicLinkSignupAttribution(token, secret, now = Date.now()
73
76
  }
74
77
  const attribution = sanitizeAttribution(payload.attribution);
75
78
  const anonymousId = normalizeAnalyticsAnonymousId(payload.anonymousId);
79
+ const sessionId = normalizeAnalyticsSessionId(payload.sessionId);
76
80
  if (!attribution && !anonymousId)
77
81
  return undefined;
78
82
  return {
79
83
  ...(attribution ? { attribution } : {}),
80
84
  ...(anonymousId ? { anonymousId } : {}),
85
+ ...(sessionId ? { sessionId } : {}),
81
86
  };
82
87
  }
83
88
  catch {
@@ -0,0 +1,5 @@
1
+ export declare const ANALYTICS_SESSION_ID_COOKIE_NAME = "an_sid";
2
+ export declare const ANALYTICS_SESSION_ID_COOKIE_MAX_AGE_SECONDS: number;
3
+ export declare const ANALYTICS_SESSION_ID_MAX_LENGTH = 127;
4
+ export declare function normalizeAnalyticsSessionId(value: unknown): string | undefined;
5
+ export declare function serializeAnalyticsSessionIdCookie(value: unknown): string | undefined;
@@ -0,0 +1,21 @@
1
+ export const ANALYTICS_SESSION_ID_COOKIE_NAME = "an_sid";
2
+ export const ANALYTICS_SESSION_ID_COOKIE_MAX_AGE_SECONDS = 30 * 60;
3
+ export const ANALYTICS_SESSION_ID_MAX_LENGTH = 127;
4
+ const ANALYTICS_SESSION_ID_PATTERN = /^[!-~]+$/;
5
+ export function normalizeAnalyticsSessionId(value) {
6
+ if (typeof value !== "string")
7
+ return undefined;
8
+ const trimmed = value.trim();
9
+ if (!trimmed ||
10
+ trimmed.length > ANALYTICS_SESSION_ID_MAX_LENGTH ||
11
+ !ANALYTICS_SESSION_ID_PATTERN.test(trimmed)) {
12
+ return undefined;
13
+ }
14
+ return trimmed;
15
+ }
16
+ export function serializeAnalyticsSessionIdCookie(value) {
17
+ const sessionId = normalizeAnalyticsSessionId(value);
18
+ if (!sessionId)
19
+ return undefined;
20
+ return `${ANALYTICS_SESSION_ID_COOKIE_NAME}=${encodeURIComponent(sessionId)}; path=/; max-age=${ANALYTICS_SESSION_ID_COOKIE_MAX_AGE_SECONDS}; SameSite=Lax`;
21
+ }
@@ -14,6 +14,7 @@ declare const _default: import("../../action.js").ActionDefinition<{
14
14
  executionCwd?: string;
15
15
  }, {
16
16
  deleted?: undefined;
17
+ enabled?: undefined;
17
18
  created: boolean;
18
19
  name: string;
19
20
  scope: "organization" | "personal";
@@ -24,25 +25,24 @@ declare const _default: import("../../action.js").ActionDefinition<{
24
25
  reasoningEffort: "auto" | "high" | "low" | "max" | "medium" | "minimal" | "none" | "xhigh";
25
26
  webhookPath: string;
26
27
  nextRun: string;
27
- enabled?: undefined;
28
28
  executionHostId?: undefined;
29
29
  executionEngine?: undefined;
30
30
  executionCwd?: undefined;
31
31
  } | {
32
+ enabled?: undefined;
33
+ nextRun?: undefined;
32
34
  created?: undefined;
33
35
  scope?: undefined;
34
36
  triggerType?: undefined;
35
37
  event?: undefined;
36
38
  deleted: boolean;
37
39
  name: string;
38
- enabled?: undefined;
39
40
  schedule?: undefined;
40
41
  timezone?: undefined;
41
42
  reasoningEffort?: undefined;
42
43
  executionHostId?: undefined;
43
44
  executionEngine?: undefined;
44
45
  executionCwd?: undefined;
45
- nextRun?: undefined;
46
46
  webhookPath?: undefined;
47
47
  } | {
48
48
  deleted?: undefined;
@@ -11,5 +11,6 @@ export interface SentrySourceMapUploadConfig extends SentrySourceMapUploadCreden
11
11
  }
12
12
  export declare function resolveSentrySourceMapUploadConfig(env?: Record<string, string | undefined>): SentrySourceMapUploadConfig | null;
13
13
  export declare function isSentrySourceMapUploadEnabled(env?: Record<string, string | undefined>): boolean;
14
+ export declare function createSentryServerSourceMapUploadPlugins(env?: Record<string, string | undefined>): Promise<Plugin[]>;
14
15
  export declare function createSentrySourceMapUploadPlugin(env?: Record<string, string | undefined>): Plugin[];
15
16
  export {};
@@ -68,6 +68,47 @@ function resolvedClientBuildId(config) {
68
68
  const buildId = JSON.parse(definedBuildId);
69
69
  return typeof buildId === "string" && buildId.trim() ? buildId.trim() : null;
70
70
  }
71
+ async function loadSentryUploadPlugin(uploadConfig) {
72
+ const { sentryVitePlugin } = await loadOptionalPeer("@sentry/vite-plugin", () => import("@sentry/vite-plugin"));
73
+ const sentryPlugin = sentryVitePlugin({
74
+ org: uploadConfig.org,
75
+ project: uploadConfig.project,
76
+ authToken: uploadConfig.authToken,
77
+ url: uploadConfig.url,
78
+ telemetry: false,
79
+ release: {
80
+ name: uploadConfig.release,
81
+ inject: false,
82
+ },
83
+ // A source-map upload is optional observability work. The cleanup plugin
84
+ // still removes maps when this handler returns, so a bad token cannot
85
+ // block the deploy or publish source contents.
86
+ errorHandler: (error) => {
87
+ const message = (error instanceof Error ? error.message : String(error)).replaceAll(uploadConfig.authToken, "[redacted]");
88
+ console.warn(`Sentry source map upload failed; continuing without publishing source maps: ${message}`);
89
+ },
90
+ });
91
+ return Array.isArray(sentryPlugin) ? sentryPlugin[0] : sentryPlugin;
92
+ }
93
+ // Nitro bundles the server in its own rolldown pass after Vite, so the client
94
+ // plugins never see the deployed server chunks. Callers must enable server
95
+ // source maps exactly when this returns plugins, or the upload has no maps and
96
+ // the cleanup has nothing to remove.
97
+ export async function createSentryServerSourceMapUploadPlugins(env = process.env) {
98
+ const credentials = resolveSentrySourceMapUploadCredentials(env);
99
+ if (!credentials)
100
+ return [];
101
+ const buildId = resolveAgentNativeBuildId(env, "");
102
+ if (!buildId) {
103
+ console.warn("Sentry server source map upload skipped because the build ID is missing.");
104
+ return [];
105
+ }
106
+ const { enforce: _enforce, ...uploadPlugin } = await loadSentryUploadPlugin({
107
+ ...credentials,
108
+ release: `agent-native-server@${buildId}`,
109
+ });
110
+ return [uploadPlugin, createUploadedSourceMapCleanupPlugin()];
111
+ }
71
112
  export function createSentrySourceMapUploadPlugin(env = process.env) {
72
113
  const credentials = resolveSentrySourceMapUploadCredentials(env);
73
114
  if (!credentials)
@@ -76,6 +117,12 @@ export function createSentrySourceMapUploadPlugin(env = process.env) {
76
117
  const proxyPlugin = {
77
118
  name: "sentry-vite-plugin",
78
119
  enforce: "pre",
120
+ // The SSR bundle is re-bundled by Nitro, which injects its own debug IDs.
121
+ // A second snippet inlined from SSR output would point server frames at a
122
+ // map whose positions no longer match.
123
+ applyToEnvironment(environment) {
124
+ return environment.name === "client";
125
+ },
79
126
  async configResolved(config) {
80
127
  if (config.command !== "build")
81
128
  return;
@@ -88,28 +135,7 @@ export function createSentrySourceMapUploadPlugin(env = process.env) {
88
135
  ...credentials,
89
136
  release: `agent-native-client@${buildId}`,
90
137
  };
91
- const { sentryVitePlugin } = await loadOptionalPeer("@sentry/vite-plugin", () => import("@sentry/vite-plugin"));
92
- const sentryPlugin = sentryVitePlugin({
93
- org: uploadConfig.org,
94
- project: uploadConfig.project,
95
- authToken: uploadConfig.authToken,
96
- url: uploadConfig.url,
97
- telemetry: false,
98
- release: {
99
- name: uploadConfig.release,
100
- inject: false,
101
- },
102
- // A source-map upload is optional observability work. The cleanup plugin
103
- // still removes maps when this handler returns, so a bad token cannot
104
- // block the deploy or publish source contents.
105
- errorHandler: (error) => {
106
- const message = (error instanceof Error ? error.message : String(error)).replaceAll(uploadConfig.authToken, "[redacted]");
107
- console.warn(`Sentry source map upload failed; continuing without publishing source maps: ${message}`);
108
- },
109
- });
110
- uploadPlugin = Array.isArray(sentryPlugin)
111
- ? sentryPlugin[0]
112
- : sentryPlugin;
138
+ uploadPlugin = await loadSentryUploadPlugin(uploadConfig);
113
139
  },
114
140
  buildStart(options) {
115
141
  const hook = uploadPlugin?.buildStart;