@dudousxd/nestjs-agent-react 0.9.0 → 0.10.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.js CHANGED
@@ -679,6 +679,15 @@ var AgentClient = class {
679
679
  const query = threadId === void 0 ? "" : `?threadId=${encodeURIComponent(threadId)}`;
680
680
  return this.request("GET", `/agent/skills${query}`);
681
681
  }
682
+ /**
683
+ * The tools this caller can reach through `agent` (the default agent when omitted), each with the
684
+ * server-declared `presentation` a chat narrates it by — the same list the model is offered.
685
+ * Prefer {@link useToolCatalog}, which fetches it once and shares it.
686
+ */
687
+ listTools(agent) {
688
+ const query = agent === void 0 ? "" : `?agent=${encodeURIComponent(agent)}`;
689
+ return this.request("GET", `/agent/tools${query}`);
690
+ }
682
691
  getThread(id) {
683
692
  return this.request("GET", `/agent/threads/${encodeURIComponent(id)}`);
684
693
  }
@@ -961,7 +970,280 @@ import React3 from "react";
961
970
  import { useCallback as useCallback3, useEffect as useEffect5, useRef as useRef4, useState as useState5 } from "react";
962
971
 
963
972
  // src/transcript/model.ts
964
- import { getToolName, isDataUIPart, isFileUIPart, isReasoningUIPart, isTextUIPart, isToolUIPart } from "ai";
973
+ import { getToolName as getToolName2, isDataUIPart, isFileUIPart, isReasoningUIPart, isTextUIPart, isToolUIPart } from "ai";
974
+
975
+ // src/presentation/tool-activity.ts
976
+ import { getToolName } from "ai";
977
+
978
+ // src/presentation/phrasing.ts
979
+ function toolCatalogFrom(entries) {
980
+ const catalog = {};
981
+ for (const entry of entries) {
982
+ if (entry.presentation !== void 0) catalog[entry.name] = entry.presentation;
983
+ }
984
+ return catalog;
985
+ }
986
+ __name(toolCatalogFrom, "toolCatalogFrom");
987
+ function readPath(value, path) {
988
+ return path.split(".").reduce((current, key) => {
989
+ if (current === null || typeof current !== "object") return void 0;
990
+ return current[key];
991
+ }, value);
992
+ }
993
+ __name(readPath, "readPath");
994
+ function renderValue(value) {
995
+ if (value === null || value === void 0) return "";
996
+ if (typeof value === "string") return value;
997
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
998
+ if (Array.isArray(value)) return value.map(renderValue).filter(Boolean).join(", ");
999
+ return "";
1000
+ }
1001
+ __name(renderValue, "renderValue");
1002
+ function fillTemplate(template, context) {
1003
+ return template.replace(/(\s*)\{([\w.]+)\}/g, (_match, space, path) => {
1004
+ const rendered = renderValue(readPath(context, path));
1005
+ return rendered === "" ? "" : `${space}${rendered}`;
1006
+ }).replace(/\s{2,}/g, " ").trim();
1007
+ }
1008
+ __name(fillTemplate, "fillTemplate");
1009
+ function phraseFor(presentation, input, isSettled2, fallback = {
1010
+ running: "Working",
1011
+ done: "Done"
1012
+ }) {
1013
+ if (presentation === void 0) return isSettled2 ? fallback.done : fallback.running;
1014
+ const filled = fillTemplate(isSettled2 ? presentation.done : presentation.running, input);
1015
+ return filled === "" ? presentation.label : filled;
1016
+ }
1017
+ __name(phraseFor, "phraseFor");
1018
+
1019
+ // src/presentation/result-view.ts
1020
+ function isRecord(value) {
1021
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1022
+ }
1023
+ __name(isRecord, "isRecord");
1024
+ function toText(value) {
1025
+ if (value === null || value === void 0) return "\u2014";
1026
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
1027
+ return String(value);
1028
+ }
1029
+ if (Array.isArray(value)) return value.map(toText).join(", ");
1030
+ return "\u2014";
1031
+ }
1032
+ __name(toText, "toText");
1033
+ function inferResultView(output) {
1034
+ if (!isRecord(output)) return void 0;
1035
+ for (const [key, value] of Object.entries(output)) {
1036
+ if (!Array.isArray(value) || value.length === 0) continue;
1037
+ if (value.every((entry) => typeof entry === "string")) {
1038
+ return {
1039
+ kind: "log",
1040
+ lines: key
1041
+ };
1042
+ }
1043
+ if (value.every(isRecord)) {
1044
+ const first = value[0];
1045
+ return {
1046
+ kind: "table",
1047
+ rows: key,
1048
+ columns: Object.keys(first).filter((column) => !isRecord(first[column])).map((column) => ({
1049
+ path: column,
1050
+ label: column
1051
+ }))
1052
+ };
1053
+ }
1054
+ }
1055
+ const fields = Object.entries(output).filter(([, value]) => [
1056
+ "string",
1057
+ "number",
1058
+ "boolean"
1059
+ ].includes(typeof value)).map(([key]) => ({
1060
+ path: key,
1061
+ label: key
1062
+ }));
1063
+ return fields.length > 0 ? {
1064
+ kind: "metrics",
1065
+ fields
1066
+ } : void 0;
1067
+ }
1068
+ __name(inferResultView, "inferResultView");
1069
+ function resolveResultView(output, view, options = {}) {
1070
+ const resolved = view ?? (options.infer === true ? inferResultView(output) : void 0);
1071
+ if (resolved === void 0 || resolved.kind === "elsewhere") return null;
1072
+ switch (resolved.kind) {
1073
+ case "note": {
1074
+ const text = fillTemplate(resolved.text, output);
1075
+ return text === "" ? null : {
1076
+ kind: "note",
1077
+ text
1078
+ };
1079
+ }
1080
+ case "metrics": {
1081
+ const readings = resolved.fields.map((field) => ({
1082
+ field,
1083
+ value: readPath(output, field.path)
1084
+ })).filter((entry) => entry.value !== void 0 && entry.value !== null).map(({ field, value }) => ({
1085
+ label: field.label,
1086
+ value: toText(value),
1087
+ unit: field.unit ?? null
1088
+ }));
1089
+ return readings.length === 0 ? null : {
1090
+ kind: "metrics",
1091
+ readings
1092
+ };
1093
+ }
1094
+ case "log": {
1095
+ const lines = readPath(output, resolved.lines);
1096
+ if (!Array.isArray(lines) || lines.length === 0) return null;
1097
+ return {
1098
+ kind: "log",
1099
+ lines: lines.map(toText)
1100
+ };
1101
+ }
1102
+ case "table": {
1103
+ const rows = readPath(output, resolved.rows);
1104
+ if (!Array.isArray(rows)) return null;
1105
+ return {
1106
+ kind: "table",
1107
+ columns: resolved.columns,
1108
+ rows: rows.map((row) => resolved.columns.map((column) => toText(readPath(row, column.path)))),
1109
+ empty: rows.length === 0 ? resolved.empty ?? null : null
1110
+ };
1111
+ }
1112
+ }
1113
+ }
1114
+ __name(resolveResultView, "resolveResultView");
1115
+
1116
+ // src/presentation/tool-activity.ts
1117
+ function isActionCall(part) {
1118
+ const metadata = part.toolMetadata;
1119
+ return typeof metadata === "object" && metadata !== null && metadata.toolKind === "action";
1120
+ }
1121
+ __name(isActionCall, "isActionCall");
1122
+ function toolCallState(part) {
1123
+ const output = "output" in part ? part.output : void 0;
1124
+ const errorText = "errorText" in part ? part.errorText : void 0;
1125
+ const outputError = output !== null && typeof output === "object" && "error" in output ? String(output.error) : void 0;
1126
+ const isDenied = part.state === "output-denied";
1127
+ const isFailed = part.state === "output-error" || outputError !== void 0 && !isDenied;
1128
+ const isSettled2 = part.state === "output-available" || part.state === "output-error" || isDenied;
1129
+ const isAwaiting = part.state === "approval-requested" || part.state === "input-available" && isActionCall(part);
1130
+ const status = isDenied ? "denied" : isFailed ? "failed" : isSettled2 ? "done" : isAwaiting ? "awaiting-approval" : "running";
1131
+ return {
1132
+ status,
1133
+ isSettled: isSettled2,
1134
+ isFailed,
1135
+ isDenied,
1136
+ output,
1137
+ error: errorText ?? outputError ?? null
1138
+ };
1139
+ }
1140
+ __name(toolCallState, "toolCallState");
1141
+ function correctedCallIds(parts) {
1142
+ const corrected = /* @__PURE__ */ new Set();
1143
+ const lastSuccessByTool = /* @__PURE__ */ new Map();
1144
+ parts.forEach((part, index) => {
1145
+ if (part.state === "output-available" && !toolCallState(part).isFailed) {
1146
+ lastSuccessByTool.set(getToolName(part), index);
1147
+ }
1148
+ });
1149
+ parts.forEach((part, index) => {
1150
+ const successAt = lastSuccessByTool.get(getToolName(part));
1151
+ if (successAt !== void 0 && index < successAt && toolCallState(part).isFailed) {
1152
+ corrected.add(part.toolCallId);
1153
+ }
1154
+ });
1155
+ return corrected;
1156
+ }
1157
+ __name(correctedCallIds, "correctedCallIds");
1158
+ function describeToolCall(part, catalog, options = {}) {
1159
+ const presentation = catalog?.[getToolName(part)];
1160
+ const state = toolCallState(part);
1161
+ const input = part.input;
1162
+ const confirm = presentation?.confirm;
1163
+ return {
1164
+ status: state.status,
1165
+ phrase: phraseFor(presentation, input, state.isSettled, options.fallback),
1166
+ label: presentation?.label ?? null,
1167
+ icon: presentation?.icon ?? null,
1168
+ tone: presentation?.tone ?? "neutral",
1169
+ detail: presentation?.detail ?? null,
1170
+ confirm: confirm === void 0 ? null : {
1171
+ title: fillTemplate(confirm.title, input),
1172
+ verb: confirm.verb,
1173
+ detail: confirm.detail !== void 0 ? fillTemplate(confirm.detail, input) : null
1174
+ },
1175
+ result: state.status === "done" ? resolveResultView(state.output, presentation?.result, {
1176
+ ...options.inferResult !== void 0 ? {
1177
+ infer: options.inferResult
1178
+ } : {}
1179
+ }) : null,
1180
+ error: state.error,
1181
+ presentation: presentation ?? null
1182
+ };
1183
+ }
1184
+ __name(describeToolCall, "describeToolCall");
1185
+ var STATUS_WEIGHT = {
1186
+ running: 4,
1187
+ "awaiting-approval": 3,
1188
+ failed: 2,
1189
+ denied: 1,
1190
+ done: 0
1191
+ };
1192
+ function descendants(call) {
1193
+ return call.children.flatMap((child) => [
1194
+ child,
1195
+ ...descendants(child)
1196
+ ]);
1197
+ }
1198
+ __name(descendants, "descendants");
1199
+ function leaves(call) {
1200
+ return call.children.length === 0 ? [
1201
+ call
1202
+ ] : call.children.flatMap(leaves);
1203
+ }
1204
+ __name(leaves, "leaves");
1205
+ function groupToolActivity(calls, options = {}) {
1206
+ const expanded = options.expandNested === true ? calls.flatMap(leaves) : [
1207
+ ...calls
1208
+ ];
1209
+ const corrected = options.hideCorrected === true ? correctedCallIds(expanded.map((call) => call.part)) : /* @__PURE__ */ new Set();
1210
+ const groups = /* @__PURE__ */ new Map();
1211
+ for (const call of expanded) {
1212
+ if (corrected.has(call.toolCallId)) continue;
1213
+ const presentation = options.catalog?.[call.name];
1214
+ const key = options.keyOf?.(call, presentation) ?? presentation?.label ?? call.name;
1215
+ const status = toolCallState(call.part).status;
1216
+ const phrase = phraseFor(presentation, call.part.input, status !== "running" && status !== "awaiting-approval", options.fallback);
1217
+ const inner = options.expandNested === true ? 0 : descendants(call).length;
1218
+ const existing = groups.get(key);
1219
+ if (existing === void 0) {
1220
+ groups.set(key, {
1221
+ key,
1222
+ label: presentation?.label ?? null,
1223
+ icon: presentation?.icon ?? null,
1224
+ status,
1225
+ count: 1,
1226
+ phrase,
1227
+ calls: [
1228
+ call
1229
+ ],
1230
+ innerCount: inner
1231
+ });
1232
+ continue;
1233
+ }
1234
+ existing.count += 1;
1235
+ existing.calls.push(call);
1236
+ existing.phrase = phrase;
1237
+ existing.innerCount += inner;
1238
+ if (STATUS_WEIGHT[status] > STATUS_WEIGHT[existing.status]) existing.status = status;
1239
+ }
1240
+ return [
1241
+ ...groups.values()
1242
+ ];
1243
+ }
1244
+ __name(groupToolActivity, "groupToolActivity");
1245
+
1246
+ // src/transcript/model.ts
965
1247
  function buildTranscriptBlocks(message, options) {
966
1248
  const blocks = [];
967
1249
  let toolBuffer = [];
@@ -978,13 +1260,19 @@ function buildTranscriptBlocks(message, options) {
978
1260
  if (toolBuffer.length === 0) {
979
1261
  return;
980
1262
  }
981
- const calls = toolBuffer.map((part) => buildToolCall(part, options.approval, approvals.get(part.toolCallId) ?? null));
1263
+ const calls = toolBuffer.map((part) => buildToolCall(part, options.approval, approvals.get(part.toolCallId) ?? null, options.toolCatalog));
1264
+ const roots = nestToolCalls(calls);
982
1265
  blocks.push({
983
1266
  kind: "tools",
984
1267
  key: `${message.id}-tools-${toolCounter++}`,
985
1268
  parts: toolBuffer,
986
1269
  calls,
987
- roots: nestToolCalls(calls)
1270
+ roots,
1271
+ activity: groupToolActivity(roots, {
1272
+ ...options.toolCatalog !== void 0 ? {
1273
+ catalog: options.toolCatalog
1274
+ } : {}
1275
+ })
988
1276
  });
989
1277
  toolBuffer = [];
990
1278
  }
@@ -1133,7 +1421,7 @@ function isSettled(state) {
1133
1421
  __name(isSettled, "isSettled");
1134
1422
  function toolKind(part) {
1135
1423
  const metadata = part.toolMetadata;
1136
- return isRecord(metadata) && typeof metadata.toolKind === "string" ? metadata.toolKind : void 0;
1424
+ return isRecord2(metadata) && typeof metadata.toolKind === "string" ? metadata.toolKind : void 0;
1137
1425
  }
1138
1426
  __name(toolKind, "toolKind");
1139
1427
  function isAwaitingApproval(part) {
@@ -1148,7 +1436,7 @@ function isAwaitingApproval(part) {
1148
1436
  __name(isAwaitingApproval, "isAwaitingApproval");
1149
1437
  function toolParentId(part) {
1150
1438
  const metadata = part.toolMetadata;
1151
- return isRecord(metadata) && typeof metadata.parentId === "string" ? metadata.parentId : null;
1439
+ return isRecord2(metadata) && typeof metadata.parentId === "string" ? metadata.parentId : null;
1152
1440
  }
1153
1441
  __name(toolParentId, "toolParentId");
1154
1442
  function nestToolCalls(calls) {
@@ -1181,18 +1469,19 @@ function isAncestor(call, candidate, byId) {
1181
1469
  return false;
1182
1470
  }
1183
1471
  __name(isAncestor, "isAncestor");
1184
- function buildToolCall(part, options, approval) {
1472
+ function buildToolCall(part, options, approval, catalog) {
1185
1473
  const toolCallId = part.toolCallId;
1186
1474
  const awaiting = isAwaitingApproval(part);
1187
1475
  const sending = awaiting ? options?.submitting(toolCallId) ?? null : null;
1188
1476
  return {
1189
1477
  part,
1190
1478
  toolCallId,
1191
- name: getToolName(part),
1479
+ name: getToolName2(part),
1192
1480
  toolKind: toolKind(part) ?? null,
1193
1481
  parentId: toolParentId(part),
1194
1482
  children: [],
1195
1483
  approval,
1484
+ description: describeToolCall(part, catalog),
1196
1485
  isAwaitingApproval: awaiting,
1197
1486
  approve: {
1198
1487
  available: awaiting && options?.canApprove === true,
@@ -1210,17 +1499,17 @@ function buildToolCall(part, options, approval) {
1210
1499
  __name(buildToolCall, "buildToolCall");
1211
1500
  function readElicitationRequest(part) {
1212
1501
  const input = part.input;
1213
- if (!isRecord(input) || !Array.isArray(input.questions) || input.questions.length === 0) {
1502
+ if (!isRecord2(input) || !Array.isArray(input.questions) || input.questions.length === 0) {
1214
1503
  return null;
1215
1504
  }
1216
1505
  const questions = [];
1217
1506
  for (const candidate of input.questions) {
1218
- if (!isRecord(candidate) || typeof candidate.id !== "string" || typeof candidate.prompt !== "string" || !Array.isArray(candidate.options) || candidate.options.length === 0) {
1507
+ if (!isRecord2(candidate) || typeof candidate.id !== "string" || typeof candidate.prompt !== "string" || !Array.isArray(candidate.options) || candidate.options.length === 0) {
1219
1508
  return null;
1220
1509
  }
1221
1510
  const options = [];
1222
1511
  for (const option of candidate.options) {
1223
- if (!isRecord(option) || typeof option.value !== "string" || typeof option.label !== "string") {
1512
+ if (!isRecord2(option) || typeof option.value !== "string" || typeof option.label !== "string") {
1224
1513
  return null;
1225
1514
  }
1226
1515
  options.push({
@@ -1245,7 +1534,7 @@ function readElicitationRequest(part) {
1245
1534
  __name(readElicitationRequest, "readElicitationRequest");
1246
1535
  function readElicitationOutcome(part) {
1247
1536
  const output = part.output;
1248
- if (!isRecord(output) || !isRecord(output.answers) || typeof output.skipped !== "boolean") {
1537
+ if (!isRecord2(output) || !isRecord2(output.answers) || typeof output.skipped !== "boolean") {
1249
1538
  return null;
1250
1539
  }
1251
1540
  const answers = {};
@@ -1332,7 +1621,7 @@ function readApprovals(parts) {
1332
1621
  continue;
1333
1622
  }
1334
1623
  const data = part.data;
1335
- if (!isRecord(data) || typeof data.id !== "string" || typeof data.approver !== "string") {
1624
+ if (!isRecord2(data) || typeof data.id !== "string" || typeof data.approver !== "string") {
1336
1625
  continue;
1337
1626
  }
1338
1627
  out.set(data.id, {
@@ -1346,7 +1635,7 @@ function readApprovals(parts) {
1346
1635
  __name(readApprovals, "readApprovals");
1347
1636
  function readUiComponent(part) {
1348
1637
  const data = part.data;
1349
- if (!isRecord(data) || typeof data.component !== "string") {
1638
+ if (!isRecord2(data) || typeof data.component !== "string") {
1350
1639
  return null;
1351
1640
  }
1352
1641
  const id = typeof data.id === "string" ? data.id : part.id;
@@ -1356,18 +1645,18 @@ function readUiComponent(part) {
1356
1645
  return {
1357
1646
  id,
1358
1647
  component: data.component,
1359
- props: isRecord(data.props) ? data.props : {},
1648
+ props: isRecord2(data.props) ? data.props : {},
1360
1649
  version: typeof data.version === "number" ? data.version : null
1361
1650
  };
1362
1651
  }
1363
1652
  __name(readUiComponent, "readUiComponent");
1364
- function isRecord(value) {
1653
+ function isRecord2(value) {
1365
1654
  return typeof value === "object" && value !== null;
1366
1655
  }
1367
- __name(isRecord, "isRecord");
1656
+ __name(isRecord2, "isRecord");
1368
1657
  function readQuery(part) {
1369
1658
  const input = part.input;
1370
- if (!isRecord(input) || typeof input.query !== "string") {
1659
+ if (!isRecord2(input) || typeof input.query !== "string") {
1371
1660
  return null;
1372
1661
  }
1373
1662
  return input.query;
@@ -1375,12 +1664,12 @@ function readQuery(part) {
1375
1664
  __name(readQuery, "readQuery");
1376
1665
  function readPassages(part) {
1377
1666
  const output = part.output;
1378
- if (!isRecord(output) || !Array.isArray(output.passages) || output.passages.length === 0) {
1667
+ if (!isRecord2(output) || !Array.isArray(output.passages) || output.passages.length === 0) {
1379
1668
  return null;
1380
1669
  }
1381
1670
  const passages = [];
1382
1671
  for (const candidate of output.passages) {
1383
- if (!isRecord(candidate) || typeof candidate.id !== "string" || typeof candidate.text !== "string") {
1672
+ if (!isRecord2(candidate) || typeof candidate.id !== "string" || typeof candidate.text !== "string") {
1384
1673
  return null;
1385
1674
  }
1386
1675
  passages.push({
@@ -1390,7 +1679,7 @@ function readPassages(part) {
1390
1679
  ...typeof candidate.source === "string" ? {
1391
1680
  source: candidate.source
1392
1681
  } : {},
1393
- ...isRecord(candidate.metadata) ? {
1682
+ ...isRecord2(candidate.metadata) ? {
1394
1683
  metadata: candidate.metadata
1395
1684
  } : {}
1396
1685
  });
@@ -1857,6 +2146,9 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
1857
2146
  ...options.sources !== void 0 ? {
1858
2147
  sources: options.sources
1859
2148
  } : {},
2149
+ ...options.toolCatalog !== void 0 ? {
2150
+ toolCatalog: options.toolCatalog
2151
+ } : {},
1860
2152
  ...options.onAnswer !== void 0 ? {
1861
2153
  elicitation: {
1862
2154
  picked: /* @__PURE__ */ __name((toolCallId, questionId) => picks.get(pickKey(toolCallId, questionId)), "picked"),
@@ -2632,6 +2924,78 @@ function isPromise(value) {
2632
2924
  }
2633
2925
  __name(isPromise, "isPromise");
2634
2926
 
2927
+ // src/presentation/use-tool-catalog.ts
2928
+ import { useCallback as useCallback5, useEffect as useEffect7, useMemo as useMemo3, useState as useState7 } from "react";
2929
+ var shared = /* @__PURE__ */ new WeakMap();
2930
+ function load(client, agent) {
2931
+ let byAgent = shared.get(client);
2932
+ if (byAgent === void 0) {
2933
+ byAgent = /* @__PURE__ */ new Map();
2934
+ shared.set(client, byAgent);
2935
+ }
2936
+ const key = agent ?? "";
2937
+ const cached = byAgent.get(key);
2938
+ if (cached !== void 0) return cached;
2939
+ const request = client.listTools(agent).catch((error) => {
2940
+ byAgent.delete(key);
2941
+ throw error;
2942
+ });
2943
+ byAgent.set(key, request);
2944
+ return request;
2945
+ }
2946
+ __name(load, "load");
2947
+ function useToolCatalog(options) {
2948
+ const { client, agent, enabled = true } = options;
2949
+ const [entries, setEntries] = useState7([]);
2950
+ const [isLoading, setLoading] = useState7(enabled);
2951
+ const [error, setError] = useState7(null);
2952
+ const [generation, setGeneration] = useState7(0);
2953
+ useEffect7(() => {
2954
+ if (!enabled) {
2955
+ setLoading(false);
2956
+ return;
2957
+ }
2958
+ let cancelled = false;
2959
+ setLoading(true);
2960
+ load(client, agent).then((loaded) => {
2961
+ if (cancelled) return;
2962
+ setEntries(loaded);
2963
+ setError(null);
2964
+ setLoading(false);
2965
+ }, (failure) => {
2966
+ if (cancelled) return;
2967
+ setError(failure instanceof Error ? failure : new Error(String(failure)));
2968
+ setLoading(false);
2969
+ });
2970
+ return () => {
2971
+ cancelled = true;
2972
+ };
2973
+ }, [
2974
+ client,
2975
+ agent,
2976
+ enabled,
2977
+ generation
2978
+ ]);
2979
+ const refresh = useCallback5(() => {
2980
+ shared.get(client)?.delete(agent ?? "");
2981
+ setGeneration((current) => current + 1);
2982
+ }, [
2983
+ client,
2984
+ agent
2985
+ ]);
2986
+ const catalog = useMemo3(() => toolCatalogFrom(entries), [
2987
+ entries
2988
+ ]);
2989
+ return {
2990
+ catalog,
2991
+ entries,
2992
+ isLoading,
2993
+ error,
2994
+ refresh
2995
+ };
2996
+ }
2997
+ __name(useToolCatalog, "useToolCatalog");
2998
+
2635
2999
  // src/stored-message-to-ui-message.ts
2636
3000
  import { DEFAULT_REFUSAL_REASON } from "@dudousxd/nestjs-agent-core";
2637
3001
  function isRefusal(result) {
@@ -2793,20 +3157,20 @@ __name(sumUsage, "sumUsage");
2793
3157
 
2794
3158
  // src/use-agent-chat.ts
2795
3159
  import { useChat } from "@ai-sdk/react";
2796
- import { useCallback as useCallback5, useEffect as useEffect7, useMemo as useMemo3, useRef as useRef6, useState as useState7 } from "react";
3160
+ import { useCallback as useCallback6, useEffect as useEffect8, useMemo as useMemo4, useRef as useRef6, useState as useState8 } from "react";
2797
3161
  function useAgentChat(options) {
2798
3162
  const latest = useRef6(options);
2799
3163
  latest.current = options;
2800
- const [runId, setRunId] = useState7(options.resumeRunId);
3164
+ const [runId, setRunId] = useState8(options.resumeRunId);
2801
3165
  const runIdRef = useRef6(runId);
2802
3166
  runIdRef.current = runId;
2803
3167
  const settlingRunIdRef = useRef6(void 0);
2804
3168
  const autoResumeRunIdRef = useRef6(void 0);
2805
- const [autoResume, setAutoResume] = useState7(false);
2806
- const [activeRunId, setActiveRunId] = useState7(null);
3169
+ const [autoResume, setAutoResume] = useState8(false);
3170
+ const [activeRunId, setActiveRunId] = useState8(null);
2807
3171
  const regenerateNext = useRef6(false);
2808
3172
  const createdThreadId = useRef6(void 0);
2809
- const client = useMemo3(() => {
3173
+ const client = useMemo4(() => {
2810
3174
  if (options.client) return options.client;
2811
3175
  return new AgentClient({
2812
3176
  ...options.baseUrl !== void 0 ? {
@@ -2821,7 +3185,7 @@ function useAgentChat(options) {
2821
3185
  getHeaders: /* @__PURE__ */ __name(async () => mergeHeaders(latest.current), "getHeaders")
2822
3186
  });
2823
3187
  }, []);
2824
- useEffect7(() => {
3188
+ useEffect8(() => {
2825
3189
  if (!options.resume || options.threadId === void 0) return;
2826
3190
  let cancelled = false;
2827
3191
  const threadId = options.threadId;
@@ -2841,7 +3205,7 @@ function useAgentChat(options) {
2841
3205
  options.resume,
2842
3206
  options.threadId
2843
3207
  ]);
2844
- const transport = useMemo3(() => {
3208
+ const transport = useMemo4(() => {
2845
3209
  function onMeta(meta) {
2846
3210
  settlingRunIdRef.current = meta.runId;
2847
3211
  setRunId(meta.runId);
@@ -2924,10 +3288,10 @@ function useAgentChat(options) {
2924
3288
  const chatRef = useRef6(chat);
2925
3289
  chatRef.current = chat;
2926
3290
  const turnInFlight = useRef6(false);
2927
- const isTurnInFlight = useCallback5(() => turnInFlight.current || transport.isAttemptLive, [
3291
+ const isTurnInFlight = useCallback6(() => turnInFlight.current || transport.isAttemptLive, [
2928
3292
  transport
2929
3293
  ]);
2930
- const sendMessage = useCallback5(async (...args) => {
3294
+ const sendMessage = useCallback6(async (...args) => {
2931
3295
  if (isTurnInFlight()) return;
2932
3296
  turnInFlight.current = true;
2933
3297
  try {
@@ -2938,15 +3302,15 @@ function useAgentChat(options) {
2938
3302
  }, [
2939
3303
  isTurnInFlight
2940
3304
  ]);
2941
- const addToolResult = useCallback5(({ tool, toolCallId, output }) => chatRef.current.addToolResult({
3305
+ const addToolResult = useCallback6(({ tool, toolCallId, output }) => chatRef.current.addToolResult({
2942
3306
  tool,
2943
3307
  toolCallId,
2944
3308
  output
2945
3309
  }), []);
2946
- const [threads, setThreads] = useState7([]);
2947
- const [quota, setQuota] = useState7(null);
2948
- const [backgroundRuns, setBackgroundRuns] = useState7([]);
2949
- const refreshBackground = useCallback5(async () => {
3310
+ const [threads, setThreads] = useState8([]);
3311
+ const [quota, setQuota] = useState8(null);
3312
+ const [backgroundRuns, setBackgroundRuns] = useState8([]);
3313
+ const refreshBackground = useCallback6(async () => {
2950
3314
  const threadId = latest.current.threadId ?? createdThreadId.current;
2951
3315
  if (threadId === void 0) {
2952
3316
  return;
@@ -2971,7 +3335,7 @@ function useAgentChat(options) {
2971
3335
  ]);
2972
3336
  backgroundRef.current = refreshBackground;
2973
3337
  const isWorking = backgroundRuns.some((run) => run.status === "running");
2974
- useEffect7(() => {
3338
+ useEffect8(() => {
2975
3339
  if (options.background !== true || options.threadId === void 0) {
2976
3340
  return;
2977
3341
  }
@@ -2981,7 +3345,7 @@ function useAgentChat(options) {
2981
3345
  options.threadId,
2982
3346
  refreshBackground
2983
3347
  ]);
2984
- useEffect7(() => {
3348
+ useEffect8(() => {
2985
3349
  const every = latest.current.backgroundPollMs ?? 5e3;
2986
3350
  if (latest.current.background !== true || !isWorking || every <= 0) {
2987
3351
  return;
@@ -2992,26 +3356,26 @@ function useAgentChat(options) {
2992
3356
  isWorking,
2993
3357
  refreshBackground
2994
3358
  ]);
2995
- const loadThreads = useCallback5(async () => {
3359
+ const loadThreads = useCallback6(async () => {
2996
3360
  const list = await client.listThreads();
2997
3361
  setThreads(list);
2998
3362
  return list;
2999
3363
  }, [
3000
3364
  client
3001
3365
  ]);
3002
- const loadThread = useCallback5((id) => client.getThread(id), [
3366
+ const loadThread = useCallback6((id) => client.getThread(id), [
3003
3367
  client
3004
3368
  ]);
3005
- const deleteThread = useCallback5(async (id) => {
3369
+ const deleteThread = useCallback6(async (id) => {
3006
3370
  await client.deleteThread(id);
3007
3371
  setThreads((current) => current.filter((thread) => thread.id !== id));
3008
3372
  }, [
3009
3373
  client
3010
3374
  ]);
3011
- const forkThread = useCallback5((threadId, messageId) => client.forkFromMessage(threadId, messageId), [
3375
+ const forkThread = useCallback6((threadId, messageId) => client.forkFromMessage(threadId, messageId), [
3012
3376
  client
3013
3377
  ]);
3014
- const renameThread = useCallback5(async (id, title) => {
3378
+ const renameThread = useCallback6(async (id, title) => {
3015
3379
  await client.renameThread(id, title);
3016
3380
  setThreads((current) => current.map((thread) => thread.id === id ? {
3017
3381
  ...thread,
@@ -3020,24 +3384,24 @@ function useAgentChat(options) {
3020
3384
  }, [
3021
3385
  client
3022
3386
  ]);
3023
- const promoteThread = useCallback5(async (id) => {
3387
+ const promoteThread = useCallback6(async (id) => {
3024
3388
  await client.promoteThread(id);
3025
3389
  await loadThreads();
3026
3390
  }, [
3027
3391
  client,
3028
3392
  loadThreads
3029
3393
  ]);
3030
- const truncateFromMessage = useCallback5((threadId, messageId) => client.truncateFromMessage(threadId, messageId).then(() => void 0), [
3394
+ const truncateFromMessage = useCallback6((threadId, messageId) => client.truncateFromMessage(threadId, messageId).then(() => void 0), [
3031
3395
  client
3032
3396
  ]);
3033
- const loadQuota = useCallback5(async () => {
3397
+ const loadQuota = useCallback6(async () => {
3034
3398
  const today = await client.getQuotaToday();
3035
3399
  setQuota(today);
3036
3400
  return today;
3037
3401
  }, [
3038
3402
  client
3039
3403
  ]);
3040
- const cancel = useCallback5(async () => {
3404
+ const cancel = useCallback6(async () => {
3041
3405
  chatRef.current.stop();
3042
3406
  const activeRunId2 = runIdRef.current;
3043
3407
  if (activeRunId2) {
@@ -3049,14 +3413,14 @@ function useAgentChat(options) {
3049
3413
  }, [
3050
3414
  client
3051
3415
  ]);
3052
- const approve = useCallback5(async ({ toolCallId }) => {
3416
+ const approve = useCallback6(async ({ toolCallId }) => {
3053
3417
  await client.approveToolCall({
3054
3418
  toolCallId
3055
3419
  });
3056
3420
  }, [
3057
3421
  client
3058
3422
  ]);
3059
- const reject = useCallback5(async ({ toolCallId, reason }) => {
3423
+ const reject = useCallback6(async ({ toolCallId, reason }) => {
3060
3424
  await client.rejectToolCall({
3061
3425
  toolCallId,
3062
3426
  ...reason !== void 0 ? {
@@ -3066,7 +3430,7 @@ function useAgentChat(options) {
3066
3430
  }, [
3067
3431
  client
3068
3432
  ]);
3069
- const answer = useCallback5(async ({ toolCallId, answers }) => {
3433
+ const answer = useCallback6(async ({ toolCallId, answers }) => {
3070
3434
  await client.answerToolCall({
3071
3435
  toolCallId,
3072
3436
  ...answers !== void 0 ? {
@@ -3076,14 +3440,14 @@ function useAgentChat(options) {
3076
3440
  }, [
3077
3441
  client
3078
3442
  ]);
3079
- const skip = useCallback5(async ({ toolCallId }) => {
3443
+ const skip = useCallback6(async ({ toolCallId }) => {
3080
3444
  await client.skipToolCall({
3081
3445
  toolCallId
3082
3446
  });
3083
3447
  }, [
3084
3448
  client
3085
3449
  ]);
3086
- const regenerate = useCallback5(() => {
3450
+ const regenerate = useCallback6(() => {
3087
3451
  if (isTurnInFlight()) return;
3088
3452
  regenerateNext.current = true;
3089
3453
  turnInFlight.current = true;
@@ -3148,25 +3512,37 @@ export {
3148
3512
  applyCompletion,
3149
3513
  backgroundRunsFromThread,
3150
3514
  buildTranscriptBlocks,
3515
+ correctedCallIds,
3151
3516
  createSkillsSource,
3152
3517
  describeTimestamp,
3518
+ describeToolCall,
3153
3519
  describeUsage,
3154
3520
  extractMessageText,
3521
+ fillTemplate,
3155
3522
  filterAutocompleteItems,
3156
3523
  findActiveTrigger,
3157
3524
  formatElapsed,
3158
3525
  formatRelativeTime,
3526
+ groupToolActivity,
3527
+ inferResultView,
3528
+ isActionCall,
3159
3529
  loadStoredSpeechLang,
3160
3530
  persistSpeechLang,
3531
+ phraseFor,
3532
+ readPath,
3161
3533
  readReasoningMs,
3534
+ resolveResultView,
3162
3535
  storedMessageToUiMessage,
3163
3536
  storedThreadToUiMessages,
3537
+ toolCallState,
3538
+ toolCatalogFrom,
3164
3539
  useAgentChat,
3165
3540
  useChatTranscript,
3166
3541
  useComposerAutocomplete,
3167
3542
  useElapsed,
3168
3543
  useSpeechRecognition,
3169
3544
  useStickToBottom,
3545
+ useToolCatalog,
3170
3546
  useTranscriptItem
3171
3547
  };
3172
3548
  //# sourceMappingURL=index.js.map