@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.
- package/dist/a2a/caller-auth.d.ts +1 -0
- package/dist/a2a/caller-auth.js +9 -3
- package/dist/a2a/client.d.ts +1 -0
- package/dist/a2a/client.js +1 -1
- package/dist/a2a/index.d.ts +2 -1
- package/dist/a2a/index.js +2 -1
- package/dist/agent/engine/ai-sdk-engine.js +3 -8
- package/dist/agent/engine/builder-engine.d.ts +1 -1
- package/dist/agent/engine/openrouter-tool-fetch.d.ts +1 -0
- package/dist/agent/engine/openrouter-tool-fetch.js +20 -0
- package/dist/agent/engine/translate-ai-sdk.d.ts +1 -1
- package/dist/agent/engine/translate-ai-sdk.js +3 -2
- package/dist/agent/model-config.d.ts +2 -2
- package/dist/agent/model-config.js +2 -0
- package/dist/app-config/observability.js +8 -1
- package/dist/client/analytics-session.js +25 -7
- package/dist/client/chat/agentkit-protocol.js +13 -2
- package/dist/client/url-scrub.js +5 -2
- package/dist/deploy/build.js +11 -0
- package/dist/file-upload/actions/upload-image.d.ts +3 -3
- package/dist/jobs/background-automation-runner.js +13 -2
- package/dist/mcp/build-server.js +7 -4
- package/dist/mcp/connect-route.js +16 -11
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/observability/routes.d.ts +6 -6
- package/dist/observability/sentiment.d.ts +1 -1
- package/dist/observability/sentiment.js +30 -6
- package/dist/org/index.d.ts +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/secrets/routes.d.ts +11 -11
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
- package/dist/server/attribution.d.ts +4 -6
- package/dist/server/attribution.js +20 -6
- package/dist/server/better-auth-instance.d.ts +2 -1
- package/dist/server/better-auth-instance.js +5 -1
- package/dist/server/magic-link-attribution.d.ts +1 -0
- package/dist/server/magic-link-attribution.js +5 -0
- package/dist/shared/analytics-session-id.d.ts +5 -0
- package/dist/shared/analytics-session-id.js +21 -0
- package/dist/triggers/actions/manage-automation.d.ts +3 -3
- package/dist/vite/sentry-source-maps.d.ts +1 -0
- package/dist/vite/sentry-source-maps.js +48 -22
- package/docs/content/actions-access-control.mdx +67 -21
- 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: "
|
|
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" :
|
|
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);
|
package/dist/org/index.d.ts
CHANGED
|
@@ -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;
|
package/dist/secrets/routes.d.ts
CHANGED
|
@@ -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 {};
|
|
@@ -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
|
|
108
|
-
*
|
|
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
|
|
242
|
-
*
|
|
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
|
-
|
|
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;
|