@agent-native/core 0.225.2-nightly-20261106152255 → 0.226.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 (115) hide show
  1. package/dist/agent/actions/get-agentkit-capabilities.d.ts +12 -1
  2. package/dist/agent/actions/get-agentkit-capabilities.js +13 -5
  3. package/dist/agent/production-agent.js +14 -4
  4. package/dist/agentkit/capabilities.d.ts +4 -2
  5. package/dist/agentkit/capabilities.js +71 -18
  6. package/dist/app-config/experience-profiles.d.ts +4 -0
  7. package/dist/app-config/experience-profiles.js +7 -0
  8. package/dist/app-config/onboarding.d.ts +2 -0
  9. package/dist/app-config/onboarding.js +5 -0
  10. package/dist/app-config/schema.d.ts +5 -0
  11. package/dist/app-config/schema.js +2 -0
  12. package/dist/application-state/handlers.d.ts +2 -2
  13. package/dist/client/agent-chat.d.ts +3 -1
  14. package/dist/client/agent-chat.js +8 -0
  15. package/dist/client/agentkit-chat/transport.d.ts +2 -1
  16. package/dist/client/agentkit-chat/transport.js +2 -1
  17. package/dist/client/auth/builder-signup.d.ts +14 -0
  18. package/dist/client/auth/builder-signup.js +75 -0
  19. package/dist/client/chat/agentkit-agent-native.d.ts +4 -0
  20. package/dist/client/chat/agentkit-agent-native.js +25 -0
  21. package/dist/client/chat/composer-draft.d.ts +1 -7
  22. package/dist/client/chat/composer-draft.js +5 -1
  23. package/dist/client/chat/native-uploads.d.ts +11 -0
  24. package/dist/client/chat/native-uploads.js +97 -0
  25. package/dist/client/experience-profiles.d.ts +182 -0
  26. package/dist/client/experience-profiles.js +19 -0
  27. package/dist/client/uploads/index.d.ts +1 -1
  28. package/dist/client/uploads/index.js +1 -1
  29. package/dist/client/use-action.js +3 -0
  30. package/dist/collab/routes.d.ts +1 -1
  31. package/dist/experience-profiles/index.d.ts +13 -0
  32. package/dist/experience-profiles/index.js +10 -0
  33. package/dist/experience-profiles/server.d.ts +38 -0
  34. package/dist/experience-profiles/server.js +76 -0
  35. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  36. package/dist/framework-package-versions.json +11 -11
  37. package/dist/localization/workspace-integration-messages.d.ts +11 -0
  38. package/dist/localization/workspace-integration-messages.js +132 -0
  39. package/dist/mcp/screen-memory-stdio.d.ts +3 -3
  40. package/dist/notifications/routes.d.ts +3 -3
  41. package/dist/org/index.d.ts +1 -1
  42. package/dist/provider-api/actions/custom-provider-registration.d.ts +5 -5
  43. package/dist/provider-api/actions/provider-api.d.ts +3 -3
  44. package/dist/provider-api/actions/provider-api.js +2 -0
  45. package/dist/provider-api/index.d.ts +7 -1
  46. package/dist/provider-api/index.js +42 -2
  47. package/dist/scripts/resources/read.d.ts +6 -1
  48. package/dist/scripts/resources/read.js +85 -8
  49. package/dist/secrets/routes.d.ts +2 -2
  50. package/dist/server/agent-chat/script-entries.js +27 -6
  51. package/dist/server/agent-chat-plugin.js +102 -33
  52. package/dist/server/agent-engine-api-key-route.d.ts +4 -4
  53. package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
  54. package/dist/server/auth.js +25 -1
  55. package/dist/server/better-auth-instance.d.ts +1 -0
  56. package/dist/server/builder-browser.d.ts +2 -0
  57. package/dist/server/builder-browser.js +8 -4
  58. package/dist/server/builder-signup-experiment.d.ts +67 -0
  59. package/dist/server/builder-signup-experiment.js +345 -0
  60. package/dist/server/core-routes-plugin.d.ts +2 -0
  61. package/dist/server/core-routes-plugin.js +77 -25
  62. package/dist/server/first-touch-route.d.ts +1 -1
  63. package/dist/server/google-oauth.d.ts +2 -0
  64. package/dist/server/google-oauth.js +5 -0
  65. package/dist/server/index.d.ts +1 -1
  66. package/dist/server/index.js +1 -1
  67. package/dist/server/transcribe-voice.d.ts +1 -1
  68. package/dist/shared/agent-chat-references.d.ts +2 -0
  69. package/dist/shared/agent-chat-references.js +8 -0
  70. package/dist/shared/auth-copy.d.ts +1 -0
  71. package/dist/shared/auth-copy.js +11 -0
  72. package/dist/shared/index.d.ts +1 -0
  73. package/dist/shared/index.js +1 -0
  74. package/dist/templates/builder-code-starter/server/lib/composer-reference-messages.ts.patch +44 -0
  75. package/dist/templates/builder-code-starter/server/plugins/agent-chat.ts.patch +10 -1
  76. package/dist/templates/chat/app/components/ChatComposerContext.tsx +31 -0
  77. package/dist/templates/chat/app/components/chat/ChatRouteContent.tsx +3 -0
  78. package/dist/templates/chat/app/components/home/HomePage.tsx +4 -2
  79. package/dist/templates/chat/app/components/layout/AgentInspector.tsx +2 -0
  80. package/dist/templates/chat/app/i18n/ar-SA.ts +7 -0
  81. package/dist/templates/chat/app/i18n/de-DE.ts +8 -0
  82. package/dist/templates/chat/app/i18n/en-US.ts +8 -0
  83. package/dist/templates/chat/app/i18n/es-ES.ts +8 -0
  84. package/dist/templates/chat/app/i18n/fr-FR.ts +8 -0
  85. package/dist/templates/chat/app/i18n/hi-IN.ts +7 -0
  86. package/dist/templates/chat/app/i18n/ja-JP.ts +8 -0
  87. package/dist/templates/chat/app/i18n/ko-KR.ts +8 -0
  88. package/dist/templates/chat/app/i18n/pt-BR.ts +8 -0
  89. package/dist/templates/chat/app/i18n/zh-CN.ts +7 -0
  90. package/dist/templates/chat/app/i18n/zh-TW.ts +7 -0
  91. package/dist/templates/chat/server/lib/composer-reference-messages.ts +34 -0
  92. package/dist/templates/chat/server/lib/composer-references.ts +60 -0
  93. package/dist/templates/chat/server/plugins/agent-chat.ts +13 -0
  94. package/docs/content/components.mdx +7 -2
  95. package/package.json +9 -4
  96. package/src/templates/builder-code-starter/server/lib/composer-reference-messages.ts.patch +44 -0
  97. package/src/templates/builder-code-starter/server/plugins/agent-chat.ts.patch +10 -1
  98. package/src/templates/chat/app/components/ChatComposerContext.tsx +31 -0
  99. package/src/templates/chat/app/components/chat/ChatRouteContent.tsx +3 -0
  100. package/src/templates/chat/app/components/home/HomePage.tsx +4 -2
  101. package/src/templates/chat/app/components/layout/AgentInspector.tsx +2 -0
  102. package/src/templates/chat/app/i18n/ar-SA.ts +7 -0
  103. package/src/templates/chat/app/i18n/de-DE.ts +8 -0
  104. package/src/templates/chat/app/i18n/en-US.ts +8 -0
  105. package/src/templates/chat/app/i18n/es-ES.ts +8 -0
  106. package/src/templates/chat/app/i18n/fr-FR.ts +8 -0
  107. package/src/templates/chat/app/i18n/hi-IN.ts +7 -0
  108. package/src/templates/chat/app/i18n/ja-JP.ts +8 -0
  109. package/src/templates/chat/app/i18n/ko-KR.ts +8 -0
  110. package/src/templates/chat/app/i18n/pt-BR.ts +8 -0
  111. package/src/templates/chat/app/i18n/zh-CN.ts +7 -0
  112. package/src/templates/chat/app/i18n/zh-TW.ts +7 -0
  113. package/src/templates/chat/server/lib/composer-reference-messages.ts +34 -0
  114. package/src/templates/chat/server/lib/composer-references.ts +60 -0
  115. package/src/templates/chat/server/plugins/agent-chat.ts +13 -0
@@ -0,0 +1,345 @@
1
+ import { createHmac, randomBytes, randomInt, timingSafeEqual, } from "node:crypto";
2
+ import { defineEventHandler, deleteCookie, getCookie, getHeader, getMethod, setCookie, setResponseHeader, setResponseStatus, } from "h3";
3
+ import { z } from "zod";
4
+ import { getAppConfig } from "../app-config/index.js";
5
+ import { getSetting, mutateSetting } from "../settings/store.js";
6
+ import { track } from "../tracking/index.js";
7
+ import { getAuthSecret, getBetterAuthInternalAdapter, } from "./better-auth-instance.js";
8
+ import { readBodyWithSizeLimit } from "./h3-helpers.js";
9
+ export const BUILDER_SIGNUP_EXPERIMENT = "design_builder_signup_v1";
10
+ export const BUILDER_SIGNUP_POLICY = "builder-signup-2026-11-06";
11
+ export const BUILDER_SIGNUP_COOKIE = "an_builder_signup";
12
+ const TTL = 7 * 24 * 60 * 60;
13
+ const assignmentSchema = z.object({
14
+ id: z.string().regex(/^[a-f0-9]{32}$/),
15
+ variant: z.enum(["control", "automatic"]),
16
+ issuedAt: z.number().int(),
17
+ acceptedAt: z.number().int().optional(),
18
+ attemptId: z.string().min(16).max(128).optional(),
19
+ method: z.enum(["password", "magic-link", "google"]).optional(),
20
+ email: z.string().email().max(320).optional(),
21
+ policy: z.literal(BUILDER_SIGNUP_POLICY),
22
+ });
23
+ function mac(body) {
24
+ return createHmac("sha256", getAuthSecret())
25
+ .update(`${BUILDER_SIGNUP_EXPERIMENT}:${body}`)
26
+ .digest();
27
+ }
28
+ export function encodeBuilderSignupAssignment(assignment) {
29
+ const body = Buffer.from(JSON.stringify(assignment)).toString("base64url");
30
+ return `${body}.${mac(body).toString("base64url")}`;
31
+ }
32
+ export function decodeBuilderSignupAssignment(value) {
33
+ if (!value || value.length > 2048)
34
+ return null;
35
+ const parts = value.split(".");
36
+ if (parts.length !== 2)
37
+ return null;
38
+ const [body, signature] = parts;
39
+ if (!body || !signature)
40
+ return null;
41
+ const expected = mac(body);
42
+ const actual = Buffer.from(signature, "base64url");
43
+ if (actual.length !== expected.length || !timingSafeEqual(actual, expected))
44
+ return null;
45
+ let json;
46
+ try {
47
+ json = JSON.parse(Buffer.from(body, "base64url").toString());
48
+ }
49
+ catch {
50
+ // coercion-ok: malformed anonymous cookies are rejected, never used as consent.
51
+ return null;
52
+ }
53
+ const parsed = assignmentSchema.safeParse(json);
54
+ if (!parsed.success)
55
+ return null;
56
+ const assignment = parsed.data;
57
+ if (assignment.issuedAt > Date.now() ||
58
+ Date.now() - assignment.issuedAt > TTL * 1000)
59
+ return null;
60
+ if (assignment.acceptedAt !== undefined &&
61
+ (assignment.acceptedAt < assignment.issuedAt ||
62
+ assignment.acceptedAt > Date.now()))
63
+ return null;
64
+ return assignment;
65
+ }
66
+ function writeAssignment(event, assignment) {
67
+ setCookie(event, BUILDER_SIGNUP_COOKIE, encodeBuilderSignupAssignment(assignment), {
68
+ httpOnly: true,
69
+ secure: getHeader(event, "x-forwarded-proto") === "https" ||
70
+ getHeader(event, "host")?.includes("localhost") !== true,
71
+ sameSite: "lax",
72
+ path: "/",
73
+ maxAge: TTL,
74
+ });
75
+ }
76
+ export function isBuilderSignupExperimentEnabled() {
77
+ const config = getAppConfig().onboarding;
78
+ return (config.builderSignupExperimentOverride ?? config.builderSignupExperiment);
79
+ }
80
+ export async function bindBuilderSignupAttempt(event, attemptId, method, email) {
81
+ if (!isBuilderSignupExperimentEnabled())
82
+ return false;
83
+ const assignment = decodeBuilderSignupAssignment(getCookie(event, BUILDER_SIGNUP_COOKIE));
84
+ if (!assignment)
85
+ return false;
86
+ if (assignment.variant === "control") {
87
+ const adapter = await getBetterAuthInternalAdapter();
88
+ if (!adapter)
89
+ throw new Error("Signup identity store is unavailable");
90
+ const identity = await adapter.findUserByEmail(email, {
91
+ includeAccounts: false,
92
+ });
93
+ const createdAt = identity?.user.createdAt;
94
+ const createdAtMs = createdAt ? new Date(createdAt).getTime() : Number.NaN;
95
+ if (!identity ||
96
+ !Number.isFinite(createdAtMs) ||
97
+ createdAtMs < assignment.issuedAt)
98
+ return false;
99
+ const key = `${BUILDER_SIGNUP_EXPERIMENT}:${identity.user.id}`;
100
+ if (!(await getSetting(key))) {
101
+ await mutateSetting(key, (current) => current ?? {
102
+ id: assignment.id,
103
+ variant: "control",
104
+ issuedAt: assignment.issuedAt,
105
+ policy: assignment.policy,
106
+ userId: identity.user.id,
107
+ status: "control",
108
+ });
109
+ track("builder_signup_experiment_outcome", {
110
+ experiment_id: BUILDER_SIGNUP_EXPERIMENT,
111
+ experiment_variant: "control",
112
+ assignment_id: assignment.id,
113
+ status: "control",
114
+ }, { authUserId: identity.user.id, userId: email });
115
+ }
116
+ return false;
117
+ }
118
+ if (typeof attemptId !== "string" ||
119
+ attemptId.length > 128 ||
120
+ !assignment.acceptedAt ||
121
+ assignment.attemptId !== attemptId)
122
+ return false;
123
+ const key = `${BUILDER_SIGNUP_EXPERIMENT}:attempt:${attemptId}`;
124
+ const normalizedEmail = email.trim().toLowerCase();
125
+ if (assignment.method !== method ||
126
+ (assignment.email && assignment.email !== normalizedEmail))
127
+ return false;
128
+ const adapter = await getBetterAuthInternalAdapter();
129
+ if (!adapter)
130
+ throw new Error("Signup identity store is unavailable");
131
+ const identity = await adapter.findUserByEmail(normalizedEmail, {
132
+ includeAccounts: false,
133
+ });
134
+ const createdAt = identity?.user.createdAt;
135
+ const createdAtMs = createdAt ? new Date(createdAt).getTime() : Number.NaN;
136
+ if (!identity ||
137
+ !Number.isFinite(createdAtMs) ||
138
+ createdAtMs < assignment.acceptedAt)
139
+ return false;
140
+ const bound = z
141
+ .object({ id: z.string(), boundUserId: z.string() })
142
+ .parse(await mutateSetting(key, (current) => current ?? { id: assignment.id, boundUserId: identity.user.id }));
143
+ if (bound.id !== assignment.id || bound.boundUserId !== identity.user.id)
144
+ return false;
145
+ await mutateSetting(`${BUILDER_SIGNUP_EXPERIMENT}:consent:${identity.user.id}`, (current) => current ?? {
146
+ ...assignment,
147
+ userId: identity.user.id,
148
+ email: normalizedEmail,
149
+ });
150
+ setCookie(event, "an_builder_signup_pending", "1", {
151
+ path: "/",
152
+ sameSite: "lax",
153
+ maxAge: TTL,
154
+ secure: getHeader(event, "host")?.includes("localhost") !== true,
155
+ });
156
+ return true;
157
+ }
158
+ export async function getBuilderSignupConnectError(userId) {
159
+ if (!userId || !isBuilderSignupExperimentEnabled())
160
+ return undefined;
161
+ const record = await getSetting(`${BUILDER_SIGNUP_EXPERIMENT}:${userId}`);
162
+ if (record?.status !== "fallback" || record.code !== "account_exists")
163
+ return undefined;
164
+ const error = z
165
+ .object({ message: z.string(), completedAt: z.number().finite() })
166
+ .parse(record);
167
+ return {
168
+ code: "account_exists",
169
+ message: error.message,
170
+ at: error.completedAt,
171
+ };
172
+ }
173
+ async function finishSignupActivation(key, attempt, outcome) {
174
+ const committed = await mutateSetting(key, (current) => {
175
+ if (!current || current.attempt !== attempt)
176
+ throw new Error("Signup activation reservation ownership changed");
177
+ const status = z
178
+ .enum(["started", "connected", "fallback"])
179
+ .parse(current.status);
180
+ if (status !== "started")
181
+ return current;
182
+ return {
183
+ ...current,
184
+ status: outcome.status,
185
+ code: outcome.code ?? null,
186
+ message: outcome.message ?? null,
187
+ completedAt: Date.now(),
188
+ };
189
+ });
190
+ return z
191
+ .object({
192
+ status: z.enum(["connected", "fallback"]),
193
+ code: z.string().nullable().optional(),
194
+ })
195
+ .parse(committed);
196
+ }
197
+ export function createBuilderSignupExperimentHandler(dependencies) {
198
+ return defineEventHandler(async (event) => {
199
+ setResponseHeader(event, "Cache-Control", "no-store");
200
+ const refuse = (status, code) => {
201
+ setResponseStatus(event, status);
202
+ return { status: "unavailable", code };
203
+ };
204
+ if (!isBuilderSignupExperimentEnabled())
205
+ return { status: "disabled" };
206
+ const method = getMethod(event);
207
+ if (method !== "GET" && method !== "POST")
208
+ return refuse(405, "method_not_allowed");
209
+ if (!dependencies.sameOrigin(event))
210
+ return refuse(403, "cross_origin");
211
+ const session = await dependencies.getSession(event);
212
+ let assignment = decodeBuilderSignupAssignment(getCookie(event, BUILDER_SIGNUP_COOKIE));
213
+ if (method === "GET") {
214
+ if (session)
215
+ return { status: "disabled" };
216
+ if (!assignment) {
217
+ assignment = {
218
+ id: randomBytes(16).toString("hex"),
219
+ variant: randomInt(2) === 0 ? "control" : "automatic",
220
+ issuedAt: Date.now(),
221
+ policy: BUILDER_SIGNUP_POLICY,
222
+ };
223
+ writeAssignment(event, assignment);
224
+ }
225
+ return { status: "assigned", ...assignment };
226
+ }
227
+ if (!/^application\/json\s*(;|$)/i.test(getHeader(event, "content-type") ?? ""))
228
+ return refuse(415, "json_required");
229
+ const body = z
230
+ .object({
231
+ operation: z.enum(["accept", "activate"]),
232
+ assignmentId: z.string().optional(),
233
+ attemptId: z.string().min(16).max(128).optional(),
234
+ method: z.enum(["password", "magic-link", "google"]).optional(),
235
+ email: z.string().email().max(320).optional(),
236
+ })
237
+ .safeParse(await readBodyWithSizeLimit(event, 4096));
238
+ if (!body.success)
239
+ return refuse(400, "invalid_request");
240
+ if (!assignment) {
241
+ deleteCookie(event, "an_builder_signup_pending", { path: "/" });
242
+ return body.data.operation === "activate"
243
+ ? { status: "fallback" }
244
+ : refuse(409, "assignment_missing");
245
+ }
246
+ if (body.data.operation === "accept") {
247
+ if (session || body.data.assignmentId !== assignment.id)
248
+ return refuse(409, "assignment_mismatch");
249
+ if (assignment.variant !== "automatic")
250
+ return { status: "not_required" };
251
+ if (!body.data.attemptId ||
252
+ !body.data.method ||
253
+ (body.data.method !== "google" && !body.data.email))
254
+ return refuse(400, "attempt_required");
255
+ assignment = {
256
+ ...assignment,
257
+ acceptedAt: Date.now(),
258
+ attemptId: body.data.attemptId,
259
+ method: body.data.method,
260
+ ...(body.data.email
261
+ ? { email: body.data.email.trim().toLowerCase() }
262
+ : {}),
263
+ };
264
+ writeAssignment(event, assignment);
265
+ setCookie(event, "an_builder_signup_pending", "1", {
266
+ path: "/",
267
+ sameSite: "lax",
268
+ maxAge: TTL,
269
+ secure: getHeader(event, "host")?.includes("localhost") !== true,
270
+ });
271
+ return { status: "accepted" };
272
+ }
273
+ if (!session?.emailVerified || !session.userId)
274
+ return refuse(401, "verified_session_required");
275
+ const terminal = (status, code) => {
276
+ deleteCookie(event, "an_builder_signup_pending", { path: "/" });
277
+ return { status, ...(code ? { code } : {}) };
278
+ };
279
+ if (assignment.variant !== "automatic")
280
+ return terminal("fallback", "control");
281
+ if (!assignment.acceptedAt || !assignment.attemptId)
282
+ return terminal("fallback");
283
+ const consent = await getSetting(`${BUILDER_SIGNUP_EXPERIMENT}:consent:${session.userId}`);
284
+ if (!consent ||
285
+ consent.attemptId !== assignment.attemptId ||
286
+ consent.id !== assignment.id ||
287
+ consent.userId !== session.userId ||
288
+ consent.email !== session.email.trim().toLowerCase())
289
+ return terminal("fallback", "signup_attempt_unbound");
290
+ const adapter = await getBetterAuthInternalAdapter();
291
+ if (!adapter)
292
+ return refuse(503, "identity_unavailable");
293
+ const identity = await adapter.findUserByEmail(session.email, {
294
+ includeAccounts: false,
295
+ });
296
+ const createdAt = identity?.user.createdAt;
297
+ const createdAtMs = createdAt ? new Date(createdAt).getTime() : Number.NaN;
298
+ if (!identity ||
299
+ identity.user.id !== session.userId ||
300
+ !Number.isFinite(createdAtMs) ||
301
+ createdAtMs < assignment.acceptedAt)
302
+ return terminal("fallback");
303
+ const key = `${BUILDER_SIGNUP_EXPERIMENT}:${session.userId}`;
304
+ const existing = await getSetting(key);
305
+ if (existing) {
306
+ const status = z
307
+ .enum(["started", "connected", "fallback"])
308
+ .parse(existing.status);
309
+ if (status !== "started")
310
+ return terminal(status);
311
+ return { status: "pending" };
312
+ }
313
+ const attempt = randomBytes(16).toString("hex");
314
+ const record = await mutateSetting(key, (current) => current ?? {
315
+ ...assignment,
316
+ status: "started",
317
+ startedAt: Date.now(),
318
+ attempt,
319
+ userId: session.userId,
320
+ });
321
+ if (record.attempt !== attempt)
322
+ return { status: "pending" };
323
+ let result;
324
+ try {
325
+ result = await dependencies.activate(event, session);
326
+ }
327
+ catch {
328
+ result = { ok: false, code: "activation_interrupted" };
329
+ }
330
+ const committed = await finishSignupActivation(key, attempt, {
331
+ status: result.ok ? "connected" : "fallback",
332
+ ...(result.code ? { code: result.code } : {}),
333
+ ...(result.message ? { message: result.message } : {}),
334
+ });
335
+ const status = committed.status;
336
+ track("builder_signup_experiment_outcome", {
337
+ experiment_id: BUILDER_SIGNUP_EXPERIMENT,
338
+ experiment_variant: assignment.variant,
339
+ assignment_id: assignment.id,
340
+ status,
341
+ code: committed.code ?? null,
342
+ }, { userId: session.email, authUserId: session.userId });
343
+ return terminal(status, committed.code ?? undefined);
344
+ });
345
+ }
@@ -610,6 +610,7 @@ type BuilderConnectMember = {
610
610
  export type BuilderAccountActivationResult = {
611
611
  ok: true;
612
612
  scope: "user" | "org";
613
+ code?: string;
613
614
  } | {
614
615
  ok: false;
615
616
  status: number;
@@ -620,6 +621,7 @@ export type BuilderAccountActivationResult = {
620
621
  code?: string;
621
622
  };
622
623
  interface BuilderAccountActivationInput {
624
+ newAccountOnly?: boolean;
623
625
  ownerEmail: string;
624
626
  session: AuthSession | null;
625
627
  provisioningToken: string | null | undefined;
@@ -10,6 +10,7 @@ import { registerBuiltinEngines } from "../agent/engine/builtin.js";
10
10
  import { OPENAI_BASE_URL_ENV_VAR, PROVIDER_ENV_META, } from "../agent/engine/provider-env-vars.js";
11
11
  import { detectEngineFromEnvForRequest, detectEngineFromUserSecrets, isStoredEngineUsableForRequest, } from "../agent/engine/registry.js";
12
12
  import { canUpdateAgentLoopSettings, readAgentLoopSettings, resetAgentLoopSettings, validateMaxIterationsInput, writeAgentLoopSettings, } from "../agent/loop-settings.js";
13
+ import { createBuilderSignupExperimentHandler, getBuilderSignupConnectError, } from "./builder-signup-experiment.js";
13
14
  export { normalizeAgentEngineStatusModel, resolveAgentEngineStatus, } from "../agent/engine-status.js";
14
15
  import { getAppConfig } from "../app-config/index.js";
15
16
  import { getState, putState, compareAndSetState, deleteState, listComposeDrafts, getComposeDraft, putComposeDraft, saveComposeDraft, deleteComposeDraft, deleteAllComposeDrafts, getStateMany, putStateMany, APP_STATE_ANONYMOUS_OWNER_CONTEXT_KEY, } from "../application-state/handlers.js";
@@ -1555,36 +1556,57 @@ export async function activateBuilderAccount(event, input) {
1555
1556
  }
1556
1557
  const activationOrg = activation.write;
1557
1558
  const credentials = await provisionBuilderAccount({
1559
+ ...(input.newAccountOnly ? { newAccountOnly: true } : {}),
1558
1560
  email: ownerEmail,
1559
1561
  name: session.name,
1560
1562
  agentNativeApp: input.tracking.agentNativeApp,
1561
1563
  agentNativeTemplate: input.tracking.agentNativeTemplate,
1562
1564
  });
1563
1565
  const { writeBuilderCredentials } = await import("./credential-provider.js");
1564
- const written = await writeBuilderCredentials(ownerEmail, credentials, activationOrg ?? undefined);
1565
- await Promise.all([
1566
- deleteSetting("builder-disconnected").catch(() => false),
1567
- ...getBuilderConnectErrorCleanupKeys(ownerEmail, connectAttemptId).map((key) => deleteSetting(key).catch(() => false)),
1568
- ]);
1569
- await trackBuilderLifecycle(event, "builder connect succeeded", ownerEmail, {
1570
- ...builderConnectTrackingProperties(input.tracking),
1571
- stage: "provision",
1572
- credential_scope: written.scope,
1573
- account_provisioned: true,
1574
- });
1575
- track("llm_credential_changed", {
1576
- change_type: "connected",
1577
- provider: "builder",
1578
- scope: written.scope,
1579
- credential_kind: "builder",
1580
- }, { userId: ownerEmail });
1581
- await recordBuilderConnectionAudit({
1582
- connected: true,
1583
- ownerEmail,
1584
- orgId: activationOrg?.orgId ?? null,
1585
- scope: written.scope,
1586
- attribution: routeAuditAttribution(event),
1587
- });
1566
+ let written;
1567
+ try {
1568
+ written = await writeBuilderCredentials(ownerEmail, credentials, activationOrg ?? undefined);
1569
+ }
1570
+ catch (error) {
1571
+ captureError(error, { route: "builder.provision.credential-write" });
1572
+ return fail(409, "A Builder.io account already exists for this email. Sign in to Builder.io to use it.", "credential_write_failed", "account_exists");
1573
+ }
1574
+ try {
1575
+ await Promise.all([
1576
+ deleteSetting("builder-disconnected").catch(() => false),
1577
+ ...getBuilderConnectErrorCleanupKeys(ownerEmail, connectAttemptId).map((key) => deleteSetting(key).catch(() => false)),
1578
+ ]);
1579
+ await trackBuilderLifecycle(event, "builder connect succeeded", ownerEmail, {
1580
+ ...builderConnectTrackingProperties(input.tracking),
1581
+ stage: "provision",
1582
+ credential_scope: written.scope,
1583
+ account_provisioned: true,
1584
+ });
1585
+ track("llm_credential_changed", {
1586
+ change_type: "connected",
1587
+ provider: "builder",
1588
+ scope: written.scope,
1589
+ credential_kind: "builder",
1590
+ }, { userId: ownerEmail });
1591
+ await recordBuilderConnectionAudit({
1592
+ connected: true,
1593
+ ownerEmail,
1594
+ orgId: activationOrg?.orgId ?? null,
1595
+ scope: written.scope,
1596
+ attribution: routeAuditAttribution(event),
1597
+ });
1598
+ }
1599
+ catch (error) {
1600
+ captureError(error, {
1601
+ route: "builder.provision.post-write",
1602
+ tags: { credential_write: "completed" },
1603
+ });
1604
+ return {
1605
+ ok: true,
1606
+ scope: written.scope,
1607
+ code: "post_write_reporting_failed",
1608
+ };
1609
+ }
1588
1610
  return { ok: true, scope: written.scope };
1589
1611
  }
1590
1612
  catch (error) {
@@ -2871,6 +2893,7 @@ export function createCoreRoutesPlugin(options = {}) {
2871
2893
  const envStatus = getBuilderBrowserStatusForEvent(event);
2872
2894
  const ownerContext = await resolveBuilderOwnerContext(event);
2873
2895
  const userEmail = ownerContext.email;
2896
+ const signupConnectError = await getBuilderSignupConnectError(ownerContext.session?.userId);
2874
2897
  const provisioningToken = userEmail &&
2875
2898
  ownerContext.session?.token &&
2876
2899
  isBuilderAccountProvisioningEnabled()
@@ -2884,7 +2907,14 @@ export function createCoreRoutesPlugin(options = {}) {
2884
2907
  // (`effective`) alongside the grants that exist, so the UI can show
2885
2908
  // the organization and personal connections as separate rows.
2886
2909
  const withConnectToken = (status, effective = null) => {
2887
- const withConnections = { ...status, ...connections, effective };
2910
+ const withConnections = {
2911
+ ...status,
2912
+ ...connections,
2913
+ effective,
2914
+ ...(signupConnectError && status.configured !== true
2915
+ ? { connectError: signupConnectError }
2916
+ : {}),
2917
+ };
2888
2918
  if (!userEmail)
2889
2919
  return withConnections;
2890
2920
  return {
@@ -3430,6 +3460,28 @@ export function createCoreRoutesPlugin(options = {}) {
3430
3460
  setResponseHeader(event, "Location", authorizationUrl);
3431
3461
  return "";
3432
3462
  }));
3463
+ getH3App(nitroApp).use(`${P}/auth/builder-signup-experiment`, createBuilderSignupExperimentHandler({
3464
+ getSession,
3465
+ sameOrigin: isSameOriginConnect,
3466
+ activate: async (event, session) => {
3467
+ const authorization = await authorizeBuilderConnectScope(event, session.email, null);
3468
+ if ("deny" in authorization)
3469
+ return { ok: false, code: authorization.deny.reason };
3470
+ return activateBuilderAccount(event, {
3471
+ ownerEmail: session.email,
3472
+ session,
3473
+ provisioningToken: signBuilderProvisioningToken(session.email, session.token ?? ""),
3474
+ requestedScope: null,
3475
+ member: authorization.member,
3476
+ connectAttemptId: null,
3477
+ tracking: {
3478
+ agentNativeApp: "design",
3479
+ agentNativeTemplate: "design",
3480
+ },
3481
+ newAccountOnly: true,
3482
+ });
3483
+ },
3484
+ }));
3433
3485
  getH3App(nitroApp).use(`${P}/builder/provision`, createBuilderProvisionHandler((event) => resolveBuilderOwnerContext(event)));
3434
3486
  // Desktop Code Agents speak Anthropic Messages locally, but Builder
3435
3487
  // Gateway credentials live on the server. This same-origin route keeps
@@ -17,8 +17,8 @@ export type FirstTouchSyncResult = {
17
17
  * browser's `an_ft` and `an_lt` again, so Safari keeps them their 30 days.
18
18
  */
19
19
  export declare function createFirstTouchHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
20
- error: string;
21
20
  reason?: undefined;
21
+ error: string;
22
22
  stored?: undefined;
23
23
  firstTouch?: undefined;
24
24
  } | {
@@ -75,6 +75,7 @@ export interface OAuthStatePayload {
75
75
  desktopVerifierHash?: string;
76
76
  desktopBrowserBindingHash?: string;
77
77
  desktopWebview?: boolean;
78
+ builderSignupAttemptId?: string;
78
79
  signupAttribution?: Record<string, string | undefined>;
79
80
  signupAnonymousId?: string;
80
81
  signupSessionId?: string;
@@ -114,6 +115,7 @@ export interface EncodeOAuthStateOptions {
114
115
  desktopVerifierHash?: string;
115
116
  desktopBrowserBindingHash?: string;
116
117
  desktopWebview?: boolean;
118
+ builderSignupAttemptId?: string;
117
119
  signupAttribution?: Record<string, string | undefined>;
118
120
  signupAnonymousId?: string;
119
121
  signupSessionId?: string;
@@ -479,6 +479,8 @@ export function encodeOAuthState(redirectUriOrOpts, owner, desktop, addAccount,
479
479
  payload.bh = opts.desktopBrowserBindingHash;
480
480
  if (opts.desktopWebview)
481
481
  payload.dw = true;
482
+ if (opts.builderSignupAttemptId)
483
+ payload.bs = opts.builderSignupAttemptId;
482
484
  if (opts.signupAttribution)
483
485
  payload.ft = opts.signupAttribution;
484
486
  const signupAnonymousId = normalizeAnalyticsAnonymousId(opts.signupAnonymousId);
@@ -538,6 +540,9 @@ export function decodeOAuthState(stateParam, fallbackUri) {
538
540
  desktopVerifierHash: typeof parsed.vh === "string" ? parsed.vh : undefined,
539
541
  desktopBrowserBindingHash: typeof parsed.bh === "string" ? parsed.bh : undefined,
540
542
  desktopWebview: parsed.dw === true,
543
+ builderSignupAttemptId: typeof parsed.bs === "string" && parsed.bs.length <= 128
544
+ ? parsed.bs
545
+ : undefined,
541
546
  signupAttribution: sanitizeStateAttribution(parsed.ft),
542
547
  signupAnonymousId: sanitizeStateAnonymousId(parsed.ai),
543
548
  signupSessionId: normalizeAnalyticsSessionId(parsed.si),
@@ -69,7 +69,7 @@ export { refreshMcpManagerForPrincipal } from "./agent-chat/mcp-glue.js";
69
69
  export { AGENT_CHAT_STREAM_PATH, AGENT_CHAT_STREAM_TOKEN_SUFFIX, AGENT_CHAT_STREAM_TOKEN_TTL_SECONDS, createAgentChatStreamToken, isAgentChatStreamingRuntime, readAgentChatStreamBearerToken, verifyAgentChatStreamToken, type AgentChatStreamPrincipal, } from "./agent-chat-stream.js";
70
70
  export type { AgentChatMcpIcon, AgentChatMcpOptions, } from "./agent-chat/mcp-options.js";
71
71
  export { configureAgentNativeEmbeddedEnvironment, createAgentNativeEmbeddedAuthOptions, createAgentNativeEmbeddedPlugin, mountAgentNativeEmbedded, normalizeAgentNativeEmbeddedSession, type AgentNativeEmbeddedAuthOptions, type AgentNativeEmbeddedGetSession, type AgentNativeEmbeddedHostSession, type AgentNativeEmbeddedPluginOptions, } from "./embedded.js";
72
- export { createThread, getThread, listThreads, updateThreadData, deleteThread, setThreadArchived, setThreadPinned, setThreadScope, type ChatThread, type ChatThreadAccessBasis, type ChatThreadOwnership, type ChatThreadScope, type ChatThreadSummary, type ChatThreadListRow, type ListThreadsOptions, } from "../chat-threads/store.js";
72
+ export { createThread, getThread, listThreads, searchThreads, updateThreadData, deleteThread, setThreadArchived, setThreadPinned, setThreadScope, type ChatThread, type ChatThreadAccessBasis, type ChatThreadOwnership, type ChatThreadScope, type ChatThreadSummary, type ChatThreadListRow, type ListThreadsOptions, } from "../chat-threads/store.js";
73
73
  export { createResourcesPlugin, defaultResourcesPlugin, } from "./resources-plugin.js";
74
74
  export { createCoreRoutesPlugin, defaultCoreRoutesPlugin, FRAMEWORK_ROUTE_PREFIX, type CoreRoutesPluginOptions, } from "./core-routes-plugin.js";
75
75
  export type { CoreRoutesMcpOptions } from "./core-routes/mcp-connect-options.js";
@@ -64,7 +64,7 @@ export { buildFrameworkPrompts, generateActionsPrompt, } from "./agent-chat/fram
64
64
  export { refreshMcpManagerForPrincipal } from "./agent-chat/mcp-glue.js";
65
65
  export { AGENT_CHAT_STREAM_PATH, AGENT_CHAT_STREAM_TOKEN_SUFFIX, AGENT_CHAT_STREAM_TOKEN_TTL_SECONDS, createAgentChatStreamToken, isAgentChatStreamingRuntime, readAgentChatStreamBearerToken, verifyAgentChatStreamToken, } from "./agent-chat-stream.js";
66
66
  export { configureAgentNativeEmbeddedEnvironment, createAgentNativeEmbeddedAuthOptions, createAgentNativeEmbeddedPlugin, mountAgentNativeEmbedded, normalizeAgentNativeEmbeddedSession, } from "./embedded.js";
67
- export { createThread, getThread, listThreads, updateThreadData, deleteThread, setThreadArchived, setThreadPinned, setThreadScope, } from "../chat-threads/store.js";
67
+ export { createThread, getThread, listThreads, searchThreads, updateThreadData, deleteThread, setThreadArchived, setThreadPinned, setThreadScope, } from "../chat-threads/store.js";
68
68
  export { createResourcesPlugin, defaultResourcesPlugin, } from "./resources-plugin.js";
69
69
  export { createCoreRoutesPlugin, defaultCoreRoutesPlugin, FRAMEWORK_ROUTE_PREFIX, } from "./core-routes-plugin.js";
70
70
  export { buildRuntimeConfigPrompt, formatRuntimeConfigReport, getRuntimeConfigReport, parseRuntimeConfigReport, runtimeConfigRequirementsFromSearchParams, } from "../shared/runtime-config.js";
@@ -17,8 +17,8 @@
17
17
  * typed JSON-in / JSON-out).
18
18
  */
19
19
  export declare function createTranscribeVoiceHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
20
- error: string;
21
20
  text?: undefined;
21
+ error: string;
22
22
  } | {
23
23
  error?: undefined;
24
24
  text: string;
@@ -0,0 +1,2 @@
1
+ import { type AgentSubmissionReference } from "@agent-native/agentkit/protocol";
2
+ export declare function parseAgentChatReferences(value: unknown): AgentSubmissionReference[];
@@ -0,0 +1,8 @@
1
+ import { parseQueueMessageInput, } from "@agent-native/agentkit/protocol";
2
+ export function parseAgentChatReferences(value) {
3
+ return (parseQueueMessageInput({
4
+ threadId: "composer-handoff",
5
+ text: "",
6
+ references: value,
7
+ }).references ?? []);
8
+ }
@@ -14,6 +14,7 @@ export interface NativeAuthCopy {
14
14
  emailLinkContinueAction: string;
15
15
  email: string;
16
16
  emailPlaceholder: string;
17
+ builderSignupDisclosure: string;
17
18
  legalPrefix: string;
18
19
  legalTerms: string;
19
20
  legalConnector: string;