@agent-native/core 0.200.0 → 0.200.1-nightly-20261002183718

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.
@@ -279,8 +279,15 @@ class AISDKEngine {
279
279
  }
280
280
  const toolNameMap = createProviderToolNameMap(opts.tools, opts.messages);
281
281
  const providerTools = limitProviderTools(opts.tools);
282
+ // The Responses API treats an omitted `strict` as strict mode and rewrites
283
+ // every optional parameter as required, so the model must invent a value
284
+ // ("" or a guessed id) for each one. Action schemas use omission to mean
285
+ // "not this mode", so those fillers turn a valid call into a mixed one
286
+ // that validation rejects on every retry.
287
+ const usesResponsesApi = this.provider === "openai" &&
288
+ (this.forceResponses || !isCustomOpenAiBaseUrl(this.baseUrl));
282
289
  const aiSdkTools = providerTools.length > 0
283
- ? engineToolsToAISDK(providerTools, jsonSchema, toolNameMap)
290
+ ? engineToolsToAISDK(providerTools, jsonSchema, toolNameMap, usesResponsesApi ? false : undefined)
284
291
  : undefined;
285
292
  const messages = engineMessagesToAISDK(opts.messages, {
286
293
  toolResultImages: this.capabilities.vision,
@@ -1,6 +1,6 @@
1
1
  import { type ProviderToolNameMap } from "./tool-name.js";
2
2
  import type { EngineTool, EngineMessage, EngineContentPart, EngineEvent } from "./types.js";
3
- export declare function engineToolsToAISDK(tools: EngineTool[], jsonSchema?: (schema: Record<string, unknown>) => unknown, toolNameMap?: ProviderToolNameMap): Record<string, any>;
3
+ export declare function engineToolsToAISDK(tools: EngineTool[], jsonSchema?: (schema: Record<string, unknown>) => unknown, toolNameMap?: ProviderToolNameMap, strict?: boolean): Record<string, any>;
4
4
  export interface EngineToAISDKOptions {
5
5
  toolResultImages?: boolean;
6
6
  toolNameMap?: ProviderToolNameMap;
@@ -2,7 +2,7 @@ import { classifyProviderError, describeErrorWithCauses, } from "./error-detail.
2
2
  import { flattenComposedRootSchema } from "./flatten-composed-root-schema.js";
3
3
  import { createProviderToolNameMap, toEngineToolName, toProviderToolName, } from "./tool-name.js";
4
4
  import { backfillEngineMessagesToolResults } from "./translate-anthropic.js";
5
- export function engineToolsToAISDK(tools, jsonSchema, toolNameMap = createProviderToolNameMap(tools)) {
5
+ export function engineToolsToAISDK(tools, jsonSchema, toolNameMap = createProviderToolNameMap(tools), strict) {
6
6
  const result = {};
7
7
  for (const tool of tools) {
8
8
  const inputSchema = flattenComposedRootSchema(tool.inputSchema);
@@ -16,6 +16,7 @@ export function engineToolsToAISDK(tools, jsonSchema, toolNameMap = createProvid
16
16
  result[providerName] = {
17
17
  description: tool.description,
18
18
  inputSchema: jsonSchema ? jsonSchema(rawSchema) : rawSchema,
19
+ ...(strict === undefined ? {} : { strict }),
19
20
  };
20
21
  }
21
22
  return result;
@@ -112,6 +112,13 @@ export declare function getActiveRunForThreadAsync(threadId: string): Promise<{
112
112
  threadId: string;
113
113
  turnId: string;
114
114
  status: string;
115
+ /**
116
+ * The one answer to "is a run in flight on this thread". A terminal run is
117
+ * still returned inside `TERMINAL_RUN_RECONNECT_WINDOW_MS` so a reconnecting
118
+ * client can replay it, which is why `status` alone being present means
119
+ * nothing; `/runs/active` reports this as its `active` flag.
120
+ */
121
+ inFlight: boolean;
115
122
  heartbeatAt: number;
116
123
  lastProgressAt: number | null;
117
124
  dispatchMode?: string | null;
@@ -1811,6 +1811,7 @@ export async function getActiveRunForThreadAsync(threadId) {
1811
1811
  threadId: successor.threadId,
1812
1812
  turnId: successor.turnId ?? successor.id,
1813
1813
  status: successor.status,
1814
+ inFlight: true,
1814
1815
  heartbeatAt: successor.heartbeatAt ?? successor.startedAt,
1815
1816
  lastProgressAt: successor.lastProgressAt,
1816
1817
  dispatchMode: successor.dispatchMode,
@@ -1833,6 +1834,7 @@ export async function getActiveRunForThreadAsync(threadId) {
1833
1834
  threadId: memRun.threadId,
1834
1835
  turnId: memRun.turnId,
1835
1836
  status,
1837
+ inFlight: status === "running",
1836
1838
  heartbeatAt,
1837
1839
  lastProgressAt: sqlSnapshot?.lastProgressAt ?? null,
1838
1840
  dispatchMode: sqlSnapshot?.dispatchMode ?? null,
@@ -1896,6 +1898,7 @@ export async function getActiveRunForThreadAsync(threadId) {
1896
1898
  threadId: sqlRun.threadId,
1897
1899
  turnId: sqlRun.turnId ?? sqlRun.id,
1898
1900
  status: sqlRun.status,
1901
+ inFlight: true,
1899
1902
  heartbeatAt: sqlRun.heartbeatAt ?? sqlRun.startedAt,
1900
1903
  lastProgressAt: sqlRun.lastProgressAt,
1901
1904
  dispatchMode: sqlRun.dispatchMode,
@@ -1917,6 +1920,7 @@ export async function getActiveRunForThreadAsync(threadId) {
1917
1920
  threadId: sqlRun.threadId,
1918
1921
  turnId: sqlRun.turnId ?? sqlRun.id,
1919
1922
  status: legacyWireRunStatus(sqlRun.status),
1923
+ inFlight: false,
1920
1924
  heartbeatAt: sqlRun.heartbeatAt ?? sqlRun.startedAt,
1921
1925
  lastProgressAt: sqlRun.lastProgressAt,
1922
1926
  dispatchMode: sqlRun.dispatchMode,
@@ -423,12 +423,15 @@ function normalizeContentForFingerprint(content) {
423
423
  ? { ...part, toolCallId: undefined }
424
424
  : part);
425
425
  }
426
- function messageIdentityKeySet(message) {
426
+ function messageIdentityKeySet(message, eventRunIds) {
427
427
  const strong = [];
428
428
  if (typeof message?.id === "string" && message.id) {
429
429
  strong.push(`id:${message.id}`);
430
430
  }
431
- const runId = getMessageRunId(message);
431
+ const runId = getMessageRunId(message) ??
432
+ (typeof message?.id === "string"
433
+ ? eventRunIds?.get(message.id)
434
+ : undefined);
432
435
  if (runId)
433
436
  strong.push(`run:${runId}`);
434
437
  const turnId = turnIdOf(message);
@@ -1425,9 +1428,7 @@ export function mergeThreadDataForClientSave(existingRepo, incomingRepo, options
1425
1428
  existingNormalized &&
1426
1429
  typeof existingNormalized === "object") {
1427
1430
  for (const [key, value] of Object.entries(existingNormalized)) {
1428
- if (key === "messages" || key === "headId")
1429
- continue;
1430
- if (key === "queuedMessages" && !preserveExistingQueuedMessages) {
1431
+ if (key === "messages" || key === "headId" || key === "queuedMessages") {
1431
1432
  continue;
1432
1433
  }
1433
1434
  if (!(key in merged)) {
@@ -1435,11 +1436,11 @@ export function mergeThreadDataForClientSave(existingRepo, incomingRepo, options
1435
1436
  }
1436
1437
  }
1437
1438
  }
1438
- else if (preserveExistingQueuedMessages &&
1439
- existingNormalized &&
1440
- typeof existingNormalized === "object" &&
1441
- existingNormalized.queuedMessages !== undefined &&
1442
- merged.queuedMessages === undefined) {
1439
+ // Queue mutations are the only writer of the queue and opt out here. Any
1440
+ // other save carries a queue it read earlier, and letting that copy win drops
1441
+ // a promotion claim or an append that landed in between.
1442
+ if (preserveExistingQueuedMessages &&
1443
+ existingNormalized?.queuedMessages !== undefined) {
1443
1444
  merged.queuedMessages = existingNormalized.queuedMessages;
1444
1445
  }
1445
1446
  if (merged.agentKit !== undefined) {
@@ -1454,10 +1455,30 @@ export function mergeThreadDataForClientSave(existingRepo, incomingRepo, options
1454
1455
  if (!existingMessages || !incomingMessages) {
1455
1456
  return pruneClaimedQueuedMessages(merged);
1456
1457
  }
1457
- const incomingKeySets = incomingMessages.map((entry) => messageIdentityKeySet(getStoredMessage(entry)));
1458
+ // The chat UI saves its replies under AgentKit ids with no runId; only the
1459
+ // AgentKit events tie them to the run the server folded under its own id.
1460
+ const eventRunIds = snapshotMessageRunIds(merged.agentKit);
1461
+ const incomingKeySets = incomingMessages.map((entry) => messageIdentityKeySet(getStoredMessage(entry), eventRunIds));
1458
1462
  const usedIncoming = new Set();
1459
1463
  const nextMessages = [];
1460
1464
  const idRewrites = new Map();
1465
+ // A message that keeps its own id owns the incoming copy with that id; a
1466
+ // run or turn match is weaker and must not take it from the message itself.
1467
+ const incomingByOwnId = new Map();
1468
+ existingMessages.forEach((entry, existingIndex) => {
1469
+ const existingMessage = getStoredMessage(entry);
1470
+ const id = messageId(existingMessage);
1471
+ if (!id ||
1472
+ (existingMessage?.role === "assistant" &&
1473
+ messageContentIsEmpty(existingMessage.content))) {
1474
+ return;
1475
+ }
1476
+ const incomingIndex = incomingKeySets.findIndex((keys, index) => !usedIncoming.has(index) && keys.strong.includes(`id:${id}`));
1477
+ if (incomingIndex === -1)
1478
+ return;
1479
+ usedIncoming.add(incomingIndex);
1480
+ incomingByOwnId.set(existingIndex, incomingIndex);
1481
+ });
1461
1482
  for (let existingIndex = 0; existingIndex < existingMessages.length; existingIndex++) {
1462
1483
  const existingEntry = existingMessages[existingIndex];
1463
1484
  const existingMessage = getStoredMessage(existingEntry);
@@ -1465,8 +1486,9 @@ export function mergeThreadDataForClientSave(existingRepo, incomingRepo, options
1465
1486
  messageContentIsEmpty(existingMessage.content)) {
1466
1487
  continue;
1467
1488
  }
1468
- const existingKeys = messageIdentityKeySet(existingMessage);
1469
- const incomingIndex = findRankedIdentityMatch(existingKeys, incomingKeySets, usedIncoming, existingIndex);
1489
+ const existingKeys = messageIdentityKeySet(existingMessage, eventRunIds);
1490
+ const incomingIndex = incomingByOwnId.get(existingIndex) ??
1491
+ findRankedIdentityMatch(existingKeys, incomingKeySets, usedIncoming, existingIndex);
1470
1492
  if (incomingIndex === -1) {
1471
1493
  nextMessages.push(existingEntry);
1472
1494
  continue;
@@ -1491,7 +1513,34 @@ export function mergeThreadDataForClientSave(existingRepo, incomingRepo, options
1491
1513
  }
1492
1514
  nextMessages.push(incomingMessages[index]);
1493
1515
  }
1494
- merged.messages = nextMessages.map((entry) => rewriteEntryParentId(entry, idRewrites));
1516
+ // One reply per run: the server's folded reply carries the run in its
1517
+ // metadata, and the chat UI's own copy of it (saved under an AgentKit id,
1518
+ // tied to the run only by events) is dropped wherever both ended up stored.
1519
+ const serverReplyRuns = new Set();
1520
+ for (const entry of nextMessages) {
1521
+ const message = getStoredMessage(entry);
1522
+ const runId = message?.role === "assistant" ? getMessageRunId(message) : null;
1523
+ if (runId)
1524
+ serverReplyRuns.add(runId);
1525
+ }
1526
+ const keptMessages = nextMessages.filter((entry) => {
1527
+ const message = getStoredMessage(entry);
1528
+ if (message?.role !== "assistant" || getMessageRunId(message))
1529
+ return true;
1530
+ const runId = typeof message.id === "string" ? eventRunIds.get(message.id) : undefined;
1531
+ if (!runId || !serverReplyRuns.has(runId))
1532
+ return true;
1533
+ const kept = nextMessages.find((candidate) => {
1534
+ const other = getStoredMessage(candidate);
1535
+ return other?.role === "assistant" && getMessageRunId(other) === runId;
1536
+ });
1537
+ const keptId = messageId(getStoredMessage(kept));
1538
+ const droppedId = messageId(message);
1539
+ if (keptId && droppedId)
1540
+ idRewrites.set(droppedId, keptId);
1541
+ return false;
1542
+ });
1543
+ merged.messages = keptMessages.map((entry) => rewriteEntryParentId(entry, idRewrites));
1495
1544
  const normalizedMerged = normalizeThreadRepository(pruneClaimedQueuedMessages(merged));
1496
1545
  normalizedMerged.headId = chooseMergedHeadId(existingNormalized, incomingNormalized, normalizedMerged);
1497
1546
  const previousUser = latestStoredUser(existingNormalized);
@@ -1324,10 +1324,13 @@ export function createAgentNativeAgentKitTransport(options = {}) {
1324
1324
  async function activeRunSnapshot(threadId) {
1325
1325
  const value = await activeRunStatus(threadId);
1326
1326
  const status = value.status;
1327
- if (value.active === false)
1328
- return null;
1329
- if (value.active !== true)
1327
+ if (typeof value.active !== "boolean")
1330
1328
  return undefined;
1329
+ // An idle thread has no run; a run that just finished keeps its id and
1330
+ // status for replay even though it is no longer `active`.
1331
+ if (value.active === false && (status === "idle" || !value.runId)) {
1332
+ return null;
1333
+ }
1331
1334
  if (typeof value.runId !== "string" || !value.runId) {
1332
1335
  throw new TypeError("Agent chat active-run response must include an active run ID.");
1333
1336
  }
@@ -1651,15 +1654,21 @@ export function createAgentNativeAgentKitTransport(options = {}) {
1651
1654
  ...(claimedMessage ? { claimedMessage } : {}),
1652
1655
  };
1653
1656
  }
1657
+ // A server that predates `active` meaning "in flight" reports a run inside
1658
+ // its reconnect window as `active` with a terminal status.
1659
+ function runIsInFlight(status) {
1660
+ return (status.active === true &&
1661
+ ![
1662
+ "completed",
1663
+ "complete",
1664
+ "failed",
1665
+ "cancelled",
1666
+ "errored",
1667
+ "aborted",
1668
+ ].includes(String(status.status ?? "")));
1669
+ }
1654
1670
  function runSlotIsClear(status) {
1655
- return (status.awaitingRedispatch !== true &&
1656
- (status.active !== true ||
1657
- status.status === "completed" ||
1658
- status.status === "complete" ||
1659
- status.status === "failed" ||
1660
- status.status === "cancelled" ||
1661
- status.status === "errored" ||
1662
- status.status === "aborted"));
1671
+ return status.awaitingRedispatch !== true && !runIsInFlight(status);
1663
1672
  }
1664
1673
  async function waitForRunSlot(threadId, maxPolls = RUN_SLOT_STABLE_POLLS * 2) {
1665
1674
  let consecutiveClearPolls = 0;
@@ -1838,11 +1847,14 @@ export function createAgentNativeAgentKitTransport(options = {}) {
1838
1847
  throw new TypeError("Agent chat queue claim response is invalid.");
1839
1848
  }
1840
1849
  if (interruptActiveRun) {
1841
- const activeRun = await activeRunSnapshot(threadId);
1842
- if (activeRun) {
1850
+ const activeRun = await activeRunStatus(threadId);
1851
+ if (runIsInFlight(activeRun)) {
1852
+ if (typeof activeRun.runId !== "string" || !activeRun.runId) {
1853
+ throw new TypeError("Agent chat active-run response must include an active run ID.");
1854
+ }
1843
1855
  await transport.cancelRun({
1844
1856
  threadId,
1845
- runId: activeRun.id,
1857
+ runId: activeRun.runId,
1846
1858
  });
1847
1859
  await waitForRunSlot(threadId, RUN_SLOT_STABLE_POLLS * 4);
1848
1860
  }
@@ -81,6 +81,26 @@ export function appendChatThreadScopeParams(params, scope) {
81
81
  params.set("scopeType", scope.type);
82
82
  params.set("scopeId", scope.id);
83
83
  }
84
+ /**
85
+ * The scope a thread save reports for the thread: a scope, `null` when the
86
+ * server holds the thread unscoped, `undefined` when the response says nothing
87
+ * (an older server or an unreadable body), so the local scope is left alone.
88
+ */
89
+ function savedThreadScope(body) {
90
+ const record = body;
91
+ if (!record || typeof record !== "object" || !("scope" in record)) {
92
+ return undefined;
93
+ }
94
+ const scope = record.scope;
95
+ if (scope === null)
96
+ return null;
97
+ if (!scope || typeof scope !== "object")
98
+ return undefined;
99
+ const { type, id } = scope;
100
+ return typeof type === "string" && typeof id === "string"
101
+ ? scope
102
+ : undefined;
103
+ }
84
104
  function withChatThreadScope(url, scope) {
85
105
  const params = new URLSearchParams();
86
106
  appendChatThreadScopeParams(params, scope);
@@ -239,6 +259,9 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
239
259
  ? new Set([initialActiveThreadRef.current.id])
240
260
  : new Set());
241
261
  const explicitlyOpenedThreadIdsRef = useRef(new Set());
262
+ // Bumped when a thread's scope is changed on purpose (detach), so a save
263
+ // response that was in flight across the change cannot restore the old scope.
264
+ const scopeMutationsRef = useRef(new Map());
242
265
  const optimisticThreadScopesRef = useRef(new Map());
243
266
  const knownThreadScopesRef = useRef(new Map());
244
267
  const serverConfirmedThreadIdsRef = useRef(new Set());
@@ -728,6 +751,8 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
728
751
  routeThreadId,
729
752
  ]);
730
753
  const detachThread = useCallback(async (threadId) => {
754
+ const bumpScopeMutation = () => scopeMutationsRef.current.set(threadId, (scopeMutationsRef.current.get(threadId) ?? 0) + 1);
755
+ bumpScopeMutation();
731
756
  try {
732
757
  const res = await fetch(withChatThreadScope(`${apiUrl}/threads/${encodeURIComponent(threadId)}`, historyScope), {
733
758
  method: "PUT",
@@ -738,6 +763,7 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
738
763
  await fetchThreads();
739
764
  return;
740
765
  }
766
+ bumpScopeMutation();
741
767
  knownThreadScopesRef.current.set(threadId, null);
742
768
  optimisticThreadScopesRef.current.set(threadId, null);
743
769
  const wasActive = activeThreadIdRef.current === threadId;
@@ -969,6 +995,7 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
969
995
  // rides only on creation: a periodic save must never move an existing thread
970
996
  // between resources, however stale this client's guess is.
971
997
  const saveThreadData = useCallback(async (id, data) => {
998
+ const scopeEpoch = scopeMutationsRef.current.get(id) ?? 0;
972
999
  try {
973
1000
  const { titleSource, ...threadDataPayload } = data;
974
1001
  const localThread = threadsRef.current.find((t) => t.id === id);
@@ -1004,6 +1031,13 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
1004
1031
  }
1005
1032
  if (!response.ok)
1006
1033
  return;
1034
+ const reportedScope = savedThreadScope(
1035
+ // coercion-ok: a save response without a readable body carries no scope, and the local scope stays as it was.
1036
+ await response.json().catch(() => null));
1037
+ // A response that was in flight across a detach describes the thread
1038
+ // as it was before it, so it must not put the old scope back.
1039
+ const scopeChangedDuringSave = (scopeMutationsRef.current.get(id) ?? 0) !== scopeEpoch;
1040
+ const savedScope = scopeChangedDuringSave ? undefined : reportedScope;
1007
1041
  serverConfirmedThreadIdsRef.current.add(id);
1008
1042
  clearClientDraftThreadMarker(id);
1009
1043
  newlyCreatedRef.current.delete(id);
@@ -1021,10 +1055,21 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
1021
1055
  ...(data.messageCount != null && {
1022
1056
  messageCount: data.messageCount,
1023
1057
  }),
1058
+ // The run adopts the scope it was sent with, which the
1059
+ // visible page at save time may no longer be; take the
1060
+ // server's, or the active pointer stays under the
1061
+ // unscoped key and a reload here starts fresh.
1062
+ ...(savedScope !== undefined
1063
+ ? { scope: savedScope }
1064
+ : {}),
1024
1065
  updatedAt: Date.now(),
1025
1066
  }
1026
1067
  : t));
1027
1068
  }
1069
+ // A thread the list no longer holds because it was detached while
1070
+ // this save ran must not come back under the page's current scope.
1071
+ if (scopeChangedDuringSave)
1072
+ return prev;
1028
1073
  const now = Date.now();
1029
1074
  return sortThreadSummaries([
1030
1075
  {
@@ -1034,7 +1079,9 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
1034
1079
  messageCount: data.messageCount ?? 0,
1035
1080
  createdAt: now,
1036
1081
  updatedAt: now,
1037
- scope: scopeRef.current ?? null,
1082
+ scope: savedScope !== undefined
1083
+ ? savedScope
1084
+ : (scopeRef.current ?? null),
1038
1085
  },
1039
1086
  ...prev,
1040
1087
  ]);
@@ -38,19 +38,19 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
38
38
  error: string;
39
39
  states?: undefined;
40
40
  } | {
41
- error?: undefined;
42
41
  states: {
43
42
  clientId: number;
44
43
  state: string;
45
44
  }[];
45
+ error?: undefined;
46
46
  }>>;
47
47
  export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
48
48
  error: string;
49
49
  users?: undefined;
50
50
  } | {
51
- error?: undefined;
52
51
  users: {
53
52
  clientId: number;
54
53
  lastSeen: number;
55
54
  }[];
55
+ error?: undefined;
56
56
  }>>;
@@ -8,8 +8,8 @@ export declare const getCollabState: import("h3").EventHandlerWithFetch<import("
8
8
  state: string;
9
9
  }>>;
10
10
  export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
11
- ok?: undefined;
12
11
  error: string;
12
+ ok?: undefined;
13
13
  } | {
14
14
  error?: undefined;
15
15
  ok: boolean;
@@ -1,6 +1,6 @@
1
1
  export declare const postCollabJson: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
2
- error: string;
3
2
  ok?: undefined;
3
+ error: string;
4
4
  } | {
5
5
  error?: undefined;
6
6
  ok: boolean;
@@ -42,8 +42,8 @@ declare const _default: import("../../action.js").ActionDefinition<{
42
42
  url: string;
43
43
  id: string;
44
44
  provider: string;
45
- error?: undefined;
46
45
  configured?: undefined;
46
+ error?: undefined;
47
47
  } | {
48
48
  url?: undefined;
49
49
  id?: undefined;
@@ -1,12 +1,12 @@
1
1
  export declare function createNotificationsHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<"" | import("./types.js").Notification[] | {
2
- error?: undefined;
3
2
  count: number;
4
3
  updated?: undefined;
4
+ error?: undefined;
5
5
  ok?: undefined;
6
6
  } | {
7
- error?: undefined;
8
7
  count?: undefined;
9
8
  updated: number;
9
+ error?: undefined;
10
10
  ok?: undefined;
11
11
  } | {
12
12
  count?: undefined;
@@ -14,8 +14,8 @@ export declare function createNotificationsHandler(): import("h3").EventHandlerW
14
14
  error: string;
15
15
  ok?: undefined;
16
16
  } | {
17
- error?: undefined;
18
17
  count?: undefined;
19
18
  updated?: undefined;
20
19
  ok: boolean;
20
+ error?: undefined;
21
21
  }>>;
@@ -27,38 +27,38 @@ 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
35
  id?: undefined;
35
- ok?: undefined;
36
36
  } | {
37
+ error?: undefined;
38
+ ok?: undefined;
37
39
  message?: undefined;
38
40
  summary: import("./types.js").TraceSummary;
39
41
  spans: import("./types.js").TraceSpan[];
40
42
  id?: undefined;
43
+ } | {
41
44
  error?: undefined;
42
45
  ok?: undefined;
43
- } | {
44
46
  message?: undefined;
45
47
  summary?: undefined;
46
48
  spans?: undefined;
47
49
  id: string;
48
- error?: undefined;
49
- ok?: undefined;
50
50
  } | {
51
+ ok?: undefined;
51
52
  message?: undefined;
52
53
  summary?: undefined;
53
54
  spans?: undefined;
54
55
  id?: undefined;
55
56
  error: any;
56
- ok?: undefined;
57
57
  } | {
58
+ error?: undefined;
58
59
  message?: undefined;
59
60
  summary?: undefined;
60
61
  spans?: undefined;
61
62
  id?: undefined;
62
63
  ok: boolean;
63
- error?: undefined;
64
64
  }>>;
@@ -39,8 +39,8 @@ export declare function handleUpdateResource(event: any): Promise<import("./stor
39
39
  error: string;
40
40
  }>;
41
41
  export declare function handleDeleteResource(event: any): Promise<{
42
- ok?: undefined;
43
42
  error: string;
43
+ ok?: undefined;
44
44
  } | {
45
45
  error?: undefined;
46
46
  ok: boolean;
@@ -5040,7 +5040,7 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
5040
5040
  : null;
5041
5041
  const { isBuilderGatewayDeployConfigured } = await import("./credential-provider.js");
5042
5042
  return {
5043
- active: true,
5043
+ active: run.inFlight,
5044
5044
  runId: run.runId,
5045
5045
  threadId: run.threadId,
5046
5046
  turnId: run.turnId,
@@ -5383,7 +5383,11 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
5383
5383
  const incomingScope = parseScopeFromBody(body.scope);
5384
5384
  await setThreadScope(threadId, owner, incomingScope);
5385
5385
  }
5386
- return { ok: true };
5386
+ // The scope the thread really has now (a detach can land
5387
+ // between the read above and this save), so the client records
5388
+ // what the server holds instead of guessing from the page.
5389
+ const saved = await resolveThreadAccess(owner, threadId, "editor", { orgId });
5390
+ return { ok: true, scope: saved?.scope ?? null };
5387
5391
  });
5388
5392
  }
5389
5393
  // POST /threads/:id/queued — apply a single queue mutation against
@@ -66,12 +66,12 @@ export declare function createAgentEngineApiKeyHandler(): import("h3").EventHand
66
66
  code: any;
67
67
  } | {
68
68
  errorCode?: undefined;
69
+ error?: undefined;
69
70
  code?: undefined;
70
71
  ok: boolean;
71
72
  key: string;
72
73
  baseUrlKey?: string;
73
74
  scope: AgentEngineApiKeyScope;
74
75
  defaultModel?: import("./agent-engine-default-model-route.js").SavedKeyDefaultModelOutcome;
75
- error?: undefined;
76
76
  }>>;
77
77
  export {};
@@ -8,17 +8,17 @@ export declare const AGENT_ENGINE_API_KEY_ACTION_NAME = "agent-engine-api-key";
8
8
  * resolveEngine's credential detection.
9
9
  */
10
10
  export declare function createAgentEngineDisconnectHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
11
- ok?: undefined;
12
11
  error: string;
13
12
  scope?: undefined;
13
+ ok?: undefined;
14
14
  } | {
15
15
  ok: boolean;
16
16
  error: any;
17
17
  scope?: undefined;
18
18
  } | {
19
- error?: undefined;
20
19
  ok: boolean;
21
20
  scope: "org" | "user";
21
+ error?: undefined;
22
22
  }>>;
23
23
  export interface DefaultModelSelectionRequest {
24
24
  engine: string;
@@ -1,9 +1,9 @@
1
1
  export declare function createAgentEngineOllamaModelsHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
2
2
  error: string;
3
- models?: undefined;
4
3
  ok?: undefined;
4
+ models?: undefined;
5
5
  } | {
6
+ error?: undefined;
6
7
  ok: boolean;
7
8
  models: string[];
8
- error?: undefined;
9
9
  }>>;
@@ -626,8 +626,8 @@ export declare function createPublicRemoteAgentsHandler(discover?: PublicAgentDi
626
626
  error: string;
627
627
  agents?: undefined;
628
628
  } | {
629
- agents: Omit<import("./agent-discovery.js").DiscoveredAgent, "auth" | "kind">[];
630
629
  error?: undefined;
630
+ agents: Omit<import("./agent-discovery.js").DiscoveredAgent, "auth" | "kind">[];
631
631
  }>>;
632
632
  export declare function getBuilderConnectErrorDisposition(error: unknown, connectAttemptId: string | null): "correlated" | "legacy" | null;
633
633
  export declare function getBuilderConnectErrorKey(ownerEmail: string, connectAttemptId?: string | null): string;
@@ -54,8 +54,8 @@ export declare function createRealtimeTokenHandler(): import("h3").EventHandlerW
54
54
  expiresAt?: undefined;
55
55
  ttlSeconds?: undefined;
56
56
  } | {
57
- error?: undefined;
58
57
  token: string;
59
58
  expiresAt: string;
60
59
  ttlSeconds: number;
60
+ error?: undefined;
61
61
  }>>;
@@ -20,6 +20,6 @@ export declare function createTranscribeVoiceHandler(): import("h3").EventHandle
20
20
  error: string;
21
21
  text?: undefined;
22
22
  } | {
23
- error?: undefined;
24
23
  text: string;
24
+ error?: undefined;
25
25
  }>>;
@@ -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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.200.0",
3
+ "version": "0.200.1-nightly-20261002183718",
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": {
@@ -668,7 +668,7 @@
668
668
  "yaml": "^2.9.0",
669
669
  "yjs": "^13.6.33",
670
670
  "zod": "^4.3.6",
671
- "@agent-native/agentkit": "^0.200.0",
671
+ "@agent-native/agentkit": "^0.200.1-nightly-20261002183718",
672
672
  "@agent-native/recap-cli": "^0.5.60"
673
673
  },
674
674
  "devDependencies": {
@@ -739,7 +739,7 @@
739
739
  "xlsx": "^0.18.5"
740
740
  },
741
741
  "peerDependencies": {
742
- "@agent-native/core-corpus": ">=0.196.0",
742
+ "@agent-native/core-corpus": "0.200.1-nightly-20261002183718",
743
743
  "@ai-sdk/anthropic": ">=3",
744
744
  "@ai-sdk/cohere": ">=3",
745
745
  "@ai-sdk/google": ">=3",