@webless/agent 0.6.7 → 0.6.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/react.cjs CHANGED
@@ -383,6 +383,203 @@ function clearPersistedAgentSession(visitorSessionId, options) {
383
383
  sessionStorage.removeItem(runtimeLastMessageKey(visitorSessionId, prefix));
384
384
  }
385
385
 
386
+ // src/runtime/subagent-child-stream.ts
387
+ var INITIAL_RETRY_DELAY_MS = 100;
388
+ var MAX_RETRY_DELAY_MS = 2e3;
389
+ var MAX_CONSECUTIVE_RETRIES = 6;
390
+ function isRecord2(value) {
391
+ return typeof value === "object" && value !== null && !Array.isArray(value);
392
+ }
393
+ function parseError(value) {
394
+ if (!isRecord2(value)) return void 0;
395
+ const { code, message } = value;
396
+ if (typeof code !== "string" || typeof message !== "string") {
397
+ return void 0;
398
+ }
399
+ return { code, message };
400
+ }
401
+ function parseChildStreamEvent(value) {
402
+ if (!isRecord2(value) || typeof value.type !== "string") {
403
+ return { type: "other" };
404
+ }
405
+ if (value.type === "session.waiting" || value.type === "session.completed" || value.type === "session.failed") {
406
+ return { type: "session.boundary" };
407
+ }
408
+ if (value.type === "subagent.event" && isRecord2(value.data) && Object.hasOwn(value.data, "event")) {
409
+ return parseChildStreamEvent(value.data.event);
410
+ }
411
+ if (value.type === "subagent.called" && isRecord2(value.data)) {
412
+ const { childStreamPath } = value.data;
413
+ if (typeof childStreamPath === "string") {
414
+ return { childStreamPath, type: "subagent.called" };
415
+ }
416
+ }
417
+ if (value.type !== "action.result" || !isRecord2(value.data)) {
418
+ return { type: "other" };
419
+ }
420
+ const { data } = value;
421
+ if (data.status !== "completed" && data.status !== "failed" && data.status !== "rejected") {
422
+ return { type: "other" };
423
+ }
424
+ if (!isRecord2(data.result) || data.result.kind !== "tool-result") {
425
+ return { type: "other" };
426
+ }
427
+ const result = data.result;
428
+ if (typeof result.callId !== "string" || typeof result.toolName !== "string") {
429
+ return { type: "other" };
430
+ }
431
+ const error = parseError(data.error);
432
+ return {
433
+ type: "action.result",
434
+ hasOutput: Object.hasOwn(result, "output"),
435
+ result: {
436
+ callId: result.callId,
437
+ toolName: result.toolName,
438
+ status: data.status,
439
+ ...Object.hasOwn(result, "output") ? { output: result.output } : {},
440
+ ...error ? { error } : {}
441
+ }
442
+ };
443
+ }
444
+ async function* readNdjsonStream(body) {
445
+ const reader = body.getReader();
446
+ const decoder = new TextDecoder();
447
+ let buffer = "";
448
+ try {
449
+ while (true) {
450
+ const { done, value } = await reader.read();
451
+ buffer += decoder.decode(value, { stream: !done });
452
+ const lines = buffer.split("\n");
453
+ buffer = lines.pop() ?? "";
454
+ for (const line of lines) {
455
+ const trimmed2 = line.trim();
456
+ if (!trimmed2) continue;
457
+ try {
458
+ const parsed = JSON.parse(trimmed2);
459
+ yield parsed;
460
+ } catch {
461
+ }
462
+ }
463
+ if (done) break;
464
+ }
465
+ const trimmed = buffer.trim();
466
+ if (trimmed) {
467
+ try {
468
+ const parsed = JSON.parse(trimmed);
469
+ yield parsed;
470
+ } catch {
471
+ }
472
+ }
473
+ } finally {
474
+ reader.releaseLock();
475
+ }
476
+ }
477
+ function streamPathAt(path, streamIndex) {
478
+ if (streamIndex === 0) return path;
479
+ return `${path}${path.includes("?") ? "&" : "?"}startIndex=${streamIndex}`;
480
+ }
481
+ function abortableDelay(delayMs, signal) {
482
+ if (signal.aborted) return Promise.resolve();
483
+ return new Promise((resolve) => {
484
+ const finish = () => {
485
+ clearTimeout(timeout);
486
+ signal.removeEventListener("abort", finish);
487
+ resolve();
488
+ };
489
+ const timeout = setTimeout(finish, delayMs);
490
+ signal.addEventListener("abort", finish, { once: true });
491
+ });
492
+ }
493
+ var SubagentChildStreamCoordinator = class {
494
+ constructor(client, handlers, parentSignal) {
495
+ this.client = client;
496
+ this.handlers = handlers;
497
+ this.parentSignal = parentSignal;
498
+ }
499
+ client;
500
+ handlers;
501
+ parentSignal;
502
+ controllers = /* @__PURE__ */ new Map();
503
+ tasks = /* @__PURE__ */ new Map();
504
+ begin(event) {
505
+ this.beginPath(event.data.childStreamPath);
506
+ }
507
+ async waitForAll() {
508
+ let observedTaskCount = -1;
509
+ while (observedTaskCount !== this.tasks.size) {
510
+ observedTaskCount = this.tasks.size;
511
+ await Promise.all(this.tasks.values());
512
+ }
513
+ }
514
+ abortAll() {
515
+ for (const controller of this.controllers.values()) controller.abort();
516
+ this.controllers.clear();
517
+ }
518
+ beginPath(childStreamPath) {
519
+ if (this.tasks.has(childStreamPath)) return;
520
+ const controller = new AbortController();
521
+ const abort = () => controller.abort();
522
+ if (this.parentSignal.aborted) {
523
+ controller.abort();
524
+ } else {
525
+ this.parentSignal.addEventListener("abort", abort, { once: true });
526
+ }
527
+ this.controllers.set(childStreamPath, controller);
528
+ const task = this.consume(childStreamPath, controller.signal).finally(
529
+ () => {
530
+ this.parentSignal.removeEventListener("abort", abort);
531
+ if (this.controllers.get(childStreamPath) === controller) {
532
+ this.controllers.delete(childStreamPath);
533
+ }
534
+ }
535
+ );
536
+ this.tasks.set(childStreamPath, task);
537
+ }
538
+ async consume(path, signal) {
539
+ let streamIndex = 0;
540
+ let consecutiveRetries = 0;
541
+ let retryDelayMs = INITIAL_RETRY_DELAY_MS;
542
+ while (!signal.aborted && consecutiveRetries < MAX_CONSECUTIVE_RETRIES) {
543
+ let receivedEvent = false;
544
+ try {
545
+ const response = await this.client.fetch(
546
+ streamPathAt(path, streamIndex),
547
+ {
548
+ cache: "no-store",
549
+ signal
550
+ }
551
+ );
552
+ if (!response.ok || response.body === null) {
553
+ await response.body?.cancel().catch(() => {
554
+ });
555
+ throw new Error(`Child stream returned ${response.status}.`);
556
+ }
557
+ for await (const rawEvent of readNdjsonStream(response.body)) {
558
+ if (signal.aborted) return;
559
+ receivedEvent = true;
560
+ streamIndex += 1;
561
+ const event = parseChildStreamEvent(rawEvent);
562
+ if (event.type === "session.boundary") return;
563
+ if (event.type === "subagent.called") {
564
+ this.beginPath(event.childStreamPath);
565
+ continue;
566
+ }
567
+ if (event.type !== "action.result") continue;
568
+ this.handlers.onToolResult?.(event.result);
569
+ if (event.hasOutput) {
570
+ this.handlers.onActionResult?.(event.result.output);
571
+ }
572
+ }
573
+ } catch {
574
+ if (signal.aborted) return;
575
+ }
576
+ consecutiveRetries = receivedEvent ? 0 : consecutiveRetries + 1;
577
+ retryDelayMs = receivedEvent ? INITIAL_RETRY_DELAY_MS : Math.min(retryDelayMs * 2, MAX_RETRY_DELAY_MS);
578
+ await abortableDelay(retryDelayMs, signal);
579
+ }
580
+ }
581
+ };
582
+
386
583
  // src/runtime/tool-ui.ts
387
584
  var AGENT_TOOL_UI_SCHEMA_VERSION = "webless.tool-ui.v1";
388
585
  var AGENT_STRUCTURED_TOOL_INPUT_SCHEMA_VERSION = "webless.structured-tool-input.v1";
@@ -396,7 +593,7 @@ function formatAgentStructuredToolInput(surface, values) {
396
593
  };
397
594
  return `${AGENT_STRUCTURED_TOOL_INPUT_HEADER} ${JSON.stringify(payload)}`;
398
595
  }
399
- function isRecord2(value) {
596
+ function isRecord3(value) {
400
597
  return value !== null && typeof value === "object" && !Array.isArray(value);
401
598
  }
402
599
  function isJsonValue(value, seen = /* @__PURE__ */ new Set()) {
@@ -445,7 +642,7 @@ function isFieldKind(value) {
445
642
  ].includes(value);
446
643
  }
447
644
  function parseField(value) {
448
- if (!isRecord2(value)) return null;
645
+ if (!isRecord3(value)) return null;
449
646
  if (!hasOnlyKeys(value, [
450
647
  "description",
451
648
  "kind",
@@ -496,7 +693,7 @@ function parseField(value) {
496
693
  if (!Array.isArray(value.options) || value.options.length > 100)
497
694
  return null;
498
695
  for (const option of value.options) {
499
- if (!isRecord2(option) || !boundedString(option.label, 160) || !isJsonValue(option.value)) {
696
+ if (!isRecord3(option) || !boundedString(option.label, 160) || !isJsonValue(option.value)) {
500
697
  return null;
501
698
  }
502
699
  }
@@ -519,7 +716,7 @@ function parseField(value) {
519
716
  };
520
717
  }
521
718
  function parseStep(value) {
522
- if (!isRecord2(value)) return null;
719
+ if (!isRecord3(value)) return null;
523
720
  if (!hasOnlyKeys(value, ["description", "fieldPaths", "id", "label"])) {
524
721
  return null;
525
722
  }
@@ -539,7 +736,7 @@ function parseStep(value) {
539
736
  };
540
737
  }
541
738
  function parseAction(value) {
542
- if (!isRecord2(value)) return null;
739
+ if (!isRecord3(value)) return null;
543
740
  if (!hasOnlyKeys(value, ["id", "label"])) return null;
544
741
  const label = boundedString(value.label, 80);
545
742
  if (value.id !== "submit" && value.id !== "back" && value.id !== "next" && value.id !== "reset" || !label) {
@@ -551,7 +748,7 @@ function parseAction(value) {
551
748
  };
552
749
  }
553
750
  function parseAgentToolUiSurface(value) {
554
- if (!isRecord2(value) || value.schemaVersion !== AGENT_TOOL_UI_SCHEMA_VERSION)
751
+ if (!isRecord3(value) || value.schemaVersion !== AGENT_TOOL_UI_SCHEMA_VERSION)
555
752
  return null;
556
753
  if (!hasOnlyKeys(value, [
557
754
  "actions",
@@ -589,7 +786,7 @@ function parseAgentToolUiSurface(value) {
589
786
  if (value.operationId !== void 0 && !operationId) return null;
590
787
  if (value.requestId !== void 0 && !requestId) return null;
591
788
  if (value.submitLabel !== void 0 && !submitLabel) return null;
592
- const values = value.values !== void 0 && isRecord2(value.values) ? value.values : void 0;
789
+ const values = value.values !== void 0 && isRecord3(value.values) ? value.values : void 0;
593
790
  if (value.values !== void 0) {
594
791
  if (!values || !Object.values(values).every((item) => isJsonValue(item)))
595
792
  return null;
@@ -626,8 +823,7 @@ function applyMessageEvent(event, rendered, handlers, workItems) {
626
823
  if (event.type === "message.completed") {
627
824
  handlers.onComplete?.();
628
825
  }
629
- if (event.type === "action.result") emitActionResult(event, handlers);
630
- if (event.type === "input.requested") emitInputRequests(event, handlers);
826
+ emitVisitorInteractionEvent(event, handlers);
631
827
  if (event.type !== "message.appended") return rendered;
632
828
  const { messageDelta, messageSoFar } = event.data;
633
829
  let delta = messageDelta;
@@ -677,6 +873,13 @@ function emitInputRequests(event, handlers) {
677
873
  })
678
874
  );
679
875
  }
876
+ function emitVisitorInteractionEvent(event, handlers) {
877
+ if (event.type === "action.result") emitActionResult(event, handlers);
878
+ if (event.type === "input.requested") emitInputRequests(event, handlers);
879
+ if (event.type === "subagent.event") {
880
+ emitVisitorInteractionEvent(event.data.event, handlers);
881
+ }
882
+ }
680
883
  function isResumeTurnMessage(received, candidate) {
681
884
  if (received === candidate) return true;
682
885
  return Boolean(candidate) && received.endsWith(`
@@ -849,11 +1052,14 @@ var AgentSession = class {
849
1052
  clientHost;
850
1053
  session;
851
1054
  activeResponse;
1055
+ childStreams;
852
1056
  capability;
853
1057
  getActiveSessionId() {
854
1058
  return this.session?.state.sessionId ?? loadPersistedAgentSession(this.visitorSessionId, this.storeOptions)?.sessionId;
855
1059
  }
856
1060
  reset() {
1061
+ this.childStreams?.abortAll();
1062
+ this.childStreams = void 0;
857
1063
  if (this.activeResponse) {
858
1064
  void this.activeResponse.cancel().catch(() => {
859
1065
  });
@@ -949,6 +1155,12 @@ var AgentSession = class {
949
1155
  this.persistSessionCursor(session);
950
1156
  }
951
1157
  this.activeResponse = response;
1158
+ const childStreams = new SubagentChildStreamCoordinator(
1159
+ client,
1160
+ handlers,
1161
+ signal
1162
+ );
1163
+ this.childStreams = childStreams;
952
1164
  let streamIndex = session?.state.streamIndex ?? 0;
953
1165
  let rendered = "";
954
1166
  const workItems = /* @__PURE__ */ new Map();
@@ -956,6 +1168,7 @@ var AgentSession = class {
956
1168
  try {
957
1169
  for await (const event of response) {
958
1170
  if (signal.aborted) break;
1171
+ if (event.type === "subagent.called") childStreams.begin(event);
959
1172
  if (event.type === "input.requested") requestedInput = true;
960
1173
  rendered = applyMessageEvent(event, rendered, handlers, workItems);
961
1174
  streamIndex += 1;
@@ -968,8 +1181,11 @@ var AgentSession = class {
968
1181
  );
969
1182
  }
970
1183
  }
1184
+ await childStreams.waitForAll();
971
1185
  } finally {
1186
+ childStreams.abortAll();
972
1187
  this.activeResponse = void 0;
1188
+ if (this.childStreams === childStreams) this.childStreams = void 0;
973
1189
  if (session) {
974
1190
  this.persistSessionCursor(session);
975
1191
  }
@@ -1005,64 +1221,80 @@ var AgentSession = class {
1005
1221
  }
1006
1222
  let rendered = renderTurn(turnEvents);
1007
1223
  const workItems = /* @__PURE__ */ new Map();
1008
- for (const event of turnEvents) {
1009
- applyWorkEvent(event, handlers, workItems);
1010
- if (event.type === "input.requested") emitInputRequests(event, handlers);
1011
- if (event.type === "action.result") emitActionResult(event, handlers);
1012
- }
1013
- if (rendered.startsWith(initialText)) {
1014
- const missedText = rendered.slice(initialText.length);
1015
- if (missedText) handlers.onDelta(missedText);
1016
- } else if (initialText.startsWith(rendered)) {
1017
- rendered = initialText;
1018
- } else if (!initialText.startsWith(rendered)) {
1019
- rendered = initialText + rendered;
1020
- }
1021
- let session = client.sessions.attach(snapshot.session.sessionId, {
1022
- streamIndex: snapshot.session.streamIndex
1023
- });
1024
- this.session = session;
1025
- this.persistSessionCursor(session);
1026
- let snapshotBoundary;
1027
- for (let index = turnEvents.length - 1; index >= 0; index -= 1) {
1028
- const event = turnEvents[index];
1029
- if (event && isTurnBoundary(event)) {
1030
- snapshotBoundary = event;
1031
- break;
1224
+ const childStreams = new SubagentChildStreamCoordinator(
1225
+ client,
1226
+ handlers,
1227
+ signal
1228
+ );
1229
+ this.childStreams = childStreams;
1230
+ try {
1231
+ for (const event of turnEvents) {
1232
+ if (event.type === "subagent.called") childStreams.begin(event);
1233
+ applyWorkEvent(event, handlers, workItems);
1234
+ emitVisitorInteractionEvent(event, handlers);
1032
1235
  }
1033
- }
1034
- if (snapshotBoundary) {
1035
- if (snapshotBoundary.type === "session.failed") {
1036
- throw new Error(
1037
- snapshotBoundary.data.message || snapshotBoundary.data.code
1236
+ if (rendered.startsWith(initialText)) {
1237
+ const missedText = rendered.slice(initialText.length);
1238
+ if (missedText) handlers.onDelta(missedText);
1239
+ } else if (initialText.startsWith(rendered)) {
1240
+ rendered = initialText;
1241
+ } else if (!initialText.startsWith(rendered)) {
1242
+ rendered = initialText + rendered;
1243
+ }
1244
+ let session = client.sessions.attach(snapshot.session.sessionId, {
1245
+ streamIndex: snapshot.session.streamIndex
1246
+ });
1247
+ this.session = session;
1248
+ this.persistSessionCursor(session);
1249
+ let snapshotBoundary;
1250
+ for (let index = turnEvents.length - 1; index >= 0; index -= 1) {
1251
+ const event = turnEvents[index];
1252
+ if (event && isTurnBoundary(event)) {
1253
+ snapshotBoundary = event;
1254
+ break;
1255
+ }
1256
+ }
1257
+ if (snapshotBoundary) {
1258
+ if (snapshotBoundary.type === "session.failed") {
1259
+ throw new Error(
1260
+ snapshotBoundary.data.message || snapshotBoundary.data.code
1261
+ );
1262
+ }
1263
+ handlers.onComplete?.();
1264
+ await childStreams.waitForAll();
1265
+ if (!rendered.trim() && !hasInputRequest) {
1266
+ throw new Error("Empty response from runtime");
1267
+ }
1268
+ return rendered.trim();
1269
+ }
1270
+ let streamIndex = snapshot.session.streamIndex;
1271
+ for await (const event of session.stream({ signal })) {
1272
+ if (signal.aborted) break;
1273
+ if (event.type === "subagent.called") childStreams.begin(event);
1274
+ rendered = applyMessageEvent(event, rendered, handlers, workItems);
1275
+ streamIndex += 1;
1276
+ savePersistedAgentSession(
1277
+ this.visitorSessionId,
1278
+ session.state.sessionId,
1279
+ streamIndex,
1280
+ this.storeOptions
1038
1281
  );
1282
+ if (isTurnBoundary(event)) break;
1039
1283
  }
1040
- handlers.onComplete?.();
1041
- if (!rendered.trim() && !hasInputRequest) {
1284
+ await childStreams.waitForAll();
1285
+ session = client.sessions.attach(session.state.sessionId, {
1286
+ streamIndex
1287
+ });
1288
+ this.session = session;
1289
+ this.persistSessionCursor(session);
1290
+ if (!rendered.trim() && !signal.aborted && !hasInputRequest) {
1042
1291
  throw new Error("Empty response from runtime");
1043
1292
  }
1044
1293
  return rendered.trim();
1294
+ } finally {
1295
+ childStreams.abortAll();
1296
+ if (this.childStreams === childStreams) this.childStreams = void 0;
1045
1297
  }
1046
- let streamIndex = snapshot.session.streamIndex;
1047
- for await (const event of session.stream({ signal })) {
1048
- if (signal.aborted) break;
1049
- rendered = applyMessageEvent(event, rendered, handlers, workItems);
1050
- streamIndex += 1;
1051
- savePersistedAgentSession(
1052
- this.visitorSessionId,
1053
- session.state.sessionId,
1054
- streamIndex,
1055
- this.storeOptions
1056
- );
1057
- if (isTurnBoundary(event)) break;
1058
- }
1059
- session = client.sessions.attach(session.state.sessionId, { streamIndex });
1060
- this.session = session;
1061
- this.persistSessionCursor(session);
1062
- if (!rendered.trim() && !signal.aborted && !hasInputRequest) {
1063
- throw new Error("Empty response from runtime");
1064
- }
1065
- return rendered.trim();
1066
1298
  }
1067
1299
  async respondTurn(responses, signal, handlers) {
1068
1300
  const client = this.ensureClient();
@@ -1083,6 +1315,12 @@ var AgentSession = class {
1083
1315
  () => session.respond(inputResponses, { signal })
1084
1316
  );
1085
1317
  this.activeResponse = response;
1318
+ const childStreams = new SubagentChildStreamCoordinator(
1319
+ client,
1320
+ handlers,
1321
+ signal
1322
+ );
1323
+ this.childStreams = childStreams;
1086
1324
  let streamIndex = session.state.streamIndex;
1087
1325
  let rendered = "";
1088
1326
  let requestedInput = false;
@@ -1090,6 +1328,7 @@ var AgentSession = class {
1090
1328
  try {
1091
1329
  for await (const event of response) {
1092
1330
  if (signal.aborted) break;
1331
+ if (event.type === "subagent.called") childStreams.begin(event);
1093
1332
  if (event.type === "input.requested") requestedInput = true;
1094
1333
  rendered = applyMessageEvent(event, rendered, handlers, workItems);
1095
1334
  streamIndex += 1;
@@ -1100,8 +1339,11 @@ var AgentSession = class {
1100
1339
  this.storeOptions
1101
1340
  );
1102
1341
  }
1342
+ await childStreams.waitForAll();
1103
1343
  } finally {
1344
+ childStreams.abortAll();
1104
1345
  this.activeResponse = void 0;
1346
+ if (this.childStreams === childStreams) this.childStreams = void 0;
1105
1347
  this.session = client.sessions.attach(session.state.sessionId, {
1106
1348
  streamIndex
1107
1349
  });
@@ -1113,6 +1355,7 @@ var AgentSession = class {
1113
1355
  return rendered.trim();
1114
1356
  }
1115
1357
  cancelActive() {
1358
+ this.childStreams?.abortAll();
1116
1359
  if (this.activeResponse) {
1117
1360
  this.activeResponse.cancel().catch(() => {
1118
1361
  });
@@ -1951,7 +2194,7 @@ var ENVELOPE_KEYS = /* @__PURE__ */ new Set([
1951
2194
  "presentationKinds",
1952
2195
  "ui"
1953
2196
  ]);
1954
- function isRecord3(value) {
2197
+ function isRecord4(value) {
1955
2198
  return value !== null && typeof value === "object" && !Array.isArray(value);
1956
2199
  }
1957
2200
  function isJsonValue2(value, seen = /* @__PURE__ */ new Set()) {
@@ -1978,7 +2221,7 @@ function decodeEnvelope(value) {
1978
2221
  }
1979
2222
  function parseAgentToolResultEnvelope(value) {
1980
2223
  const decoded = decodeEnvelope(value);
1981
- if (!isRecord3(decoded)) return null;
2224
+ if (!isRecord4(decoded)) return null;
1982
2225
  const keys = Object.keys(decoded);
1983
2226
  if (keys.some((key) => !ENVELOPE_KEYS.has(key)) || decoded.schemaVersion !== "webless.tool-result.v1" || !isJsonValue2(decoded.output) || !Array.isArray(decoded.presentationKinds) || decoded.presentationKinds.length < 1 || decoded.presentationKinds.length > 16) {
1984
2227
  return null;
@@ -3978,7 +4221,7 @@ function ConfirmationCard({
3978
4221
  // src/react/components/ToolInputCard/ToolInputCard.tsx
3979
4222
  var import_react9 = require("react");
3980
4223
  var import_jsx_runtime7 = require("react/jsx-runtime");
3981
- function isRecord4(value) {
4224
+ function isRecord5(value) {
3982
4225
  return value !== null && typeof value === "object" && !Array.isArray(value);
3983
4226
  }
3984
4227
  function pathSegments(path) {
@@ -3992,7 +4235,7 @@ function valueAtPath(root, path) {
3992
4235
  current = Number.isInteger(index) ? current[index] : void 0;
3993
4236
  continue;
3994
4237
  }
3995
- current = isRecord4(current) ? current[segment] : void 0;
4238
+ current = isRecord5(current) ? current[segment] : void 0;
3996
4239
  }
3997
4240
  return current;
3998
4241
  }
@@ -4015,7 +4258,7 @@ function initialValues(surface) {
4015
4258
  }
4016
4259
  function cloneJsonValue(value) {
4017
4260
  if (Array.isArray(value)) return value.map(cloneJsonValue);
4018
- if (isRecord4(value)) {
4261
+ if (isRecord5(value)) {
4019
4262
  return Object.fromEntries(
4020
4263
  Object.entries(value).map(([key, item]) => [key, cloneJsonValue(item)])
4021
4264
  );
@@ -4031,7 +4274,7 @@ function assignPath(target, path, value) {
4031
4274
  return;
4032
4275
  }
4033
4276
  const existing = current[segment];
4034
- if (!isRecord4(existing)) current[segment] = {};
4277
+ if (!isRecord5(existing)) current[segment] = {};
4035
4278
  current = current[segment];
4036
4279
  });
4037
4280
  }
@@ -4327,7 +4570,7 @@ function ToolInputCard({
4327
4570
  (field) => validateField(field, values[field.path] ?? "")
4328
4571
  );
4329
4572
  if (nextErrors.some(Boolean)) return;
4330
- const result = isRecord4(surface.values) ? cloneJsonValue(surface.values) : {};
4573
+ const result = isRecord5(surface.values) ? cloneJsonValue(surface.values) : {};
4331
4574
  for (const field of surface.fields) {
4332
4575
  const parsed = parsedFieldValue(field, values[field.path] ?? "");
4333
4576
  if (parsed !== void 0) assignPath(result, field.path, parsed);