@dudousxd/nestjs-agent-react 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -41,27 +41,41 @@ __export(src_exports, {
41
41
  MessageList: () => MessageList,
42
42
  SPEECH_LANGUAGES: () => SPEECH_LANGUAGES,
43
43
  applyCompletion: () => applyCompletion,
44
+ approvalCountdown: () => approvalCountdown,
44
45
  backgroundRunsFromThread: () => backgroundRunsFromThread,
45
46
  buildTranscriptBlocks: () => buildTranscriptBlocks,
47
+ correctedCallIds: () => correctedCallIds,
46
48
  createSkillsSource: () => createSkillsSource,
47
49
  describeTimestamp: () => describeTimestamp,
50
+ describeToolCall: () => describeToolCall,
48
51
  describeUsage: () => describeUsage,
49
52
  extractMessageText: () => extractMessageText,
53
+ fillTemplate: () => fillTemplate,
50
54
  filterAutocompleteItems: () => filterAutocompleteItems,
51
55
  findActiveTrigger: () => findActiveTrigger,
52
56
  formatElapsed: () => formatElapsed,
53
57
  formatRelativeTime: () => formatRelativeTime,
58
+ groupToolActivity: () => groupToolActivity,
59
+ inferResultView: () => inferResultView,
60
+ isActionCall: () => isActionCall,
54
61
  loadStoredSpeechLang: () => loadStoredSpeechLang,
55
62
  persistSpeechLang: () => persistSpeechLang,
63
+ phraseFor: () => phraseFor,
64
+ readPath: () => readPath,
56
65
  readReasoningMs: () => readReasoningMs,
66
+ resolveResultView: () => resolveResultView,
57
67
  storedMessageToUiMessage: () => storedMessageToUiMessage,
58
68
  storedThreadToUiMessages: () => storedThreadToUiMessages,
69
+ toolCallState: () => toolCallState,
70
+ toolCatalogFrom: () => toolCatalogFrom,
59
71
  useAgentChat: () => useAgentChat,
72
+ useApprovalCountdown: () => useApprovalCountdown,
60
73
  useChatTranscript: () => useChatTranscript,
61
74
  useComposerAutocomplete: () => useComposerAutocomplete,
62
75
  useElapsed: () => useElapsed,
63
76
  useSpeechRecognition: () => useSpeechRecognition,
64
77
  useStickToBottom: () => useStickToBottom,
78
+ useToolCatalog: () => useToolCatalog,
65
79
  useTranscriptItem: () => useTranscriptItem
66
80
  });
67
81
  module.exports = __toCommonJS(src_exports);
@@ -509,6 +523,10 @@ var AgentChatTransport = class {
509
523
  });
510
524
  }
511
525
  break;
526
+ case "approval-settled":
527
+ ensureStep();
528
+ forwardAsData(event, false);
529
+ break;
512
530
  case "ui":
513
531
  ensureStep();
514
532
  closeRuns();
@@ -744,6 +762,15 @@ var AgentClient = class {
744
762
  const query = threadId === void 0 ? "" : `?threadId=${encodeURIComponent(threadId)}`;
745
763
  return this.request("GET", `/agent/skills${query}`);
746
764
  }
765
+ /**
766
+ * The tools this caller can reach through `agent` (the default agent when omitted), each with the
767
+ * server-declared `presentation` a chat narrates it by — the same list the model is offered.
768
+ * Prefer {@link useToolCatalog}, which fetches it once and shares it.
769
+ */
770
+ listTools(agent) {
771
+ const query = agent === void 0 ? "" : `?agent=${encodeURIComponent(agent)}`;
772
+ return this.request("GET", `/agent/tools${query}`);
773
+ }
747
774
  getThread(id) {
748
775
  return this.request("GET", `/agent/threads/${encodeURIComponent(id)}`);
749
776
  }
@@ -799,6 +826,10 @@ var AgentClient = class {
799
826
  cancelStream(runId) {
800
827
  return this.request("POST", `/agent/chat/${encodeURIComponent(runId)}/cancel`);
801
828
  }
829
+ /**
830
+ * `remember` approves later calls of the same tool in the same thread; `via` names the surface
831
+ * the decision came through (the server records `'web'` when omitted).
832
+ */
802
833
  approveToolCall(input) {
803
834
  return this.request("POST", "/agent/tool-call/approve", input);
804
835
  }
@@ -1026,7 +1057,280 @@ var import_react6 = __toESM(require("react"), 1);
1026
1057
  var import_react5 = require("react");
1027
1058
 
1028
1059
  // src/transcript/model.ts
1060
+ var import_ai2 = require("ai");
1061
+
1062
+ // src/presentation/tool-activity.ts
1029
1063
  var import_ai = require("ai");
1064
+
1065
+ // src/presentation/phrasing.ts
1066
+ function toolCatalogFrom(entries) {
1067
+ const catalog = {};
1068
+ for (const entry of entries) {
1069
+ if (entry.presentation !== void 0) catalog[entry.name] = entry.presentation;
1070
+ }
1071
+ return catalog;
1072
+ }
1073
+ __name(toolCatalogFrom, "toolCatalogFrom");
1074
+ function readPath(value, path) {
1075
+ return path.split(".").reduce((current, key) => {
1076
+ if (current === null || typeof current !== "object") return void 0;
1077
+ return current[key];
1078
+ }, value);
1079
+ }
1080
+ __name(readPath, "readPath");
1081
+ function renderValue(value) {
1082
+ if (value === null || value === void 0) return "";
1083
+ if (typeof value === "string") return value;
1084
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
1085
+ if (Array.isArray(value)) return value.map(renderValue).filter(Boolean).join(", ");
1086
+ return "";
1087
+ }
1088
+ __name(renderValue, "renderValue");
1089
+ function fillTemplate(template, context) {
1090
+ return template.replace(/(\s*)\{([\w.]+)\}/g, (_match, space, path) => {
1091
+ const rendered = renderValue(readPath(context, path));
1092
+ return rendered === "" ? "" : `${space}${rendered}`;
1093
+ }).replace(/\s{2,}/g, " ").trim();
1094
+ }
1095
+ __name(fillTemplate, "fillTemplate");
1096
+ function phraseFor(presentation, input, isSettled2, fallback = {
1097
+ running: "Working",
1098
+ done: "Done"
1099
+ }) {
1100
+ if (presentation === void 0) return isSettled2 ? fallback.done : fallback.running;
1101
+ const filled = fillTemplate(isSettled2 ? presentation.done : presentation.running, input);
1102
+ return filled === "" ? presentation.label : filled;
1103
+ }
1104
+ __name(phraseFor, "phraseFor");
1105
+
1106
+ // src/presentation/result-view.ts
1107
+ function isRecord(value) {
1108
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1109
+ }
1110
+ __name(isRecord, "isRecord");
1111
+ function toText(value) {
1112
+ if (value === null || value === void 0) return "\u2014";
1113
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
1114
+ return String(value);
1115
+ }
1116
+ if (Array.isArray(value)) return value.map(toText).join(", ");
1117
+ return "\u2014";
1118
+ }
1119
+ __name(toText, "toText");
1120
+ function inferResultView(output) {
1121
+ if (!isRecord(output)) return void 0;
1122
+ for (const [key, value] of Object.entries(output)) {
1123
+ if (!Array.isArray(value) || value.length === 0) continue;
1124
+ if (value.every((entry) => typeof entry === "string")) {
1125
+ return {
1126
+ kind: "log",
1127
+ lines: key
1128
+ };
1129
+ }
1130
+ if (value.every(isRecord)) {
1131
+ const first = value[0];
1132
+ return {
1133
+ kind: "table",
1134
+ rows: key,
1135
+ columns: Object.keys(first).filter((column) => !isRecord(first[column])).map((column) => ({
1136
+ path: column,
1137
+ label: column
1138
+ }))
1139
+ };
1140
+ }
1141
+ }
1142
+ const fields = Object.entries(output).filter(([, value]) => [
1143
+ "string",
1144
+ "number",
1145
+ "boolean"
1146
+ ].includes(typeof value)).map(([key]) => ({
1147
+ path: key,
1148
+ label: key
1149
+ }));
1150
+ return fields.length > 0 ? {
1151
+ kind: "metrics",
1152
+ fields
1153
+ } : void 0;
1154
+ }
1155
+ __name(inferResultView, "inferResultView");
1156
+ function resolveResultView(output, view, options = {}) {
1157
+ const resolved = view ?? (options.infer === true ? inferResultView(output) : void 0);
1158
+ if (resolved === void 0 || resolved.kind === "elsewhere") return null;
1159
+ switch (resolved.kind) {
1160
+ case "note": {
1161
+ const text = fillTemplate(resolved.text, output);
1162
+ return text === "" ? null : {
1163
+ kind: "note",
1164
+ text
1165
+ };
1166
+ }
1167
+ case "metrics": {
1168
+ const readings = resolved.fields.map((field) => ({
1169
+ field,
1170
+ value: readPath(output, field.path)
1171
+ })).filter((entry) => entry.value !== void 0 && entry.value !== null).map(({ field, value }) => ({
1172
+ label: field.label,
1173
+ value: toText(value),
1174
+ unit: field.unit ?? null
1175
+ }));
1176
+ return readings.length === 0 ? null : {
1177
+ kind: "metrics",
1178
+ readings
1179
+ };
1180
+ }
1181
+ case "log": {
1182
+ const lines = readPath(output, resolved.lines);
1183
+ if (!Array.isArray(lines) || lines.length === 0) return null;
1184
+ return {
1185
+ kind: "log",
1186
+ lines: lines.map(toText)
1187
+ };
1188
+ }
1189
+ case "table": {
1190
+ const rows = readPath(output, resolved.rows);
1191
+ if (!Array.isArray(rows)) return null;
1192
+ return {
1193
+ kind: "table",
1194
+ columns: resolved.columns,
1195
+ rows: rows.map((row) => resolved.columns.map((column) => toText(readPath(row, column.path)))),
1196
+ empty: rows.length === 0 ? resolved.empty ?? null : null
1197
+ };
1198
+ }
1199
+ }
1200
+ }
1201
+ __name(resolveResultView, "resolveResultView");
1202
+
1203
+ // src/presentation/tool-activity.ts
1204
+ function isActionCall(part) {
1205
+ const metadata = part.toolMetadata;
1206
+ return typeof metadata === "object" && metadata !== null && metadata.toolKind === "action";
1207
+ }
1208
+ __name(isActionCall, "isActionCall");
1209
+ function toolCallState(part) {
1210
+ const output = "output" in part ? part.output : void 0;
1211
+ const errorText = "errorText" in part ? part.errorText : void 0;
1212
+ const outputError = output !== null && typeof output === "object" && "error" in output ? String(output.error) : void 0;
1213
+ const isDenied = part.state === "output-denied";
1214
+ const isFailed = part.state === "output-error" || outputError !== void 0 && !isDenied;
1215
+ const isSettled2 = part.state === "output-available" || part.state === "output-error" || isDenied;
1216
+ const isAwaiting = part.state === "approval-requested" || part.state === "input-available" && isActionCall(part);
1217
+ const status = isDenied ? "denied" : isFailed ? "failed" : isSettled2 ? "done" : isAwaiting ? "awaiting-approval" : "running";
1218
+ return {
1219
+ status,
1220
+ isSettled: isSettled2,
1221
+ isFailed,
1222
+ isDenied,
1223
+ output,
1224
+ error: errorText ?? outputError ?? null
1225
+ };
1226
+ }
1227
+ __name(toolCallState, "toolCallState");
1228
+ function correctedCallIds(parts) {
1229
+ const corrected = /* @__PURE__ */ new Set();
1230
+ const lastSuccessByTool = /* @__PURE__ */ new Map();
1231
+ parts.forEach((part, index) => {
1232
+ if (part.state === "output-available" && !toolCallState(part).isFailed) {
1233
+ lastSuccessByTool.set((0, import_ai.getToolName)(part), index);
1234
+ }
1235
+ });
1236
+ parts.forEach((part, index) => {
1237
+ const successAt = lastSuccessByTool.get((0, import_ai.getToolName)(part));
1238
+ if (successAt !== void 0 && index < successAt && toolCallState(part).isFailed) {
1239
+ corrected.add(part.toolCallId);
1240
+ }
1241
+ });
1242
+ return corrected;
1243
+ }
1244
+ __name(correctedCallIds, "correctedCallIds");
1245
+ function describeToolCall(part, catalog, options = {}) {
1246
+ const presentation = catalog?.[(0, import_ai.getToolName)(part)];
1247
+ const state = toolCallState(part);
1248
+ const input = part.input;
1249
+ const confirm = presentation?.confirm;
1250
+ return {
1251
+ status: state.status,
1252
+ phrase: phraseFor(presentation, input, state.isSettled, options.fallback),
1253
+ label: presentation?.label ?? null,
1254
+ icon: presentation?.icon ?? null,
1255
+ tone: presentation?.tone ?? "neutral",
1256
+ detail: presentation?.detail ?? null,
1257
+ confirm: confirm === void 0 ? null : {
1258
+ title: fillTemplate(confirm.title, input),
1259
+ verb: confirm.verb,
1260
+ detail: confirm.detail !== void 0 ? fillTemplate(confirm.detail, input) : null
1261
+ },
1262
+ result: state.status === "done" ? resolveResultView(state.output, presentation?.result, {
1263
+ ...options.inferResult !== void 0 ? {
1264
+ infer: options.inferResult
1265
+ } : {}
1266
+ }) : null,
1267
+ error: state.error,
1268
+ presentation: presentation ?? null
1269
+ };
1270
+ }
1271
+ __name(describeToolCall, "describeToolCall");
1272
+ var STATUS_WEIGHT = {
1273
+ running: 4,
1274
+ "awaiting-approval": 3,
1275
+ failed: 2,
1276
+ denied: 1,
1277
+ done: 0
1278
+ };
1279
+ function descendants(call) {
1280
+ return call.children.flatMap((child) => [
1281
+ child,
1282
+ ...descendants(child)
1283
+ ]);
1284
+ }
1285
+ __name(descendants, "descendants");
1286
+ function leaves(call) {
1287
+ return call.children.length === 0 ? [
1288
+ call
1289
+ ] : call.children.flatMap(leaves);
1290
+ }
1291
+ __name(leaves, "leaves");
1292
+ function groupToolActivity(calls, options = {}) {
1293
+ const expanded = options.expandNested === true ? calls.flatMap(leaves) : [
1294
+ ...calls
1295
+ ];
1296
+ const corrected = options.hideCorrected === true ? correctedCallIds(expanded.map((call) => call.part)) : /* @__PURE__ */ new Set();
1297
+ const groups = /* @__PURE__ */ new Map();
1298
+ for (const call of expanded) {
1299
+ if (corrected.has(call.toolCallId)) continue;
1300
+ const presentation = options.catalog?.[call.name];
1301
+ const key = options.keyOf?.(call, presentation) ?? presentation?.label ?? call.name;
1302
+ const status = toolCallState(call.part).status;
1303
+ const phrase = phraseFor(presentation, call.part.input, status !== "running" && status !== "awaiting-approval", options.fallback);
1304
+ const inner = options.expandNested === true ? 0 : descendants(call).length;
1305
+ const existing = groups.get(key);
1306
+ if (existing === void 0) {
1307
+ groups.set(key, {
1308
+ key,
1309
+ label: presentation?.label ?? null,
1310
+ icon: presentation?.icon ?? null,
1311
+ status,
1312
+ count: 1,
1313
+ phrase,
1314
+ calls: [
1315
+ call
1316
+ ],
1317
+ innerCount: inner
1318
+ });
1319
+ continue;
1320
+ }
1321
+ existing.count += 1;
1322
+ existing.calls.push(call);
1323
+ existing.phrase = phrase;
1324
+ existing.innerCount += inner;
1325
+ if (STATUS_WEIGHT[status] > STATUS_WEIGHT[existing.status]) existing.status = status;
1326
+ }
1327
+ return [
1328
+ ...groups.values()
1329
+ ];
1330
+ }
1331
+ __name(groupToolActivity, "groupToolActivity");
1332
+
1333
+ // src/transcript/model.ts
1030
1334
  function buildTranscriptBlocks(message, options) {
1031
1335
  const blocks = [];
1032
1336
  let toolBuffer = [];
@@ -1043,13 +1347,19 @@ function buildTranscriptBlocks(message, options) {
1043
1347
  if (toolBuffer.length === 0) {
1044
1348
  return;
1045
1349
  }
1046
- const calls = toolBuffer.map((part) => buildToolCall(part, options.approval, approvals.get(part.toolCallId) ?? null));
1350
+ const calls = toolBuffer.map((part) => buildToolCall(part, options.approval, approvalOf(approvals.get(part.toolCallId), part), options.toolCatalog));
1351
+ const roots = nestToolCalls(calls);
1047
1352
  blocks.push({
1048
1353
  kind: "tools",
1049
1354
  key: `${message.id}-tools-${toolCounter++}`,
1050
1355
  parts: toolBuffer,
1051
1356
  calls,
1052
- roots: nestToolCalls(calls)
1357
+ roots,
1358
+ activity: groupToolActivity(roots, {
1359
+ ...options.toolCatalog !== void 0 ? {
1360
+ catalog: options.toolCatalog
1361
+ } : {}
1362
+ })
1053
1363
  });
1054
1364
  toolBuffer = [];
1055
1365
  }
@@ -1086,7 +1396,7 @@ function buildTranscriptBlocks(message, options) {
1086
1396
  }
1087
1397
  __name(flushAll, "flushAll");
1088
1398
  for (const part of message.parts ?? []) {
1089
- if ((0, import_ai.isToolUIPart)(part)) {
1399
+ if ((0, import_ai2.isToolUIPart)(part)) {
1090
1400
  const elicitation = options.elicitation;
1091
1401
  if (elicitation !== void 0) {
1092
1402
  const request = readElicitationRequest(part);
@@ -1106,17 +1416,17 @@ function buildTranscriptBlocks(message, options) {
1106
1416
  toolBuffer.push(part);
1107
1417
  continue;
1108
1418
  }
1109
- if ((0, import_ai.isFileUIPart)(part)) {
1419
+ if ((0, import_ai2.isFileUIPart)(part)) {
1110
1420
  flushTools();
1111
1421
  flushSources();
1112
1422
  fileBuffer.push(part);
1113
1423
  continue;
1114
1424
  }
1115
- if (part.type === APPROVAL_PART) {
1425
+ if (part.type === APPROVAL_PART || part.type === SETTLED_PART) {
1116
1426
  continue;
1117
1427
  }
1118
1428
  flushAll();
1119
- if ((0, import_ai.isDataUIPart)(part)) {
1429
+ if ((0, import_ai2.isDataUIPart)(part)) {
1120
1430
  const ui = part.type === UI_PART ? readUiComponent(part) : null;
1121
1431
  if (ui !== null) {
1122
1432
  blocks.push({
@@ -1127,7 +1437,7 @@ function buildTranscriptBlocks(message, options) {
1127
1437
  }
1128
1438
  continue;
1129
1439
  }
1130
- if ((0, import_ai.isTextUIPart)(part)) {
1440
+ if ((0, import_ai2.isTextUIPart)(part)) {
1131
1441
  blocks.push({
1132
1442
  kind: "text",
1133
1443
  key: `${message.id}-text-${textCounter++}`,
@@ -1136,7 +1446,7 @@ function buildTranscriptBlocks(message, options) {
1136
1446
  });
1137
1447
  continue;
1138
1448
  }
1139
- if ((0, import_ai.isReasoningUIPart)(part)) {
1449
+ if ((0, import_ai2.isReasoningUIPart)(part)) {
1140
1450
  const key = `${message.id}-reasoning-${reasoningCounter++}`;
1141
1451
  const isStreaming = part.state === "streaming";
1142
1452
  blocks.push({
@@ -1198,7 +1508,7 @@ function isSettled(state) {
1198
1508
  __name(isSettled, "isSettled");
1199
1509
  function toolKind(part) {
1200
1510
  const metadata = part.toolMetadata;
1201
- return isRecord(metadata) && typeof metadata.toolKind === "string" ? metadata.toolKind : void 0;
1511
+ return isRecord2(metadata) && typeof metadata.toolKind === "string" ? metadata.toolKind : void 0;
1202
1512
  }
1203
1513
  __name(toolKind, "toolKind");
1204
1514
  function isAwaitingApproval(part) {
@@ -1213,7 +1523,7 @@ function isAwaitingApproval(part) {
1213
1523
  __name(isAwaitingApproval, "isAwaitingApproval");
1214
1524
  function toolParentId(part) {
1215
1525
  const metadata = part.toolMetadata;
1216
- return isRecord(metadata) && typeof metadata.parentId === "string" ? metadata.parentId : null;
1526
+ return isRecord2(metadata) && typeof metadata.parentId === "string" ? metadata.parentId : null;
1217
1527
  }
1218
1528
  __name(toolParentId, "toolParentId");
1219
1529
  function nestToolCalls(calls) {
@@ -1246,23 +1556,28 @@ function isAncestor(call, candidate, byId) {
1246
1556
  return false;
1247
1557
  }
1248
1558
  __name(isAncestor, "isAncestor");
1249
- function buildToolCall(part, options, approval) {
1559
+ function buildToolCall(part, options, approval, catalog) {
1250
1560
  const toolCallId = part.toolCallId;
1251
1561
  const awaiting = isAwaitingApproval(part);
1252
1562
  const sending = awaiting ? options?.submitting(toolCallId) ?? null : null;
1253
1563
  return {
1254
1564
  part,
1255
1565
  toolCallId,
1256
- name: (0, import_ai.getToolName)(part),
1566
+ name: (0, import_ai2.getToolName)(part),
1257
1567
  toolKind: toolKind(part) ?? null,
1258
1568
  parentId: toolParentId(part),
1259
1569
  children: [],
1260
1570
  approval,
1571
+ description: describeToolCall(part, catalog),
1261
1572
  isAwaitingApproval: awaiting,
1262
1573
  approve: {
1263
1574
  available: awaiting && options?.canApprove === true,
1264
1575
  isSubmitting: sending === "approve",
1265
- run: /* @__PURE__ */ __name(() => options?.approve(toolCallId), "run")
1576
+ // Read by field, not passed through: `onClick={call.approve.run}` hands this a click event,
1577
+ // and a host's handler must not receive that as its options.
1578
+ run: /* @__PURE__ */ __name((approveOptions) => approveOptions?.remember === true ? options?.approve(toolCallId, {
1579
+ remember: true
1580
+ }) : options?.approve(toolCallId), "run")
1266
1581
  },
1267
1582
  reject: {
1268
1583
  available: awaiting && options?.canReject === true,
@@ -1275,17 +1590,17 @@ function buildToolCall(part, options, approval) {
1275
1590
  __name(buildToolCall, "buildToolCall");
1276
1591
  function readElicitationRequest(part) {
1277
1592
  const input = part.input;
1278
- if (!isRecord(input) || !Array.isArray(input.questions) || input.questions.length === 0) {
1593
+ if (!isRecord2(input) || !Array.isArray(input.questions) || input.questions.length === 0) {
1279
1594
  return null;
1280
1595
  }
1281
1596
  const questions = [];
1282
1597
  for (const candidate of input.questions) {
1283
- if (!isRecord(candidate) || typeof candidate.id !== "string" || typeof candidate.prompt !== "string" || !Array.isArray(candidate.options) || candidate.options.length === 0) {
1598
+ if (!isRecord2(candidate) || typeof candidate.id !== "string" || typeof candidate.prompt !== "string" || !Array.isArray(candidate.options) || candidate.options.length === 0) {
1284
1599
  return null;
1285
1600
  }
1286
1601
  const options = [];
1287
1602
  for (const option of candidate.options) {
1288
- if (!isRecord(option) || typeof option.value !== "string" || typeof option.label !== "string") {
1603
+ if (!isRecord2(option) || typeof option.value !== "string" || typeof option.label !== "string") {
1289
1604
  return null;
1290
1605
  }
1291
1606
  options.push({
@@ -1310,7 +1625,7 @@ function readElicitationRequest(part) {
1310
1625
  __name(readElicitationRequest, "readElicitationRequest");
1311
1626
  function readElicitationOutcome(part) {
1312
1627
  const output = part.output;
1313
- if (!isRecord(output) || !isRecord(output.answers) || typeof output.skipped !== "boolean") {
1628
+ if (!isRecord2(output) || !isRecord2(output.answers) || typeof output.skipped !== "boolean") {
1314
1629
  return null;
1315
1630
  }
1316
1631
  const answers = {};
@@ -1390,28 +1705,93 @@ function buildElicitationBlock(key, part, request, options) {
1390
1705
  __name(buildElicitationBlock, "buildElicitationBlock");
1391
1706
  var UI_PART = "data-ui";
1392
1707
  var APPROVAL_PART = "data-approval-requested";
1708
+ var SETTLED_PART = "data-approval-settled";
1709
+ var SETTLED_STATUSES = [
1710
+ "approved",
1711
+ "rejected",
1712
+ "expired"
1713
+ ];
1393
1714
  function readApprovals(parts) {
1394
1715
  const out = /* @__PURE__ */ new Map();
1716
+ const entry = /* @__PURE__ */ __name((id) => {
1717
+ let found = out.get(id);
1718
+ if (found === void 0) {
1719
+ found = {
1720
+ approver: null,
1721
+ expiresAt: null,
1722
+ reason: null,
1723
+ status: null,
1724
+ remember: false,
1725
+ decidedBy: null,
1726
+ decidedVia: null,
1727
+ decisionReason: null
1728
+ };
1729
+ out.set(id, found);
1730
+ }
1731
+ return found;
1732
+ }, "entry");
1395
1733
  for (const part of parts) {
1396
- if (part.type !== APPROVAL_PART) {
1734
+ if (part.type !== APPROVAL_PART && part.type !== SETTLED_PART) {
1397
1735
  continue;
1398
1736
  }
1399
1737
  const data = part.data;
1400
- if (!isRecord(data) || typeof data.id !== "string" || typeof data.approver !== "string") {
1738
+ if (!isRecord2(data) || typeof data.id !== "string") {
1401
1739
  continue;
1402
1740
  }
1403
- out.set(data.id, {
1404
- approver: data.approver,
1405
- expiresAt: typeof data.expiresAt === "string" ? data.expiresAt : null,
1406
- reason: typeof data.reason === "string" ? data.reason : null
1407
- });
1741
+ const approval = entry(data.id);
1742
+ if (part.type === APPROVAL_PART) {
1743
+ if (typeof data.approver !== "string") {
1744
+ continue;
1745
+ }
1746
+ approval.approver = data.approver;
1747
+ approval.expiresAt = typeof data.expiresAt === "string" ? data.expiresAt : null;
1748
+ approval.reason = typeof data.reason === "string" ? data.reason : null;
1749
+ continue;
1750
+ }
1751
+ if (typeof data.status !== "string" || !SETTLED_STATUSES.includes(data.status)) {
1752
+ continue;
1753
+ }
1754
+ approval.status = data.status;
1755
+ if (approval.approver === null && typeof data.approver === "string") {
1756
+ approval.approver = data.approver;
1757
+ }
1758
+ approval.remember = data.remember === true;
1759
+ approval.decidedBy = typeof data.decidedBy === "string" ? data.decidedBy : null;
1760
+ approval.decidedVia = typeof data.decidedVia === "string" ? data.decidedVia : null;
1761
+ approval.decisionReason = typeof data.reason === "string" ? data.reason : null;
1408
1762
  }
1409
1763
  return out;
1410
1764
  }
1411
1765
  __name(readApprovals, "readApprovals");
1766
+ function approvalOf(parts, call) {
1767
+ if (parts === void 0 || parts.approver === null) {
1768
+ return null;
1769
+ }
1770
+ return {
1771
+ approver: parts.approver,
1772
+ expiresAt: parts.expiresAt,
1773
+ reason: parts.reason,
1774
+ status: parts.status ?? statusFromPart(call),
1775
+ remember: parts.remember,
1776
+ decidedBy: parts.decidedBy,
1777
+ decidedVia: parts.decidedVia,
1778
+ decisionReason: parts.decisionReason
1779
+ };
1780
+ }
1781
+ __name(approvalOf, "approvalOf");
1782
+ function statusFromPart(call) {
1783
+ if (call.state === "output-denied") {
1784
+ return "rejected";
1785
+ }
1786
+ if (call.state === "output-available" || call.state === "output-error") {
1787
+ return "approved";
1788
+ }
1789
+ return "pending";
1790
+ }
1791
+ __name(statusFromPart, "statusFromPart");
1412
1792
  function readUiComponent(part) {
1413
1793
  const data = part.data;
1414
- if (!isRecord(data) || typeof data.component !== "string") {
1794
+ if (!isRecord2(data) || typeof data.component !== "string") {
1415
1795
  return null;
1416
1796
  }
1417
1797
  const id = typeof data.id === "string" ? data.id : part.id;
@@ -1421,18 +1801,18 @@ function readUiComponent(part) {
1421
1801
  return {
1422
1802
  id,
1423
1803
  component: data.component,
1424
- props: isRecord(data.props) ? data.props : {},
1804
+ props: isRecord2(data.props) ? data.props : {},
1425
1805
  version: typeof data.version === "number" ? data.version : null
1426
1806
  };
1427
1807
  }
1428
1808
  __name(readUiComponent, "readUiComponent");
1429
- function isRecord(value) {
1809
+ function isRecord2(value) {
1430
1810
  return typeof value === "object" && value !== null;
1431
1811
  }
1432
- __name(isRecord, "isRecord");
1812
+ __name(isRecord2, "isRecord");
1433
1813
  function readQuery(part) {
1434
1814
  const input = part.input;
1435
- if (!isRecord(input) || typeof input.query !== "string") {
1815
+ if (!isRecord2(input) || typeof input.query !== "string") {
1436
1816
  return null;
1437
1817
  }
1438
1818
  return input.query;
@@ -1440,12 +1820,12 @@ function readQuery(part) {
1440
1820
  __name(readQuery, "readQuery");
1441
1821
  function readPassages(part) {
1442
1822
  const output = part.output;
1443
- if (!isRecord(output) || !Array.isArray(output.passages) || output.passages.length === 0) {
1823
+ if (!isRecord2(output) || !Array.isArray(output.passages) || output.passages.length === 0) {
1444
1824
  return null;
1445
1825
  }
1446
1826
  const passages = [];
1447
1827
  for (const candidate of output.passages) {
1448
- if (!isRecord(candidate) || typeof candidate.id !== "string" || typeof candidate.text !== "string") {
1828
+ if (!isRecord2(candidate) || typeof candidate.id !== "string" || typeof candidate.text !== "string") {
1449
1829
  return null;
1450
1830
  }
1451
1831
  passages.push({
@@ -1455,7 +1835,7 @@ function readPassages(part) {
1455
1835
  ...typeof candidate.source === "string" ? {
1456
1836
  source: candidate.source
1457
1837
  } : {},
1458
- ...isRecord(candidate.metadata) ? {
1838
+ ...isRecord2(candidate.metadata) ? {
1459
1839
  metadata: candidate.metadata
1460
1840
  } : {}
1461
1841
  });
@@ -1466,7 +1846,7 @@ __name(readPassages, "readPassages");
1466
1846
  function extractMessageText(parts) {
1467
1847
  const out = [];
1468
1848
  for (const part of parts ?? []) {
1469
- if ((0, import_ai.isTextUIPart)(part)) {
1849
+ if ((0, import_ai2.isTextUIPart)(part)) {
1470
1850
  out.push(part.text);
1471
1851
  }
1472
1852
  }
@@ -1794,10 +2174,10 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
1794
2174
  }, [
1795
2175
  settle
1796
2176
  ]);
1797
- const approve = (0, import_react5.useCallback)((toolCallId) => {
2177
+ const approve = (0, import_react5.useCallback)((toolCallId, options2) => {
1798
2178
  const onApprove = latest.current.options.onApprove;
1799
2179
  if (onApprove) {
1800
- settle(toolCallId, "approve", () => onApprove(toolCallId));
2180
+ settle(toolCallId, "approve", () => options2 === void 0 ? onApprove(toolCallId) : onApprove(toolCallId, options2));
1801
2181
  }
1802
2182
  }, [
1803
2183
  settle
@@ -1922,6 +2302,9 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
1922
2302
  ...options.sources !== void 0 ? {
1923
2303
  sources: options.sources
1924
2304
  } : {},
2305
+ ...options.toolCatalog !== void 0 ? {
2306
+ toolCatalog: options.toolCatalog
2307
+ } : {},
1925
2308
  ...options.onAnswer !== void 0 ? {
1926
2309
  elicitation: {
1927
2310
  picked: /* @__PURE__ */ __name((toolCallId, questionId) => picks.get(pickKey(toolCallId, questionId)), "picked"),
@@ -2697,6 +3080,121 @@ function isPromise(value) {
2697
3080
  }
2698
3081
  __name(isPromise, "isPromise");
2699
3082
 
3083
+ // src/presentation/use-tool-catalog.ts
3084
+ var import_react8 = require("react");
3085
+ var shared = /* @__PURE__ */ new WeakMap();
3086
+ function load(client, agent) {
3087
+ let byAgent = shared.get(client);
3088
+ if (byAgent === void 0) {
3089
+ byAgent = /* @__PURE__ */ new Map();
3090
+ shared.set(client, byAgent);
3091
+ }
3092
+ const key = agent ?? "";
3093
+ const cached = byAgent.get(key);
3094
+ if (cached !== void 0) return cached;
3095
+ const request = client.listTools(agent).catch((error) => {
3096
+ byAgent.delete(key);
3097
+ throw error;
3098
+ });
3099
+ byAgent.set(key, request);
3100
+ return request;
3101
+ }
3102
+ __name(load, "load");
3103
+ function useToolCatalog(options) {
3104
+ const { client, agent, enabled = true } = options;
3105
+ const [entries, setEntries] = (0, import_react8.useState)([]);
3106
+ const [isLoading, setLoading] = (0, import_react8.useState)(enabled);
3107
+ const [error, setError] = (0, import_react8.useState)(null);
3108
+ const [generation, setGeneration] = (0, import_react8.useState)(0);
3109
+ (0, import_react8.useEffect)(() => {
3110
+ if (!enabled) {
3111
+ setLoading(false);
3112
+ return;
3113
+ }
3114
+ let cancelled = false;
3115
+ setLoading(true);
3116
+ load(client, agent).then((loaded) => {
3117
+ if (cancelled) return;
3118
+ setEntries(loaded);
3119
+ setError(null);
3120
+ setLoading(false);
3121
+ }, (failure) => {
3122
+ if (cancelled) return;
3123
+ setError(failure instanceof Error ? failure : new Error(String(failure)));
3124
+ setLoading(false);
3125
+ });
3126
+ return () => {
3127
+ cancelled = true;
3128
+ };
3129
+ }, [
3130
+ client,
3131
+ agent,
3132
+ enabled,
3133
+ generation
3134
+ ]);
3135
+ const refresh = (0, import_react8.useCallback)(() => {
3136
+ shared.get(client)?.delete(agent ?? "");
3137
+ setGeneration((current) => current + 1);
3138
+ }, [
3139
+ client,
3140
+ agent
3141
+ ]);
3142
+ const catalog = (0, import_react8.useMemo)(() => toolCatalogFrom(entries), [
3143
+ entries
3144
+ ]);
3145
+ return {
3146
+ catalog,
3147
+ entries,
3148
+ isLoading,
3149
+ error,
3150
+ refresh
3151
+ };
3152
+ }
3153
+ __name(useToolCatalog, "useToolCatalog");
3154
+
3155
+ // src/approvals/countdown.ts
3156
+ var import_react9 = require("react");
3157
+ function approvalCountdown(expiresAt, now = Date.now()) {
3158
+ const deadline = expiresAt == null ? Number.NaN : Date.parse(expiresAt);
3159
+ if (!Number.isFinite(deadline)) {
3160
+ return {
3161
+ remainingMs: null,
3162
+ isExpired: false
3163
+ };
3164
+ }
3165
+ const remainingMs = Math.max(0, deadline - now);
3166
+ return {
3167
+ remainingMs,
3168
+ isExpired: remainingMs === 0
3169
+ };
3170
+ }
3171
+ __name(approvalCountdown, "approvalCountdown");
3172
+ function useApprovalCountdown(expiresAt, options = {}) {
3173
+ const { intervalMs = 1e3 } = options;
3174
+ const nowRef = (0, import_react9.useRef)(options.now ?? Date.now);
3175
+ nowRef.current = options.now ?? Date.now;
3176
+ const [state, setState] = (0, import_react9.useState)(() => approvalCountdown(expiresAt, nowRef.current()));
3177
+ (0, import_react9.useEffect)(() => {
3178
+ const read = /* @__PURE__ */ __name(() => approvalCountdown(expiresAt, nowRef.current()), "read");
3179
+ const first = read();
3180
+ setState(first);
3181
+ if (first.remainingMs === null || first.isExpired) {
3182
+ return;
3183
+ }
3184
+ const timer = setInterval(() => {
3185
+ const next = read();
3186
+ setState(next);
3187
+ if (next.isExpired) clearInterval(timer);
3188
+ }, intervalMs);
3189
+ return () => clearInterval(timer);
3190
+ }, [
3191
+ expiresAt,
3192
+ intervalMs
3193
+ ]);
3194
+ return state;
3195
+ }
3196
+ __name(useApprovalCountdown, "useApprovalCountdown");
3197
+
2700
3198
  // src/stored-message-to-ui-message.ts
2701
3199
  var import_nestjs_agent_core = require("@dudousxd/nestjs-agent-core");
2702
3200
  function isRefusal(result) {
@@ -2756,6 +3254,41 @@ function storedMessageToUiMessage(message) {
2756
3254
  }
2757
3255
  });
2758
3256
  }
3257
+ for (const approval of message.approvals ?? []) {
3258
+ parts.push({
3259
+ type: "data-approval-requested",
3260
+ id: approval.toolCallId,
3261
+ data: {
3262
+ id: approval.toolCallId,
3263
+ approver: approval.approver,
3264
+ ...approval.expiresAt !== void 0 ? {
3265
+ expiresAt: approval.expiresAt
3266
+ } : {}
3267
+ }
3268
+ });
3269
+ if (approval.status !== "pending") {
3270
+ parts.push({
3271
+ type: "data-approval-settled",
3272
+ id: approval.toolCallId,
3273
+ data: {
3274
+ id: approval.toolCallId,
3275
+ status: approval.status,
3276
+ ...approval.decidedBy !== void 0 ? {
3277
+ decidedBy: approval.decidedBy
3278
+ } : {},
3279
+ ...approval.decidedVia !== void 0 ? {
3280
+ decidedVia: approval.decidedVia
3281
+ } : {},
3282
+ ...approval.remember === true ? {
3283
+ remember: true
3284
+ } : {},
3285
+ ...approval.reason !== void 0 ? {
3286
+ reason: approval.reason
3287
+ } : {}
3288
+ }
3289
+ });
3290
+ }
3291
+ }
2759
3292
  for (const call of message.toolCalls ?? []) {
2760
3293
  const result = message.toolResults?.find((candidate) => candidate.id === call.id);
2761
3294
  const toolKind2 = call.kind;
@@ -2857,21 +3390,21 @@ function sumUsage(rows) {
2857
3390
  __name(sumUsage, "sumUsage");
2858
3391
 
2859
3392
  // src/use-agent-chat.ts
2860
- var import_react8 = require("@ai-sdk/react");
2861
- var import_react9 = require("react");
3393
+ var import_react10 = require("@ai-sdk/react");
3394
+ var import_react11 = require("react");
2862
3395
  function useAgentChat(options) {
2863
- const latest = (0, import_react9.useRef)(options);
3396
+ const latest = (0, import_react11.useRef)(options);
2864
3397
  latest.current = options;
2865
- const [runId, setRunId] = (0, import_react9.useState)(options.resumeRunId);
2866
- const runIdRef = (0, import_react9.useRef)(runId);
3398
+ const [runId, setRunId] = (0, import_react11.useState)(options.resumeRunId);
3399
+ const runIdRef = (0, import_react11.useRef)(runId);
2867
3400
  runIdRef.current = runId;
2868
- const settlingRunIdRef = (0, import_react9.useRef)(void 0);
2869
- const autoResumeRunIdRef = (0, import_react9.useRef)(void 0);
2870
- const [autoResume, setAutoResume] = (0, import_react9.useState)(false);
2871
- const [activeRunId, setActiveRunId] = (0, import_react9.useState)(null);
2872
- const regenerateNext = (0, import_react9.useRef)(false);
2873
- const createdThreadId = (0, import_react9.useRef)(void 0);
2874
- const client = (0, import_react9.useMemo)(() => {
3401
+ const settlingRunIdRef = (0, import_react11.useRef)(void 0);
3402
+ const autoResumeRunIdRef = (0, import_react11.useRef)(void 0);
3403
+ const [autoResume, setAutoResume] = (0, import_react11.useState)(false);
3404
+ const [activeRunId, setActiveRunId] = (0, import_react11.useState)(null);
3405
+ const regenerateNext = (0, import_react11.useRef)(false);
3406
+ const createdThreadId = (0, import_react11.useRef)(void 0);
3407
+ const client = (0, import_react11.useMemo)(() => {
2875
3408
  if (options.client) return options.client;
2876
3409
  return new AgentClient({
2877
3410
  ...options.baseUrl !== void 0 ? {
@@ -2886,7 +3419,7 @@ function useAgentChat(options) {
2886
3419
  getHeaders: /* @__PURE__ */ __name(async () => mergeHeaders(latest.current), "getHeaders")
2887
3420
  });
2888
3421
  }, []);
2889
- (0, import_react9.useEffect)(() => {
3422
+ (0, import_react11.useEffect)(() => {
2890
3423
  if (!options.resume || options.threadId === void 0) return;
2891
3424
  let cancelled = false;
2892
3425
  const threadId = options.threadId;
@@ -2906,7 +3439,7 @@ function useAgentChat(options) {
2906
3439
  options.resume,
2907
3440
  options.threadId
2908
3441
  ]);
2909
- const transport = (0, import_react9.useMemo)(() => {
3442
+ const transport = (0, import_react11.useMemo)(() => {
2910
3443
  function onMeta(meta) {
2911
3444
  settlingRunIdRef.current = meta.runId;
2912
3445
  setRunId(meta.runId);
@@ -2955,8 +3488,8 @@ function useAgentChat(options) {
2955
3488
  }, "onAttemptStart")
2956
3489
  });
2957
3490
  }, []);
2958
- const backgroundRef = (0, import_react9.useRef)(() => Promise.resolve());
2959
- const chat = (0, import_react8.useChat)({
3491
+ const backgroundRef = (0, import_react11.useRef)(() => Promise.resolve());
3492
+ const chat = (0, import_react10.useChat)({
2960
3493
  transport,
2961
3494
  resume: options.resumeRunId !== void 0 || autoResume,
2962
3495
  ...options.threadId !== void 0 ? {
@@ -2986,13 +3519,13 @@ function useAgentChat(options) {
2986
3519
  }
2987
3520
  }, "onFinish")
2988
3521
  });
2989
- const chatRef = (0, import_react9.useRef)(chat);
3522
+ const chatRef = (0, import_react11.useRef)(chat);
2990
3523
  chatRef.current = chat;
2991
- const turnInFlight = (0, import_react9.useRef)(false);
2992
- const isTurnInFlight = (0, import_react9.useCallback)(() => turnInFlight.current || transport.isAttemptLive, [
3524
+ const turnInFlight = (0, import_react11.useRef)(false);
3525
+ const isTurnInFlight = (0, import_react11.useCallback)(() => turnInFlight.current || transport.isAttemptLive, [
2993
3526
  transport
2994
3527
  ]);
2995
- const sendMessage = (0, import_react9.useCallback)(async (...args) => {
3528
+ const sendMessage = (0, import_react11.useCallback)(async (...args) => {
2996
3529
  if (isTurnInFlight()) return;
2997
3530
  turnInFlight.current = true;
2998
3531
  try {
@@ -3003,15 +3536,15 @@ function useAgentChat(options) {
3003
3536
  }, [
3004
3537
  isTurnInFlight
3005
3538
  ]);
3006
- const addToolResult = (0, import_react9.useCallback)(({ tool, toolCallId, output }) => chatRef.current.addToolResult({
3539
+ const addToolResult = (0, import_react11.useCallback)(({ tool, toolCallId, output }) => chatRef.current.addToolResult({
3007
3540
  tool,
3008
3541
  toolCallId,
3009
3542
  output
3010
3543
  }), []);
3011
- const [threads, setThreads] = (0, import_react9.useState)([]);
3012
- const [quota, setQuota] = (0, import_react9.useState)(null);
3013
- const [backgroundRuns, setBackgroundRuns] = (0, import_react9.useState)([]);
3014
- const refreshBackground = (0, import_react9.useCallback)(async () => {
3544
+ const [threads, setThreads] = (0, import_react11.useState)([]);
3545
+ const [quota, setQuota] = (0, import_react11.useState)(null);
3546
+ const [backgroundRuns, setBackgroundRuns] = (0, import_react11.useState)([]);
3547
+ const refreshBackground = (0, import_react11.useCallback)(async () => {
3015
3548
  const threadId = latest.current.threadId ?? createdThreadId.current;
3016
3549
  if (threadId === void 0) {
3017
3550
  return;
@@ -3036,7 +3569,7 @@ function useAgentChat(options) {
3036
3569
  ]);
3037
3570
  backgroundRef.current = refreshBackground;
3038
3571
  const isWorking = backgroundRuns.some((run) => run.status === "running");
3039
- (0, import_react9.useEffect)(() => {
3572
+ (0, import_react11.useEffect)(() => {
3040
3573
  if (options.background !== true || options.threadId === void 0) {
3041
3574
  return;
3042
3575
  }
@@ -3046,7 +3579,7 @@ function useAgentChat(options) {
3046
3579
  options.threadId,
3047
3580
  refreshBackground
3048
3581
  ]);
3049
- (0, import_react9.useEffect)(() => {
3582
+ (0, import_react11.useEffect)(() => {
3050
3583
  const every = latest.current.backgroundPollMs ?? 5e3;
3051
3584
  if (latest.current.background !== true || !isWorking || every <= 0) {
3052
3585
  return;
@@ -3057,26 +3590,26 @@ function useAgentChat(options) {
3057
3590
  isWorking,
3058
3591
  refreshBackground
3059
3592
  ]);
3060
- const loadThreads = (0, import_react9.useCallback)(async () => {
3593
+ const loadThreads = (0, import_react11.useCallback)(async () => {
3061
3594
  const list = await client.listThreads();
3062
3595
  setThreads(list);
3063
3596
  return list;
3064
3597
  }, [
3065
3598
  client
3066
3599
  ]);
3067
- const loadThread = (0, import_react9.useCallback)((id) => client.getThread(id), [
3600
+ const loadThread = (0, import_react11.useCallback)((id) => client.getThread(id), [
3068
3601
  client
3069
3602
  ]);
3070
- const deleteThread = (0, import_react9.useCallback)(async (id) => {
3603
+ const deleteThread = (0, import_react11.useCallback)(async (id) => {
3071
3604
  await client.deleteThread(id);
3072
3605
  setThreads((current) => current.filter((thread) => thread.id !== id));
3073
3606
  }, [
3074
3607
  client
3075
3608
  ]);
3076
- const forkThread = (0, import_react9.useCallback)((threadId, messageId) => client.forkFromMessage(threadId, messageId), [
3609
+ const forkThread = (0, import_react11.useCallback)((threadId, messageId) => client.forkFromMessage(threadId, messageId), [
3077
3610
  client
3078
3611
  ]);
3079
- const renameThread = (0, import_react9.useCallback)(async (id, title) => {
3612
+ const renameThread = (0, import_react11.useCallback)(async (id, title) => {
3080
3613
  await client.renameThread(id, title);
3081
3614
  setThreads((current) => current.map((thread) => thread.id === id ? {
3082
3615
  ...thread,
@@ -3085,24 +3618,24 @@ function useAgentChat(options) {
3085
3618
  }, [
3086
3619
  client
3087
3620
  ]);
3088
- const promoteThread = (0, import_react9.useCallback)(async (id) => {
3621
+ const promoteThread = (0, import_react11.useCallback)(async (id) => {
3089
3622
  await client.promoteThread(id);
3090
3623
  await loadThreads();
3091
3624
  }, [
3092
3625
  client,
3093
3626
  loadThreads
3094
3627
  ]);
3095
- const truncateFromMessage = (0, import_react9.useCallback)((threadId, messageId) => client.truncateFromMessage(threadId, messageId).then(() => void 0), [
3628
+ const truncateFromMessage = (0, import_react11.useCallback)((threadId, messageId) => client.truncateFromMessage(threadId, messageId).then(() => void 0), [
3096
3629
  client
3097
3630
  ]);
3098
- const loadQuota = (0, import_react9.useCallback)(async () => {
3631
+ const loadQuota = (0, import_react11.useCallback)(async () => {
3099
3632
  const today = await client.getQuotaToday();
3100
3633
  setQuota(today);
3101
3634
  return today;
3102
3635
  }, [
3103
3636
  client
3104
3637
  ]);
3105
- const cancel = (0, import_react9.useCallback)(async () => {
3638
+ const cancel = (0, import_react11.useCallback)(async () => {
3106
3639
  chatRef.current.stop();
3107
3640
  const activeRunId2 = runIdRef.current;
3108
3641
  if (activeRunId2) {
@@ -3114,24 +3647,33 @@ function useAgentChat(options) {
3114
3647
  }, [
3115
3648
  client
3116
3649
  ]);
3117
- const approve = (0, import_react9.useCallback)(async ({ toolCallId }) => {
3650
+ const approve = (0, import_react11.useCallback)(async ({ toolCallId, remember, via }) => {
3118
3651
  await client.approveToolCall({
3119
- toolCallId
3652
+ toolCallId,
3653
+ ...remember === true ? {
3654
+ remember: true
3655
+ } : {},
3656
+ ...via !== void 0 ? {
3657
+ via
3658
+ } : {}
3120
3659
  });
3121
3660
  }, [
3122
3661
  client
3123
3662
  ]);
3124
- const reject = (0, import_react9.useCallback)(async ({ toolCallId, reason }) => {
3663
+ const reject = (0, import_react11.useCallback)(async ({ toolCallId, reason, via }) => {
3125
3664
  await client.rejectToolCall({
3126
3665
  toolCallId,
3127
3666
  ...reason !== void 0 ? {
3128
3667
  reason
3668
+ } : {},
3669
+ ...via !== void 0 ? {
3670
+ via
3129
3671
  } : {}
3130
3672
  });
3131
3673
  }, [
3132
3674
  client
3133
3675
  ]);
3134
- const answer = (0, import_react9.useCallback)(async ({ toolCallId, answers }) => {
3676
+ const answer = (0, import_react11.useCallback)(async ({ toolCallId, answers }) => {
3135
3677
  await client.answerToolCall({
3136
3678
  toolCallId,
3137
3679
  ...answers !== void 0 ? {
@@ -3141,14 +3683,14 @@ function useAgentChat(options) {
3141
3683
  }, [
3142
3684
  client
3143
3685
  ]);
3144
- const skip = (0, import_react9.useCallback)(async ({ toolCallId }) => {
3686
+ const skip = (0, import_react11.useCallback)(async ({ toolCallId }) => {
3145
3687
  await client.skipToolCall({
3146
3688
  toolCallId
3147
3689
  });
3148
3690
  }, [
3149
3691
  client
3150
3692
  ]);
3151
- const regenerate = (0, import_react9.useCallback)(() => {
3693
+ const regenerate = (0, import_react11.useCallback)(() => {
3152
3694
  if (isTurnInFlight()) return;
3153
3695
  regenerateNext.current = true;
3154
3696
  turnInFlight.current = true;
@@ -3212,27 +3754,41 @@ __name(mergeHeaders, "mergeHeaders");
3212
3754
  MessageList,
3213
3755
  SPEECH_LANGUAGES,
3214
3756
  applyCompletion,
3757
+ approvalCountdown,
3215
3758
  backgroundRunsFromThread,
3216
3759
  buildTranscriptBlocks,
3760
+ correctedCallIds,
3217
3761
  createSkillsSource,
3218
3762
  describeTimestamp,
3763
+ describeToolCall,
3219
3764
  describeUsage,
3220
3765
  extractMessageText,
3766
+ fillTemplate,
3221
3767
  filterAutocompleteItems,
3222
3768
  findActiveTrigger,
3223
3769
  formatElapsed,
3224
3770
  formatRelativeTime,
3771
+ groupToolActivity,
3772
+ inferResultView,
3773
+ isActionCall,
3225
3774
  loadStoredSpeechLang,
3226
3775
  persistSpeechLang,
3776
+ phraseFor,
3777
+ readPath,
3227
3778
  readReasoningMs,
3779
+ resolveResultView,
3228
3780
  storedMessageToUiMessage,
3229
3781
  storedThreadToUiMessages,
3782
+ toolCallState,
3783
+ toolCatalogFrom,
3230
3784
  useAgentChat,
3785
+ useApprovalCountdown,
3231
3786
  useChatTranscript,
3232
3787
  useComposerAutocomplete,
3233
3788
  useElapsed,
3234
3789
  useSpeechRecognition,
3235
3790
  useStickToBottom,
3791
+ useToolCatalog,
3236
3792
  useTranscriptItem
3237
3793
  });
3238
3794
  //# sourceMappingURL=index.cjs.map