@agent-native/core 0.226.0 → 0.226.1-nightly-20261107004051

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.
@@ -31,6 +31,20 @@ export declare function withExecutionLeaseRequested<T>(work: () => T): T;
31
31
  export declare function withExecutionFence<T>(fence: ExecutionFence, work: () => T): T;
32
32
  export declare function runWithoutExecutionFence<T>(work: () => T): T;
33
33
  export declare function lockAndAssertCurrentExecutionFences(tx: DbExec, ignoredFence?: ExecutionFence): Promise<void>;
34
+ /**
35
+ * A turn lease that lapsed on its own still belongs to its worker: a stalled
36
+ * DB call or a blocked event loop outlived the 15s lease, and nobody acted on
37
+ * it. Ending the run here ends it with no terminal event, and the reaper later
38
+ * reports it as "stopped before finishing".
39
+ *
40
+ * Every revoke (Stop, the reaper, Agent Teams, A2A) sets `lease_expires_at`
41
+ * and `updated_at` to now together, and every new claim bumps the generation,
42
+ * so only a lease that expired well after its last renewal counts. The run row
43
+ * must also still be running at that generation; task leases have no such row
44
+ * and stay strict. Locking the lease row first orders this read after any
45
+ * revoke that committed and before any that has not.
46
+ */
47
+ export declare function ownsLapsedTurnLease(tx: DbExec, fence: ExecutionFence): Promise<boolean>;
34
48
  export declare function withFencedExecutionWrite<T>(write: (tx: DbExec) => Promise<T>, scope?: {
35
49
  runId?: string;
36
50
  threadId?: string;
@@ -92,10 +92,58 @@ export async function lockAndAssertCurrentExecutionFences(tx, ignoredFence) {
92
92
  activeFence.generation,
93
93
  ],
94
94
  });
95
- if (rows.length !== 1)
95
+ if (rows.length === 1)
96
+ continue;
97
+ if (activeFence.outlivesStop ||
98
+ !(await ownsLapsedTurnLease(tx, activeFence))) {
96
99
  throw new StaleExecutionFenceError(activeFence);
100
+ }
97
101
  }
98
102
  }
103
+ /**
104
+ * A turn lease that lapsed on its own still belongs to its worker: a stalled
105
+ * DB call or a blocked event loop outlived the 15s lease, and nobody acted on
106
+ * it. Ending the run here ends it with no terminal event, and the reaper later
107
+ * reports it as "stopped before finishing".
108
+ *
109
+ * Every revoke (Stop, the reaper, Agent Teams, A2A) sets `lease_expires_at`
110
+ * and `updated_at` to now together, and every new claim bumps the generation,
111
+ * so only a lease that expired well after its last renewal counts. The run row
112
+ * must also still be running at that generation; task leases have no such row
113
+ * and stay strict. Locking the lease row first orders this read after any
114
+ * revoke that committed and before any that has not.
115
+ */
116
+ export async function ownsLapsedTurnLease(tx, fence) {
117
+ const lease = await tx.execute({
118
+ sql: `SELECT generation
119
+ FROM agent_execution_leases
120
+ WHERE thread_id = ?
121
+ AND turn_id = ?
122
+ AND owner_run_id = ?
123
+ AND generation = CAST(? AS BIGINT)
124
+ AND lease_expires_at >= updated_at + INTERVAL '1 second'
125
+ FOR UPDATE`,
126
+ args: [fence.threadId, fence.turnId, fence.runId, fence.generation],
127
+ timeoutMs: LAPSED_LEASE_STATEMENT_TIMEOUT_MS,
128
+ maxAttempts: 1,
129
+ });
130
+ if (lease.rows.length !== 1)
131
+ return false;
132
+ const run = await tx.execute({
133
+ sql: `SELECT 1
134
+ FROM agent_runs
135
+ WHERE id = ?
136
+ AND status = 'running'
137
+ AND worker_generation = CAST(? AS BIGINT)`,
138
+ args: [fence.runId, fence.generation],
139
+ timeoutMs: LAPSED_LEASE_STATEMENT_TIMEOUT_MS,
140
+ maxAttempts: 1,
141
+ });
142
+ return run.rows.length === 1;
143
+ }
144
+ // Bounded like the lease renewal that calls it, so a lapsed lease never holds
145
+ // a pooled connection open past the next heartbeat.
146
+ const LAPSED_LEASE_STATEMENT_TIMEOUT_MS = 4_000;
99
147
  export async function withFencedExecutionWrite(write, scope) {
100
148
  const context = executionFenceStorage.getStore();
101
149
  const fences = context?.fences ?? [];
@@ -54,6 +54,8 @@ async function flushRunEventsBeforeAbort(run) {
54
54
  }
55
55
  }
56
56
  const CLEANUP_DELAY_MS = 5 * 60 * 1000;
57
+ const HEARTBEAT_ATTEMPT_DEADLINE_MS = 5_000;
58
+ const MAX_PENDING_HEARTBEATS = 2;
57
59
  export const DEFAULT_HOSTED_RUN_SOFT_TIMEOUT_MS = 40_000;
58
60
  export const HOSTED_SOFT_TIMEOUT_CEILING_MS = 40_000;
59
61
  export const DEFAULT_BACKGROUND_NO_PROGRESS_TIMEOUT_MS = RUN_NO_PROGRESS_HARD_TIMEOUT_MS;
@@ -1313,9 +1315,20 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
1313
1315
  let consecutiveHeartbeatFailures = 0;
1314
1316
  let heartbeatInFlight = false;
1315
1317
  let livenessResolved = false;
1318
+ let heartbeatAttempt = 0;
1319
+ let pendingHeartbeats = 0;
1316
1320
  const heartbeatTimer = setInterval(() => {
1317
- if (!heartbeatInFlight) {
1321
+ if (!heartbeatInFlight && pendingHeartbeats < MAX_PENDING_HEARTBEATS) {
1318
1322
  heartbeatInFlight = true;
1323
+ pendingHeartbeats += 1;
1324
+ const attempt = ++heartbeatAttempt;
1325
+ // One renewal stuck acquiring a connection must not hold the slot until
1326
+ // the lease lapses, so a later tick retries while it settles. Only one
1327
+ // retry may overlap it, or a stalled pool would fill with renewals.
1328
+ const releaseStuckHeartbeat = setTimeout(() => {
1329
+ if (heartbeatAttempt === attempt)
1330
+ heartbeatInFlight = false;
1331
+ }, HEARTBEAT_ATTEMPT_DEADLINE_MS);
1319
1332
  (options?.executionLease
1320
1333
  ? executionFencePromise.then(async (fence) => {
1321
1334
  if (!fence)
@@ -1353,7 +1366,10 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
1353
1366
  }
1354
1367
  })
1355
1368
  .finally(() => {
1356
- heartbeatInFlight = false;
1369
+ clearTimeout(releaseStuckHeartbeat);
1370
+ pendingHeartbeats -= 1;
1371
+ if (heartbeatAttempt === attempt)
1372
+ heartbeatInFlight = false;
1357
1373
  });
1358
1374
  }
1359
1375
  void checkSqlAbort();
@@ -18,7 +18,7 @@ import { approvalKeyForHistory, approvalKeyForPrivateHistory, PRIVATE_APPROVAL_U
18
18
  import { admitAutoContinue, admitManualContinue, } from "./auto-continue.js";
19
19
  import { AGENT_CHAT_RECOVERY_OF_RUN_FIELD } from "./durable-background.js";
20
20
  import { LLM_MISSING_CREDENTIALS_ERROR_CODE, LLM_MISSING_CREDENTIALS_MESSAGE, } from "./engine/credential-errors.js";
21
- import { currentExecutionFence, currentExecutionFenceForScope, ExecutionFenceError, MissingExecutionFenceError, lockAndAssertCurrentExecutionFences, StaleExecutionFenceError, withFencedExecutionWrite, } from "./execution-fence.js";
21
+ import { currentExecutionFence, currentExecutionFenceForScope, ExecutionFenceError, MissingExecutionFenceError, lockAndAssertCurrentExecutionFences, ownsLapsedTurnLease, StaleExecutionFenceError, withFencedExecutionWrite, } from "./execution-fence.js";
22
22
  import { AGENT_RUN_MIGRATIONS, AGENT_RUN_MIGRATIONS_TABLE, } from "./run-migrations.js";
23
23
  import { lockThreadRunSlot } from "./run-slot-lock.js";
24
24
  import { trackRunTerminal, } from "./run-terminal-tracking.js";
@@ -295,7 +295,16 @@ export const agentRunsStore = defineStore({
295
295
  ...fromMigrationEntries(AGENT_RUN_MIGRATIONS_TABLE, AGENT_RUN_MIGRATIONS),
296
296
  {
297
297
  name: "thread-projection-retry-quarantine-runtime-schema",
298
+ // Stands in for legacy v9–v11, which a local boot skips: a database
299
+ // whose baseline was already recorded never re-runs the baseline's
300
+ // column ensures either, so this entry must create every column it
301
+ // touches before the index that reads them. The retry_order backfill
302
+ // does not belong here: a database that already recorded this entry
303
+ // never runs an edited body again, so the backfill lives in the
304
+ // append-only repair entry at the end of this list.
298
305
  run: async (exec) => {
306
+ await ensureColumnExists("agent_runs", "thread_projection_pending", "ALTER TABLE agent_runs ADD COLUMN IF NOT EXISTS thread_projection_pending BOOLEAN NOT NULL DEFAULT FALSE");
307
+ await ensureColumnExists("agent_runs", "thread_projection_retry_order", "ALTER TABLE agent_runs ADD COLUMN IF NOT EXISTS thread_projection_retry_order BIGINT");
299
308
  await exec.execute({
300
309
  sql: "ALTER TABLE agent_runs ADD COLUMN IF NOT EXISTS thread_projection_error_code TEXT",
301
310
  });
@@ -406,12 +415,64 @@ export const agentRunsStore = defineStore({
406
415
  )`,
407
416
  ],
408
417
  },
418
+ {
419
+ name: "thread-projection-retry-order-backfill-repair",
420
+ kind: "data",
421
+ // Append-only repair for databases that recorded
422
+ // thread-projection-retry-quarantine-runtime-schema before its
423
+ // column ensures existed: the ledger skips that entry forever, so
424
+ // the retry_order backfill legacy v10 performed for pending rows
425
+ // has to land here instead of in an edited body. Marked data so
426
+ // hosted replays skip it entirely. The self-check makes the body
427
+ // once-only even for a runtime whose ledger view is unavailable:
428
+ // re-running the backfill against live rows would re-impose queue
429
+ // order on projections that are still being written.
430
+ run: async (exec) => {
431
+ const alreadyApplied = await exec.execute({
432
+ // Literal name of STORE_MIGRATIONS_TABLE, kept interpolation-free.
433
+ sql: "SELECT 1 FROM _an_store_migrations WHERE store_id = 'agent_runs' AND name = ? LIMIT 1",
434
+ args: ["thread-projection-retry-order-backfill-repair"],
435
+ });
436
+ if (alreadyApplied.rows.length > 0)
437
+ return;
438
+ await ensureColumnExists("agent_runs", "thread_projection_pending", "ALTER TABLE agent_runs ADD COLUMN IF NOT EXISTS thread_projection_pending BOOLEAN NOT NULL DEFAULT FALSE");
439
+ await ensureColumnExists("agent_runs", "thread_projection_retry_order", "ALTER TABLE agent_runs ADD COLUMN IF NOT EXISTS thread_projection_retry_order BIGINT");
440
+ await exec.execute({
441
+ sql: "CREATE SEQUENCE IF NOT EXISTS agent_run_projection_retry_order_seq",
442
+ });
443
+ await exec.execute({
444
+ sql: `CREATE INDEX IF NOT EXISTS agent_runs_thread_projection_retry_order_idx
445
+ ON agent_runs (thread_projection_retry_order ASC NULLS FIRST, completed_at ASC, id ASC)
446
+ WHERE thread_projection_pending IS TRUE`,
447
+ });
448
+ const unassigned = await exec.execute({
449
+ sql: `SELECT 1 FROM agent_runs
450
+ WHERE thread_projection_pending IS TRUE
451
+ AND thread_projection_retry_order IS NULL
452
+ LIMIT 1`,
453
+ args: [],
454
+ });
455
+ if (unassigned.rows.length === 0)
456
+ return;
457
+ await exec.execute({
458
+ sql: `UPDATE agent_runs
459
+ SET thread_projection_retry_order = nextval('agent_run_projection_retry_order_seq')
460
+ WHERE thread_projection_pending IS TRUE
461
+ AND thread_projection_retry_order IS NULL`,
462
+ });
463
+ },
464
+ },
409
465
  ],
410
466
  });
411
467
  export function ensureRunTables() {
412
468
  return agentRunsStore.ready();
413
469
  }
414
470
  export const TURN_EXECUTION_LEASE_MS = 15_000;
471
+ // A hung renewal holds the worker's only heartbeat slot, so the database gives
472
+ // up on each of its statements well inside the lease and the next tick tries
473
+ // again. Set once for the renewal's own short transaction: it runs every
474
+ // 1.5 s per active run, so a per-statement setting would triple its queries.
475
+ const LEASE_RENEWAL_STATEMENT_TIMEOUT_MS = 4_000;
415
476
  function truthySqlValue(value) {
416
477
  return value === true || value === "t" || value === 1 || value === "1";
417
478
  }
@@ -525,24 +586,34 @@ async function renewExecutionLease(fence, renewRunLiveness) {
525
586
  throw new Error("Turn execution leases require transaction support");
526
587
  }
527
588
  await client.transaction(async (tx) => {
528
- const renewed = await tx.execute({
589
+ await tx.execute({
590
+ sql: "SELECT set_config('statement_timeout', ?, true)",
591
+ args: [`${LEASE_RENEWAL_STATEMENT_TIMEOUT_MS}ms`],
592
+ });
593
+ const renew = (requireLive) => tx.execute({
529
594
  sql: `UPDATE agent_execution_leases
530
- SET lease_expires_at = clock_timestamp() +
531
- (CAST(? AS BIGINT) * INTERVAL '1 millisecond'),
532
- updated_at = clock_timestamp()
533
- WHERE thread_id = ? AND turn_id = ? AND owner_run_id = ?
534
- AND generation = CAST(? AS BIGINT)
535
- AND lease_expires_at > clock_timestamp()`,
595
+ SET lease_expires_at = clock_timestamp() +
596
+ (CAST(? AS BIGINT) * INTERVAL '1 millisecond'),
597
+ updated_at = clock_timestamp()
598
+ WHERE thread_id = ? AND turn_id = ? AND owner_run_id = ?
599
+ AND generation = CAST(? AS BIGINT)
600
+ AND (lease_expires_at > clock_timestamp() OR NOT CAST(? AS BOOLEAN))`,
536
601
  args: [
537
602
  TURN_EXECUTION_LEASE_MS,
538
603
  fence.threadId,
539
604
  fence.turnId,
540
605
  fence.runId,
541
606
  fence.generation,
607
+ requireLive,
542
608
  ],
543
609
  });
544
- if (renewed.rowsAffected !== 1)
545
- throw new StaleExecutionFenceError(fence);
610
+ if ((await renew(true)).rowsAffected !== 1) {
611
+ if (!renewRunLiveness ||
612
+ !(await ownsLapsedTurnLease(tx, fence)) ||
613
+ (await renew(false)).rowsAffected !== 1) {
614
+ throw new StaleExecutionFenceError(fence);
615
+ }
616
+ }
546
617
  if (renewRunLiveness) {
547
618
  await tx.execute({
548
619
  sql: `UPDATE agent_runs
@@ -172,6 +172,46 @@ export const chatThreadsStore = defineStore({
172
172
  PRIMARY KEY (thread_id, user_email)
173
173
  )`,
174
174
  },
175
+ {
176
+ // Stands in for the inbox entries of the folded schema list (v5–v8),
177
+ // which a local boot skips: a database whose snapshot or baseline was
178
+ // already recorded otherwise keeps the v5 inbox shape while the
179
+ // queued-submission queries select the v6/v8 columns. The ensure*
180
+ // wrappers probe the catalog first, so a hosted replay of this entry
181
+ // skips the lock-taking DDL once the shape exists.
182
+ name: "chat-thread-inbox-runtime-schema",
183
+ run: async () => {
184
+ await ensureTableExists("agent_chat_submission_inbox", `CREATE TABLE IF NOT EXISTS agent_chat_submission_inbox (
185
+ thread_id TEXT NOT NULL,
186
+ message_id TEXT NOT NULL,
187
+ state TEXT NOT NULL,
188
+ actor_email TEXT NOT NULL,
189
+ actor_auth_user_id TEXT,
190
+ actor_identity_authenticated_at_ms BIGINT,
191
+ actor_name TEXT,
192
+ actor_org_id TEXT,
193
+ actor_org_scope TEXT,
194
+ actor_anonymous BOOLEAN NOT NULL DEFAULT FALSE,
195
+ payload_hash TEXT NOT NULL,
196
+ payload_json TEXT NOT NULL,
197
+ interrupt_active_run BOOLEAN NOT NULL DEFAULT FALSE,
198
+ submitted_run_id TEXT,
199
+ queue_order BIGSERIAL NOT NULL,
200
+ move_to_top_at BIGINT,
201
+ retry_after BIGINT,
202
+ created_at BIGINT NOT NULL,
203
+ updated_at BIGINT NOT NULL,
204
+ PRIMARY KEY (thread_id, message_id)
205
+ )`);
206
+ await ensureIndexExists("agent_chat_submission_inbox_pending_idx", `CREATE INDEX IF NOT EXISTS agent_chat_submission_inbox_pending_idx
207
+ ON agent_chat_submission_inbox (state, retry_after, interrupt_active_run DESC, move_to_top_at DESC, queue_order ASC)`);
208
+ await ensureColumnExists("agent_chat_submission_inbox", "interrupt_run_id", "ALTER TABLE agent_chat_submission_inbox ADD COLUMN IF NOT EXISTS interrupt_run_id TEXT");
209
+ await ensureColumnExists("agent_chat_submission_inbox", "retry_count", "ALTER TABLE agent_chat_submission_inbox ADD COLUMN IF NOT EXISTS retry_count INTEGER NOT NULL DEFAULT 0");
210
+ await ensureIndexExists("agent_chat_submission_inbox_thread_pending_idx", `CREATE INDEX IF NOT EXISTS agent_chat_submission_inbox_thread_pending_idx
211
+ ON agent_chat_submission_inbox (thread_id, interrupt_active_run DESC, move_to_top_at DESC, queue_order ASC)
212
+ WHERE state = 'queued'`);
213
+ },
214
+ },
175
215
  ],
176
216
  });
177
217
  function ensureTable() {
@@ -235,10 +235,11 @@ function ensureUiActionCapability(signal) {
235
235
  credentials: "same-origin",
236
236
  cache: "no-store",
237
237
  signal: controller?.signal,
238
- }).then((res) => {
239
- // The capability is the Set-Cookie header; an unread body keeps the
240
- // request open and the page never reaches network idle.
241
- res.body?.cancel().catch(() => { });
238
+ }).then(async (res) => {
239
+ // The capability is the Set-Cookie header, but the body must still be
240
+ // read: an unread body keeps the request open so the page never reaches
241
+ // network idle, and a cancelled one is reported as an aborted request.
242
+ await res.arrayBuffer();
242
243
  if (!res.ok) {
243
244
  throw new Error("Could not establish the browser UI capability.");
244
245
  }
package/dist/db/client.js CHANGED
@@ -777,6 +777,82 @@ export function postgresStatementTimeoutMs(clientTimeoutMs) {
777
777
  const headroomMs = Math.min(POSTGRES_STATEMENT_TIMEOUT_HEADROOM_MS, Math.max(1, Math.floor(safeTimeoutMs * 0.1)));
778
778
  return Math.max(1, safeTimeoutMs - headroomMs);
779
779
  }
780
+ // The CTE is materialized so the previous value is read before set_config
781
+ // replaces it; inlined, both calls share one projection with no order. A
782
+ // stricter cap the transaction already holds is kept; 0 means none.
783
+ const BOUND_STATEMENT_TIMEOUT_SQL = `WITH previous AS MATERIALIZED (
784
+ SELECT current_setting('statement_timeout') AS value,
785
+ setting::bigint AS ms
786
+ FROM pg_settings
787
+ WHERE name = 'statement_timeout'
788
+ )
789
+ SELECT value AS previous, ms AS previous_ms,
790
+ set_config(
791
+ 'statement_timeout',
792
+ CASE WHEN ms > 0 AND ms <= CAST(? AS BIGINT) THEN value ELSE ? END,
793
+ true
794
+ )
795
+ FROM previous
796
+ LIMIT 1`;
797
+ const SET_STATEMENT_TIMEOUT_SQL = "SELECT set_config('statement_timeout', ?, true)";
798
+ /**
799
+ * Runs one budgeted statement inside a transaction under a server-side
800
+ * timeout. A client-side timeout only abandons the promise, so without it the
801
+ * statement keeps its row locks and its connection. The transaction's previous
802
+ * setting is put back once the statement succeeds, or the cap would apply to
803
+ * every later statement and override a stricter one set earlier; a statement
804
+ * that fails aborts the transaction, which leaves nothing to put back.
805
+ */
806
+ async function withTransactionStatementTimeout(runSetting, timeoutMs, statement) {
807
+ const startedAt = Date.now();
808
+ const remainingMs = () => Math.max(1, timeoutMs - (Date.now() - startedAt));
809
+ const serverTimeout = () => postgresStatementTimeoutMs(remainingMs());
810
+ const applied = serverTimeout();
811
+ const bound = await runSetting({ sql: BOUND_STATEMENT_TIMEOUT_SQL, args: [applied, `${applied}ms`] }, remainingMs());
812
+ const row = bound[0];
813
+ const previous = row?.previous;
814
+ const previousMs = Number(row?.previous_ms);
815
+ if (typeof previous !== "string" || !Number.isFinite(previousMs)) {
816
+ throw new Error("Could not read the transaction's statement_timeout before bounding a statement");
817
+ }
818
+ let installed = previousMs > 0 && previousMs <= applied ? previousMs : applied;
819
+ // A slow round trip above leaves less of the budget than the server was
820
+ // given, so the statement could outlive its caller holding its locks.
821
+ // Tightening is itself a round trip, so a budget it also outruns is spent:
822
+ // the statement never starts.
823
+ if (installed >= remainingMs()) {
824
+ installed = serverTimeout();
825
+ await runSetting({ sql: SET_STATEMENT_TIMEOUT_SQL, args: [`${installed}ms`] }, remainingMs());
826
+ if (installed >= remainingMs()) {
827
+ // A caller may catch this and keep using the transaction.
828
+ await runSetting({ sql: SET_STATEMENT_TIMEOUT_SQL, args: [previous] }, POSTGRES_STATEMENT_TIMEOUT_RESET_MS);
829
+ throw Object.assign(new Error(`The ${timeoutMs}ms statement budget ran out while setting its server timeout`), { code: "STATEMENT_BUDGET_EXHAUSTED" });
830
+ }
831
+ }
832
+ const result = await statement(remainingMs());
833
+ await runSetting({ sql: SET_STATEMENT_TIMEOUT_SQL, args: [previous] }, POSTGRES_STATEMENT_TIMEOUT_RESET_MS);
834
+ return result;
835
+ }
836
+ function postgresJsTransactionExec(txSql) {
837
+ const query = (sql, timeoutMs) => {
838
+ // raw-sql-ok: forwards a statement its caller already built and bound.
839
+ const { rawSql, args } = sqlAndArgs(sql);
840
+ const pgSql = postgresSqlForStatement(sql, rawSql);
841
+ return withDbTimeout("query", () => txSql.unsafe(pgSql, args), timeoutMs, undefined, { sql: rawSql });
842
+ };
843
+ return {
844
+ async execute(sql) {
845
+ const { timeoutMs } = dbExecQueryBudget(sql);
846
+ const result = hasExplicitDbTimeout(sql)
847
+ ? await withTransactionStatementTimeout(async (setting, ms) => Array.from(await query(setting, ms)), timeoutMs, (remainingMs) => query(sql, remainingMs))
848
+ : await query(sql, timeoutMs);
849
+ return {
850
+ rows: Array.from(result),
851
+ rowsAffected: result.count ?? 0,
852
+ };
853
+ },
854
+ };
855
+ }
780
856
  export function dbExecQueryBudget(statement) {
781
857
  if (typeof statement === "string") {
782
858
  return { timeoutMs: dbOpTimeoutMs(), maxAttempts: 3 };
@@ -1568,12 +1644,7 @@ async function createDbExecInternal(config = {}, trackSingletonResources = false
1568
1644
  if (!hasExplicitDbTimeout(sql)) {
1569
1645
  return queryNeonClient(client, sql);
1570
1646
  }
1571
- const { timeoutMs } = dbExecQueryBudget(sql);
1572
- const startedAt = Date.now();
1573
- const remainingMs = () => Math.max(1, timeoutMs - (Date.now() - startedAt));
1574
- const statementTimeoutMs = postgresStatementTimeoutMs(remainingMs());
1575
- await queryNeonClient(client, `SET LOCAL statement_timeout = ${statementTimeoutMs}`, remainingMs());
1576
- return queryNeonClient(client, sql, remainingMs());
1647
+ return withTransactionStatementTimeout(async (setting, ms) => (await queryNeonClient(client, setting, ms)).rows, dbExecQueryBudget(sql).timeoutMs, (remainingMs) => queryNeonClient(client, sql, remainingMs));
1577
1648
  },
1578
1649
  };
1579
1650
  try {
@@ -1646,18 +1717,7 @@ async function createDbExecInternal(config = {}, trackSingletonResources = false
1646
1717
  });
1647
1718
  try {
1648
1719
  const result = await conn.begin(async (txSql) => {
1649
- const tx = {
1650
- async execute(sql) {
1651
- const { rawSql, args } = sqlAndArgs(sql);
1652
- const { timeoutMs } = dbExecQueryBudget(sql);
1653
- const pgSql = postgresSqlForStatement(sql, rawSql);
1654
- const result = await withDbTimeout("query", () => txSql.unsafe(pgSql, args), timeoutMs, undefined, { sql: rawSql });
1655
- return {
1656
- rows: Array.from(result),
1657
- rowsAffected: result.count ?? 0,
1658
- };
1659
- },
1660
- };
1720
+ const tx = postgresJsTransactionExec(txSql);
1661
1721
  return fn(tx);
1662
1722
  });
1663
1723
  return result;
@@ -1710,18 +1770,7 @@ async function createDbExecInternal(config = {}, trackSingletonResources = false
1710
1770
  async transaction(fn) {
1711
1771
  const activePool = getPool();
1712
1772
  const result = await activePool.begin(async (txSql) => {
1713
- const tx = {
1714
- async execute(sql) {
1715
- const { rawSql, args } = sqlAndArgs(sql);
1716
- const { timeoutMs } = dbExecQueryBudget(sql);
1717
- const pgSql = postgresSqlForStatement(sql, rawSql);
1718
- const result = await withDbTimeout("query", () => txSql.unsafe(pgSql, args), timeoutMs, undefined, { sql: rawSql });
1719
- return {
1720
- rows: Array.from(result),
1721
- rowsAffected: result.count ?? 0,
1722
- };
1723
- },
1724
- };
1773
+ const tx = postgresJsTransactionExec(txSql);
1725
1774
  return runHoldingPoolConnection(activePool, () => fn(tx));
1726
1775
  });
1727
1776
  return result;
@@ -1037,6 +1037,7 @@ export const SCHEMA_SNAPSHOT = {
1037
1037
  ],
1038
1038
  ["chat_threads", "chat-thread-inbox-interrupt-replay", "904890f43aebd9fe"],
1039
1039
  ["chat_threads", "chat-thread-inbox-retry-count", "b25ff25b6a61ccc9"],
1040
+ ["chat_threads", "chat-thread-inbox-runtime-schema", null],
1040
1041
  [
1041
1042
  "chat_threads",
1042
1043
  "chat-thread-inbox-thread-order-index",
@@ -156,6 +156,27 @@ export declare function emitSingleTemplateNetlifyRecurringJobsFunction(projectCw
156
156
  export declare function emitSingleTemplateNetlifyBackgroundFunction(projectCwd: string): void;
157
157
  export declare function assertEmittedBackgroundFunctionOnDisk(destDir: string, functionName: string): void;
158
158
  export declare function emitSingleTemplateNetlifyIntegrationRecoveryFunction(projectCwd: string): void;
159
+ /**
160
+ * Names imported from `mod` with `import { a, b as c } from "mod"`, including
161
+ * clauses that also bind the default export (`import d, { a } from "mod"`).
162
+ * Matches both minified output and the spaced form the generated Worker entry
163
+ * uses.
164
+ */
165
+ export declare function collectNamedImportsFrom(code: string, mod: string): string[];
166
+ /** Points every `from "mod"` in `code` at `importPath`. */
167
+ export declare function rewriteModuleImportSpecifier(code: string, mod: string, importPath: string): string;
168
+ /**
169
+ * esbuild entry that re-bundles a bare external for a Cloudflare Worker. A
170
+ * namespace import works for CommonJS and for ES modules with or without a
171
+ * default export; `import x from` and `export { default } from` fail to
172
+ * bundle an ES module that has no default export. A default export is kept
173
+ * as is, even when it is `null` or `undefined`, and so is a named export the
174
+ * module defines; the default export's property is only a fallback for names
175
+ * the module lacks. Each name is exported from a local binding, so a reserved
176
+ * word such as `class` is still a legal export and no export can collide with
177
+ * the entry's own bindings.
178
+ */
179
+ export declare function cloudflareExternalBundleEntry(resolvedMod: string, neededExports: Iterable<string>): string;
159
180
  /**
160
181
  * Post-build patches for `cloudflare_module` server output. Recurses (via
161
182
  * `walkServerJavaScriptFiles`) because esbuild/Nitro can emit a dependency at
@@ -3693,6 +3693,65 @@ const CF_MODULE_NODE_BUILTINS = [
3693
3693
  "inspector",
3694
3694
  "vm",
3695
3695
  ];
3696
+ function escapeModuleSpecifier(mod) {
3697
+ return mod.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3698
+ }
3699
+ /**
3700
+ * Names imported from `mod` with `import { a, b as c } from "mod"`, including
3701
+ * clauses that also bind the default export (`import d, { a } from "mod"`).
3702
+ * Matches both minified output and the spaced form the generated Worker entry
3703
+ * uses.
3704
+ */
3705
+ export function collectNamedImportsFrom(code, mod) {
3706
+ const re = new RegExp(`import(?:\\s+[\\w$]+\\s*,)?\\s*\\{([^}]+)\\}\\s*from\\s*["']${escapeModuleSpecifier(mod)}["']`, "g");
3707
+ const names = [];
3708
+ for (const m of code.matchAll(re)) {
3709
+ const clause = m[1];
3710
+ if (!clause)
3711
+ continue;
3712
+ for (const part of clause.split(",")) {
3713
+ const name = part
3714
+ .trim()
3715
+ .split(/\s+as\s+/)[0]
3716
+ ?.trim();
3717
+ // `default` is re-exported on its own and can't be an `export const`.
3718
+ if (name && name !== "default" && /^[a-zA-Z_$]/.test(name)) {
3719
+ names.push(name);
3720
+ }
3721
+ }
3722
+ }
3723
+ return names;
3724
+ }
3725
+ /** Points every `from "mod"` in `code` at `importPath`. */
3726
+ export function rewriteModuleImportSpecifier(code, mod, importPath) {
3727
+ const re = new RegExp(`from\\s*["']${escapeModuleSpecifier(mod)}["']`, "g");
3728
+ return code.replace(re, `from"${importPath}"`);
3729
+ }
3730
+ /**
3731
+ * esbuild entry that re-bundles a bare external for a Cloudflare Worker. A
3732
+ * namespace import works for CommonJS and for ES modules with or without a
3733
+ * default export; `import x from` and `export { default } from` fail to
3734
+ * bundle an ES module that has no default export. A default export is kept
3735
+ * as is, even when it is `null` or `undefined`, and so is a named export the
3736
+ * module defines; the default export's property is only a fallback for names
3737
+ * the module lacks. Each name is exported from a local binding, so a reserved
3738
+ * word such as `class` is still a legal export and no export can collide with
3739
+ * the entry's own bindings.
3740
+ */
3741
+ export function cloudflareExternalBundleEntry(resolvedMod, neededExports) {
3742
+ const names = Array.from(neededExports);
3743
+ return [
3744
+ `import * as _ns from "${resolvedMod}";`,
3745
+ `const _mod = "default" in _ns ? _ns.default : _ns;`,
3746
+ `export default _mod;`,
3747
+ ...(names.length > 0
3748
+ ? names.flatMap((n, i) => [
3749
+ `const _e${i} = ${JSON.stringify(n)} in _ns ? _ns.${n} : _mod?.${n};`,
3750
+ `export { _e${i} as ${n} };`,
3751
+ ])
3752
+ : [`export * from "${resolvedMod}";`]),
3753
+ ].join("\n");
3754
+ }
3696
3755
  /**
3697
3756
  * Post-build patches for `cloudflare_module` server output. Recurses (via
3698
3757
  * `walkServerJavaScriptFiles`) because esbuild/Nitro can emit a dependency at
@@ -5099,9 +5158,7 @@ export default bundle;
5099
5158
  const importPath = relPath.startsWith(".")
5100
5159
  ? relPath
5101
5160
  : "./" + relPath;
5102
- const escaped = mod.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
5103
- const re = new RegExp(`from["']${escaped}["']`, "g");
5104
- const rewritten = code.replace(re, `from"${importPath}"`);
5161
+ const rewritten = rewriteModuleImportSpecifier(code, mod, importPath);
5105
5162
  if (rewritten !== code)
5106
5163
  fs.writeFileSync(p, rewritten);
5107
5164
  }
@@ -5144,28 +5201,13 @@ export default bundle;
5144
5201
  if (!entry.name.endsWith(".mjs") && !entry.name.endsWith(".js"))
5145
5202
  continue;
5146
5203
  const code = fs.readFileSync(p, "utf-8");
5147
- const escaped = mod.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
5148
- const re = new RegExp(`import\\{([^}]+)\\}from["']${escaped}["']`, "g");
5149
- for (const m2 of code.matchAll(re)) {
5150
- for (const part of m2[1].split(",")) {
5151
- const name = part
5152
- .trim()
5153
- .split(/\s+as\s+/)[0]
5154
- .trim();
5155
- if (name && /^[a-zA-Z_$]/.test(name))
5156
- neededExports.add(name);
5157
- }
5204
+ for (const name of collectNamedImportsFrom(code, mod)) {
5205
+ neededExports.add(name);
5158
5206
  }
5159
5207
  }
5160
5208
  }
5161
5209
  findNeededExports(outputDir);
5162
- const entryCode = neededExports.size > 0
5163
- ? [
5164
- `import _mod from "${resolvedMod}";`,
5165
- `export default _mod;`,
5166
- ...Array.from(neededExports).map((n) => `export const ${n} = _mod.${n} ?? _mod?.default?.${n};`),
5167
- ].join("\n")
5168
- : `export * from "${resolvedMod}"; export { default } from "${resolvedMod}";`;
5210
+ const entryCode = cloudflareExternalBundleEntry(resolvedMod, neededExports);
5169
5211
  execFileSync(esbuild.executable, [
5170
5212
  ...esbuild.args,
5171
5213
  "--bundle",
@@ -5190,18 +5232,16 @@ export default bundle;
5190
5232
  }
5191
5233
  if (!entry.name.endsWith(".mjs") && !entry.name.endsWith(".js"))
5192
5234
  continue;
5193
- let code = fs.readFileSync(p, "utf-8");
5235
+ const code = fs.readFileSync(p, "utf-8");
5194
5236
  const relPath = path
5195
5237
  .relative(path.dirname(p), outFile)
5196
5238
  .replace(/\\/g, "/");
5197
5239
  const importPath = relPath.startsWith(".")
5198
5240
  ? relPath
5199
5241
  : "./" + relPath;
5200
- const re = new RegExp(`from["']${mod.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}["']`, "g");
5201
- if (re.test(code)) {
5202
- code = code.replace(re, `from"${importPath}"`);
5203
- fs.writeFileSync(p, code);
5204
- }
5242
+ const rewritten = rewriteModuleImportSpecifier(code, mod, importPath);
5243
+ if (rewritten !== code)
5244
+ fs.writeFileSync(p, rewritten);
5205
5245
  }
5206
5246
  }
5207
5247
  rewriteImports(outputDir);
@@ -1,10 +1,10 @@
1
1
  {
2
- "@agent-native/agentkit": "0.226.0",
2
+ "@agent-native/agentkit": "0.226.1-nightly-20261107004051",
3
3
  "@agent-native/code-agents-ui": "0.1.75",
4
- "@agent-native/core": "0.226.0",
5
- "@agent-native/core-corpus": "0.226.0",
4
+ "@agent-native/core": "0.226.1-nightly-20261107004051",
5
+ "@agent-native/core-corpus": "0.226.1-nightly-20261107004051",
6
6
  "@agent-native/creative-context": "0.8.68",
7
- "@agent-native/dispatch": "0.42.3",
7
+ "@agent-native/dispatch": "0.42.4-nightly-20261107004051",
8
8
  "@agent-native/embedding": "0.2.0",
9
9
  "@agent-native/migrate": "0.0.7",
10
10
  "@agent-native/otel": "0.1.35",
@@ -12,6 +12,6 @@
12
12
  "@agent-native/recap-cli": "0.5.99",
13
13
  "@agent-native/scheduling": "0.2.55",
14
14
  "@agent-native/shared-app-config": "0.1.2",
15
- "@agent-native/skills": "0.4.3",
16
- "@agent-native/toolkit": "0.226.0"
15
+ "@agent-native/skills": "0.4.4-nightly-20261107004051",
16
+ "@agent-native/toolkit": "0.226.1-nightly-20261107004051"
17
17
  }
@@ -20,6 +20,16 @@ const assignmentSchema = z.object({
20
20
  email: z.string().email().max(320).optional(),
21
21
  policy: z.literal(BUILDER_SIGNUP_POLICY),
22
22
  });
23
+ function experimentProperties(assignment) {
24
+ return {
25
+ app_name: "design",
26
+ template_name: "design",
27
+ experiment_id: BUILDER_SIGNUP_EXPERIMENT,
28
+ ...(assignment
29
+ ? { experiment_variant: assignment.variant, assignment_id: assignment.id }
30
+ : {}),
31
+ };
32
+ }
23
33
  function mac(body) {
24
34
  return createHmac("sha256", getAuthSecret())
25
35
  .update(`${BUILDER_SIGNUP_EXPERIMENT}:${body}`)
@@ -83,35 +93,35 @@ export async function bindBuilderSignupAttempt(event, attemptId, method, email)
83
93
  const assignment = decodeBuilderSignupAssignment(getCookie(event, BUILDER_SIGNUP_COOKIE));
84
94
  if (!assignment)
85
95
  return false;
96
+ const normalizedEmail = email.trim().toLowerCase();
97
+ const adapter = await getBetterAuthInternalAdapter();
98
+ if (!adapter)
99
+ throw new Error("Signup identity store is unavailable");
100
+ const identity = await adapter.findUserByEmail(normalizedEmail, {
101
+ includeAccounts: false,
102
+ });
103
+ const createdAt = identity?.user.createdAt;
104
+ const createdAtMs = createdAt ? new Date(createdAt).getTime() : Number.NaN;
105
+ if (!identity ||
106
+ !Number.isFinite(createdAtMs) ||
107
+ createdAtMs < assignment.issuedAt)
108
+ return false;
109
+ track("builder_signup_experiment_enrolled", { ...experimentProperties(assignment), method }, { authUserId: identity.user.id, userId: normalizedEmail });
86
110
  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
111
  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
- });
112
+ const record = await mutateSetting(key, (current) => current ?? {
113
+ id: assignment.id,
114
+ variant: "control",
115
+ issuedAt: assignment.issuedAt,
116
+ policy: assignment.policy,
117
+ userId: identity.user.id,
118
+ status: "control",
119
+ });
120
+ if (record.id === assignment.id && record.status === "control") {
109
121
  track("builder_signup_experiment_outcome", {
110
- experiment_id: BUILDER_SIGNUP_EXPERIMENT,
111
- experiment_variant: "control",
112
- assignment_id: assignment.id,
122
+ ...experimentProperties(assignment),
113
123
  status: "control",
114
- }, { authUserId: identity.user.id, userId: email });
124
+ }, { authUserId: identity.user.id, userId: normalizedEmail });
115
125
  }
116
126
  return false;
117
127
  }
@@ -121,21 +131,10 @@ export async function bindBuilderSignupAttempt(event, attemptId, method, email)
121
131
  assignment.attemptId !== attemptId)
122
132
  return false;
123
133
  const key = `${BUILDER_SIGNUP_EXPERIMENT}:attempt:${attemptId}`;
124
- const normalizedEmail = email.trim().toLowerCase();
125
134
  if (assignment.method !== method ||
126
135
  (assignment.email && assignment.email !== normalizedEmail))
127
136
  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)
137
+ if (createdAtMs < assignment.acceptedAt)
139
138
  return false;
140
139
  const bound = z
141
140
  .object({ id: z.string(), boundUserId: z.string() })
@@ -239,9 +238,15 @@ export function createBuilderSignupExperimentHandler(dependencies) {
239
238
  return refuse(400, "invalid_request");
240
239
  if (!assignment) {
241
240
  deleteCookie(event, "an_builder_signup_pending", { path: "/" });
242
- return body.data.operation === "activate"
243
- ? { status: "fallback" }
244
- : refuse(409, "assignment_missing");
241
+ if (body.data.operation === "activate") {
242
+ if (session?.emailVerified && session.userId)
243
+ track("builder_signup_experiment_unattributed", {
244
+ ...experimentProperties(),
245
+ code: "assignment_missing",
246
+ }, { userId: session.email, authUserId: session.userId });
247
+ return { status: "fallback", code: "assignment_missing" };
248
+ }
249
+ return refuse(409, "assignment_missing");
245
250
  }
246
251
  if (body.data.operation === "accept") {
247
252
  if (session || body.data.assignmentId !== assignment.id)
@@ -272,14 +277,27 @@ export function createBuilderSignupExperimentHandler(dependencies) {
272
277
  }
273
278
  if (!session?.emailVerified || !session.userId)
274
279
  return refuse(401, "verified_session_required");
275
- const terminal = (status, code) => {
280
+ const trackingSource = {
281
+ userId: session.email,
282
+ authUserId: session.userId,
283
+ };
284
+ const terminal = (status, code, replayed = false, durationMs) => {
285
+ track("builder_signup_experiment_outcome", {
286
+ ...experimentProperties(assignment),
287
+ status,
288
+ code: code ?? status,
289
+ replayed,
290
+ ...(durationMs === undefined
291
+ ? {}
292
+ : { activation_duration_ms: durationMs }),
293
+ }, trackingSource);
276
294
  deleteCookie(event, "an_builder_signup_pending", { path: "/" });
277
295
  return { status, ...(code ? { code } : {}) };
278
296
  };
279
297
  if (assignment.variant !== "automatic")
280
298
  return terminal("fallback", "control");
281
299
  if (!assignment.acceptedAt || !assignment.attemptId)
282
- return terminal("fallback");
300
+ return terminal("fallback", "acceptance_missing");
283
301
  const consent = await getSetting(`${BUILDER_SIGNUP_EXPERIMENT}:consent:${session.userId}`);
284
302
  if (!consent ||
285
303
  consent.attemptId !== assignment.attemptId ||
@@ -288,8 +306,13 @@ export function createBuilderSignupExperimentHandler(dependencies) {
288
306
  consent.email !== session.email.trim().toLowerCase())
289
307
  return terminal("fallback", "signup_attempt_unbound");
290
308
  const adapter = await getBetterAuthInternalAdapter();
291
- if (!adapter)
309
+ if (!adapter) {
310
+ track("builder_signup_experiment_activation_unavailable", {
311
+ ...experimentProperties(assignment),
312
+ code: "identity_unavailable",
313
+ }, { userId: session.email, authUserId: session.userId });
292
314
  return refuse(503, "identity_unavailable");
315
+ }
293
316
  const identity = await adapter.findUserByEmail(session.email, {
294
317
  includeAccounts: false,
295
318
  });
@@ -299,7 +322,7 @@ export function createBuilderSignupExperimentHandler(dependencies) {
299
322
  identity.user.id !== session.userId ||
300
323
  !Number.isFinite(createdAtMs) ||
301
324
  createdAtMs < assignment.acceptedAt)
302
- return terminal("fallback");
325
+ return terminal("fallback", "identity_ineligible");
303
326
  const key = `${BUILDER_SIGNUP_EXPERIMENT}:${session.userId}`;
304
327
  const existing = await getSetting(key);
305
328
  if (existing) {
@@ -307,7 +330,7 @@ export function createBuilderSignupExperimentHandler(dependencies) {
307
330
  .enum(["started", "connected", "fallback"])
308
331
  .parse(existing.status);
309
332
  if (status !== "started")
310
- return terminal(status);
333
+ return terminal(status, z.string().nullable().optional().parse(existing.code) ?? undefined, true);
311
334
  return { status: "pending" };
312
335
  }
313
336
  const attempt = randomBytes(16).toString("hex");
@@ -320,6 +343,9 @@ export function createBuilderSignupExperimentHandler(dependencies) {
320
343
  });
321
344
  if (record.attempt !== attempt)
322
345
  return { status: "pending" };
346
+ track("builder_signup_experiment_activation_started", {
347
+ ...experimentProperties(assignment),
348
+ }, { userId: session.email, authUserId: session.userId });
323
349
  let result;
324
350
  try {
325
351
  result = await dependencies.activate(event, session);
@@ -333,13 +359,6 @@ export function createBuilderSignupExperimentHandler(dependencies) {
333
359
  ...(result.message ? { message: result.message } : {}),
334
360
  });
335
361
  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);
362
+ return terminal(status, committed.code ?? undefined, false, Date.now() - z.number().parse(record.startedAt));
344
363
  });
345
364
  }
@@ -984,9 +984,13 @@ export function getOnboardingHtml(opts = {}) {
984
984
  homePath: appHomePath,
985
985
  }).resumeHref;
986
986
  const workspaceRuntime = isWorkspaceRuntime();
987
- const trackingApp = getAppConfig().app.slug ??
988
- getAppConfig().app.template ??
989
- getAppConfig().app.id ??
987
+ const trackingApp = getAppConfig().app.slug?.trim() ||
988
+ getAppConfig().app.template?.trim() ||
989
+ getAppConfig().app.id?.trim() ||
990
+ resolveBuiltInAuthMarketingSlug({
991
+ ...(opts.requestHost ? { requestHost: opts.requestHost } : {}),
992
+ ...(opts.requestPath ? { requestPath: opts.requestPath } : {}),
993
+ }) ||
990
994
  "";
991
995
  const publicOAuthOrigin = getPublicOAuthOrigin();
992
996
  const workspaceGatewayReturnOrigin = getWorkspaceGatewayReturnOrigin();
@@ -26,7 +26,7 @@ export const NATIVE_AUTH_COPY = {
26
26
  emailLinkContinueAction: "Continue",
27
27
  email: "Email",
28
28
  emailPlaceholder: "you@example.com",
29
- builderSignupDisclosure: "Your Design signup also creates a Builder.io account. By continuing, you agree to Builder’s",
29
+ builderSignupDisclosure: "You also create a Builder.io account and agree to Builder’s",
30
30
  legalPrefix: "By signing up, you accept our",
31
31
  legalTerms: "Terms",
32
32
  legalConnector: "and",
@@ -69,7 +69,7 @@ export const NATIVE_AUTH_COPY = {
69
69
  emailLinkContinueAction: "继续",
70
70
  email: "电子邮箱",
71
71
  emailPlaceholder: "you@example.com",
72
- builderSignupDisclosure: "注册 Design 也会创建 Builder.io 帐户。继续即表示你同意 Builder 的",
72
+ builderSignupDisclosure: "你还将创建 Builder.io 帐户,并同意 Builder 的",
73
73
  legalPrefix: "注册即表示你接受我们的",
74
74
  legalTerms: "条款",
75
75
  legalConnector: "和",
@@ -112,7 +112,7 @@ export const NATIVE_AUTH_COPY = {
112
112
  emailLinkContinueAction: "繼續",
113
113
  email: "電子郵件",
114
114
  emailPlaceholder: "you@example.com",
115
- builderSignupDisclosure: "註冊 Design 也會建立 Builder.io 帳戶。繼續即表示你同意 Builder 的",
115
+ builderSignupDisclosure: "你也將建立 Builder.io 帳戶,並同意 Builder 的",
116
116
  legalPrefix: "註冊即表示你接受我們的",
117
117
  legalTerms: "條款",
118
118
  legalConnector: "和",
@@ -155,7 +155,7 @@ export const NATIVE_AUTH_COPY = {
155
155
  emailLinkContinueAction: "Continuar",
156
156
  email: "Email",
157
157
  emailPlaceholder: "you@example.com",
158
- builderSignupDisclosure: "Al registrarte en Design también se crea una cuenta de Builder.io. Al continuar, aceptas los",
158
+ builderSignupDisclosure: "También creas una cuenta de Builder.io y aceptas sus",
159
159
  legalPrefix: "Al registrarte, aceptas nuestros",
160
160
  legalTerms: "Términos",
161
161
  legalConnector: "y",
@@ -198,7 +198,7 @@ export const NATIVE_AUTH_COPY = {
198
198
  emailLinkContinueAction: "Continuer",
199
199
  email: "E-mail",
200
200
  emailPlaceholder: "you@example.com",
201
- builderSignupDisclosure: "Votre inscription à Design crée aussi un compte Builder.io. En continuant, vous acceptez les",
201
+ builderSignupDisclosure: "Vous créez aussi un compte Builder.io et acceptez ses",
202
202
  legalPrefix: "En vous inscrivant, vous acceptez nos",
203
203
  legalTerms: "Conditions",
204
204
  legalConnector: "et",
@@ -241,7 +241,7 @@ export const NATIVE_AUTH_COPY = {
241
241
  emailLinkContinueAction: "Weiter",
242
242
  email: "E-Mail",
243
243
  emailPlaceholder: "you@example.com",
244
- builderSignupDisclosure: "Mit deiner Design-Registrierung wird auch ein Builder.io-Konto erstellt. Wenn du fortfährst, akzeptierst du Builders",
244
+ builderSignupDisclosure: "Du erstellst auch ein Builder.io-Konto und akzeptierst Builders",
245
245
  legalPrefix: "Mit der Registrierung akzeptierst du unsere",
246
246
  legalTerms: "Bedingungen",
247
247
  legalConnector: "und",
@@ -284,7 +284,7 @@ export const NATIVE_AUTH_COPY = {
284
284
  emailLinkContinueAction: "続行",
285
285
  email: "メール",
286
286
  emailPlaceholder: "you@example.com",
287
- builderSignupDisclosure: "Design に登録すると Builder.io アカウントも作成されます。続行すると Builder の以下に同意します:",
287
+ builderSignupDisclosure: "Builder.io アカウントも作成し、Builder の以下に同意します:",
288
288
  legalPrefix: "登録すると、以下に同意したものとみなされます:",
289
289
  legalTerms: "利用規約",
290
290
  legalConnector: "および",
@@ -327,7 +327,7 @@ export const NATIVE_AUTH_COPY = {
327
327
  emailLinkContinueAction: "계속",
328
328
  email: "이메일",
329
329
  emailPlaceholder: "you@example.com",
330
- builderSignupDisclosure: "Design에 가입하면 Builder.io 계정도 생성됩니다. 계속하면 Builder의 다음에 동의합니다:",
330
+ builderSignupDisclosure: "Builder.io 계정도 생성하고 Builder의 다음 사항에 동의합니다:",
331
331
  legalPrefix: "가입하면 다음에 동의하게 됩니다:",
332
332
  legalTerms: "약관",
333
333
  legalConnector: "및",
@@ -370,7 +370,7 @@ export const NATIVE_AUTH_COPY = {
370
370
  emailLinkContinueAction: "Continuar",
371
371
  email: "Email",
372
372
  emailPlaceholder: "you@example.com",
373
- builderSignupDisclosure: "Seu cadastro no Design também cria uma conta Builder.io. Ao continuar, você aceita os",
373
+ builderSignupDisclosure: "Você também cria uma conta Builder.io e aceita seus",
374
374
  legalPrefix: "Ao se cadastrar, você aceita nossos",
375
375
  legalTerms: "Termos",
376
376
  legalConnector: "e",
@@ -413,7 +413,7 @@ export const NATIVE_AUTH_COPY = {
413
413
  emailLinkContinueAction: "जारी रखें",
414
414
  email: "ईमेल",
415
415
  emailPlaceholder: "you@example.com",
416
- builderSignupDisclosure: "Design पर साइन अप करने से Builder.io खाता भी बनता है। जारी रखकर, आप Builder की",
416
+ builderSignupDisclosure: "आप Builder.io खाता भी बनाते हैं और Builder की निम्न नीतियों से सहमत हैं:",
417
417
  legalPrefix: "साइन अप करके, आप हमारी",
418
418
  legalTerms: "शर्तें",
419
419
  legalConnector: "और",
@@ -456,7 +456,7 @@ export const NATIVE_AUTH_COPY = {
456
456
  emailLinkContinueAction: "متابعة",
457
457
  email: "البريد الإلكتروني",
458
458
  emailPlaceholder: "you@example.com",
459
- builderSignupDisclosure: "يؤدي التسجيل في Design أيضًا إلى إنشاء حساب Builder.io. بالمتابعة، توافق على",
459
+ builderSignupDisclosure: "تنشئ أيضًا حساب Builder.io وتوافق على",
460
460
  legalPrefix: "بالتسجيل، فإنك توافق على",
461
461
  legalTerms: "الشروط",
462
462
  legalConnector: "و",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.226.0",
3
+ "version": "0.226.1-nightly-20261107004051",
4
4
  "description": "The agentic application framework for building autonomous agents with intuitive UIs",
5
5
  "homepage": "https://github.com/BuilderIO/agent-native#readme",
6
6
  "bugs": {
@@ -765,7 +765,7 @@
765
765
  "yaml": "^2.9.0",
766
766
  "yjs": "^13.6.33",
767
767
  "zod": "^4.3.6",
768
- "@agent-native/agentkit": "^0.226.0",
768
+ "@agent-native/agentkit": "^0.226.1-nightly-20261107004051",
769
769
  "@agent-native/recap-cli": "^0.5.99"
770
770
  },
771
771
  "devDependencies": {
@@ -838,7 +838,7 @@
838
838
  "xlsx": "^0.18.5"
839
839
  },
840
840
  "peerDependencies": {
841
- "@agent-native/core-corpus": ">=0.196.0",
841
+ "@agent-native/core-corpus": "0.226.1-nightly-20261107004051",
842
842
  "@ai-sdk/anthropic": ">=3",
843
843
  "@ai-sdk/cohere": ">=3",
844
844
  "@ai-sdk/google": ">=3",