@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/README.md +43 -0
- package/dist/index.cjs +668 -187
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +251 -2
- package/dist/index.d.ts +251 -2
- package/dist/index.js +576 -110
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -43,26 +43,100 @@ __export(src_exports, {
|
|
|
43
43
|
applyCompletion: () => applyCompletion,
|
|
44
44
|
backgroundRunsFromThread: () => backgroundRunsFromThread,
|
|
45
45
|
buildTranscriptBlocks: () => buildTranscriptBlocks,
|
|
46
|
+
correctedCallIds: () => correctedCallIds,
|
|
46
47
|
createSkillsSource: () => createSkillsSource,
|
|
47
48
|
describeTimestamp: () => describeTimestamp,
|
|
49
|
+
describeToolCall: () => describeToolCall,
|
|
48
50
|
describeUsage: () => describeUsage,
|
|
49
51
|
extractMessageText: () => extractMessageText,
|
|
52
|
+
fillTemplate: () => fillTemplate,
|
|
50
53
|
filterAutocompleteItems: () => filterAutocompleteItems,
|
|
51
54
|
findActiveTrigger: () => findActiveTrigger,
|
|
55
|
+
formatElapsed: () => formatElapsed,
|
|
52
56
|
formatRelativeTime: () => formatRelativeTime,
|
|
57
|
+
groupToolActivity: () => groupToolActivity,
|
|
58
|
+
inferResultView: () => inferResultView,
|
|
59
|
+
isActionCall: () => isActionCall,
|
|
53
60
|
loadStoredSpeechLang: () => loadStoredSpeechLang,
|
|
54
61
|
persistSpeechLang: () => persistSpeechLang,
|
|
62
|
+
phraseFor: () => phraseFor,
|
|
63
|
+
readPath: () => readPath,
|
|
64
|
+
readReasoningMs: () => readReasoningMs,
|
|
65
|
+
resolveResultView: () => resolveResultView,
|
|
55
66
|
storedMessageToUiMessage: () => storedMessageToUiMessage,
|
|
56
67
|
storedThreadToUiMessages: () => storedThreadToUiMessages,
|
|
68
|
+
toolCallState: () => toolCallState,
|
|
69
|
+
toolCatalogFrom: () => toolCatalogFrom,
|
|
57
70
|
useAgentChat: () => useAgentChat,
|
|
58
71
|
useChatTranscript: () => useChatTranscript,
|
|
59
72
|
useComposerAutocomplete: () => useComposerAutocomplete,
|
|
73
|
+
useElapsed: () => useElapsed,
|
|
60
74
|
useSpeechRecognition: () => useSpeechRecognition,
|
|
61
75
|
useStickToBottom: () => useStickToBottom,
|
|
76
|
+
useToolCatalog: () => useToolCatalog,
|
|
62
77
|
useTranscriptItem: () => useTranscriptItem
|
|
63
78
|
});
|
|
64
79
|
module.exports = __toCommonJS(src_exports);
|
|
65
80
|
|
|
81
|
+
// src/reasoning/timing.ts
|
|
82
|
+
var import_react = require("react");
|
|
83
|
+
var REASONING_METADATA_KEY = "agent";
|
|
84
|
+
function reasoningDurationMetadata(reasoningMs) {
|
|
85
|
+
return {
|
|
86
|
+
[REASONING_METADATA_KEY]: {
|
|
87
|
+
reasoningMs
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
__name(reasoningDurationMetadata, "reasoningDurationMetadata");
|
|
92
|
+
function readReasoningMs(part) {
|
|
93
|
+
const metadata = part.providerMetadata;
|
|
94
|
+
if (typeof metadata !== "object" || metadata === null) return null;
|
|
95
|
+
const scoped = metadata[REASONING_METADATA_KEY];
|
|
96
|
+
if (typeof scoped !== "object" || scoped === null) return null;
|
|
97
|
+
const value = scoped.reasoningMs;
|
|
98
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : null;
|
|
99
|
+
}
|
|
100
|
+
__name(readReasoningMs, "readReasoningMs");
|
|
101
|
+
function useElapsed(running, options = {}) {
|
|
102
|
+
const { intervalMs = 1e3 } = options;
|
|
103
|
+
const nowRef = (0, import_react.useRef)(options.now ?? Date.now);
|
|
104
|
+
nowRef.current = options.now ?? Date.now;
|
|
105
|
+
const startedAt = (0, import_react.useRef)(null);
|
|
106
|
+
const [elapsed, setElapsed] = (0, import_react.useState)(0);
|
|
107
|
+
(0, import_react.useEffect)(() => {
|
|
108
|
+
if (!running) {
|
|
109
|
+
if (startedAt.current !== null) {
|
|
110
|
+
setElapsed(nowRef.current() - startedAt.current);
|
|
111
|
+
startedAt.current = null;
|
|
112
|
+
}
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
startedAt.current = nowRef.current();
|
|
116
|
+
setElapsed(0);
|
|
117
|
+
const timer = setInterval(() => {
|
|
118
|
+
if (startedAt.current !== null) setElapsed(nowRef.current() - startedAt.current);
|
|
119
|
+
}, intervalMs);
|
|
120
|
+
return () => clearInterval(timer);
|
|
121
|
+
}, [
|
|
122
|
+
running,
|
|
123
|
+
intervalMs
|
|
124
|
+
]);
|
|
125
|
+
return elapsed;
|
|
126
|
+
}
|
|
127
|
+
__name(useElapsed, "useElapsed");
|
|
128
|
+
function formatElapsed(ms) {
|
|
129
|
+
if (!Number.isFinite(ms) || ms < 1e3) return "<1s";
|
|
130
|
+
const totalSeconds = Math.floor(ms / 1e3);
|
|
131
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
132
|
+
const minutes = Math.floor(totalSeconds % 3600 / 60);
|
|
133
|
+
const seconds = totalSeconds % 60;
|
|
134
|
+
if (hours > 0) return minutes > 0 ? `${hours}h ${minutes}m` : `${hours}h`;
|
|
135
|
+
if (minutes > 0) return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;
|
|
136
|
+
return `${seconds}s`;
|
|
137
|
+
}
|
|
138
|
+
__name(formatElapsed, "formatElapsed");
|
|
139
|
+
|
|
66
140
|
// src/agent-chat-transport.ts
|
|
67
141
|
var HEADER_RUN_ID = "x-agent-run-id";
|
|
68
142
|
var HEADER_THREAD_ID = "x-agent-thread-id";
|
|
@@ -220,6 +294,7 @@ var AgentChatTransport = class {
|
|
|
220
294
|
let stepIndex = 0;
|
|
221
295
|
let textId = null;
|
|
222
296
|
let reasoningId = null;
|
|
297
|
+
let reasoningStartedAt = 0;
|
|
223
298
|
let textSeq = 0;
|
|
224
299
|
let reasoningSeq = 0;
|
|
225
300
|
const announced = /* @__PURE__ */ new Set();
|
|
@@ -256,7 +331,7 @@ var AgentChatTransport = class {
|
|
|
256
331
|
if (!stepOpen) openStep();
|
|
257
332
|
}
|
|
258
333
|
__name(ensureStep, "ensureStep");
|
|
259
|
-
function closeRuns() {
|
|
334
|
+
function closeRuns(reasoningMs) {
|
|
260
335
|
if (textId !== null) {
|
|
261
336
|
controller.enqueue({
|
|
262
337
|
type: "text-end",
|
|
@@ -267,15 +342,16 @@ var AgentChatTransport = class {
|
|
|
267
342
|
if (reasoningId !== null) {
|
|
268
343
|
controller.enqueue({
|
|
269
344
|
type: "reasoning-end",
|
|
270
|
-
id: reasoningId
|
|
345
|
+
id: reasoningId,
|
|
346
|
+
providerMetadata: reasoningDurationMetadata(reasoningMs ?? Math.max(0, Date.now() - reasoningStartedAt))
|
|
271
347
|
});
|
|
272
348
|
reasoningId = null;
|
|
273
349
|
}
|
|
274
350
|
}
|
|
275
351
|
__name(closeRuns, "closeRuns");
|
|
276
|
-
function closeStep() {
|
|
352
|
+
function closeStep(reasoningMs) {
|
|
277
353
|
if (!stepOpen) return;
|
|
278
|
-
closeRuns();
|
|
354
|
+
closeRuns(reasoningMs);
|
|
279
355
|
controller.enqueue({
|
|
280
356
|
type: "finish-step"
|
|
281
357
|
});
|
|
@@ -314,7 +390,7 @@ var AgentChatTransport = class {
|
|
|
314
390
|
openStep();
|
|
315
391
|
break;
|
|
316
392
|
case "step-finish":
|
|
317
|
-
closeStep();
|
|
393
|
+
closeStep(event.reasoningMs);
|
|
318
394
|
if (event.costUsd !== void 0) {
|
|
319
395
|
controller.enqueue({
|
|
320
396
|
type: "message-metadata",
|
|
@@ -345,6 +421,7 @@ var AgentChatTransport = class {
|
|
|
345
421
|
if (reasoningId === null) {
|
|
346
422
|
reasoningId = reasoningSeq === 0 ? `rsn-${stepIndex}` : `rsn-${stepIndex}.${reasoningSeq}`;
|
|
347
423
|
reasoningSeq += 1;
|
|
424
|
+
reasoningStartedAt = Date.now();
|
|
348
425
|
controller.enqueue({
|
|
349
426
|
type: "reasoning-start",
|
|
350
427
|
id: reasoningId
|
|
@@ -679,6 +756,15 @@ var AgentClient = class {
|
|
|
679
756
|
const query = threadId === void 0 ? "" : `?threadId=${encodeURIComponent(threadId)}`;
|
|
680
757
|
return this.request("GET", `/agent/skills${query}`);
|
|
681
758
|
}
|
|
759
|
+
/**
|
|
760
|
+
* The tools this caller can reach through `agent` (the default agent when omitted), each with the
|
|
761
|
+
* server-declared `presentation` a chat narrates it by — the same list the model is offered.
|
|
762
|
+
* Prefer {@link useToolCatalog}, which fetches it once and shares it.
|
|
763
|
+
*/
|
|
764
|
+
listTools(agent) {
|
|
765
|
+
const query = agent === void 0 ? "" : `?agent=${encodeURIComponent(agent)}`;
|
|
766
|
+
return this.request("GET", `/agent/tools${query}`);
|
|
767
|
+
}
|
|
682
768
|
getThread(id) {
|
|
683
769
|
return this.request("GET", `/agent/threads/${encodeURIComponent(id)}`);
|
|
684
770
|
}
|
|
@@ -792,10 +878,10 @@ var AgentClient = class {
|
|
|
792
878
|
};
|
|
793
879
|
|
|
794
880
|
// src/components/chat-input.tsx
|
|
795
|
-
var
|
|
881
|
+
var import_react3 = __toESM(require("react"), 1);
|
|
796
882
|
|
|
797
883
|
// src/components/use-speech-recognition.ts
|
|
798
|
-
var
|
|
884
|
+
var import_react2 = require("react");
|
|
799
885
|
function getRecognitionCtor() {
|
|
800
886
|
if (typeof window === "undefined") return null;
|
|
801
887
|
const scope = window;
|
|
@@ -803,15 +889,15 @@ function getRecognitionCtor() {
|
|
|
803
889
|
}
|
|
804
890
|
__name(getRecognitionCtor, "getRecognitionCtor");
|
|
805
891
|
function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTranscript }) {
|
|
806
|
-
const recognitionRef = (0,
|
|
807
|
-
const [isListening, setIsListening] = (0,
|
|
808
|
-
const ctor = (0,
|
|
892
|
+
const recognitionRef = (0, import_react2.useRef)(null);
|
|
893
|
+
const [isListening, setIsListening] = (0, import_react2.useState)(false);
|
|
894
|
+
const ctor = (0, import_react2.useMemo)(() => getRecognitionCtor(), []);
|
|
809
895
|
const isSupported = ctor !== null;
|
|
810
|
-
const finalRef = (0,
|
|
811
|
-
const interimRef = (0,
|
|
896
|
+
const finalRef = (0, import_react2.useRef)(onFinalTranscript);
|
|
897
|
+
const interimRef = (0, import_react2.useRef)(onInterimTranscript);
|
|
812
898
|
finalRef.current = onFinalTranscript;
|
|
813
899
|
interimRef.current = onInterimTranscript;
|
|
814
|
-
(0,
|
|
900
|
+
(0, import_react2.useEffect)(() => {
|
|
815
901
|
if (!ctor) return;
|
|
816
902
|
const recognition = new ctor();
|
|
817
903
|
recognition.lang = lang;
|
|
@@ -850,7 +936,7 @@ function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTran
|
|
|
850
936
|
ctor,
|
|
851
937
|
lang
|
|
852
938
|
]);
|
|
853
|
-
const start = (0,
|
|
939
|
+
const start = (0, import_react2.useCallback)(() => {
|
|
854
940
|
const recognition = recognitionRef.current;
|
|
855
941
|
if (!recognition) return;
|
|
856
942
|
try {
|
|
@@ -860,7 +946,7 @@ function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTran
|
|
|
860
946
|
console.warn("SpeechRecognition start failed", error);
|
|
861
947
|
}
|
|
862
948
|
}, []);
|
|
863
|
-
const stop = (0,
|
|
949
|
+
const stop = (0, import_react2.useCallback)(() => {
|
|
864
950
|
const recognition = recognitionRef.current;
|
|
865
951
|
if (!recognition) return;
|
|
866
952
|
try {
|
|
@@ -879,8 +965,8 @@ __name(useSpeechRecognition, "useSpeechRecognition");
|
|
|
879
965
|
|
|
880
966
|
// src/components/chat-input.tsx
|
|
881
967
|
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 }) {
|
|
882
|
-
const [value, setValue] = (0,
|
|
883
|
-
const [interim, setInterim] = (0,
|
|
968
|
+
const [value, setValue] = (0, import_react3.useState)("");
|
|
969
|
+
const [interim, setInterim] = (0, import_react3.useState)("");
|
|
884
970
|
const speech = useSpeechRecognition({
|
|
885
971
|
lang: speechLang,
|
|
886
972
|
onFinalTranscript: /* @__PURE__ */ __name((text) => {
|
|
@@ -891,7 +977,7 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
|
|
|
891
977
|
}, "onFinalTranscript"),
|
|
892
978
|
onInterimTranscript: /* @__PURE__ */ __name((text) => setInterim(text), "onInterimTranscript")
|
|
893
979
|
});
|
|
894
|
-
(0,
|
|
980
|
+
(0, import_react3.useEffect)(() => {
|
|
895
981
|
if (!speech.isListening) setInterim("");
|
|
896
982
|
}, [
|
|
897
983
|
speech.isListening
|
|
@@ -919,9 +1005,9 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
|
|
|
919
1005
|
const displayValue = speech.isListening && interim ? `${value}${value && !value.endsWith(" ") ? " " : ""}${interim}` : value;
|
|
920
1006
|
const showMic = enableSpeech && speech.isSupported;
|
|
921
1007
|
const showStop = isStreaming && onStop !== void 0;
|
|
922
|
-
return /* @__PURE__ */
|
|
1008
|
+
return /* @__PURE__ */ import_react3.default.createElement("div", {
|
|
923
1009
|
className
|
|
924
|
-
}, /* @__PURE__ */
|
|
1010
|
+
}, /* @__PURE__ */ import_react3.default.createElement("textarea", {
|
|
925
1011
|
className: textareaClassName,
|
|
926
1012
|
rows,
|
|
927
1013
|
value: displayValue,
|
|
@@ -932,17 +1018,17 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
|
|
|
932
1018
|
}, "onChange"),
|
|
933
1019
|
onKeyDown: handleKeyDown,
|
|
934
1020
|
placeholder: placeholder ?? "Ask something (Enter to send, Shift+Enter for newline)"
|
|
935
|
-
}), /* @__PURE__ */
|
|
1021
|
+
}), /* @__PURE__ */ import_react3.default.createElement("button", {
|
|
936
1022
|
type: "button",
|
|
937
1023
|
className: sendButtonClassName,
|
|
938
1024
|
onClick: submit,
|
|
939
1025
|
disabled: disabled || !value.trim()
|
|
940
|
-
}, sendLabel), showStop ? /* @__PURE__ */
|
|
1026
|
+
}, sendLabel), showStop ? /* @__PURE__ */ import_react3.default.createElement("button", {
|
|
941
1027
|
type: "button",
|
|
942
1028
|
className: stopButtonClassName,
|
|
943
1029
|
onClick: /* @__PURE__ */ __name(() => void onStop(), "onClick"),
|
|
944
1030
|
"aria-label": "Stop generating"
|
|
945
|
-
}, stopLabel) : null, showMic ? /* @__PURE__ */
|
|
1031
|
+
}, stopLabel) : null, showMic ? /* @__PURE__ */ import_react3.default.createElement("button", {
|
|
946
1032
|
type: "button",
|
|
947
1033
|
className: micButtonClassName,
|
|
948
1034
|
onClick: toggleMic,
|
|
@@ -955,13 +1041,286 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
|
|
|
955
1041
|
__name(ChatInput, "ChatInput");
|
|
956
1042
|
|
|
957
1043
|
// src/components/message-item.tsx
|
|
958
|
-
var
|
|
1044
|
+
var import_react6 = __toESM(require("react"), 1);
|
|
959
1045
|
|
|
960
1046
|
// src/transcript/use-chat-transcript.ts
|
|
961
|
-
var
|
|
1047
|
+
var import_react5 = require("react");
|
|
962
1048
|
|
|
963
1049
|
// src/transcript/model.ts
|
|
1050
|
+
var import_ai2 = require("ai");
|
|
1051
|
+
|
|
1052
|
+
// src/presentation/tool-activity.ts
|
|
964
1053
|
var import_ai = require("ai");
|
|
1054
|
+
|
|
1055
|
+
// src/presentation/phrasing.ts
|
|
1056
|
+
function toolCatalogFrom(entries) {
|
|
1057
|
+
const catalog = {};
|
|
1058
|
+
for (const entry of entries) {
|
|
1059
|
+
if (entry.presentation !== void 0) catalog[entry.name] = entry.presentation;
|
|
1060
|
+
}
|
|
1061
|
+
return catalog;
|
|
1062
|
+
}
|
|
1063
|
+
__name(toolCatalogFrom, "toolCatalogFrom");
|
|
1064
|
+
function readPath(value, path) {
|
|
1065
|
+
return path.split(".").reduce((current, key) => {
|
|
1066
|
+
if (current === null || typeof current !== "object") return void 0;
|
|
1067
|
+
return current[key];
|
|
1068
|
+
}, value);
|
|
1069
|
+
}
|
|
1070
|
+
__name(readPath, "readPath");
|
|
1071
|
+
function renderValue(value) {
|
|
1072
|
+
if (value === null || value === void 0) return "";
|
|
1073
|
+
if (typeof value === "string") return value;
|
|
1074
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
1075
|
+
if (Array.isArray(value)) return value.map(renderValue).filter(Boolean).join(", ");
|
|
1076
|
+
return "";
|
|
1077
|
+
}
|
|
1078
|
+
__name(renderValue, "renderValue");
|
|
1079
|
+
function fillTemplate(template, context) {
|
|
1080
|
+
return template.replace(/(\s*)\{([\w.]+)\}/g, (_match, space, path) => {
|
|
1081
|
+
const rendered = renderValue(readPath(context, path));
|
|
1082
|
+
return rendered === "" ? "" : `${space}${rendered}`;
|
|
1083
|
+
}).replace(/\s{2,}/g, " ").trim();
|
|
1084
|
+
}
|
|
1085
|
+
__name(fillTemplate, "fillTemplate");
|
|
1086
|
+
function phraseFor(presentation, input, isSettled2, fallback = {
|
|
1087
|
+
running: "Working",
|
|
1088
|
+
done: "Done"
|
|
1089
|
+
}) {
|
|
1090
|
+
if (presentation === void 0) return isSettled2 ? fallback.done : fallback.running;
|
|
1091
|
+
const filled = fillTemplate(isSettled2 ? presentation.done : presentation.running, input);
|
|
1092
|
+
return filled === "" ? presentation.label : filled;
|
|
1093
|
+
}
|
|
1094
|
+
__name(phraseFor, "phraseFor");
|
|
1095
|
+
|
|
1096
|
+
// src/presentation/result-view.ts
|
|
1097
|
+
function isRecord(value) {
|
|
1098
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1099
|
+
}
|
|
1100
|
+
__name(isRecord, "isRecord");
|
|
1101
|
+
function toText(value) {
|
|
1102
|
+
if (value === null || value === void 0) return "\u2014";
|
|
1103
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
1104
|
+
return String(value);
|
|
1105
|
+
}
|
|
1106
|
+
if (Array.isArray(value)) return value.map(toText).join(", ");
|
|
1107
|
+
return "\u2014";
|
|
1108
|
+
}
|
|
1109
|
+
__name(toText, "toText");
|
|
1110
|
+
function inferResultView(output) {
|
|
1111
|
+
if (!isRecord(output)) return void 0;
|
|
1112
|
+
for (const [key, value] of Object.entries(output)) {
|
|
1113
|
+
if (!Array.isArray(value) || value.length === 0) continue;
|
|
1114
|
+
if (value.every((entry) => typeof entry === "string")) {
|
|
1115
|
+
return {
|
|
1116
|
+
kind: "log",
|
|
1117
|
+
lines: key
|
|
1118
|
+
};
|
|
1119
|
+
}
|
|
1120
|
+
if (value.every(isRecord)) {
|
|
1121
|
+
const first = value[0];
|
|
1122
|
+
return {
|
|
1123
|
+
kind: "table",
|
|
1124
|
+
rows: key,
|
|
1125
|
+
columns: Object.keys(first).filter((column) => !isRecord(first[column])).map((column) => ({
|
|
1126
|
+
path: column,
|
|
1127
|
+
label: column
|
|
1128
|
+
}))
|
|
1129
|
+
};
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
const fields = Object.entries(output).filter(([, value]) => [
|
|
1133
|
+
"string",
|
|
1134
|
+
"number",
|
|
1135
|
+
"boolean"
|
|
1136
|
+
].includes(typeof value)).map(([key]) => ({
|
|
1137
|
+
path: key,
|
|
1138
|
+
label: key
|
|
1139
|
+
}));
|
|
1140
|
+
return fields.length > 0 ? {
|
|
1141
|
+
kind: "metrics",
|
|
1142
|
+
fields
|
|
1143
|
+
} : void 0;
|
|
1144
|
+
}
|
|
1145
|
+
__name(inferResultView, "inferResultView");
|
|
1146
|
+
function resolveResultView(output, view, options = {}) {
|
|
1147
|
+
const resolved = view ?? (options.infer === true ? inferResultView(output) : void 0);
|
|
1148
|
+
if (resolved === void 0 || resolved.kind === "elsewhere") return null;
|
|
1149
|
+
switch (resolved.kind) {
|
|
1150
|
+
case "note": {
|
|
1151
|
+
const text = fillTemplate(resolved.text, output);
|
|
1152
|
+
return text === "" ? null : {
|
|
1153
|
+
kind: "note",
|
|
1154
|
+
text
|
|
1155
|
+
};
|
|
1156
|
+
}
|
|
1157
|
+
case "metrics": {
|
|
1158
|
+
const readings = resolved.fields.map((field) => ({
|
|
1159
|
+
field,
|
|
1160
|
+
value: readPath(output, field.path)
|
|
1161
|
+
})).filter((entry) => entry.value !== void 0 && entry.value !== null).map(({ field, value }) => ({
|
|
1162
|
+
label: field.label,
|
|
1163
|
+
value: toText(value),
|
|
1164
|
+
unit: field.unit ?? null
|
|
1165
|
+
}));
|
|
1166
|
+
return readings.length === 0 ? null : {
|
|
1167
|
+
kind: "metrics",
|
|
1168
|
+
readings
|
|
1169
|
+
};
|
|
1170
|
+
}
|
|
1171
|
+
case "log": {
|
|
1172
|
+
const lines = readPath(output, resolved.lines);
|
|
1173
|
+
if (!Array.isArray(lines) || lines.length === 0) return null;
|
|
1174
|
+
return {
|
|
1175
|
+
kind: "log",
|
|
1176
|
+
lines: lines.map(toText)
|
|
1177
|
+
};
|
|
1178
|
+
}
|
|
1179
|
+
case "table": {
|
|
1180
|
+
const rows = readPath(output, resolved.rows);
|
|
1181
|
+
if (!Array.isArray(rows)) return null;
|
|
1182
|
+
return {
|
|
1183
|
+
kind: "table",
|
|
1184
|
+
columns: resolved.columns,
|
|
1185
|
+
rows: rows.map((row) => resolved.columns.map((column) => toText(readPath(row, column.path)))),
|
|
1186
|
+
empty: rows.length === 0 ? resolved.empty ?? null : null
|
|
1187
|
+
};
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
__name(resolveResultView, "resolveResultView");
|
|
1192
|
+
|
|
1193
|
+
// src/presentation/tool-activity.ts
|
|
1194
|
+
function isActionCall(part) {
|
|
1195
|
+
const metadata = part.toolMetadata;
|
|
1196
|
+
return typeof metadata === "object" && metadata !== null && metadata.toolKind === "action";
|
|
1197
|
+
}
|
|
1198
|
+
__name(isActionCall, "isActionCall");
|
|
1199
|
+
function toolCallState(part) {
|
|
1200
|
+
const output = "output" in part ? part.output : void 0;
|
|
1201
|
+
const errorText = "errorText" in part ? part.errorText : void 0;
|
|
1202
|
+
const outputError = output !== null && typeof output === "object" && "error" in output ? String(output.error) : void 0;
|
|
1203
|
+
const isDenied = part.state === "output-denied";
|
|
1204
|
+
const isFailed = part.state === "output-error" || outputError !== void 0 && !isDenied;
|
|
1205
|
+
const isSettled2 = part.state === "output-available" || part.state === "output-error" || isDenied;
|
|
1206
|
+
const isAwaiting = part.state === "approval-requested" || part.state === "input-available" && isActionCall(part);
|
|
1207
|
+
const status = isDenied ? "denied" : isFailed ? "failed" : isSettled2 ? "done" : isAwaiting ? "awaiting-approval" : "running";
|
|
1208
|
+
return {
|
|
1209
|
+
status,
|
|
1210
|
+
isSettled: isSettled2,
|
|
1211
|
+
isFailed,
|
|
1212
|
+
isDenied,
|
|
1213
|
+
output,
|
|
1214
|
+
error: errorText ?? outputError ?? null
|
|
1215
|
+
};
|
|
1216
|
+
}
|
|
1217
|
+
__name(toolCallState, "toolCallState");
|
|
1218
|
+
function correctedCallIds(parts) {
|
|
1219
|
+
const corrected = /* @__PURE__ */ new Set();
|
|
1220
|
+
const lastSuccessByTool = /* @__PURE__ */ new Map();
|
|
1221
|
+
parts.forEach((part, index) => {
|
|
1222
|
+
if (part.state === "output-available" && !toolCallState(part).isFailed) {
|
|
1223
|
+
lastSuccessByTool.set((0, import_ai.getToolName)(part), index);
|
|
1224
|
+
}
|
|
1225
|
+
});
|
|
1226
|
+
parts.forEach((part, index) => {
|
|
1227
|
+
const successAt = lastSuccessByTool.get((0, import_ai.getToolName)(part));
|
|
1228
|
+
if (successAt !== void 0 && index < successAt && toolCallState(part).isFailed) {
|
|
1229
|
+
corrected.add(part.toolCallId);
|
|
1230
|
+
}
|
|
1231
|
+
});
|
|
1232
|
+
return corrected;
|
|
1233
|
+
}
|
|
1234
|
+
__name(correctedCallIds, "correctedCallIds");
|
|
1235
|
+
function describeToolCall(part, catalog, options = {}) {
|
|
1236
|
+
const presentation = catalog?.[(0, import_ai.getToolName)(part)];
|
|
1237
|
+
const state = toolCallState(part);
|
|
1238
|
+
const input = part.input;
|
|
1239
|
+
const confirm = presentation?.confirm;
|
|
1240
|
+
return {
|
|
1241
|
+
status: state.status,
|
|
1242
|
+
phrase: phraseFor(presentation, input, state.isSettled, options.fallback),
|
|
1243
|
+
label: presentation?.label ?? null,
|
|
1244
|
+
icon: presentation?.icon ?? null,
|
|
1245
|
+
tone: presentation?.tone ?? "neutral",
|
|
1246
|
+
detail: presentation?.detail ?? null,
|
|
1247
|
+
confirm: confirm === void 0 ? null : {
|
|
1248
|
+
title: fillTemplate(confirm.title, input),
|
|
1249
|
+
verb: confirm.verb,
|
|
1250
|
+
detail: confirm.detail !== void 0 ? fillTemplate(confirm.detail, input) : null
|
|
1251
|
+
},
|
|
1252
|
+
result: state.status === "done" ? resolveResultView(state.output, presentation?.result, {
|
|
1253
|
+
...options.inferResult !== void 0 ? {
|
|
1254
|
+
infer: options.inferResult
|
|
1255
|
+
} : {}
|
|
1256
|
+
}) : null,
|
|
1257
|
+
error: state.error,
|
|
1258
|
+
presentation: presentation ?? null
|
|
1259
|
+
};
|
|
1260
|
+
}
|
|
1261
|
+
__name(describeToolCall, "describeToolCall");
|
|
1262
|
+
var STATUS_WEIGHT = {
|
|
1263
|
+
running: 4,
|
|
1264
|
+
"awaiting-approval": 3,
|
|
1265
|
+
failed: 2,
|
|
1266
|
+
denied: 1,
|
|
1267
|
+
done: 0
|
|
1268
|
+
};
|
|
1269
|
+
function descendants(call) {
|
|
1270
|
+
return call.children.flatMap((child) => [
|
|
1271
|
+
child,
|
|
1272
|
+
...descendants(child)
|
|
1273
|
+
]);
|
|
1274
|
+
}
|
|
1275
|
+
__name(descendants, "descendants");
|
|
1276
|
+
function leaves(call) {
|
|
1277
|
+
return call.children.length === 0 ? [
|
|
1278
|
+
call
|
|
1279
|
+
] : call.children.flatMap(leaves);
|
|
1280
|
+
}
|
|
1281
|
+
__name(leaves, "leaves");
|
|
1282
|
+
function groupToolActivity(calls, options = {}) {
|
|
1283
|
+
const expanded = options.expandNested === true ? calls.flatMap(leaves) : [
|
|
1284
|
+
...calls
|
|
1285
|
+
];
|
|
1286
|
+
const corrected = options.hideCorrected === true ? correctedCallIds(expanded.map((call) => call.part)) : /* @__PURE__ */ new Set();
|
|
1287
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1288
|
+
for (const call of expanded) {
|
|
1289
|
+
if (corrected.has(call.toolCallId)) continue;
|
|
1290
|
+
const presentation = options.catalog?.[call.name];
|
|
1291
|
+
const key = options.keyOf?.(call, presentation) ?? presentation?.label ?? call.name;
|
|
1292
|
+
const status = toolCallState(call.part).status;
|
|
1293
|
+
const phrase = phraseFor(presentation, call.part.input, status !== "running" && status !== "awaiting-approval", options.fallback);
|
|
1294
|
+
const inner = options.expandNested === true ? 0 : descendants(call).length;
|
|
1295
|
+
const existing = groups.get(key);
|
|
1296
|
+
if (existing === void 0) {
|
|
1297
|
+
groups.set(key, {
|
|
1298
|
+
key,
|
|
1299
|
+
label: presentation?.label ?? null,
|
|
1300
|
+
icon: presentation?.icon ?? null,
|
|
1301
|
+
status,
|
|
1302
|
+
count: 1,
|
|
1303
|
+
phrase,
|
|
1304
|
+
calls: [
|
|
1305
|
+
call
|
|
1306
|
+
],
|
|
1307
|
+
innerCount: inner
|
|
1308
|
+
});
|
|
1309
|
+
continue;
|
|
1310
|
+
}
|
|
1311
|
+
existing.count += 1;
|
|
1312
|
+
existing.calls.push(call);
|
|
1313
|
+
existing.phrase = phrase;
|
|
1314
|
+
existing.innerCount += inner;
|
|
1315
|
+
if (STATUS_WEIGHT[status] > STATUS_WEIGHT[existing.status]) existing.status = status;
|
|
1316
|
+
}
|
|
1317
|
+
return [
|
|
1318
|
+
...groups.values()
|
|
1319
|
+
];
|
|
1320
|
+
}
|
|
1321
|
+
__name(groupToolActivity, "groupToolActivity");
|
|
1322
|
+
|
|
1323
|
+
// src/transcript/model.ts
|
|
965
1324
|
function buildTranscriptBlocks(message, options) {
|
|
966
1325
|
const blocks = [];
|
|
967
1326
|
let toolBuffer = [];
|
|
@@ -978,13 +1337,19 @@ function buildTranscriptBlocks(message, options) {
|
|
|
978
1337
|
if (toolBuffer.length === 0) {
|
|
979
1338
|
return;
|
|
980
1339
|
}
|
|
981
|
-
const calls = toolBuffer.map((part) => buildToolCall(part, options.approval, approvals.get(part.toolCallId) ?? null));
|
|
1340
|
+
const calls = toolBuffer.map((part) => buildToolCall(part, options.approval, approvals.get(part.toolCallId) ?? null, options.toolCatalog));
|
|
1341
|
+
const roots = nestToolCalls(calls);
|
|
982
1342
|
blocks.push({
|
|
983
1343
|
kind: "tools",
|
|
984
1344
|
key: `${message.id}-tools-${toolCounter++}`,
|
|
985
1345
|
parts: toolBuffer,
|
|
986
1346
|
calls,
|
|
987
|
-
roots
|
|
1347
|
+
roots,
|
|
1348
|
+
activity: groupToolActivity(roots, {
|
|
1349
|
+
...options.toolCatalog !== void 0 ? {
|
|
1350
|
+
catalog: options.toolCatalog
|
|
1351
|
+
} : {}
|
|
1352
|
+
})
|
|
988
1353
|
});
|
|
989
1354
|
toolBuffer = [];
|
|
990
1355
|
}
|
|
@@ -1021,7 +1386,7 @@ function buildTranscriptBlocks(message, options) {
|
|
|
1021
1386
|
}
|
|
1022
1387
|
__name(flushAll, "flushAll");
|
|
1023
1388
|
for (const part of message.parts ?? []) {
|
|
1024
|
-
if ((0,
|
|
1389
|
+
if ((0, import_ai2.isToolUIPart)(part)) {
|
|
1025
1390
|
const elicitation = options.elicitation;
|
|
1026
1391
|
if (elicitation !== void 0) {
|
|
1027
1392
|
const request = readElicitationRequest(part);
|
|
@@ -1041,7 +1406,7 @@ function buildTranscriptBlocks(message, options) {
|
|
|
1041
1406
|
toolBuffer.push(part);
|
|
1042
1407
|
continue;
|
|
1043
1408
|
}
|
|
1044
|
-
if ((0,
|
|
1409
|
+
if ((0, import_ai2.isFileUIPart)(part)) {
|
|
1045
1410
|
flushTools();
|
|
1046
1411
|
flushSources();
|
|
1047
1412
|
fileBuffer.push(part);
|
|
@@ -1051,7 +1416,7 @@ function buildTranscriptBlocks(message, options) {
|
|
|
1051
1416
|
continue;
|
|
1052
1417
|
}
|
|
1053
1418
|
flushAll();
|
|
1054
|
-
if ((0,
|
|
1419
|
+
if ((0, import_ai2.isDataUIPart)(part)) {
|
|
1055
1420
|
const ui = part.type === UI_PART ? readUiComponent(part) : null;
|
|
1056
1421
|
if (ui !== null) {
|
|
1057
1422
|
blocks.push({
|
|
@@ -1062,7 +1427,7 @@ function buildTranscriptBlocks(message, options) {
|
|
|
1062
1427
|
}
|
|
1063
1428
|
continue;
|
|
1064
1429
|
}
|
|
1065
|
-
if ((0,
|
|
1430
|
+
if ((0, import_ai2.isTextUIPart)(part)) {
|
|
1066
1431
|
blocks.push({
|
|
1067
1432
|
kind: "text",
|
|
1068
1433
|
key: `${message.id}-text-${textCounter++}`,
|
|
@@ -1071,7 +1436,7 @@ function buildTranscriptBlocks(message, options) {
|
|
|
1071
1436
|
});
|
|
1072
1437
|
continue;
|
|
1073
1438
|
}
|
|
1074
|
-
if ((0,
|
|
1439
|
+
if ((0, import_ai2.isReasoningUIPart)(part)) {
|
|
1075
1440
|
const key = `${message.id}-reasoning-${reasoningCounter++}`;
|
|
1076
1441
|
const isStreaming = part.state === "streaming";
|
|
1077
1442
|
blocks.push({
|
|
@@ -1079,6 +1444,7 @@ function buildTranscriptBlocks(message, options) {
|
|
|
1079
1444
|
key,
|
|
1080
1445
|
text: part.text,
|
|
1081
1446
|
isStreaming,
|
|
1447
|
+
durationMs: readReasoningMs(part),
|
|
1082
1448
|
isOpen: options.isReasoningOpen(key, isStreaming),
|
|
1083
1449
|
toggle: /* @__PURE__ */ __name((open) => options.toggleReasoning(key, open), "toggle")
|
|
1084
1450
|
});
|
|
@@ -1132,7 +1498,7 @@ function isSettled(state) {
|
|
|
1132
1498
|
__name(isSettled, "isSettled");
|
|
1133
1499
|
function toolKind(part) {
|
|
1134
1500
|
const metadata = part.toolMetadata;
|
|
1135
|
-
return
|
|
1501
|
+
return isRecord2(metadata) && typeof metadata.toolKind === "string" ? metadata.toolKind : void 0;
|
|
1136
1502
|
}
|
|
1137
1503
|
__name(toolKind, "toolKind");
|
|
1138
1504
|
function isAwaitingApproval(part) {
|
|
@@ -1147,7 +1513,7 @@ function isAwaitingApproval(part) {
|
|
|
1147
1513
|
__name(isAwaitingApproval, "isAwaitingApproval");
|
|
1148
1514
|
function toolParentId(part) {
|
|
1149
1515
|
const metadata = part.toolMetadata;
|
|
1150
|
-
return
|
|
1516
|
+
return isRecord2(metadata) && typeof metadata.parentId === "string" ? metadata.parentId : null;
|
|
1151
1517
|
}
|
|
1152
1518
|
__name(toolParentId, "toolParentId");
|
|
1153
1519
|
function nestToolCalls(calls) {
|
|
@@ -1180,18 +1546,19 @@ function isAncestor(call, candidate, byId) {
|
|
|
1180
1546
|
return false;
|
|
1181
1547
|
}
|
|
1182
1548
|
__name(isAncestor, "isAncestor");
|
|
1183
|
-
function buildToolCall(part, options, approval) {
|
|
1549
|
+
function buildToolCall(part, options, approval, catalog) {
|
|
1184
1550
|
const toolCallId = part.toolCallId;
|
|
1185
1551
|
const awaiting = isAwaitingApproval(part);
|
|
1186
1552
|
const sending = awaiting ? options?.submitting(toolCallId) ?? null : null;
|
|
1187
1553
|
return {
|
|
1188
1554
|
part,
|
|
1189
1555
|
toolCallId,
|
|
1190
|
-
name: (0,
|
|
1556
|
+
name: (0, import_ai2.getToolName)(part),
|
|
1191
1557
|
toolKind: toolKind(part) ?? null,
|
|
1192
1558
|
parentId: toolParentId(part),
|
|
1193
1559
|
children: [],
|
|
1194
1560
|
approval,
|
|
1561
|
+
description: describeToolCall(part, catalog),
|
|
1195
1562
|
isAwaitingApproval: awaiting,
|
|
1196
1563
|
approve: {
|
|
1197
1564
|
available: awaiting && options?.canApprove === true,
|
|
@@ -1209,17 +1576,17 @@ function buildToolCall(part, options, approval) {
|
|
|
1209
1576
|
__name(buildToolCall, "buildToolCall");
|
|
1210
1577
|
function readElicitationRequest(part) {
|
|
1211
1578
|
const input = part.input;
|
|
1212
|
-
if (!
|
|
1579
|
+
if (!isRecord2(input) || !Array.isArray(input.questions) || input.questions.length === 0) {
|
|
1213
1580
|
return null;
|
|
1214
1581
|
}
|
|
1215
1582
|
const questions = [];
|
|
1216
1583
|
for (const candidate of input.questions) {
|
|
1217
|
-
if (!
|
|
1584
|
+
if (!isRecord2(candidate) || typeof candidate.id !== "string" || typeof candidate.prompt !== "string" || !Array.isArray(candidate.options) || candidate.options.length === 0) {
|
|
1218
1585
|
return null;
|
|
1219
1586
|
}
|
|
1220
1587
|
const options = [];
|
|
1221
1588
|
for (const option of candidate.options) {
|
|
1222
|
-
if (!
|
|
1589
|
+
if (!isRecord2(option) || typeof option.value !== "string" || typeof option.label !== "string") {
|
|
1223
1590
|
return null;
|
|
1224
1591
|
}
|
|
1225
1592
|
options.push({
|
|
@@ -1244,7 +1611,7 @@ function readElicitationRequest(part) {
|
|
|
1244
1611
|
__name(readElicitationRequest, "readElicitationRequest");
|
|
1245
1612
|
function readElicitationOutcome(part) {
|
|
1246
1613
|
const output = part.output;
|
|
1247
|
-
if (!
|
|
1614
|
+
if (!isRecord2(output) || !isRecord2(output.answers) || typeof output.skipped !== "boolean") {
|
|
1248
1615
|
return null;
|
|
1249
1616
|
}
|
|
1250
1617
|
const answers = {};
|
|
@@ -1331,7 +1698,7 @@ function readApprovals(parts) {
|
|
|
1331
1698
|
continue;
|
|
1332
1699
|
}
|
|
1333
1700
|
const data = part.data;
|
|
1334
|
-
if (!
|
|
1701
|
+
if (!isRecord2(data) || typeof data.id !== "string" || typeof data.approver !== "string") {
|
|
1335
1702
|
continue;
|
|
1336
1703
|
}
|
|
1337
1704
|
out.set(data.id, {
|
|
@@ -1345,7 +1712,7 @@ function readApprovals(parts) {
|
|
|
1345
1712
|
__name(readApprovals, "readApprovals");
|
|
1346
1713
|
function readUiComponent(part) {
|
|
1347
1714
|
const data = part.data;
|
|
1348
|
-
if (!
|
|
1715
|
+
if (!isRecord2(data) || typeof data.component !== "string") {
|
|
1349
1716
|
return null;
|
|
1350
1717
|
}
|
|
1351
1718
|
const id = typeof data.id === "string" ? data.id : part.id;
|
|
@@ -1355,18 +1722,18 @@ function readUiComponent(part) {
|
|
|
1355
1722
|
return {
|
|
1356
1723
|
id,
|
|
1357
1724
|
component: data.component,
|
|
1358
|
-
props:
|
|
1725
|
+
props: isRecord2(data.props) ? data.props : {},
|
|
1359
1726
|
version: typeof data.version === "number" ? data.version : null
|
|
1360
1727
|
};
|
|
1361
1728
|
}
|
|
1362
1729
|
__name(readUiComponent, "readUiComponent");
|
|
1363
|
-
function
|
|
1730
|
+
function isRecord2(value) {
|
|
1364
1731
|
return typeof value === "object" && value !== null;
|
|
1365
1732
|
}
|
|
1366
|
-
__name(
|
|
1733
|
+
__name(isRecord2, "isRecord");
|
|
1367
1734
|
function readQuery(part) {
|
|
1368
1735
|
const input = part.input;
|
|
1369
|
-
if (!
|
|
1736
|
+
if (!isRecord2(input) || typeof input.query !== "string") {
|
|
1370
1737
|
return null;
|
|
1371
1738
|
}
|
|
1372
1739
|
return input.query;
|
|
@@ -1374,12 +1741,12 @@ function readQuery(part) {
|
|
|
1374
1741
|
__name(readQuery, "readQuery");
|
|
1375
1742
|
function readPassages(part) {
|
|
1376
1743
|
const output = part.output;
|
|
1377
|
-
if (!
|
|
1744
|
+
if (!isRecord2(output) || !Array.isArray(output.passages) || output.passages.length === 0) {
|
|
1378
1745
|
return null;
|
|
1379
1746
|
}
|
|
1380
1747
|
const passages = [];
|
|
1381
1748
|
for (const candidate of output.passages) {
|
|
1382
|
-
if (!
|
|
1749
|
+
if (!isRecord2(candidate) || typeof candidate.id !== "string" || typeof candidate.text !== "string") {
|
|
1383
1750
|
return null;
|
|
1384
1751
|
}
|
|
1385
1752
|
passages.push({
|
|
@@ -1389,7 +1756,7 @@ function readPassages(part) {
|
|
|
1389
1756
|
...typeof candidate.source === "string" ? {
|
|
1390
1757
|
source: candidate.source
|
|
1391
1758
|
} : {},
|
|
1392
|
-
...
|
|
1759
|
+
...isRecord2(candidate.metadata) ? {
|
|
1393
1760
|
metadata: candidate.metadata
|
|
1394
1761
|
} : {}
|
|
1395
1762
|
});
|
|
@@ -1400,7 +1767,7 @@ __name(readPassages, "readPassages");
|
|
|
1400
1767
|
function extractMessageText(parts) {
|
|
1401
1768
|
const out = [];
|
|
1402
1769
|
for (const part of parts ?? []) {
|
|
1403
|
-
if ((0,
|
|
1770
|
+
if ((0, import_ai2.isTextUIPart)(part)) {
|
|
1404
1771
|
out.push(part.text);
|
|
1405
1772
|
}
|
|
1406
1773
|
}
|
|
@@ -1491,11 +1858,11 @@ function formatCostUsd(cost) {
|
|
|
1491
1858
|
__name(formatCostUsd, "formatCostUsd");
|
|
1492
1859
|
|
|
1493
1860
|
// src/transcript/use-stick-to-bottom.ts
|
|
1494
|
-
var
|
|
1861
|
+
var import_react4 = require("react");
|
|
1495
1862
|
function useStickToBottom({ contentKey, threshold = 32 }) {
|
|
1496
|
-
const containerRef = (0,
|
|
1497
|
-
const [isAtBottom, setIsAtBottom] = (0,
|
|
1498
|
-
const measure = (0,
|
|
1863
|
+
const containerRef = (0, import_react4.useRef)(null);
|
|
1864
|
+
const [isAtBottom, setIsAtBottom] = (0, import_react4.useState)(true);
|
|
1865
|
+
const measure = (0, import_react4.useCallback)(() => {
|
|
1499
1866
|
const element = containerRef.current;
|
|
1500
1867
|
if (!element) {
|
|
1501
1868
|
return;
|
|
@@ -1505,7 +1872,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
|
|
|
1505
1872
|
}, [
|
|
1506
1873
|
threshold
|
|
1507
1874
|
]);
|
|
1508
|
-
const scrollToBottom = (0,
|
|
1875
|
+
const scrollToBottom = (0, import_react4.useCallback)(() => {
|
|
1509
1876
|
const element = containerRef.current;
|
|
1510
1877
|
if (!element) {
|
|
1511
1878
|
return;
|
|
@@ -1513,7 +1880,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
|
|
|
1513
1880
|
element.scrollTop = element.scrollHeight;
|
|
1514
1881
|
setIsAtBottom(true);
|
|
1515
1882
|
}, []);
|
|
1516
|
-
const setContainer = (0,
|
|
1883
|
+
const setContainer = (0, import_react4.useCallback)((element) => {
|
|
1517
1884
|
containerRef.current = element;
|
|
1518
1885
|
if (element) {
|
|
1519
1886
|
measure();
|
|
@@ -1521,7 +1888,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
|
|
|
1521
1888
|
}, [
|
|
1522
1889
|
measure
|
|
1523
1890
|
]);
|
|
1524
|
-
(0,
|
|
1891
|
+
(0, import_react4.useEffect)(() => {
|
|
1525
1892
|
if (isAtBottom) {
|
|
1526
1893
|
scrollToBottom();
|
|
1527
1894
|
}
|
|
@@ -1530,7 +1897,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
|
|
|
1530
1897
|
isAtBottom,
|
|
1531
1898
|
scrollToBottom
|
|
1532
1899
|
]);
|
|
1533
|
-
const getContainerProps = (0,
|
|
1900
|
+
const getContainerProps = (0, import_react4.useCallback)(() => ({
|
|
1534
1901
|
ref: setContainer,
|
|
1535
1902
|
onScroll: measure
|
|
1536
1903
|
}), [
|
|
@@ -1552,14 +1919,14 @@ var DEFAULT_LOAD_EARLIER_STEP = 50;
|
|
|
1552
1919
|
var DEFAULT_COPY_RESET_MS = 1500;
|
|
1553
1920
|
function useChatTranscript(options) {
|
|
1554
1921
|
const { messages, status, initialVisibleCount = DEFAULT_VISIBLE_COUNT, loadEarlierStep = DEFAULT_LOAD_EARLIER_STEP, followUps, stickToBottomThreshold } = options;
|
|
1555
|
-
const latest = (0,
|
|
1922
|
+
const latest = (0, import_react5.useRef)(options);
|
|
1556
1923
|
latest.current = options;
|
|
1557
|
-
const [visibleCount, setVisibleCount] = (0,
|
|
1558
|
-
const [stopRequested, setStopRequested] = (0,
|
|
1924
|
+
const [visibleCount, setVisibleCount] = (0, import_react5.useState)(initialVisibleCount);
|
|
1925
|
+
const [stopRequested, setStopRequested] = (0, import_react5.useState)(false);
|
|
1559
1926
|
const isStreaming = status === "streaming";
|
|
1560
1927
|
const isBusy = status === "submitted" || isStreaming;
|
|
1561
1928
|
const isEmpty = messages.length === 0;
|
|
1562
|
-
(0,
|
|
1929
|
+
(0, import_react5.useEffect)(() => {
|
|
1563
1930
|
if (!isBusy) {
|
|
1564
1931
|
setStopRequested(false);
|
|
1565
1932
|
}
|
|
@@ -1576,7 +1943,7 @@ function useChatTranscript(options) {
|
|
|
1576
1943
|
streamingMessageId,
|
|
1577
1944
|
options
|
|
1578
1945
|
});
|
|
1579
|
-
const stop = (0,
|
|
1946
|
+
const stop = (0, import_react5.useCallback)(() => {
|
|
1580
1947
|
const current = latest.current;
|
|
1581
1948
|
if (current.status !== "submitted" && current.status !== "streaming") {
|
|
1582
1949
|
return;
|
|
@@ -1584,8 +1951,8 @@ function useChatTranscript(options) {
|
|
|
1584
1951
|
setStopRequested(true);
|
|
1585
1952
|
void current.onStop?.();
|
|
1586
1953
|
}, []);
|
|
1587
|
-
const loadEarlier = (0,
|
|
1588
|
-
const showAll = (0,
|
|
1954
|
+
const loadEarlier = (0, import_react5.useCallback)(() => setVisibleCount((count) => count + (latest.current.loadEarlierStep ?? DEFAULT_LOAD_EARLIER_STEP)), []);
|
|
1955
|
+
const showAll = (0, import_react5.useCallback)(() => setVisibleCount(latest.current.messages.length), []);
|
|
1589
1956
|
const scroll = useStickToBottom({
|
|
1590
1957
|
contentKey: contentSignature(messages),
|
|
1591
1958
|
...stickToBottomThreshold !== void 0 ? {
|
|
@@ -1621,7 +1988,7 @@ function useChatTranscript(options) {
|
|
|
1621
1988
|
__name(useChatTranscript, "useChatTranscript");
|
|
1622
1989
|
function useTranscriptItem(options) {
|
|
1623
1990
|
const { message, isStreaming = false } = options;
|
|
1624
|
-
const messagesRef = (0,
|
|
1991
|
+
const messagesRef = (0, import_react5.useRef)([
|
|
1625
1992
|
message
|
|
1626
1993
|
]);
|
|
1627
1994
|
if (messagesRef.current[0] !== message) {
|
|
@@ -1639,13 +2006,13 @@ function useTranscriptItem(options) {
|
|
|
1639
2006
|
}
|
|
1640
2007
|
__name(useTranscriptItem, "useTranscriptItem");
|
|
1641
2008
|
function useTranscriptItems({ messages, visibleStart, streamingMessageId, options }) {
|
|
1642
|
-
const [drafts, setDrafts] = (0,
|
|
1643
|
-
const [copied, setCopied] = (0,
|
|
1644
|
-
const [openReasoning, setOpenReasoning] = (0,
|
|
1645
|
-
const [picks, setPicks] = (0,
|
|
1646
|
-
const [settling, setSettling] = (0,
|
|
1647
|
-
const [settleErrors, setSettleErrors] = (0,
|
|
1648
|
-
const latest = (0,
|
|
2009
|
+
const [drafts, setDrafts] = (0, import_react5.useState)(() => /* @__PURE__ */ new Map());
|
|
2010
|
+
const [copied, setCopied] = (0, import_react5.useState)(() => /* @__PURE__ */ new Set());
|
|
2011
|
+
const [openReasoning, setOpenReasoning] = (0, import_react5.useState)(() => /* @__PURE__ */ new Map());
|
|
2012
|
+
const [picks, setPicks] = (0, import_react5.useState)(() => /* @__PURE__ */ new Map());
|
|
2013
|
+
const [settling, setSettling] = (0, import_react5.useState)(() => /* @__PURE__ */ new Map());
|
|
2014
|
+
const [settleErrors, setSettleErrors] = (0, import_react5.useState)(() => /* @__PURE__ */ new Map());
|
|
2015
|
+
const latest = (0, import_react5.useRef)({
|
|
1649
2016
|
options,
|
|
1650
2017
|
drafts,
|
|
1651
2018
|
picks,
|
|
@@ -1657,23 +2024,23 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
1657
2024
|
picks,
|
|
1658
2025
|
messages
|
|
1659
2026
|
};
|
|
1660
|
-
const copyTimers = (0,
|
|
1661
|
-
(0,
|
|
2027
|
+
const copyTimers = (0, import_react5.useRef)(/* @__PURE__ */ new Map());
|
|
2028
|
+
(0, import_react5.useEffect)(() => () => {
|
|
1662
2029
|
for (const timer of copyTimers.current.values()) {
|
|
1663
2030
|
clearTimeout(timer);
|
|
1664
2031
|
}
|
|
1665
2032
|
copyTimers.current.clear();
|
|
1666
2033
|
}, []);
|
|
1667
|
-
const callbackCache = (0,
|
|
1668
|
-
const reasoningToggleCache = (0,
|
|
1669
|
-
const toggleReasoning = (0,
|
|
2034
|
+
const callbackCache = (0, import_react5.useRef)(/* @__PURE__ */ new Map());
|
|
2035
|
+
const reasoningToggleCache = (0, import_react5.useRef)(/* @__PURE__ */ new Map());
|
|
2036
|
+
const toggleReasoning = (0, import_react5.useCallback)((key, open) => {
|
|
1670
2037
|
setOpenReasoning((current) => {
|
|
1671
2038
|
const next = new Map(current);
|
|
1672
2039
|
next.set(key, open ?? !(current.get(key) ?? false));
|
|
1673
2040
|
return next;
|
|
1674
2041
|
});
|
|
1675
2042
|
}, []);
|
|
1676
|
-
const stableToggle = (0,
|
|
2043
|
+
const stableToggle = (0, import_react5.useCallback)((key) => {
|
|
1677
2044
|
let cached = reasoningToggleCache.current.get(key);
|
|
1678
2045
|
if (!cached) {
|
|
1679
2046
|
cached = /* @__PURE__ */ __name((open) => toggleReasoning(key, open), "cached");
|
|
@@ -1683,10 +2050,10 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
1683
2050
|
}, [
|
|
1684
2051
|
toggleReasoning
|
|
1685
2052
|
]);
|
|
1686
|
-
const pick = (0,
|
|
2053
|
+
const pick = (0, import_react5.useCallback)((toolCallId, questionId, values) => {
|
|
1687
2054
|
setPicks((current) => new Map(current).set(pickKey(toolCallId, questionId), values));
|
|
1688
2055
|
}, []);
|
|
1689
|
-
const settle = (0,
|
|
2056
|
+
const settle = (0, import_react5.useCallback)((toolCallId, action, send) => {
|
|
1690
2057
|
setSettleErrors((current) => {
|
|
1691
2058
|
if (!current.has(toolCallId)) {
|
|
1692
2059
|
return current;
|
|
@@ -1710,7 +2077,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
1710
2077
|
failed(error);
|
|
1711
2078
|
}
|
|
1712
2079
|
}, []);
|
|
1713
|
-
const answer = (0,
|
|
2080
|
+
const answer = (0, import_react5.useCallback)((toolCallId) => {
|
|
1714
2081
|
const current = latest.current;
|
|
1715
2082
|
const onAnswer = current.options.onAnswer;
|
|
1716
2083
|
if (!onAnswer) {
|
|
@@ -1720,7 +2087,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
1720
2087
|
}, [
|
|
1721
2088
|
settle
|
|
1722
2089
|
]);
|
|
1723
|
-
const skip = (0,
|
|
2090
|
+
const skip = (0, import_react5.useCallback)((toolCallId) => {
|
|
1724
2091
|
const onSkip = latest.current.options.onSkip;
|
|
1725
2092
|
if (onSkip) {
|
|
1726
2093
|
settle(toolCallId, "skip", () => onSkip(toolCallId));
|
|
@@ -1728,7 +2095,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
1728
2095
|
}, [
|
|
1729
2096
|
settle
|
|
1730
2097
|
]);
|
|
1731
|
-
const approve = (0,
|
|
2098
|
+
const approve = (0, import_react5.useCallback)((toolCallId) => {
|
|
1732
2099
|
const onApprove = latest.current.options.onApprove;
|
|
1733
2100
|
if (onApprove) {
|
|
1734
2101
|
settle(toolCallId, "approve", () => onApprove(toolCallId));
|
|
@@ -1736,7 +2103,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
1736
2103
|
}, [
|
|
1737
2104
|
settle
|
|
1738
2105
|
]);
|
|
1739
|
-
const reject = (0,
|
|
2106
|
+
const reject = (0, import_react5.useCallback)((toolCallId) => {
|
|
1740
2107
|
const onReject = latest.current.options.onReject;
|
|
1741
2108
|
if (onReject) {
|
|
1742
2109
|
settle(toolCallId, "reject", () => onReject(toolCallId));
|
|
@@ -1744,7 +2111,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
1744
2111
|
}, [
|
|
1745
2112
|
settle
|
|
1746
2113
|
]);
|
|
1747
|
-
const callbacksFor = (0,
|
|
2114
|
+
const callbacksFor = (0, import_react5.useCallback)((id) => {
|
|
1748
2115
|
const cached = callbackCache.current.get(id);
|
|
1749
2116
|
if (cached) {
|
|
1750
2117
|
return cached;
|
|
@@ -1856,6 +2223,9 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
1856
2223
|
...options.sources !== void 0 ? {
|
|
1857
2224
|
sources: options.sources
|
|
1858
2225
|
} : {},
|
|
2226
|
+
...options.toolCatalog !== void 0 ? {
|
|
2227
|
+
toolCatalog: options.toolCatalog
|
|
2228
|
+
} : {},
|
|
1859
2229
|
...options.onAnswer !== void 0 ? {
|
|
1860
2230
|
elicitation: {
|
|
1861
2231
|
picked: /* @__PURE__ */ __name((toolCallId, questionId) => picks.get(pickKey(toolCallId, questionId)), "picked"),
|
|
@@ -1983,7 +2353,7 @@ function MessageItem({ message, isStreaming = false, editable, onEditSubmit, reg
|
|
|
1983
2353
|
getCreatedAt: /* @__PURE__ */ __name(() => createdAt, "getCreatedAt")
|
|
1984
2354
|
} : {}
|
|
1985
2355
|
});
|
|
1986
|
-
return /* @__PURE__ */
|
|
2356
|
+
return /* @__PURE__ */ import_react6.default.createElement(MessageItemView, {
|
|
1987
2357
|
item,
|
|
1988
2358
|
...slots
|
|
1989
2359
|
});
|
|
@@ -1991,51 +2361,51 @@ function MessageItem({ message, isStreaming = false, editable, onEditSubmit, reg
|
|
|
1991
2361
|
__name(MessageItem, "MessageItem");
|
|
1992
2362
|
function MessageItemView({ item, ...slots }) {
|
|
1993
2363
|
const { classNames } = slots;
|
|
1994
|
-
const actionRow = /* @__PURE__ */
|
|
2364
|
+
const actionRow = /* @__PURE__ */ import_react6.default.createElement("div", {
|
|
1995
2365
|
className: classNames?.actions,
|
|
1996
2366
|
"data-actions-for": item.role
|
|
1997
|
-
}, item.copy.available ? /* @__PURE__ */
|
|
2367
|
+
}, item.copy.available ? /* @__PURE__ */ import_react6.default.createElement("button", {
|
|
1998
2368
|
type: "button",
|
|
1999
2369
|
onClick: item.copy.copy,
|
|
2000
2370
|
className: classNames?.actionButton,
|
|
2001
2371
|
title: item.copy.copied ? "Copied!" : "Copy message text"
|
|
2002
|
-
}, item.copy.copied ? "Copied" : "Copy") : null, item.fork.available ? /* @__PURE__ */
|
|
2372
|
+
}, item.copy.copied ? "Copied" : "Copy") : null, item.fork.available ? /* @__PURE__ */ import_react6.default.createElement("button", {
|
|
2003
2373
|
type: "button",
|
|
2004
2374
|
onClick: item.fork.run,
|
|
2005
2375
|
className: classNames?.actionButton,
|
|
2006
2376
|
title: "Fork thread from this message"
|
|
2007
|
-
}, "Fork") : null, item.regenerate.available ? /* @__PURE__ */
|
|
2377
|
+
}, "Fork") : null, item.regenerate.available ? /* @__PURE__ */ import_react6.default.createElement("button", {
|
|
2008
2378
|
type: "button",
|
|
2009
2379
|
onClick: item.regenerate.run,
|
|
2010
2380
|
className: classNames?.actionButton,
|
|
2011
2381
|
title: "Regenerate response"
|
|
2012
|
-
}, "Regenerate") : null, slots.meta, !item.isUser && item.usage ? /* @__PURE__ */
|
|
2382
|
+
}, "Regenerate") : null, slots.meta, !item.isUser && item.usage ? /* @__PURE__ */ import_react6.default.createElement("span", {
|
|
2013
2383
|
className: classNames?.usage,
|
|
2014
2384
|
title: `Input ${item.usage.inputTokens.toLocaleString()} \xB7 Output ${item.usage.outputTokens.toLocaleString()} tokens`
|
|
2015
|
-
}, item.usage.costLabel, " \xB7 ", item.usage.tokensLabel) : null, item.timestamp ? /* @__PURE__ */
|
|
2385
|
+
}, item.usage.costLabel, " \xB7 ", item.usage.tokensLabel) : null, item.timestamp ? /* @__PURE__ */ import_react6.default.createElement("span", {
|
|
2016
2386
|
className: classNames?.timestamp,
|
|
2017
2387
|
title: item.timestamp.absolute
|
|
2018
2388
|
}, item.timestamp.relative) : null);
|
|
2019
2389
|
if (item.edit.available) {
|
|
2020
|
-
return /* @__PURE__ */
|
|
2390
|
+
return /* @__PURE__ */ import_react6.default.createElement(EditableUserBubble, {
|
|
2021
2391
|
item,
|
|
2022
2392
|
slots,
|
|
2023
2393
|
actions: actionRow
|
|
2024
2394
|
});
|
|
2025
2395
|
}
|
|
2026
2396
|
const className = joinClasses(classNames?.root, classNames?.byRole?.[item.role]);
|
|
2027
|
-
return /* @__PURE__ */
|
|
2397
|
+
return /* @__PURE__ */ import_react6.default.createElement("div", {
|
|
2028
2398
|
className,
|
|
2029
2399
|
"data-role": item.role,
|
|
2030
2400
|
"data-streaming": item.isStreaming ? "true" : void 0
|
|
2031
|
-
}, /* @__PURE__ */
|
|
2401
|
+
}, /* @__PURE__ */ import_react6.default.createElement("div", null, renderBlocks(item, slots)), actionRow);
|
|
2032
2402
|
}
|
|
2033
2403
|
__name(MessageItemView, "MessageItemView");
|
|
2034
2404
|
function renderBlocks(item, slots) {
|
|
2035
2405
|
const nodes = [];
|
|
2036
2406
|
for (const block of item.blocks) {
|
|
2037
2407
|
if (block.kind === "text") {
|
|
2038
|
-
nodes.push(/* @__PURE__ */
|
|
2408
|
+
nodes.push(/* @__PURE__ */ import_react6.default.createElement("div", {
|
|
2039
2409
|
key: block.key,
|
|
2040
2410
|
className: slots.classNames?.text
|
|
2041
2411
|
}, slots.renderText ? slots.renderText(block.text, {
|
|
@@ -2056,7 +2426,7 @@ function renderBlocks(item, slots) {
|
|
|
2056
2426
|
continue;
|
|
2057
2427
|
}
|
|
2058
2428
|
if (block.kind === "ui" && slots.renderUi) {
|
|
2059
|
-
nodes.push(/* @__PURE__ */
|
|
2429
|
+
nodes.push(/* @__PURE__ */ import_react6.default.createElement("div", {
|
|
2060
2430
|
key: block.key,
|
|
2061
2431
|
"data-slot": "ui",
|
|
2062
2432
|
"data-component": block.component
|
|
@@ -2067,18 +2437,18 @@ function renderBlocks(item, slots) {
|
|
|
2067
2437
|
}
|
|
2068
2438
|
__name(renderBlocks, "renderBlocks");
|
|
2069
2439
|
function renderFilesBlock(block, slots) {
|
|
2070
|
-
return /* @__PURE__ */
|
|
2440
|
+
return /* @__PURE__ */ import_react6.default.createElement("div", {
|
|
2071
2441
|
key: block.key,
|
|
2072
2442
|
className: slots.classNames?.files,
|
|
2073
2443
|
"data-files": "true"
|
|
2074
|
-
}, slots.renderFiles ? slots.renderFiles(block.files) : block.files.map((file) => /* @__PURE__ */
|
|
2444
|
+
}, slots.renderFiles ? slots.renderFiles(block.files) : block.files.map((file) => /* @__PURE__ */ import_react6.default.createElement("a", {
|
|
2075
2445
|
key: file.url,
|
|
2076
2446
|
href: file.url,
|
|
2077
2447
|
target: "_blank",
|
|
2078
2448
|
rel: "noreferrer",
|
|
2079
2449
|
className: slots.classNames?.file,
|
|
2080
2450
|
title: file.filename ?? file.mediaType
|
|
2081
|
-
}, file.isImage ? /* @__PURE__ */
|
|
2451
|
+
}, file.isImage ? /* @__PURE__ */ import_react6.default.createElement("img", {
|
|
2082
2452
|
src: file.url,
|
|
2083
2453
|
alt: file.filename ?? "image",
|
|
2084
2454
|
className: slots.classNames?.fileImage
|
|
@@ -2086,17 +2456,17 @@ function renderFilesBlock(block, slots) {
|
|
|
2086
2456
|
}
|
|
2087
2457
|
__name(renderFilesBlock, "renderFilesBlock");
|
|
2088
2458
|
function renderReasoningBlock(block, slots) {
|
|
2089
|
-
return /* @__PURE__ */
|
|
2459
|
+
return /* @__PURE__ */ import_react6.default.createElement("div", {
|
|
2090
2460
|
key: block.key,
|
|
2091
2461
|
className: slots.classNames?.reasoning,
|
|
2092
2462
|
"data-reasoning": "true",
|
|
2093
2463
|
"data-streaming": block.isStreaming ? "true" : void 0
|
|
2094
|
-
}, /* @__PURE__ */
|
|
2464
|
+
}, /* @__PURE__ */ import_react6.default.createElement("button", {
|
|
2095
2465
|
type: "button",
|
|
2096
2466
|
className: slots.classNames?.reasoningToggle,
|
|
2097
2467
|
onClick: /* @__PURE__ */ __name(() => block.toggle(), "onClick"),
|
|
2098
2468
|
"aria-expanded": block.isOpen
|
|
2099
|
-
}, slots.reasoningLabel ?? "Reasoning"), block.isOpen ? /* @__PURE__ */
|
|
2469
|
+
}, slots.reasoningLabel ?? "Reasoning"), block.isOpen ? /* @__PURE__ */ import_react6.default.createElement("div", {
|
|
2100
2470
|
className: slots.classNames?.reasoningText
|
|
2101
2471
|
}, slots.renderReasoning ? slots.renderReasoning(block.text, {
|
|
2102
2472
|
isStreaming: block.isStreaming,
|
|
@@ -2107,7 +2477,7 @@ __name(renderReasoningBlock, "renderReasoningBlock");
|
|
|
2107
2477
|
function renderToolBlock(item, block, slots) {
|
|
2108
2478
|
if (slots.renderToolGroup) {
|
|
2109
2479
|
return [
|
|
2110
|
-
/* @__PURE__ */
|
|
2480
|
+
/* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, {
|
|
2111
2481
|
key: block.key
|
|
2112
2482
|
}, slots.renderToolGroup(block.parts, block.key))
|
|
2113
2483
|
];
|
|
@@ -2118,7 +2488,7 @@ function renderToolBlock(item, block, slots) {
|
|
|
2118
2488
|
const renderToolPart = slots.renderToolPart;
|
|
2119
2489
|
return block.parts.map((part) => {
|
|
2120
2490
|
const partKey = `${item.id}-${part.toolCallId}`;
|
|
2121
|
-
return /* @__PURE__ */
|
|
2491
|
+
return /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, {
|
|
2122
2492
|
key: partKey
|
|
2123
2493
|
}, renderToolPart(part, partKey));
|
|
2124
2494
|
});
|
|
@@ -2128,14 +2498,14 @@ function EditableUserBubble({ item, slots, actions }) {
|
|
|
2128
2498
|
const { classNames } = slots;
|
|
2129
2499
|
const { edit } = item;
|
|
2130
2500
|
if (!edit.isEditing) {
|
|
2131
|
-
return /* @__PURE__ */
|
|
2501
|
+
return /* @__PURE__ */ import_react6.default.createElement("div", {
|
|
2132
2502
|
className: joinClasses(classNames?.root, classNames?.byRole?.user),
|
|
2133
2503
|
"data-role": "user"
|
|
2134
|
-
}, /* @__PURE__ */
|
|
2504
|
+
}, /* @__PURE__ */ import_react6.default.createElement("div", {
|
|
2135
2505
|
className: classNames?.text
|
|
2136
2506
|
}, slots.renderText ? slots.renderText(item.text, {
|
|
2137
2507
|
isStreaming: false
|
|
2138
|
-
}) : item.text), /* @__PURE__ */
|
|
2508
|
+
}) : item.text), /* @__PURE__ */ import_react6.default.createElement("button", {
|
|
2139
2509
|
type: "button",
|
|
2140
2510
|
onClick: edit.start,
|
|
2141
2511
|
className: classNames?.actionButton,
|
|
@@ -2143,18 +2513,18 @@ function EditableUserBubble({ item, slots, actions }) {
|
|
|
2143
2513
|
}, "Edit"), actions);
|
|
2144
2514
|
}
|
|
2145
2515
|
const textareaProps = edit.getTextareaProps();
|
|
2146
|
-
return /* @__PURE__ */
|
|
2516
|
+
return /* @__PURE__ */ import_react6.default.createElement("div", {
|
|
2147
2517
|
"data-editing": "true"
|
|
2148
|
-
}, /* @__PURE__ */
|
|
2518
|
+
}, /* @__PURE__ */ import_react6.default.createElement("textarea", {
|
|
2149
2519
|
...textareaProps,
|
|
2150
2520
|
rows: Math.min(8, edit.draft.split("\n").length + 1),
|
|
2151
2521
|
className: classNames?.editTextarea
|
|
2152
|
-
}), /* @__PURE__ */
|
|
2522
|
+
}), /* @__PURE__ */ import_react6.default.createElement("div", {
|
|
2153
2523
|
className: classNames?.editActions
|
|
2154
|
-
}, /* @__PURE__ */
|
|
2524
|
+
}, /* @__PURE__ */ import_react6.default.createElement("button", {
|
|
2155
2525
|
type: "button",
|
|
2156
2526
|
onClick: edit.cancel
|
|
2157
|
-
}, "Cancel"), /* @__PURE__ */
|
|
2527
|
+
}, "Cancel"), /* @__PURE__ */ import_react6.default.createElement("button", {
|
|
2158
2528
|
type: "button",
|
|
2159
2529
|
onClick: edit.save,
|
|
2160
2530
|
disabled: !edit.canSave
|
|
@@ -2394,35 +2764,35 @@ function toItem(entry) {
|
|
|
2394
2764
|
__name(toItem, "toItem");
|
|
2395
2765
|
|
|
2396
2766
|
// src/composer/use-composer-autocomplete.ts
|
|
2397
|
-
var
|
|
2767
|
+
var import_react7 = require("react");
|
|
2398
2768
|
function useComposerAutocomplete(options) {
|
|
2399
2769
|
const { value, sources, acceptOnTab = true } = options;
|
|
2400
|
-
const latest = (0,
|
|
2770
|
+
const latest = (0, import_react7.useRef)(options);
|
|
2401
2771
|
latest.current = options;
|
|
2402
|
-
const inputRef = (0,
|
|
2403
|
-
const [caret, setCaret] = (0,
|
|
2404
|
-
const [items, setItems] = (0,
|
|
2405
|
-
const [isLoading, setLoading] = (0,
|
|
2406
|
-
const [error, setError] = (0,
|
|
2407
|
-
const [activeIndex, setActiveIndex] = (0,
|
|
2408
|
-
const [dismissedIndex, setDismissedIndex] = (0,
|
|
2772
|
+
const inputRef = (0, import_react7.useRef)(null);
|
|
2773
|
+
const [caret, setCaret] = (0, import_react7.useState)(value.length);
|
|
2774
|
+
const [items, setItems] = (0, import_react7.useState)([]);
|
|
2775
|
+
const [isLoading, setLoading] = (0, import_react7.useState)(false);
|
|
2776
|
+
const [error, setError] = (0, import_react7.useState)(null);
|
|
2777
|
+
const [activeIndex, setActiveIndex] = (0, import_react7.useState)(0);
|
|
2778
|
+
const [dismissedIndex, setDismissedIndex] = (0, import_react7.useState)(null);
|
|
2409
2779
|
const safeCaret = Math.min(caret, value.length);
|
|
2410
|
-
const match = (0,
|
|
2780
|
+
const match = (0, import_react7.useMemo)(() => findActiveTrigger(value, safeCaret, sources), [
|
|
2411
2781
|
value,
|
|
2412
2782
|
safeCaret,
|
|
2413
2783
|
sources
|
|
2414
2784
|
]);
|
|
2415
2785
|
const isActive = match !== null && dismissedIndex !== match.index;
|
|
2416
|
-
const matchRef = (0,
|
|
2786
|
+
const matchRef = (0, import_react7.useRef)(match);
|
|
2417
2787
|
matchRef.current = match;
|
|
2418
|
-
const caretRef = (0,
|
|
2788
|
+
const caretRef = (0, import_react7.useRef)(safeCaret);
|
|
2419
2789
|
caretRef.current = safeCaret;
|
|
2420
|
-
const itemsRef = (0,
|
|
2790
|
+
const itemsRef = (0, import_react7.useRef)(items);
|
|
2421
2791
|
itemsRef.current = items;
|
|
2422
|
-
const activeIndexRef = (0,
|
|
2792
|
+
const activeIndexRef = (0, import_react7.useRef)(activeIndex);
|
|
2423
2793
|
activeIndexRef.current = activeIndex;
|
|
2424
2794
|
const requestKey = isActive && match ? `${match.source.id}\0${match.query}` : null;
|
|
2425
|
-
(0,
|
|
2795
|
+
(0, import_react7.useEffect)(() => {
|
|
2426
2796
|
const current = matchRef.current;
|
|
2427
2797
|
if (requestKey === null || current === null) {
|
|
2428
2798
|
setItems([]);
|
|
@@ -2470,25 +2840,25 @@ function useComposerAutocomplete(options) {
|
|
|
2470
2840
|
]);
|
|
2471
2841
|
const isOpen = isActive;
|
|
2472
2842
|
const activeItem = isOpen ? items[activeIndex] ?? null : null;
|
|
2473
|
-
const reactId = (0,
|
|
2843
|
+
const reactId = (0, import_react7.useId)();
|
|
2474
2844
|
const listboxId = options.id ?? `agent-autocomplete-${reactId}`;
|
|
2475
|
-
const optionId = (0,
|
|
2845
|
+
const optionId = (0, import_react7.useCallback)((index) => `${listboxId}-option-${index}`, [
|
|
2476
2846
|
listboxId
|
|
2477
2847
|
]);
|
|
2478
|
-
const highlight = (0,
|
|
2848
|
+
const highlight = (0, import_react7.useCallback)((index) => {
|
|
2479
2849
|
const total = itemsRef.current.length;
|
|
2480
2850
|
if (total === 0) return;
|
|
2481
2851
|
setActiveIndex((index % total + total) % total);
|
|
2482
2852
|
}, []);
|
|
2483
|
-
const moveHighlight = (0,
|
|
2853
|
+
const moveHighlight = (0, import_react7.useCallback)((delta) => highlight(activeIndexRef.current + delta), [
|
|
2484
2854
|
highlight
|
|
2485
2855
|
]);
|
|
2486
|
-
const dismiss = (0,
|
|
2856
|
+
const dismiss = (0, import_react7.useCallback)(() => {
|
|
2487
2857
|
const current = matchRef.current;
|
|
2488
2858
|
if (current) setDismissedIndex(current.index);
|
|
2489
2859
|
}, []);
|
|
2490
|
-
const pendingCaret = (0,
|
|
2491
|
-
const accept = (0,
|
|
2860
|
+
const pendingCaret = (0, import_react7.useRef)(null);
|
|
2861
|
+
const accept = (0, import_react7.useCallback)((item) => {
|
|
2492
2862
|
const current = matchRef.current;
|
|
2493
2863
|
if (!current) return;
|
|
2494
2864
|
const chosen = item ?? itemsRef.current[activeIndexRef.current];
|
|
@@ -2499,16 +2869,16 @@ function useComposerAutocomplete(options) {
|
|
|
2499
2869
|
setDismissedIndex(null);
|
|
2500
2870
|
pendingCaret.current = edit.caret;
|
|
2501
2871
|
}, []);
|
|
2502
|
-
(0,
|
|
2872
|
+
(0, import_react7.useLayoutEffect)(() => {
|
|
2503
2873
|
const position = pendingCaret.current;
|
|
2504
2874
|
if (position === null) return;
|
|
2505
2875
|
pendingCaret.current = null;
|
|
2506
2876
|
inputRef.current?.setSelectionRange(position, position);
|
|
2507
2877
|
});
|
|
2508
|
-
const readCaret = (0,
|
|
2878
|
+
const readCaret = (0, import_react7.useCallback)((element) => {
|
|
2509
2879
|
setCaret(element.selectionStart ?? element.value.length);
|
|
2510
2880
|
}, []);
|
|
2511
|
-
const onKeyDown = (0,
|
|
2881
|
+
const onKeyDown = (0, import_react7.useCallback)((event) => {
|
|
2512
2882
|
if (!isOpen) return;
|
|
2513
2883
|
const hasItems = itemsRef.current.length > 0;
|
|
2514
2884
|
switch (event.key) {
|
|
@@ -2546,23 +2916,23 @@ function useComposerAutocomplete(options) {
|
|
|
2546
2916
|
dismiss,
|
|
2547
2917
|
moveHighlight
|
|
2548
2918
|
]);
|
|
2549
|
-
const onChange = (0,
|
|
2919
|
+
const onChange = (0, import_react7.useCallback)((event) => {
|
|
2550
2920
|
readCaret(event.target);
|
|
2551
2921
|
const next = findActiveTrigger(event.target.value, event.target.selectionStart ?? event.target.value.length, latest.current.sources);
|
|
2552
2922
|
setDismissedIndex((current) => current !== null && next?.index === current ? current : null);
|
|
2553
2923
|
}, [
|
|
2554
2924
|
readCaret
|
|
2555
2925
|
]);
|
|
2556
|
-
const onSelect = (0,
|
|
2926
|
+
const onSelect = (0, import_react7.useCallback)((event) => readCaret(event.currentTarget), [
|
|
2557
2927
|
readCaret
|
|
2558
2928
|
]);
|
|
2559
|
-
const onClick = (0,
|
|
2929
|
+
const onClick = (0, import_react7.useCallback)((event) => readCaret(event.currentTarget), [
|
|
2560
2930
|
readCaret
|
|
2561
2931
|
]);
|
|
2562
|
-
const setInput = (0,
|
|
2932
|
+
const setInput = (0, import_react7.useCallback)((element) => {
|
|
2563
2933
|
inputRef.current = element;
|
|
2564
2934
|
}, []);
|
|
2565
|
-
const getInputProps = (0,
|
|
2935
|
+
const getInputProps = (0, import_react7.useCallback)(() => ({
|
|
2566
2936
|
ref: setInput,
|
|
2567
2937
|
onChange,
|
|
2568
2938
|
onKeyDown,
|
|
@@ -2590,7 +2960,7 @@ function useComposerAutocomplete(options) {
|
|
|
2590
2960
|
activeIndex,
|
|
2591
2961
|
optionId
|
|
2592
2962
|
]);
|
|
2593
|
-
const getListboxProps = (0,
|
|
2963
|
+
const getListboxProps = (0, import_react7.useCallback)(() => ({
|
|
2594
2964
|
id: listboxId,
|
|
2595
2965
|
role: "listbox",
|
|
2596
2966
|
"aria-label": match?.source.label ?? match?.source.id ?? "Suggestions"
|
|
@@ -2598,7 +2968,7 @@ function useComposerAutocomplete(options) {
|
|
|
2598
2968
|
listboxId,
|
|
2599
2969
|
match
|
|
2600
2970
|
]);
|
|
2601
|
-
const getOptionProps = (0,
|
|
2971
|
+
const getOptionProps = (0, import_react7.useCallback)((index) => ({
|
|
2602
2972
|
id: optionId(index),
|
|
2603
2973
|
role: "option",
|
|
2604
2974
|
"aria-selected": index === activeIndex
|
|
@@ -2631,6 +3001,78 @@ function isPromise(value) {
|
|
|
2631
3001
|
}
|
|
2632
3002
|
__name(isPromise, "isPromise");
|
|
2633
3003
|
|
|
3004
|
+
// src/presentation/use-tool-catalog.ts
|
|
3005
|
+
var import_react8 = require("react");
|
|
3006
|
+
var shared = /* @__PURE__ */ new WeakMap();
|
|
3007
|
+
function load(client, agent) {
|
|
3008
|
+
let byAgent = shared.get(client);
|
|
3009
|
+
if (byAgent === void 0) {
|
|
3010
|
+
byAgent = /* @__PURE__ */ new Map();
|
|
3011
|
+
shared.set(client, byAgent);
|
|
3012
|
+
}
|
|
3013
|
+
const key = agent ?? "";
|
|
3014
|
+
const cached = byAgent.get(key);
|
|
3015
|
+
if (cached !== void 0) return cached;
|
|
3016
|
+
const request = client.listTools(agent).catch((error) => {
|
|
3017
|
+
byAgent.delete(key);
|
|
3018
|
+
throw error;
|
|
3019
|
+
});
|
|
3020
|
+
byAgent.set(key, request);
|
|
3021
|
+
return request;
|
|
3022
|
+
}
|
|
3023
|
+
__name(load, "load");
|
|
3024
|
+
function useToolCatalog(options) {
|
|
3025
|
+
const { client, agent, enabled = true } = options;
|
|
3026
|
+
const [entries, setEntries] = (0, import_react8.useState)([]);
|
|
3027
|
+
const [isLoading, setLoading] = (0, import_react8.useState)(enabled);
|
|
3028
|
+
const [error, setError] = (0, import_react8.useState)(null);
|
|
3029
|
+
const [generation, setGeneration] = (0, import_react8.useState)(0);
|
|
3030
|
+
(0, import_react8.useEffect)(() => {
|
|
3031
|
+
if (!enabled) {
|
|
3032
|
+
setLoading(false);
|
|
3033
|
+
return;
|
|
3034
|
+
}
|
|
3035
|
+
let cancelled = false;
|
|
3036
|
+
setLoading(true);
|
|
3037
|
+
load(client, agent).then((loaded) => {
|
|
3038
|
+
if (cancelled) return;
|
|
3039
|
+
setEntries(loaded);
|
|
3040
|
+
setError(null);
|
|
3041
|
+
setLoading(false);
|
|
3042
|
+
}, (failure) => {
|
|
3043
|
+
if (cancelled) return;
|
|
3044
|
+
setError(failure instanceof Error ? failure : new Error(String(failure)));
|
|
3045
|
+
setLoading(false);
|
|
3046
|
+
});
|
|
3047
|
+
return () => {
|
|
3048
|
+
cancelled = true;
|
|
3049
|
+
};
|
|
3050
|
+
}, [
|
|
3051
|
+
client,
|
|
3052
|
+
agent,
|
|
3053
|
+
enabled,
|
|
3054
|
+
generation
|
|
3055
|
+
]);
|
|
3056
|
+
const refresh = (0, import_react8.useCallback)(() => {
|
|
3057
|
+
shared.get(client)?.delete(agent ?? "");
|
|
3058
|
+
setGeneration((current) => current + 1);
|
|
3059
|
+
}, [
|
|
3060
|
+
client,
|
|
3061
|
+
agent
|
|
3062
|
+
]);
|
|
3063
|
+
const catalog = (0, import_react8.useMemo)(() => toolCatalogFrom(entries), [
|
|
3064
|
+
entries
|
|
3065
|
+
]);
|
|
3066
|
+
return {
|
|
3067
|
+
catalog,
|
|
3068
|
+
entries,
|
|
3069
|
+
isLoading,
|
|
3070
|
+
error,
|
|
3071
|
+
refresh
|
|
3072
|
+
};
|
|
3073
|
+
}
|
|
3074
|
+
__name(useToolCatalog, "useToolCatalog");
|
|
3075
|
+
|
|
2634
3076
|
// src/stored-message-to-ui-message.ts
|
|
2635
3077
|
var import_nestjs_agent_core = require("@dudousxd/nestjs-agent-core");
|
|
2636
3078
|
function isRefusal(result) {
|
|
@@ -2652,6 +3094,16 @@ function refusalReason(result) {
|
|
|
2652
3094
|
__name(refusalReason, "refusalReason");
|
|
2653
3095
|
function storedMessageToUiMessage(message) {
|
|
2654
3096
|
const parts = [];
|
|
3097
|
+
if (message.reasoning) {
|
|
3098
|
+
parts.push({
|
|
3099
|
+
type: "reasoning",
|
|
3100
|
+
text: message.reasoning,
|
|
3101
|
+
state: "done",
|
|
3102
|
+
...message.reasoningMs !== void 0 ? {
|
|
3103
|
+
providerMetadata: reasoningDurationMetadata(message.reasoningMs)
|
|
3104
|
+
} : {}
|
|
3105
|
+
});
|
|
3106
|
+
}
|
|
2655
3107
|
if (message.content) {
|
|
2656
3108
|
parts.push({
|
|
2657
3109
|
type: "text",
|
|
@@ -2666,6 +3118,20 @@ function storedMessageToUiMessage(message) {
|
|
|
2666
3118
|
url: attachment.url
|
|
2667
3119
|
});
|
|
2668
3120
|
}
|
|
3121
|
+
for (const component of message.ui ?? []) {
|
|
3122
|
+
parts.push({
|
|
3123
|
+
type: "data-ui",
|
|
3124
|
+
id: component.id,
|
|
3125
|
+
data: {
|
|
3126
|
+
id: component.id,
|
|
3127
|
+
component: component.component,
|
|
3128
|
+
props: component.props,
|
|
3129
|
+
...component.version !== void 0 ? {
|
|
3130
|
+
version: component.version
|
|
3131
|
+
} : {}
|
|
3132
|
+
}
|
|
3133
|
+
});
|
|
3134
|
+
}
|
|
2669
3135
|
for (const call of message.toolCalls ?? []) {
|
|
2670
3136
|
const result = message.toolResults?.find((candidate) => candidate.id === call.id);
|
|
2671
3137
|
const toolKind2 = call.kind;
|
|
@@ -2767,21 +3233,21 @@ function sumUsage(rows) {
|
|
|
2767
3233
|
__name(sumUsage, "sumUsage");
|
|
2768
3234
|
|
|
2769
3235
|
// src/use-agent-chat.ts
|
|
2770
|
-
var
|
|
2771
|
-
var
|
|
3236
|
+
var import_react9 = require("@ai-sdk/react");
|
|
3237
|
+
var import_react10 = require("react");
|
|
2772
3238
|
function useAgentChat(options) {
|
|
2773
|
-
const latest = (0,
|
|
3239
|
+
const latest = (0, import_react10.useRef)(options);
|
|
2774
3240
|
latest.current = options;
|
|
2775
|
-
const [runId, setRunId] = (0,
|
|
2776
|
-
const runIdRef = (0,
|
|
3241
|
+
const [runId, setRunId] = (0, import_react10.useState)(options.resumeRunId);
|
|
3242
|
+
const runIdRef = (0, import_react10.useRef)(runId);
|
|
2777
3243
|
runIdRef.current = runId;
|
|
2778
|
-
const settlingRunIdRef = (0,
|
|
2779
|
-
const autoResumeRunIdRef = (0,
|
|
2780
|
-
const [autoResume, setAutoResume] = (0,
|
|
2781
|
-
const [activeRunId, setActiveRunId] = (0,
|
|
2782
|
-
const regenerateNext = (0,
|
|
2783
|
-
const createdThreadId = (0,
|
|
2784
|
-
const client = (0,
|
|
3244
|
+
const settlingRunIdRef = (0, import_react10.useRef)(void 0);
|
|
3245
|
+
const autoResumeRunIdRef = (0, import_react10.useRef)(void 0);
|
|
3246
|
+
const [autoResume, setAutoResume] = (0, import_react10.useState)(false);
|
|
3247
|
+
const [activeRunId, setActiveRunId] = (0, import_react10.useState)(null);
|
|
3248
|
+
const regenerateNext = (0, import_react10.useRef)(false);
|
|
3249
|
+
const createdThreadId = (0, import_react10.useRef)(void 0);
|
|
3250
|
+
const client = (0, import_react10.useMemo)(() => {
|
|
2785
3251
|
if (options.client) return options.client;
|
|
2786
3252
|
return new AgentClient({
|
|
2787
3253
|
...options.baseUrl !== void 0 ? {
|
|
@@ -2796,7 +3262,7 @@ function useAgentChat(options) {
|
|
|
2796
3262
|
getHeaders: /* @__PURE__ */ __name(async () => mergeHeaders(latest.current), "getHeaders")
|
|
2797
3263
|
});
|
|
2798
3264
|
}, []);
|
|
2799
|
-
(0,
|
|
3265
|
+
(0, import_react10.useEffect)(() => {
|
|
2800
3266
|
if (!options.resume || options.threadId === void 0) return;
|
|
2801
3267
|
let cancelled = false;
|
|
2802
3268
|
const threadId = options.threadId;
|
|
@@ -2816,7 +3282,7 @@ function useAgentChat(options) {
|
|
|
2816
3282
|
options.resume,
|
|
2817
3283
|
options.threadId
|
|
2818
3284
|
]);
|
|
2819
|
-
const transport = (0,
|
|
3285
|
+
const transport = (0, import_react10.useMemo)(() => {
|
|
2820
3286
|
function onMeta(meta) {
|
|
2821
3287
|
settlingRunIdRef.current = meta.runId;
|
|
2822
3288
|
setRunId(meta.runId);
|
|
@@ -2865,8 +3331,8 @@ function useAgentChat(options) {
|
|
|
2865
3331
|
}, "onAttemptStart")
|
|
2866
3332
|
});
|
|
2867
3333
|
}, []);
|
|
2868
|
-
const backgroundRef = (0,
|
|
2869
|
-
const chat = (0,
|
|
3334
|
+
const backgroundRef = (0, import_react10.useRef)(() => Promise.resolve());
|
|
3335
|
+
const chat = (0, import_react9.useChat)({
|
|
2870
3336
|
transport,
|
|
2871
3337
|
resume: options.resumeRunId !== void 0 || autoResume,
|
|
2872
3338
|
...options.threadId !== void 0 ? {
|
|
@@ -2896,13 +3362,13 @@ function useAgentChat(options) {
|
|
|
2896
3362
|
}
|
|
2897
3363
|
}, "onFinish")
|
|
2898
3364
|
});
|
|
2899
|
-
const chatRef = (0,
|
|
3365
|
+
const chatRef = (0, import_react10.useRef)(chat);
|
|
2900
3366
|
chatRef.current = chat;
|
|
2901
|
-
const turnInFlight = (0,
|
|
2902
|
-
const isTurnInFlight = (0,
|
|
3367
|
+
const turnInFlight = (0, import_react10.useRef)(false);
|
|
3368
|
+
const isTurnInFlight = (0, import_react10.useCallback)(() => turnInFlight.current || transport.isAttemptLive, [
|
|
2903
3369
|
transport
|
|
2904
3370
|
]);
|
|
2905
|
-
const sendMessage = (0,
|
|
3371
|
+
const sendMessage = (0, import_react10.useCallback)(async (...args) => {
|
|
2906
3372
|
if (isTurnInFlight()) return;
|
|
2907
3373
|
turnInFlight.current = true;
|
|
2908
3374
|
try {
|
|
@@ -2913,15 +3379,15 @@ function useAgentChat(options) {
|
|
|
2913
3379
|
}, [
|
|
2914
3380
|
isTurnInFlight
|
|
2915
3381
|
]);
|
|
2916
|
-
const addToolResult = (0,
|
|
3382
|
+
const addToolResult = (0, import_react10.useCallback)(({ tool, toolCallId, output }) => chatRef.current.addToolResult({
|
|
2917
3383
|
tool,
|
|
2918
3384
|
toolCallId,
|
|
2919
3385
|
output
|
|
2920
3386
|
}), []);
|
|
2921
|
-
const [threads, setThreads] = (0,
|
|
2922
|
-
const [quota, setQuota] = (0,
|
|
2923
|
-
const [backgroundRuns, setBackgroundRuns] = (0,
|
|
2924
|
-
const refreshBackground = (0,
|
|
3387
|
+
const [threads, setThreads] = (0, import_react10.useState)([]);
|
|
3388
|
+
const [quota, setQuota] = (0, import_react10.useState)(null);
|
|
3389
|
+
const [backgroundRuns, setBackgroundRuns] = (0, import_react10.useState)([]);
|
|
3390
|
+
const refreshBackground = (0, import_react10.useCallback)(async () => {
|
|
2925
3391
|
const threadId = latest.current.threadId ?? createdThreadId.current;
|
|
2926
3392
|
if (threadId === void 0) {
|
|
2927
3393
|
return;
|
|
@@ -2946,7 +3412,7 @@ function useAgentChat(options) {
|
|
|
2946
3412
|
]);
|
|
2947
3413
|
backgroundRef.current = refreshBackground;
|
|
2948
3414
|
const isWorking = backgroundRuns.some((run) => run.status === "running");
|
|
2949
|
-
(0,
|
|
3415
|
+
(0, import_react10.useEffect)(() => {
|
|
2950
3416
|
if (options.background !== true || options.threadId === void 0) {
|
|
2951
3417
|
return;
|
|
2952
3418
|
}
|
|
@@ -2956,7 +3422,7 @@ function useAgentChat(options) {
|
|
|
2956
3422
|
options.threadId,
|
|
2957
3423
|
refreshBackground
|
|
2958
3424
|
]);
|
|
2959
|
-
(0,
|
|
3425
|
+
(0, import_react10.useEffect)(() => {
|
|
2960
3426
|
const every = latest.current.backgroundPollMs ?? 5e3;
|
|
2961
3427
|
if (latest.current.background !== true || !isWorking || every <= 0) {
|
|
2962
3428
|
return;
|
|
@@ -2967,26 +3433,26 @@ function useAgentChat(options) {
|
|
|
2967
3433
|
isWorking,
|
|
2968
3434
|
refreshBackground
|
|
2969
3435
|
]);
|
|
2970
|
-
const loadThreads = (0,
|
|
3436
|
+
const loadThreads = (0, import_react10.useCallback)(async () => {
|
|
2971
3437
|
const list = await client.listThreads();
|
|
2972
3438
|
setThreads(list);
|
|
2973
3439
|
return list;
|
|
2974
3440
|
}, [
|
|
2975
3441
|
client
|
|
2976
3442
|
]);
|
|
2977
|
-
const loadThread = (0,
|
|
3443
|
+
const loadThread = (0, import_react10.useCallback)((id) => client.getThread(id), [
|
|
2978
3444
|
client
|
|
2979
3445
|
]);
|
|
2980
|
-
const deleteThread = (0,
|
|
3446
|
+
const deleteThread = (0, import_react10.useCallback)(async (id) => {
|
|
2981
3447
|
await client.deleteThread(id);
|
|
2982
3448
|
setThreads((current) => current.filter((thread) => thread.id !== id));
|
|
2983
3449
|
}, [
|
|
2984
3450
|
client
|
|
2985
3451
|
]);
|
|
2986
|
-
const forkThread = (0,
|
|
3452
|
+
const forkThread = (0, import_react10.useCallback)((threadId, messageId) => client.forkFromMessage(threadId, messageId), [
|
|
2987
3453
|
client
|
|
2988
3454
|
]);
|
|
2989
|
-
const renameThread = (0,
|
|
3455
|
+
const renameThread = (0, import_react10.useCallback)(async (id, title) => {
|
|
2990
3456
|
await client.renameThread(id, title);
|
|
2991
3457
|
setThreads((current) => current.map((thread) => thread.id === id ? {
|
|
2992
3458
|
...thread,
|
|
@@ -2995,24 +3461,24 @@ function useAgentChat(options) {
|
|
|
2995
3461
|
}, [
|
|
2996
3462
|
client
|
|
2997
3463
|
]);
|
|
2998
|
-
const promoteThread = (0,
|
|
3464
|
+
const promoteThread = (0, import_react10.useCallback)(async (id) => {
|
|
2999
3465
|
await client.promoteThread(id);
|
|
3000
3466
|
await loadThreads();
|
|
3001
3467
|
}, [
|
|
3002
3468
|
client,
|
|
3003
3469
|
loadThreads
|
|
3004
3470
|
]);
|
|
3005
|
-
const truncateFromMessage = (0,
|
|
3471
|
+
const truncateFromMessage = (0, import_react10.useCallback)((threadId, messageId) => client.truncateFromMessage(threadId, messageId).then(() => void 0), [
|
|
3006
3472
|
client
|
|
3007
3473
|
]);
|
|
3008
|
-
const loadQuota = (0,
|
|
3474
|
+
const loadQuota = (0, import_react10.useCallback)(async () => {
|
|
3009
3475
|
const today = await client.getQuotaToday();
|
|
3010
3476
|
setQuota(today);
|
|
3011
3477
|
return today;
|
|
3012
3478
|
}, [
|
|
3013
3479
|
client
|
|
3014
3480
|
]);
|
|
3015
|
-
const cancel = (0,
|
|
3481
|
+
const cancel = (0, import_react10.useCallback)(async () => {
|
|
3016
3482
|
chatRef.current.stop();
|
|
3017
3483
|
const activeRunId2 = runIdRef.current;
|
|
3018
3484
|
if (activeRunId2) {
|
|
@@ -3024,14 +3490,14 @@ function useAgentChat(options) {
|
|
|
3024
3490
|
}, [
|
|
3025
3491
|
client
|
|
3026
3492
|
]);
|
|
3027
|
-
const approve = (0,
|
|
3493
|
+
const approve = (0, import_react10.useCallback)(async ({ toolCallId }) => {
|
|
3028
3494
|
await client.approveToolCall({
|
|
3029
3495
|
toolCallId
|
|
3030
3496
|
});
|
|
3031
3497
|
}, [
|
|
3032
3498
|
client
|
|
3033
3499
|
]);
|
|
3034
|
-
const reject = (0,
|
|
3500
|
+
const reject = (0, import_react10.useCallback)(async ({ toolCallId, reason }) => {
|
|
3035
3501
|
await client.rejectToolCall({
|
|
3036
3502
|
toolCallId,
|
|
3037
3503
|
...reason !== void 0 ? {
|
|
@@ -3041,7 +3507,7 @@ function useAgentChat(options) {
|
|
|
3041
3507
|
}, [
|
|
3042
3508
|
client
|
|
3043
3509
|
]);
|
|
3044
|
-
const answer = (0,
|
|
3510
|
+
const answer = (0, import_react10.useCallback)(async ({ toolCallId, answers }) => {
|
|
3045
3511
|
await client.answerToolCall({
|
|
3046
3512
|
toolCallId,
|
|
3047
3513
|
...answers !== void 0 ? {
|
|
@@ -3051,14 +3517,14 @@ function useAgentChat(options) {
|
|
|
3051
3517
|
}, [
|
|
3052
3518
|
client
|
|
3053
3519
|
]);
|
|
3054
|
-
const skip = (0,
|
|
3520
|
+
const skip = (0, import_react10.useCallback)(async ({ toolCallId }) => {
|
|
3055
3521
|
await client.skipToolCall({
|
|
3056
3522
|
toolCallId
|
|
3057
3523
|
});
|
|
3058
3524
|
}, [
|
|
3059
3525
|
client
|
|
3060
3526
|
]);
|
|
3061
|
-
const regenerate = (0,
|
|
3527
|
+
const regenerate = (0, import_react10.useCallback)(() => {
|
|
3062
3528
|
if (isTurnInFlight()) return;
|
|
3063
3529
|
regenerateNext.current = true;
|
|
3064
3530
|
turnInFlight.current = true;
|
|
@@ -3124,22 +3590,37 @@ __name(mergeHeaders, "mergeHeaders");
|
|
|
3124
3590
|
applyCompletion,
|
|
3125
3591
|
backgroundRunsFromThread,
|
|
3126
3592
|
buildTranscriptBlocks,
|
|
3593
|
+
correctedCallIds,
|
|
3127
3594
|
createSkillsSource,
|
|
3128
3595
|
describeTimestamp,
|
|
3596
|
+
describeToolCall,
|
|
3129
3597
|
describeUsage,
|
|
3130
3598
|
extractMessageText,
|
|
3599
|
+
fillTemplate,
|
|
3131
3600
|
filterAutocompleteItems,
|
|
3132
3601
|
findActiveTrigger,
|
|
3602
|
+
formatElapsed,
|
|
3133
3603
|
formatRelativeTime,
|
|
3604
|
+
groupToolActivity,
|
|
3605
|
+
inferResultView,
|
|
3606
|
+
isActionCall,
|
|
3134
3607
|
loadStoredSpeechLang,
|
|
3135
3608
|
persistSpeechLang,
|
|
3609
|
+
phraseFor,
|
|
3610
|
+
readPath,
|
|
3611
|
+
readReasoningMs,
|
|
3612
|
+
resolveResultView,
|
|
3136
3613
|
storedMessageToUiMessage,
|
|
3137
3614
|
storedThreadToUiMessages,
|
|
3615
|
+
toolCallState,
|
|
3616
|
+
toolCatalogFrom,
|
|
3138
3617
|
useAgentChat,
|
|
3139
3618
|
useChatTranscript,
|
|
3140
3619
|
useComposerAutocomplete,
|
|
3620
|
+
useElapsed,
|
|
3141
3621
|
useSpeechRecognition,
|
|
3142
3622
|
useStickToBottom,
|
|
3623
|
+
useToolCatalog,
|
|
3143
3624
|
useTranscriptItem
|
|
3144
3625
|
});
|
|
3145
3626
|
//# sourceMappingURL=index.cjs.map
|