@dudousxd/nestjs-agent-react 0.8.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
@@ -1,6 +1,65 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
3
 
4
+ // src/reasoning/timing.ts
5
+ import { useEffect, useRef, useState } from "react";
6
+ var REASONING_METADATA_KEY = "agent";
7
+ function reasoningDurationMetadata(reasoningMs) {
8
+ return {
9
+ [REASONING_METADATA_KEY]: {
10
+ reasoningMs
11
+ }
12
+ };
13
+ }
14
+ __name(reasoningDurationMetadata, "reasoningDurationMetadata");
15
+ function readReasoningMs(part) {
16
+ const metadata = part.providerMetadata;
17
+ if (typeof metadata !== "object" || metadata === null) return null;
18
+ const scoped = metadata[REASONING_METADATA_KEY];
19
+ if (typeof scoped !== "object" || scoped === null) return null;
20
+ const value = scoped.reasoningMs;
21
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : null;
22
+ }
23
+ __name(readReasoningMs, "readReasoningMs");
24
+ function useElapsed(running, options = {}) {
25
+ const { intervalMs = 1e3 } = options;
26
+ const nowRef = useRef(options.now ?? Date.now);
27
+ nowRef.current = options.now ?? Date.now;
28
+ const startedAt = useRef(null);
29
+ const [elapsed, setElapsed] = useState(0);
30
+ useEffect(() => {
31
+ if (!running) {
32
+ if (startedAt.current !== null) {
33
+ setElapsed(nowRef.current() - startedAt.current);
34
+ startedAt.current = null;
35
+ }
36
+ return;
37
+ }
38
+ startedAt.current = nowRef.current();
39
+ setElapsed(0);
40
+ const timer = setInterval(() => {
41
+ if (startedAt.current !== null) setElapsed(nowRef.current() - startedAt.current);
42
+ }, intervalMs);
43
+ return () => clearInterval(timer);
44
+ }, [
45
+ running,
46
+ intervalMs
47
+ ]);
48
+ return elapsed;
49
+ }
50
+ __name(useElapsed, "useElapsed");
51
+ function formatElapsed(ms) {
52
+ if (!Number.isFinite(ms) || ms < 1e3) return "<1s";
53
+ const totalSeconds = Math.floor(ms / 1e3);
54
+ const hours = Math.floor(totalSeconds / 3600);
55
+ const minutes = Math.floor(totalSeconds % 3600 / 60);
56
+ const seconds = totalSeconds % 60;
57
+ if (hours > 0) return minutes > 0 ? `${hours}h ${minutes}m` : `${hours}h`;
58
+ if (minutes > 0) return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;
59
+ return `${seconds}s`;
60
+ }
61
+ __name(formatElapsed, "formatElapsed");
62
+
4
63
  // src/agent-chat-transport.ts
5
64
  var HEADER_RUN_ID = "x-agent-run-id";
6
65
  var HEADER_THREAD_ID = "x-agent-thread-id";
@@ -158,6 +217,7 @@ var AgentChatTransport = class {
158
217
  let stepIndex = 0;
159
218
  let textId = null;
160
219
  let reasoningId = null;
220
+ let reasoningStartedAt = 0;
161
221
  let textSeq = 0;
162
222
  let reasoningSeq = 0;
163
223
  const announced = /* @__PURE__ */ new Set();
@@ -194,7 +254,7 @@ var AgentChatTransport = class {
194
254
  if (!stepOpen) openStep();
195
255
  }
196
256
  __name(ensureStep, "ensureStep");
197
- function closeRuns() {
257
+ function closeRuns(reasoningMs) {
198
258
  if (textId !== null) {
199
259
  controller.enqueue({
200
260
  type: "text-end",
@@ -205,15 +265,16 @@ var AgentChatTransport = class {
205
265
  if (reasoningId !== null) {
206
266
  controller.enqueue({
207
267
  type: "reasoning-end",
208
- id: reasoningId
268
+ id: reasoningId,
269
+ providerMetadata: reasoningDurationMetadata(reasoningMs ?? Math.max(0, Date.now() - reasoningStartedAt))
209
270
  });
210
271
  reasoningId = null;
211
272
  }
212
273
  }
213
274
  __name(closeRuns, "closeRuns");
214
- function closeStep() {
275
+ function closeStep(reasoningMs) {
215
276
  if (!stepOpen) return;
216
- closeRuns();
277
+ closeRuns(reasoningMs);
217
278
  controller.enqueue({
218
279
  type: "finish-step"
219
280
  });
@@ -252,7 +313,7 @@ var AgentChatTransport = class {
252
313
  openStep();
253
314
  break;
254
315
  case "step-finish":
255
- closeStep();
316
+ closeStep(event.reasoningMs);
256
317
  if (event.costUsd !== void 0) {
257
318
  controller.enqueue({
258
319
  type: "message-metadata",
@@ -283,6 +344,7 @@ var AgentChatTransport = class {
283
344
  if (reasoningId === null) {
284
345
  reasoningId = reasoningSeq === 0 ? `rsn-${stepIndex}` : `rsn-${stepIndex}.${reasoningSeq}`;
285
346
  reasoningSeq += 1;
347
+ reasoningStartedAt = Date.now();
286
348
  controller.enqueue({
287
349
  type: "reasoning-start",
288
350
  id: reasoningId
@@ -617,6 +679,15 @@ var AgentClient = class {
617
679
  const query = threadId === void 0 ? "" : `?threadId=${encodeURIComponent(threadId)}`;
618
680
  return this.request("GET", `/agent/skills${query}`);
619
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
+ }
620
691
  getThread(id) {
621
692
  return this.request("GET", `/agent/threads/${encodeURIComponent(id)}`);
622
693
  }
@@ -730,10 +801,10 @@ var AgentClient = class {
730
801
  };
731
802
 
732
803
  // src/components/chat-input.tsx
733
- import React2, { useEffect as useEffect2, useState as useState2 } from "react";
804
+ import React2, { useEffect as useEffect3, useState as useState3 } from "react";
734
805
 
735
806
  // src/components/use-speech-recognition.ts
736
- import { useCallback, useEffect, useMemo, useRef, useState } from "react";
807
+ import { useCallback, useEffect as useEffect2, useMemo, useRef as useRef2, useState as useState2 } from "react";
737
808
  function getRecognitionCtor() {
738
809
  if (typeof window === "undefined") return null;
739
810
  const scope = window;
@@ -741,15 +812,15 @@ function getRecognitionCtor() {
741
812
  }
742
813
  __name(getRecognitionCtor, "getRecognitionCtor");
743
814
  function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTranscript }) {
744
- const recognitionRef = useRef(null);
745
- const [isListening, setIsListening] = useState(false);
815
+ const recognitionRef = useRef2(null);
816
+ const [isListening, setIsListening] = useState2(false);
746
817
  const ctor = useMemo(() => getRecognitionCtor(), []);
747
818
  const isSupported = ctor !== null;
748
- const finalRef = useRef(onFinalTranscript);
749
- const interimRef = useRef(onInterimTranscript);
819
+ const finalRef = useRef2(onFinalTranscript);
820
+ const interimRef = useRef2(onInterimTranscript);
750
821
  finalRef.current = onFinalTranscript;
751
822
  interimRef.current = onInterimTranscript;
752
- useEffect(() => {
823
+ useEffect2(() => {
753
824
  if (!ctor) return;
754
825
  const recognition = new ctor();
755
826
  recognition.lang = lang;
@@ -817,8 +888,8 @@ __name(useSpeechRecognition, "useSpeechRecognition");
817
888
 
818
889
  // src/components/chat-input.tsx
819
890
  function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = true, speechLang = "en-US", sendLabel = "Send", onStop, isStreaming = false, stopLabel = "Stop generating", className, textareaClassName, sendButtonClassName, micButtonClassName, stopButtonClassName, renderMic }) {
820
- const [value, setValue] = useState2("");
821
- const [interim, setInterim] = useState2("");
891
+ const [value, setValue] = useState3("");
892
+ const [interim, setInterim] = useState3("");
822
893
  const speech = useSpeechRecognition({
823
894
  lang: speechLang,
824
895
  onFinalTranscript: /* @__PURE__ */ __name((text) => {
@@ -829,7 +900,7 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
829
900
  }, "onFinalTranscript"),
830
901
  onInterimTranscript: /* @__PURE__ */ __name((text) => setInterim(text), "onInterimTranscript")
831
902
  });
832
- useEffect2(() => {
903
+ useEffect3(() => {
833
904
  if (!speech.isListening) setInterim("");
834
905
  }, [
835
906
  speech.isListening
@@ -896,10 +967,283 @@ __name(ChatInput, "ChatInput");
896
967
  import React3 from "react";
897
968
 
898
969
  // src/transcript/use-chat-transcript.ts
899
- import { useCallback as useCallback3, useEffect as useEffect4, useRef as useRef3, useState as useState4 } from "react";
970
+ import { useCallback as useCallback3, useEffect as useEffect5, useRef as useRef4, useState as useState5 } from "react";
971
+
972
+ // src/transcript/model.ts
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");
900
1245
 
901
1246
  // src/transcript/model.ts
902
- import { getToolName, isDataUIPart, isFileUIPart, isReasoningUIPart, isTextUIPart, isToolUIPart } from "ai";
903
1247
  function buildTranscriptBlocks(message, options) {
904
1248
  const blocks = [];
905
1249
  let toolBuffer = [];
@@ -916,13 +1260,19 @@ function buildTranscriptBlocks(message, options) {
916
1260
  if (toolBuffer.length === 0) {
917
1261
  return;
918
1262
  }
919
- 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);
920
1265
  blocks.push({
921
1266
  kind: "tools",
922
1267
  key: `${message.id}-tools-${toolCounter++}`,
923
1268
  parts: toolBuffer,
924
1269
  calls,
925
- roots: nestToolCalls(calls)
1270
+ roots,
1271
+ activity: groupToolActivity(roots, {
1272
+ ...options.toolCatalog !== void 0 ? {
1273
+ catalog: options.toolCatalog
1274
+ } : {}
1275
+ })
926
1276
  });
927
1277
  toolBuffer = [];
928
1278
  }
@@ -1017,6 +1367,7 @@ function buildTranscriptBlocks(message, options) {
1017
1367
  key,
1018
1368
  text: part.text,
1019
1369
  isStreaming,
1370
+ durationMs: readReasoningMs(part),
1020
1371
  isOpen: options.isReasoningOpen(key, isStreaming),
1021
1372
  toggle: /* @__PURE__ */ __name((open) => options.toggleReasoning(key, open), "toggle")
1022
1373
  });
@@ -1070,7 +1421,7 @@ function isSettled(state) {
1070
1421
  __name(isSettled, "isSettled");
1071
1422
  function toolKind(part) {
1072
1423
  const metadata = part.toolMetadata;
1073
- return isRecord(metadata) && typeof metadata.toolKind === "string" ? metadata.toolKind : void 0;
1424
+ return isRecord2(metadata) && typeof metadata.toolKind === "string" ? metadata.toolKind : void 0;
1074
1425
  }
1075
1426
  __name(toolKind, "toolKind");
1076
1427
  function isAwaitingApproval(part) {
@@ -1085,7 +1436,7 @@ function isAwaitingApproval(part) {
1085
1436
  __name(isAwaitingApproval, "isAwaitingApproval");
1086
1437
  function toolParentId(part) {
1087
1438
  const metadata = part.toolMetadata;
1088
- return isRecord(metadata) && typeof metadata.parentId === "string" ? metadata.parentId : null;
1439
+ return isRecord2(metadata) && typeof metadata.parentId === "string" ? metadata.parentId : null;
1089
1440
  }
1090
1441
  __name(toolParentId, "toolParentId");
1091
1442
  function nestToolCalls(calls) {
@@ -1118,18 +1469,19 @@ function isAncestor(call, candidate, byId) {
1118
1469
  return false;
1119
1470
  }
1120
1471
  __name(isAncestor, "isAncestor");
1121
- function buildToolCall(part, options, approval) {
1472
+ function buildToolCall(part, options, approval, catalog) {
1122
1473
  const toolCallId = part.toolCallId;
1123
1474
  const awaiting = isAwaitingApproval(part);
1124
1475
  const sending = awaiting ? options?.submitting(toolCallId) ?? null : null;
1125
1476
  return {
1126
1477
  part,
1127
1478
  toolCallId,
1128
- name: getToolName(part),
1479
+ name: getToolName2(part),
1129
1480
  toolKind: toolKind(part) ?? null,
1130
1481
  parentId: toolParentId(part),
1131
1482
  children: [],
1132
1483
  approval,
1484
+ description: describeToolCall(part, catalog),
1133
1485
  isAwaitingApproval: awaiting,
1134
1486
  approve: {
1135
1487
  available: awaiting && options?.canApprove === true,
@@ -1147,17 +1499,17 @@ function buildToolCall(part, options, approval) {
1147
1499
  __name(buildToolCall, "buildToolCall");
1148
1500
  function readElicitationRequest(part) {
1149
1501
  const input = part.input;
1150
- if (!isRecord(input) || !Array.isArray(input.questions) || input.questions.length === 0) {
1502
+ if (!isRecord2(input) || !Array.isArray(input.questions) || input.questions.length === 0) {
1151
1503
  return null;
1152
1504
  }
1153
1505
  const questions = [];
1154
1506
  for (const candidate of input.questions) {
1155
- 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) {
1156
1508
  return null;
1157
1509
  }
1158
1510
  const options = [];
1159
1511
  for (const option of candidate.options) {
1160
- if (!isRecord(option) || typeof option.value !== "string" || typeof option.label !== "string") {
1512
+ if (!isRecord2(option) || typeof option.value !== "string" || typeof option.label !== "string") {
1161
1513
  return null;
1162
1514
  }
1163
1515
  options.push({
@@ -1182,7 +1534,7 @@ function readElicitationRequest(part) {
1182
1534
  __name(readElicitationRequest, "readElicitationRequest");
1183
1535
  function readElicitationOutcome(part) {
1184
1536
  const output = part.output;
1185
- if (!isRecord(output) || !isRecord(output.answers) || typeof output.skipped !== "boolean") {
1537
+ if (!isRecord2(output) || !isRecord2(output.answers) || typeof output.skipped !== "boolean") {
1186
1538
  return null;
1187
1539
  }
1188
1540
  const answers = {};
@@ -1269,7 +1621,7 @@ function readApprovals(parts) {
1269
1621
  continue;
1270
1622
  }
1271
1623
  const data = part.data;
1272
- if (!isRecord(data) || typeof data.id !== "string" || typeof data.approver !== "string") {
1624
+ if (!isRecord2(data) || typeof data.id !== "string" || typeof data.approver !== "string") {
1273
1625
  continue;
1274
1626
  }
1275
1627
  out.set(data.id, {
@@ -1283,7 +1635,7 @@ function readApprovals(parts) {
1283
1635
  __name(readApprovals, "readApprovals");
1284
1636
  function readUiComponent(part) {
1285
1637
  const data = part.data;
1286
- if (!isRecord(data) || typeof data.component !== "string") {
1638
+ if (!isRecord2(data) || typeof data.component !== "string") {
1287
1639
  return null;
1288
1640
  }
1289
1641
  const id = typeof data.id === "string" ? data.id : part.id;
@@ -1293,18 +1645,18 @@ function readUiComponent(part) {
1293
1645
  return {
1294
1646
  id,
1295
1647
  component: data.component,
1296
- props: isRecord(data.props) ? data.props : {},
1648
+ props: isRecord2(data.props) ? data.props : {},
1297
1649
  version: typeof data.version === "number" ? data.version : null
1298
1650
  };
1299
1651
  }
1300
1652
  __name(readUiComponent, "readUiComponent");
1301
- function isRecord(value) {
1653
+ function isRecord2(value) {
1302
1654
  return typeof value === "object" && value !== null;
1303
1655
  }
1304
- __name(isRecord, "isRecord");
1656
+ __name(isRecord2, "isRecord");
1305
1657
  function readQuery(part) {
1306
1658
  const input = part.input;
1307
- if (!isRecord(input) || typeof input.query !== "string") {
1659
+ if (!isRecord2(input) || typeof input.query !== "string") {
1308
1660
  return null;
1309
1661
  }
1310
1662
  return input.query;
@@ -1312,12 +1664,12 @@ function readQuery(part) {
1312
1664
  __name(readQuery, "readQuery");
1313
1665
  function readPassages(part) {
1314
1666
  const output = part.output;
1315
- if (!isRecord(output) || !Array.isArray(output.passages) || output.passages.length === 0) {
1667
+ if (!isRecord2(output) || !Array.isArray(output.passages) || output.passages.length === 0) {
1316
1668
  return null;
1317
1669
  }
1318
1670
  const passages = [];
1319
1671
  for (const candidate of output.passages) {
1320
- if (!isRecord(candidate) || typeof candidate.id !== "string" || typeof candidate.text !== "string") {
1672
+ if (!isRecord2(candidate) || typeof candidate.id !== "string" || typeof candidate.text !== "string") {
1321
1673
  return null;
1322
1674
  }
1323
1675
  passages.push({
@@ -1327,7 +1679,7 @@ function readPassages(part) {
1327
1679
  ...typeof candidate.source === "string" ? {
1328
1680
  source: candidate.source
1329
1681
  } : {},
1330
- ...isRecord(candidate.metadata) ? {
1682
+ ...isRecord2(candidate.metadata) ? {
1331
1683
  metadata: candidate.metadata
1332
1684
  } : {}
1333
1685
  });
@@ -1429,10 +1781,10 @@ function formatCostUsd(cost) {
1429
1781
  __name(formatCostUsd, "formatCostUsd");
1430
1782
 
1431
1783
  // src/transcript/use-stick-to-bottom.ts
1432
- import { useCallback as useCallback2, useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
1784
+ import { useCallback as useCallback2, useEffect as useEffect4, useRef as useRef3, useState as useState4 } from "react";
1433
1785
  function useStickToBottom({ contentKey, threshold = 32 }) {
1434
- const containerRef = useRef2(null);
1435
- const [isAtBottom, setIsAtBottom] = useState3(true);
1786
+ const containerRef = useRef3(null);
1787
+ const [isAtBottom, setIsAtBottom] = useState4(true);
1436
1788
  const measure = useCallback2(() => {
1437
1789
  const element = containerRef.current;
1438
1790
  if (!element) {
@@ -1459,7 +1811,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
1459
1811
  }, [
1460
1812
  measure
1461
1813
  ]);
1462
- useEffect3(() => {
1814
+ useEffect4(() => {
1463
1815
  if (isAtBottom) {
1464
1816
  scrollToBottom();
1465
1817
  }
@@ -1490,14 +1842,14 @@ var DEFAULT_LOAD_EARLIER_STEP = 50;
1490
1842
  var DEFAULT_COPY_RESET_MS = 1500;
1491
1843
  function useChatTranscript(options) {
1492
1844
  const { messages, status, initialVisibleCount = DEFAULT_VISIBLE_COUNT, loadEarlierStep = DEFAULT_LOAD_EARLIER_STEP, followUps, stickToBottomThreshold } = options;
1493
- const latest = useRef3(options);
1845
+ const latest = useRef4(options);
1494
1846
  latest.current = options;
1495
- const [visibleCount, setVisibleCount] = useState4(initialVisibleCount);
1496
- const [stopRequested, setStopRequested] = useState4(false);
1847
+ const [visibleCount, setVisibleCount] = useState5(initialVisibleCount);
1848
+ const [stopRequested, setStopRequested] = useState5(false);
1497
1849
  const isStreaming = status === "streaming";
1498
1850
  const isBusy = status === "submitted" || isStreaming;
1499
1851
  const isEmpty = messages.length === 0;
1500
- useEffect4(() => {
1852
+ useEffect5(() => {
1501
1853
  if (!isBusy) {
1502
1854
  setStopRequested(false);
1503
1855
  }
@@ -1559,7 +1911,7 @@ function useChatTranscript(options) {
1559
1911
  __name(useChatTranscript, "useChatTranscript");
1560
1912
  function useTranscriptItem(options) {
1561
1913
  const { message, isStreaming = false } = options;
1562
- const messagesRef = useRef3([
1914
+ const messagesRef = useRef4([
1563
1915
  message
1564
1916
  ]);
1565
1917
  if (messagesRef.current[0] !== message) {
@@ -1577,13 +1929,13 @@ function useTranscriptItem(options) {
1577
1929
  }
1578
1930
  __name(useTranscriptItem, "useTranscriptItem");
1579
1931
  function useTranscriptItems({ messages, visibleStart, streamingMessageId, options }) {
1580
- const [drafts, setDrafts] = useState4(() => /* @__PURE__ */ new Map());
1581
- const [copied, setCopied] = useState4(() => /* @__PURE__ */ new Set());
1582
- const [openReasoning, setOpenReasoning] = useState4(() => /* @__PURE__ */ new Map());
1583
- const [picks, setPicks] = useState4(() => /* @__PURE__ */ new Map());
1584
- const [settling, setSettling] = useState4(() => /* @__PURE__ */ new Map());
1585
- const [settleErrors, setSettleErrors] = useState4(() => /* @__PURE__ */ new Map());
1586
- const latest = useRef3({
1932
+ const [drafts, setDrafts] = useState5(() => /* @__PURE__ */ new Map());
1933
+ const [copied, setCopied] = useState5(() => /* @__PURE__ */ new Set());
1934
+ const [openReasoning, setOpenReasoning] = useState5(() => /* @__PURE__ */ new Map());
1935
+ const [picks, setPicks] = useState5(() => /* @__PURE__ */ new Map());
1936
+ const [settling, setSettling] = useState5(() => /* @__PURE__ */ new Map());
1937
+ const [settleErrors, setSettleErrors] = useState5(() => /* @__PURE__ */ new Map());
1938
+ const latest = useRef4({
1587
1939
  options,
1588
1940
  drafts,
1589
1941
  picks,
@@ -1595,15 +1947,15 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
1595
1947
  picks,
1596
1948
  messages
1597
1949
  };
1598
- const copyTimers = useRef3(/* @__PURE__ */ new Map());
1599
- useEffect4(() => () => {
1950
+ const copyTimers = useRef4(/* @__PURE__ */ new Map());
1951
+ useEffect5(() => () => {
1600
1952
  for (const timer of copyTimers.current.values()) {
1601
1953
  clearTimeout(timer);
1602
1954
  }
1603
1955
  copyTimers.current.clear();
1604
1956
  }, []);
1605
- const callbackCache = useRef3(/* @__PURE__ */ new Map());
1606
- const reasoningToggleCache = useRef3(/* @__PURE__ */ new Map());
1957
+ const callbackCache = useRef4(/* @__PURE__ */ new Map());
1958
+ const reasoningToggleCache = useRef4(/* @__PURE__ */ new Map());
1607
1959
  const toggleReasoning = useCallback3((key, open) => {
1608
1960
  setOpenReasoning((current) => {
1609
1961
  const next = new Map(current);
@@ -1794,6 +2146,9 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
1794
2146
  ...options.sources !== void 0 ? {
1795
2147
  sources: options.sources
1796
2148
  } : {},
2149
+ ...options.toolCatalog !== void 0 ? {
2150
+ toolCatalog: options.toolCatalog
2151
+ } : {},
1797
2152
  ...options.onAnswer !== void 0 ? {
1798
2153
  elicitation: {
1799
2154
  picked: /* @__PURE__ */ __name((toolCallId, questionId) => picks.get(pickKey(toolCallId, questionId)), "picked"),
@@ -2332,18 +2687,18 @@ function toItem(entry) {
2332
2687
  __name(toItem, "toItem");
2333
2688
 
2334
2689
  // src/composer/use-composer-autocomplete.ts
2335
- import { useCallback as useCallback4, useEffect as useEffect5, useId, useLayoutEffect, useMemo as useMemo2, useRef as useRef4, useState as useState5 } from "react";
2690
+ import { useCallback as useCallback4, useEffect as useEffect6, useId, useLayoutEffect, useMemo as useMemo2, useRef as useRef5, useState as useState6 } from "react";
2336
2691
  function useComposerAutocomplete(options) {
2337
2692
  const { value, sources, acceptOnTab = true } = options;
2338
- const latest = useRef4(options);
2693
+ const latest = useRef5(options);
2339
2694
  latest.current = options;
2340
- const inputRef = useRef4(null);
2341
- const [caret, setCaret] = useState5(value.length);
2342
- const [items, setItems] = useState5([]);
2343
- const [isLoading, setLoading] = useState5(false);
2344
- const [error, setError] = useState5(null);
2345
- const [activeIndex, setActiveIndex] = useState5(0);
2346
- const [dismissedIndex, setDismissedIndex] = useState5(null);
2695
+ const inputRef = useRef5(null);
2696
+ const [caret, setCaret] = useState6(value.length);
2697
+ const [items, setItems] = useState6([]);
2698
+ const [isLoading, setLoading] = useState6(false);
2699
+ const [error, setError] = useState6(null);
2700
+ const [activeIndex, setActiveIndex] = useState6(0);
2701
+ const [dismissedIndex, setDismissedIndex] = useState6(null);
2347
2702
  const safeCaret = Math.min(caret, value.length);
2348
2703
  const match = useMemo2(() => findActiveTrigger(value, safeCaret, sources), [
2349
2704
  value,
@@ -2351,16 +2706,16 @@ function useComposerAutocomplete(options) {
2351
2706
  sources
2352
2707
  ]);
2353
2708
  const isActive = match !== null && dismissedIndex !== match.index;
2354
- const matchRef = useRef4(match);
2709
+ const matchRef = useRef5(match);
2355
2710
  matchRef.current = match;
2356
- const caretRef = useRef4(safeCaret);
2711
+ const caretRef = useRef5(safeCaret);
2357
2712
  caretRef.current = safeCaret;
2358
- const itemsRef = useRef4(items);
2713
+ const itemsRef = useRef5(items);
2359
2714
  itemsRef.current = items;
2360
- const activeIndexRef = useRef4(activeIndex);
2715
+ const activeIndexRef = useRef5(activeIndex);
2361
2716
  activeIndexRef.current = activeIndex;
2362
2717
  const requestKey = isActive && match ? `${match.source.id}\0${match.query}` : null;
2363
- useEffect5(() => {
2718
+ useEffect6(() => {
2364
2719
  const current = matchRef.current;
2365
2720
  if (requestKey === null || current === null) {
2366
2721
  setItems([]);
@@ -2425,7 +2780,7 @@ function useComposerAutocomplete(options) {
2425
2780
  const current = matchRef.current;
2426
2781
  if (current) setDismissedIndex(current.index);
2427
2782
  }, []);
2428
- const pendingCaret = useRef4(null);
2783
+ const pendingCaret = useRef5(null);
2429
2784
  const accept = useCallback4((item) => {
2430
2785
  const current = matchRef.current;
2431
2786
  if (!current) return;
@@ -2569,6 +2924,78 @@ function isPromise(value) {
2569
2924
  }
2570
2925
  __name(isPromise, "isPromise");
2571
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
+
2572
2999
  // src/stored-message-to-ui-message.ts
2573
3000
  import { DEFAULT_REFUSAL_REASON } from "@dudousxd/nestjs-agent-core";
2574
3001
  function isRefusal(result) {
@@ -2590,6 +3017,16 @@ function refusalReason(result) {
2590
3017
  __name(refusalReason, "refusalReason");
2591
3018
  function storedMessageToUiMessage(message) {
2592
3019
  const parts = [];
3020
+ if (message.reasoning) {
3021
+ parts.push({
3022
+ type: "reasoning",
3023
+ text: message.reasoning,
3024
+ state: "done",
3025
+ ...message.reasoningMs !== void 0 ? {
3026
+ providerMetadata: reasoningDurationMetadata(message.reasoningMs)
3027
+ } : {}
3028
+ });
3029
+ }
2593
3030
  if (message.content) {
2594
3031
  parts.push({
2595
3032
  type: "text",
@@ -2604,6 +3041,20 @@ function storedMessageToUiMessage(message) {
2604
3041
  url: attachment.url
2605
3042
  });
2606
3043
  }
3044
+ for (const component of message.ui ?? []) {
3045
+ parts.push({
3046
+ type: "data-ui",
3047
+ id: component.id,
3048
+ data: {
3049
+ id: component.id,
3050
+ component: component.component,
3051
+ props: component.props,
3052
+ ...component.version !== void 0 ? {
3053
+ version: component.version
3054
+ } : {}
3055
+ }
3056
+ });
3057
+ }
2607
3058
  for (const call of message.toolCalls ?? []) {
2608
3059
  const result = message.toolResults?.find((candidate) => candidate.id === call.id);
2609
3060
  const toolKind2 = call.kind;
@@ -2706,20 +3157,20 @@ __name(sumUsage, "sumUsage");
2706
3157
 
2707
3158
  // src/use-agent-chat.ts
2708
3159
  import { useChat } from "@ai-sdk/react";
2709
- import { useCallback as useCallback5, useEffect as useEffect6, useMemo as useMemo3, useRef as useRef5, useState as useState6 } from "react";
3160
+ import { useCallback as useCallback6, useEffect as useEffect8, useMemo as useMemo4, useRef as useRef6, useState as useState8 } from "react";
2710
3161
  function useAgentChat(options) {
2711
- const latest = useRef5(options);
3162
+ const latest = useRef6(options);
2712
3163
  latest.current = options;
2713
- const [runId, setRunId] = useState6(options.resumeRunId);
2714
- const runIdRef = useRef5(runId);
3164
+ const [runId, setRunId] = useState8(options.resumeRunId);
3165
+ const runIdRef = useRef6(runId);
2715
3166
  runIdRef.current = runId;
2716
- const settlingRunIdRef = useRef5(void 0);
2717
- const autoResumeRunIdRef = useRef5(void 0);
2718
- const [autoResume, setAutoResume] = useState6(false);
2719
- const [activeRunId, setActiveRunId] = useState6(null);
2720
- const regenerateNext = useRef5(false);
2721
- const createdThreadId = useRef5(void 0);
2722
- const client = useMemo3(() => {
3167
+ const settlingRunIdRef = useRef6(void 0);
3168
+ const autoResumeRunIdRef = useRef6(void 0);
3169
+ const [autoResume, setAutoResume] = useState8(false);
3170
+ const [activeRunId, setActiveRunId] = useState8(null);
3171
+ const regenerateNext = useRef6(false);
3172
+ const createdThreadId = useRef6(void 0);
3173
+ const client = useMemo4(() => {
2723
3174
  if (options.client) return options.client;
2724
3175
  return new AgentClient({
2725
3176
  ...options.baseUrl !== void 0 ? {
@@ -2734,7 +3185,7 @@ function useAgentChat(options) {
2734
3185
  getHeaders: /* @__PURE__ */ __name(async () => mergeHeaders(latest.current), "getHeaders")
2735
3186
  });
2736
3187
  }, []);
2737
- useEffect6(() => {
3188
+ useEffect8(() => {
2738
3189
  if (!options.resume || options.threadId === void 0) return;
2739
3190
  let cancelled = false;
2740
3191
  const threadId = options.threadId;
@@ -2754,7 +3205,7 @@ function useAgentChat(options) {
2754
3205
  options.resume,
2755
3206
  options.threadId
2756
3207
  ]);
2757
- const transport = useMemo3(() => {
3208
+ const transport = useMemo4(() => {
2758
3209
  function onMeta(meta) {
2759
3210
  settlingRunIdRef.current = meta.runId;
2760
3211
  setRunId(meta.runId);
@@ -2803,7 +3254,7 @@ function useAgentChat(options) {
2803
3254
  }, "onAttemptStart")
2804
3255
  });
2805
3256
  }, []);
2806
- const backgroundRef = useRef5(() => Promise.resolve());
3257
+ const backgroundRef = useRef6(() => Promise.resolve());
2807
3258
  const chat = useChat({
2808
3259
  transport,
2809
3260
  resume: options.resumeRunId !== void 0 || autoResume,
@@ -2834,13 +3285,13 @@ function useAgentChat(options) {
2834
3285
  }
2835
3286
  }, "onFinish")
2836
3287
  });
2837
- const chatRef = useRef5(chat);
3288
+ const chatRef = useRef6(chat);
2838
3289
  chatRef.current = chat;
2839
- const turnInFlight = useRef5(false);
2840
- const isTurnInFlight = useCallback5(() => turnInFlight.current || transport.isAttemptLive, [
3290
+ const turnInFlight = useRef6(false);
3291
+ const isTurnInFlight = useCallback6(() => turnInFlight.current || transport.isAttemptLive, [
2841
3292
  transport
2842
3293
  ]);
2843
- const sendMessage = useCallback5(async (...args) => {
3294
+ const sendMessage = useCallback6(async (...args) => {
2844
3295
  if (isTurnInFlight()) return;
2845
3296
  turnInFlight.current = true;
2846
3297
  try {
@@ -2851,15 +3302,15 @@ function useAgentChat(options) {
2851
3302
  }, [
2852
3303
  isTurnInFlight
2853
3304
  ]);
2854
- const addToolResult = useCallback5(({ tool, toolCallId, output }) => chatRef.current.addToolResult({
3305
+ const addToolResult = useCallback6(({ tool, toolCallId, output }) => chatRef.current.addToolResult({
2855
3306
  tool,
2856
3307
  toolCallId,
2857
3308
  output
2858
3309
  }), []);
2859
- const [threads, setThreads] = useState6([]);
2860
- const [quota, setQuota] = useState6(null);
2861
- const [backgroundRuns, setBackgroundRuns] = useState6([]);
2862
- 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 () => {
2863
3314
  const threadId = latest.current.threadId ?? createdThreadId.current;
2864
3315
  if (threadId === void 0) {
2865
3316
  return;
@@ -2884,7 +3335,7 @@ function useAgentChat(options) {
2884
3335
  ]);
2885
3336
  backgroundRef.current = refreshBackground;
2886
3337
  const isWorking = backgroundRuns.some((run) => run.status === "running");
2887
- useEffect6(() => {
3338
+ useEffect8(() => {
2888
3339
  if (options.background !== true || options.threadId === void 0) {
2889
3340
  return;
2890
3341
  }
@@ -2894,7 +3345,7 @@ function useAgentChat(options) {
2894
3345
  options.threadId,
2895
3346
  refreshBackground
2896
3347
  ]);
2897
- useEffect6(() => {
3348
+ useEffect8(() => {
2898
3349
  const every = latest.current.backgroundPollMs ?? 5e3;
2899
3350
  if (latest.current.background !== true || !isWorking || every <= 0) {
2900
3351
  return;
@@ -2905,26 +3356,26 @@ function useAgentChat(options) {
2905
3356
  isWorking,
2906
3357
  refreshBackground
2907
3358
  ]);
2908
- const loadThreads = useCallback5(async () => {
3359
+ const loadThreads = useCallback6(async () => {
2909
3360
  const list = await client.listThreads();
2910
3361
  setThreads(list);
2911
3362
  return list;
2912
3363
  }, [
2913
3364
  client
2914
3365
  ]);
2915
- const loadThread = useCallback5((id) => client.getThread(id), [
3366
+ const loadThread = useCallback6((id) => client.getThread(id), [
2916
3367
  client
2917
3368
  ]);
2918
- const deleteThread = useCallback5(async (id) => {
3369
+ const deleteThread = useCallback6(async (id) => {
2919
3370
  await client.deleteThread(id);
2920
3371
  setThreads((current) => current.filter((thread) => thread.id !== id));
2921
3372
  }, [
2922
3373
  client
2923
3374
  ]);
2924
- const forkThread = useCallback5((threadId, messageId) => client.forkFromMessage(threadId, messageId), [
3375
+ const forkThread = useCallback6((threadId, messageId) => client.forkFromMessage(threadId, messageId), [
2925
3376
  client
2926
3377
  ]);
2927
- const renameThread = useCallback5(async (id, title) => {
3378
+ const renameThread = useCallback6(async (id, title) => {
2928
3379
  await client.renameThread(id, title);
2929
3380
  setThreads((current) => current.map((thread) => thread.id === id ? {
2930
3381
  ...thread,
@@ -2933,24 +3384,24 @@ function useAgentChat(options) {
2933
3384
  }, [
2934
3385
  client
2935
3386
  ]);
2936
- const promoteThread = useCallback5(async (id) => {
3387
+ const promoteThread = useCallback6(async (id) => {
2937
3388
  await client.promoteThread(id);
2938
3389
  await loadThreads();
2939
3390
  }, [
2940
3391
  client,
2941
3392
  loadThreads
2942
3393
  ]);
2943
- 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), [
2944
3395
  client
2945
3396
  ]);
2946
- const loadQuota = useCallback5(async () => {
3397
+ const loadQuota = useCallback6(async () => {
2947
3398
  const today = await client.getQuotaToday();
2948
3399
  setQuota(today);
2949
3400
  return today;
2950
3401
  }, [
2951
3402
  client
2952
3403
  ]);
2953
- const cancel = useCallback5(async () => {
3404
+ const cancel = useCallback6(async () => {
2954
3405
  chatRef.current.stop();
2955
3406
  const activeRunId2 = runIdRef.current;
2956
3407
  if (activeRunId2) {
@@ -2962,14 +3413,14 @@ function useAgentChat(options) {
2962
3413
  }, [
2963
3414
  client
2964
3415
  ]);
2965
- const approve = useCallback5(async ({ toolCallId }) => {
3416
+ const approve = useCallback6(async ({ toolCallId }) => {
2966
3417
  await client.approveToolCall({
2967
3418
  toolCallId
2968
3419
  });
2969
3420
  }, [
2970
3421
  client
2971
3422
  ]);
2972
- const reject = useCallback5(async ({ toolCallId, reason }) => {
3423
+ const reject = useCallback6(async ({ toolCallId, reason }) => {
2973
3424
  await client.rejectToolCall({
2974
3425
  toolCallId,
2975
3426
  ...reason !== void 0 ? {
@@ -2979,7 +3430,7 @@ function useAgentChat(options) {
2979
3430
  }, [
2980
3431
  client
2981
3432
  ]);
2982
- const answer = useCallback5(async ({ toolCallId, answers }) => {
3433
+ const answer = useCallback6(async ({ toolCallId, answers }) => {
2983
3434
  await client.answerToolCall({
2984
3435
  toolCallId,
2985
3436
  ...answers !== void 0 ? {
@@ -2989,14 +3440,14 @@ function useAgentChat(options) {
2989
3440
  }, [
2990
3441
  client
2991
3442
  ]);
2992
- const skip = useCallback5(async ({ toolCallId }) => {
3443
+ const skip = useCallback6(async ({ toolCallId }) => {
2993
3444
  await client.skipToolCall({
2994
3445
  toolCallId
2995
3446
  });
2996
3447
  }, [
2997
3448
  client
2998
3449
  ]);
2999
- const regenerate = useCallback5(() => {
3450
+ const regenerate = useCallback6(() => {
3000
3451
  if (isTurnInFlight()) return;
3001
3452
  regenerateNext.current = true;
3002
3453
  turnInFlight.current = true;
@@ -3061,22 +3512,37 @@ export {
3061
3512
  applyCompletion,
3062
3513
  backgroundRunsFromThread,
3063
3514
  buildTranscriptBlocks,
3515
+ correctedCallIds,
3064
3516
  createSkillsSource,
3065
3517
  describeTimestamp,
3518
+ describeToolCall,
3066
3519
  describeUsage,
3067
3520
  extractMessageText,
3521
+ fillTemplate,
3068
3522
  filterAutocompleteItems,
3069
3523
  findActiveTrigger,
3524
+ formatElapsed,
3070
3525
  formatRelativeTime,
3526
+ groupToolActivity,
3527
+ inferResultView,
3528
+ isActionCall,
3071
3529
  loadStoredSpeechLang,
3072
3530
  persistSpeechLang,
3531
+ phraseFor,
3532
+ readPath,
3533
+ readReasoningMs,
3534
+ resolveResultView,
3073
3535
  storedMessageToUiMessage,
3074
3536
  storedThreadToUiMessages,
3537
+ toolCallState,
3538
+ toolCatalogFrom,
3075
3539
  useAgentChat,
3076
3540
  useChatTranscript,
3077
3541
  useComposerAutocomplete,
3542
+ useElapsed,
3078
3543
  useSpeechRecognition,
3079
3544
  useStickToBottom,
3545
+ useToolCatalog,
3080
3546
  useTranscriptItem
3081
3547
  };
3082
3548
  //# sourceMappingURL=index.js.map