@dudousxd/nestjs-agent-react 0.8.0 → 0.9.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 +15 -0
- package/dist/index.cjs +255 -162
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +33 -1
- package/dist/index.d.ts +33 -1
- package/dist/index.js +160 -70
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -49,20 +49,82 @@ __export(src_exports, {
|
|
|
49
49
|
extractMessageText: () => extractMessageText,
|
|
50
50
|
filterAutocompleteItems: () => filterAutocompleteItems,
|
|
51
51
|
findActiveTrigger: () => findActiveTrigger,
|
|
52
|
+
formatElapsed: () => formatElapsed,
|
|
52
53
|
formatRelativeTime: () => formatRelativeTime,
|
|
53
54
|
loadStoredSpeechLang: () => loadStoredSpeechLang,
|
|
54
55
|
persistSpeechLang: () => persistSpeechLang,
|
|
56
|
+
readReasoningMs: () => readReasoningMs,
|
|
55
57
|
storedMessageToUiMessage: () => storedMessageToUiMessage,
|
|
56
58
|
storedThreadToUiMessages: () => storedThreadToUiMessages,
|
|
57
59
|
useAgentChat: () => useAgentChat,
|
|
58
60
|
useChatTranscript: () => useChatTranscript,
|
|
59
61
|
useComposerAutocomplete: () => useComposerAutocomplete,
|
|
62
|
+
useElapsed: () => useElapsed,
|
|
60
63
|
useSpeechRecognition: () => useSpeechRecognition,
|
|
61
64
|
useStickToBottom: () => useStickToBottom,
|
|
62
65
|
useTranscriptItem: () => useTranscriptItem
|
|
63
66
|
});
|
|
64
67
|
module.exports = __toCommonJS(src_exports);
|
|
65
68
|
|
|
69
|
+
// src/reasoning/timing.ts
|
|
70
|
+
var import_react = require("react");
|
|
71
|
+
var REASONING_METADATA_KEY = "agent";
|
|
72
|
+
function reasoningDurationMetadata(reasoningMs) {
|
|
73
|
+
return {
|
|
74
|
+
[REASONING_METADATA_KEY]: {
|
|
75
|
+
reasoningMs
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
__name(reasoningDurationMetadata, "reasoningDurationMetadata");
|
|
80
|
+
function readReasoningMs(part) {
|
|
81
|
+
const metadata = part.providerMetadata;
|
|
82
|
+
if (typeof metadata !== "object" || metadata === null) return null;
|
|
83
|
+
const scoped = metadata[REASONING_METADATA_KEY];
|
|
84
|
+
if (typeof scoped !== "object" || scoped === null) return null;
|
|
85
|
+
const value = scoped.reasoningMs;
|
|
86
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : null;
|
|
87
|
+
}
|
|
88
|
+
__name(readReasoningMs, "readReasoningMs");
|
|
89
|
+
function useElapsed(running, options = {}) {
|
|
90
|
+
const { intervalMs = 1e3 } = options;
|
|
91
|
+
const nowRef = (0, import_react.useRef)(options.now ?? Date.now);
|
|
92
|
+
nowRef.current = options.now ?? Date.now;
|
|
93
|
+
const startedAt = (0, import_react.useRef)(null);
|
|
94
|
+
const [elapsed, setElapsed] = (0, import_react.useState)(0);
|
|
95
|
+
(0, import_react.useEffect)(() => {
|
|
96
|
+
if (!running) {
|
|
97
|
+
if (startedAt.current !== null) {
|
|
98
|
+
setElapsed(nowRef.current() - startedAt.current);
|
|
99
|
+
startedAt.current = null;
|
|
100
|
+
}
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
startedAt.current = nowRef.current();
|
|
104
|
+
setElapsed(0);
|
|
105
|
+
const timer = setInterval(() => {
|
|
106
|
+
if (startedAt.current !== null) setElapsed(nowRef.current() - startedAt.current);
|
|
107
|
+
}, intervalMs);
|
|
108
|
+
return () => clearInterval(timer);
|
|
109
|
+
}, [
|
|
110
|
+
running,
|
|
111
|
+
intervalMs
|
|
112
|
+
]);
|
|
113
|
+
return elapsed;
|
|
114
|
+
}
|
|
115
|
+
__name(useElapsed, "useElapsed");
|
|
116
|
+
function formatElapsed(ms) {
|
|
117
|
+
if (!Number.isFinite(ms) || ms < 1e3) return "<1s";
|
|
118
|
+
const totalSeconds = Math.floor(ms / 1e3);
|
|
119
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
120
|
+
const minutes = Math.floor(totalSeconds % 3600 / 60);
|
|
121
|
+
const seconds = totalSeconds % 60;
|
|
122
|
+
if (hours > 0) return minutes > 0 ? `${hours}h ${minutes}m` : `${hours}h`;
|
|
123
|
+
if (minutes > 0) return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;
|
|
124
|
+
return `${seconds}s`;
|
|
125
|
+
}
|
|
126
|
+
__name(formatElapsed, "formatElapsed");
|
|
127
|
+
|
|
66
128
|
// src/agent-chat-transport.ts
|
|
67
129
|
var HEADER_RUN_ID = "x-agent-run-id";
|
|
68
130
|
var HEADER_THREAD_ID = "x-agent-thread-id";
|
|
@@ -220,6 +282,7 @@ var AgentChatTransport = class {
|
|
|
220
282
|
let stepIndex = 0;
|
|
221
283
|
let textId = null;
|
|
222
284
|
let reasoningId = null;
|
|
285
|
+
let reasoningStartedAt = 0;
|
|
223
286
|
let textSeq = 0;
|
|
224
287
|
let reasoningSeq = 0;
|
|
225
288
|
const announced = /* @__PURE__ */ new Set();
|
|
@@ -256,7 +319,7 @@ var AgentChatTransport = class {
|
|
|
256
319
|
if (!stepOpen) openStep();
|
|
257
320
|
}
|
|
258
321
|
__name(ensureStep, "ensureStep");
|
|
259
|
-
function closeRuns() {
|
|
322
|
+
function closeRuns(reasoningMs) {
|
|
260
323
|
if (textId !== null) {
|
|
261
324
|
controller.enqueue({
|
|
262
325
|
type: "text-end",
|
|
@@ -267,15 +330,16 @@ var AgentChatTransport = class {
|
|
|
267
330
|
if (reasoningId !== null) {
|
|
268
331
|
controller.enqueue({
|
|
269
332
|
type: "reasoning-end",
|
|
270
|
-
id: reasoningId
|
|
333
|
+
id: reasoningId,
|
|
334
|
+
providerMetadata: reasoningDurationMetadata(reasoningMs ?? Math.max(0, Date.now() - reasoningStartedAt))
|
|
271
335
|
});
|
|
272
336
|
reasoningId = null;
|
|
273
337
|
}
|
|
274
338
|
}
|
|
275
339
|
__name(closeRuns, "closeRuns");
|
|
276
|
-
function closeStep() {
|
|
340
|
+
function closeStep(reasoningMs) {
|
|
277
341
|
if (!stepOpen) return;
|
|
278
|
-
closeRuns();
|
|
342
|
+
closeRuns(reasoningMs);
|
|
279
343
|
controller.enqueue({
|
|
280
344
|
type: "finish-step"
|
|
281
345
|
});
|
|
@@ -314,7 +378,7 @@ var AgentChatTransport = class {
|
|
|
314
378
|
openStep();
|
|
315
379
|
break;
|
|
316
380
|
case "step-finish":
|
|
317
|
-
closeStep();
|
|
381
|
+
closeStep(event.reasoningMs);
|
|
318
382
|
if (event.costUsd !== void 0) {
|
|
319
383
|
controller.enqueue({
|
|
320
384
|
type: "message-metadata",
|
|
@@ -345,6 +409,7 @@ var AgentChatTransport = class {
|
|
|
345
409
|
if (reasoningId === null) {
|
|
346
410
|
reasoningId = reasoningSeq === 0 ? `rsn-${stepIndex}` : `rsn-${stepIndex}.${reasoningSeq}`;
|
|
347
411
|
reasoningSeq += 1;
|
|
412
|
+
reasoningStartedAt = Date.now();
|
|
348
413
|
controller.enqueue({
|
|
349
414
|
type: "reasoning-start",
|
|
350
415
|
id: reasoningId
|
|
@@ -792,10 +857,10 @@ var AgentClient = class {
|
|
|
792
857
|
};
|
|
793
858
|
|
|
794
859
|
// src/components/chat-input.tsx
|
|
795
|
-
var
|
|
860
|
+
var import_react3 = __toESM(require("react"), 1);
|
|
796
861
|
|
|
797
862
|
// src/components/use-speech-recognition.ts
|
|
798
|
-
var
|
|
863
|
+
var import_react2 = require("react");
|
|
799
864
|
function getRecognitionCtor() {
|
|
800
865
|
if (typeof window === "undefined") return null;
|
|
801
866
|
const scope = window;
|
|
@@ -803,15 +868,15 @@ function getRecognitionCtor() {
|
|
|
803
868
|
}
|
|
804
869
|
__name(getRecognitionCtor, "getRecognitionCtor");
|
|
805
870
|
function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTranscript }) {
|
|
806
|
-
const recognitionRef = (0,
|
|
807
|
-
const [isListening, setIsListening] = (0,
|
|
808
|
-
const ctor = (0,
|
|
871
|
+
const recognitionRef = (0, import_react2.useRef)(null);
|
|
872
|
+
const [isListening, setIsListening] = (0, import_react2.useState)(false);
|
|
873
|
+
const ctor = (0, import_react2.useMemo)(() => getRecognitionCtor(), []);
|
|
809
874
|
const isSupported = ctor !== null;
|
|
810
|
-
const finalRef = (0,
|
|
811
|
-
const interimRef = (0,
|
|
875
|
+
const finalRef = (0, import_react2.useRef)(onFinalTranscript);
|
|
876
|
+
const interimRef = (0, import_react2.useRef)(onInterimTranscript);
|
|
812
877
|
finalRef.current = onFinalTranscript;
|
|
813
878
|
interimRef.current = onInterimTranscript;
|
|
814
|
-
(0,
|
|
879
|
+
(0, import_react2.useEffect)(() => {
|
|
815
880
|
if (!ctor) return;
|
|
816
881
|
const recognition = new ctor();
|
|
817
882
|
recognition.lang = lang;
|
|
@@ -850,7 +915,7 @@ function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTran
|
|
|
850
915
|
ctor,
|
|
851
916
|
lang
|
|
852
917
|
]);
|
|
853
|
-
const start = (0,
|
|
918
|
+
const start = (0, import_react2.useCallback)(() => {
|
|
854
919
|
const recognition = recognitionRef.current;
|
|
855
920
|
if (!recognition) return;
|
|
856
921
|
try {
|
|
@@ -860,7 +925,7 @@ function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTran
|
|
|
860
925
|
console.warn("SpeechRecognition start failed", error);
|
|
861
926
|
}
|
|
862
927
|
}, []);
|
|
863
|
-
const stop = (0,
|
|
928
|
+
const stop = (0, import_react2.useCallback)(() => {
|
|
864
929
|
const recognition = recognitionRef.current;
|
|
865
930
|
if (!recognition) return;
|
|
866
931
|
try {
|
|
@@ -879,8 +944,8 @@ __name(useSpeechRecognition, "useSpeechRecognition");
|
|
|
879
944
|
|
|
880
945
|
// src/components/chat-input.tsx
|
|
881
946
|
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,
|
|
947
|
+
const [value, setValue] = (0, import_react3.useState)("");
|
|
948
|
+
const [interim, setInterim] = (0, import_react3.useState)("");
|
|
884
949
|
const speech = useSpeechRecognition({
|
|
885
950
|
lang: speechLang,
|
|
886
951
|
onFinalTranscript: /* @__PURE__ */ __name((text) => {
|
|
@@ -891,7 +956,7 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
|
|
|
891
956
|
}, "onFinalTranscript"),
|
|
892
957
|
onInterimTranscript: /* @__PURE__ */ __name((text) => setInterim(text), "onInterimTranscript")
|
|
893
958
|
});
|
|
894
|
-
(0,
|
|
959
|
+
(0, import_react3.useEffect)(() => {
|
|
895
960
|
if (!speech.isListening) setInterim("");
|
|
896
961
|
}, [
|
|
897
962
|
speech.isListening
|
|
@@ -919,9 +984,9 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
|
|
|
919
984
|
const displayValue = speech.isListening && interim ? `${value}${value && !value.endsWith(" ") ? " " : ""}${interim}` : value;
|
|
920
985
|
const showMic = enableSpeech && speech.isSupported;
|
|
921
986
|
const showStop = isStreaming && onStop !== void 0;
|
|
922
|
-
return /* @__PURE__ */
|
|
987
|
+
return /* @__PURE__ */ import_react3.default.createElement("div", {
|
|
923
988
|
className
|
|
924
|
-
}, /* @__PURE__ */
|
|
989
|
+
}, /* @__PURE__ */ import_react3.default.createElement("textarea", {
|
|
925
990
|
className: textareaClassName,
|
|
926
991
|
rows,
|
|
927
992
|
value: displayValue,
|
|
@@ -932,17 +997,17 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
|
|
|
932
997
|
}, "onChange"),
|
|
933
998
|
onKeyDown: handleKeyDown,
|
|
934
999
|
placeholder: placeholder ?? "Ask something (Enter to send, Shift+Enter for newline)"
|
|
935
|
-
}), /* @__PURE__ */
|
|
1000
|
+
}), /* @__PURE__ */ import_react3.default.createElement("button", {
|
|
936
1001
|
type: "button",
|
|
937
1002
|
className: sendButtonClassName,
|
|
938
1003
|
onClick: submit,
|
|
939
1004
|
disabled: disabled || !value.trim()
|
|
940
|
-
}, sendLabel), showStop ? /* @__PURE__ */
|
|
1005
|
+
}, sendLabel), showStop ? /* @__PURE__ */ import_react3.default.createElement("button", {
|
|
941
1006
|
type: "button",
|
|
942
1007
|
className: stopButtonClassName,
|
|
943
1008
|
onClick: /* @__PURE__ */ __name(() => void onStop(), "onClick"),
|
|
944
1009
|
"aria-label": "Stop generating"
|
|
945
|
-
}, stopLabel) : null, showMic ? /* @__PURE__ */
|
|
1010
|
+
}, stopLabel) : null, showMic ? /* @__PURE__ */ import_react3.default.createElement("button", {
|
|
946
1011
|
type: "button",
|
|
947
1012
|
className: micButtonClassName,
|
|
948
1013
|
onClick: toggleMic,
|
|
@@ -955,10 +1020,10 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
|
|
|
955
1020
|
__name(ChatInput, "ChatInput");
|
|
956
1021
|
|
|
957
1022
|
// src/components/message-item.tsx
|
|
958
|
-
var
|
|
1023
|
+
var import_react6 = __toESM(require("react"), 1);
|
|
959
1024
|
|
|
960
1025
|
// src/transcript/use-chat-transcript.ts
|
|
961
|
-
var
|
|
1026
|
+
var import_react5 = require("react");
|
|
962
1027
|
|
|
963
1028
|
// src/transcript/model.ts
|
|
964
1029
|
var import_ai = require("ai");
|
|
@@ -1079,6 +1144,7 @@ function buildTranscriptBlocks(message, options) {
|
|
|
1079
1144
|
key,
|
|
1080
1145
|
text: part.text,
|
|
1081
1146
|
isStreaming,
|
|
1147
|
+
durationMs: readReasoningMs(part),
|
|
1082
1148
|
isOpen: options.isReasoningOpen(key, isStreaming),
|
|
1083
1149
|
toggle: /* @__PURE__ */ __name((open) => options.toggleReasoning(key, open), "toggle")
|
|
1084
1150
|
});
|
|
@@ -1491,11 +1557,11 @@ function formatCostUsd(cost) {
|
|
|
1491
1557
|
__name(formatCostUsd, "formatCostUsd");
|
|
1492
1558
|
|
|
1493
1559
|
// src/transcript/use-stick-to-bottom.ts
|
|
1494
|
-
var
|
|
1560
|
+
var import_react4 = require("react");
|
|
1495
1561
|
function useStickToBottom({ contentKey, threshold = 32 }) {
|
|
1496
|
-
const containerRef = (0,
|
|
1497
|
-
const [isAtBottom, setIsAtBottom] = (0,
|
|
1498
|
-
const measure = (0,
|
|
1562
|
+
const containerRef = (0, import_react4.useRef)(null);
|
|
1563
|
+
const [isAtBottom, setIsAtBottom] = (0, import_react4.useState)(true);
|
|
1564
|
+
const measure = (0, import_react4.useCallback)(() => {
|
|
1499
1565
|
const element = containerRef.current;
|
|
1500
1566
|
if (!element) {
|
|
1501
1567
|
return;
|
|
@@ -1505,7 +1571,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
|
|
|
1505
1571
|
}, [
|
|
1506
1572
|
threshold
|
|
1507
1573
|
]);
|
|
1508
|
-
const scrollToBottom = (0,
|
|
1574
|
+
const scrollToBottom = (0, import_react4.useCallback)(() => {
|
|
1509
1575
|
const element = containerRef.current;
|
|
1510
1576
|
if (!element) {
|
|
1511
1577
|
return;
|
|
@@ -1513,7 +1579,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
|
|
|
1513
1579
|
element.scrollTop = element.scrollHeight;
|
|
1514
1580
|
setIsAtBottom(true);
|
|
1515
1581
|
}, []);
|
|
1516
|
-
const setContainer = (0,
|
|
1582
|
+
const setContainer = (0, import_react4.useCallback)((element) => {
|
|
1517
1583
|
containerRef.current = element;
|
|
1518
1584
|
if (element) {
|
|
1519
1585
|
measure();
|
|
@@ -1521,7 +1587,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
|
|
|
1521
1587
|
}, [
|
|
1522
1588
|
measure
|
|
1523
1589
|
]);
|
|
1524
|
-
(0,
|
|
1590
|
+
(0, import_react4.useEffect)(() => {
|
|
1525
1591
|
if (isAtBottom) {
|
|
1526
1592
|
scrollToBottom();
|
|
1527
1593
|
}
|
|
@@ -1530,7 +1596,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
|
|
|
1530
1596
|
isAtBottom,
|
|
1531
1597
|
scrollToBottom
|
|
1532
1598
|
]);
|
|
1533
|
-
const getContainerProps = (0,
|
|
1599
|
+
const getContainerProps = (0, import_react4.useCallback)(() => ({
|
|
1534
1600
|
ref: setContainer,
|
|
1535
1601
|
onScroll: measure
|
|
1536
1602
|
}), [
|
|
@@ -1552,14 +1618,14 @@ var DEFAULT_LOAD_EARLIER_STEP = 50;
|
|
|
1552
1618
|
var DEFAULT_COPY_RESET_MS = 1500;
|
|
1553
1619
|
function useChatTranscript(options) {
|
|
1554
1620
|
const { messages, status, initialVisibleCount = DEFAULT_VISIBLE_COUNT, loadEarlierStep = DEFAULT_LOAD_EARLIER_STEP, followUps, stickToBottomThreshold } = options;
|
|
1555
|
-
const latest = (0,
|
|
1621
|
+
const latest = (0, import_react5.useRef)(options);
|
|
1556
1622
|
latest.current = options;
|
|
1557
|
-
const [visibleCount, setVisibleCount] = (0,
|
|
1558
|
-
const [stopRequested, setStopRequested] = (0,
|
|
1623
|
+
const [visibleCount, setVisibleCount] = (0, import_react5.useState)(initialVisibleCount);
|
|
1624
|
+
const [stopRequested, setStopRequested] = (0, import_react5.useState)(false);
|
|
1559
1625
|
const isStreaming = status === "streaming";
|
|
1560
1626
|
const isBusy = status === "submitted" || isStreaming;
|
|
1561
1627
|
const isEmpty = messages.length === 0;
|
|
1562
|
-
(0,
|
|
1628
|
+
(0, import_react5.useEffect)(() => {
|
|
1563
1629
|
if (!isBusy) {
|
|
1564
1630
|
setStopRequested(false);
|
|
1565
1631
|
}
|
|
@@ -1576,7 +1642,7 @@ function useChatTranscript(options) {
|
|
|
1576
1642
|
streamingMessageId,
|
|
1577
1643
|
options
|
|
1578
1644
|
});
|
|
1579
|
-
const stop = (0,
|
|
1645
|
+
const stop = (0, import_react5.useCallback)(() => {
|
|
1580
1646
|
const current = latest.current;
|
|
1581
1647
|
if (current.status !== "submitted" && current.status !== "streaming") {
|
|
1582
1648
|
return;
|
|
@@ -1584,8 +1650,8 @@ function useChatTranscript(options) {
|
|
|
1584
1650
|
setStopRequested(true);
|
|
1585
1651
|
void current.onStop?.();
|
|
1586
1652
|
}, []);
|
|
1587
|
-
const loadEarlier = (0,
|
|
1588
|
-
const showAll = (0,
|
|
1653
|
+
const loadEarlier = (0, import_react5.useCallback)(() => setVisibleCount((count) => count + (latest.current.loadEarlierStep ?? DEFAULT_LOAD_EARLIER_STEP)), []);
|
|
1654
|
+
const showAll = (0, import_react5.useCallback)(() => setVisibleCount(latest.current.messages.length), []);
|
|
1589
1655
|
const scroll = useStickToBottom({
|
|
1590
1656
|
contentKey: contentSignature(messages),
|
|
1591
1657
|
...stickToBottomThreshold !== void 0 ? {
|
|
@@ -1621,7 +1687,7 @@ function useChatTranscript(options) {
|
|
|
1621
1687
|
__name(useChatTranscript, "useChatTranscript");
|
|
1622
1688
|
function useTranscriptItem(options) {
|
|
1623
1689
|
const { message, isStreaming = false } = options;
|
|
1624
|
-
const messagesRef = (0,
|
|
1690
|
+
const messagesRef = (0, import_react5.useRef)([
|
|
1625
1691
|
message
|
|
1626
1692
|
]);
|
|
1627
1693
|
if (messagesRef.current[0] !== message) {
|
|
@@ -1639,13 +1705,13 @@ function useTranscriptItem(options) {
|
|
|
1639
1705
|
}
|
|
1640
1706
|
__name(useTranscriptItem, "useTranscriptItem");
|
|
1641
1707
|
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,
|
|
1708
|
+
const [drafts, setDrafts] = (0, import_react5.useState)(() => /* @__PURE__ */ new Map());
|
|
1709
|
+
const [copied, setCopied] = (0, import_react5.useState)(() => /* @__PURE__ */ new Set());
|
|
1710
|
+
const [openReasoning, setOpenReasoning] = (0, import_react5.useState)(() => /* @__PURE__ */ new Map());
|
|
1711
|
+
const [picks, setPicks] = (0, import_react5.useState)(() => /* @__PURE__ */ new Map());
|
|
1712
|
+
const [settling, setSettling] = (0, import_react5.useState)(() => /* @__PURE__ */ new Map());
|
|
1713
|
+
const [settleErrors, setSettleErrors] = (0, import_react5.useState)(() => /* @__PURE__ */ new Map());
|
|
1714
|
+
const latest = (0, import_react5.useRef)({
|
|
1649
1715
|
options,
|
|
1650
1716
|
drafts,
|
|
1651
1717
|
picks,
|
|
@@ -1657,23 +1723,23 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
1657
1723
|
picks,
|
|
1658
1724
|
messages
|
|
1659
1725
|
};
|
|
1660
|
-
const copyTimers = (0,
|
|
1661
|
-
(0,
|
|
1726
|
+
const copyTimers = (0, import_react5.useRef)(/* @__PURE__ */ new Map());
|
|
1727
|
+
(0, import_react5.useEffect)(() => () => {
|
|
1662
1728
|
for (const timer of copyTimers.current.values()) {
|
|
1663
1729
|
clearTimeout(timer);
|
|
1664
1730
|
}
|
|
1665
1731
|
copyTimers.current.clear();
|
|
1666
1732
|
}, []);
|
|
1667
|
-
const callbackCache = (0,
|
|
1668
|
-
const reasoningToggleCache = (0,
|
|
1669
|
-
const toggleReasoning = (0,
|
|
1733
|
+
const callbackCache = (0, import_react5.useRef)(/* @__PURE__ */ new Map());
|
|
1734
|
+
const reasoningToggleCache = (0, import_react5.useRef)(/* @__PURE__ */ new Map());
|
|
1735
|
+
const toggleReasoning = (0, import_react5.useCallback)((key, open) => {
|
|
1670
1736
|
setOpenReasoning((current) => {
|
|
1671
1737
|
const next = new Map(current);
|
|
1672
1738
|
next.set(key, open ?? !(current.get(key) ?? false));
|
|
1673
1739
|
return next;
|
|
1674
1740
|
});
|
|
1675
1741
|
}, []);
|
|
1676
|
-
const stableToggle = (0,
|
|
1742
|
+
const stableToggle = (0, import_react5.useCallback)((key) => {
|
|
1677
1743
|
let cached = reasoningToggleCache.current.get(key);
|
|
1678
1744
|
if (!cached) {
|
|
1679
1745
|
cached = /* @__PURE__ */ __name((open) => toggleReasoning(key, open), "cached");
|
|
@@ -1683,10 +1749,10 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
1683
1749
|
}, [
|
|
1684
1750
|
toggleReasoning
|
|
1685
1751
|
]);
|
|
1686
|
-
const pick = (0,
|
|
1752
|
+
const pick = (0, import_react5.useCallback)((toolCallId, questionId, values) => {
|
|
1687
1753
|
setPicks((current) => new Map(current).set(pickKey(toolCallId, questionId), values));
|
|
1688
1754
|
}, []);
|
|
1689
|
-
const settle = (0,
|
|
1755
|
+
const settle = (0, import_react5.useCallback)((toolCallId, action, send) => {
|
|
1690
1756
|
setSettleErrors((current) => {
|
|
1691
1757
|
if (!current.has(toolCallId)) {
|
|
1692
1758
|
return current;
|
|
@@ -1710,7 +1776,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
1710
1776
|
failed(error);
|
|
1711
1777
|
}
|
|
1712
1778
|
}, []);
|
|
1713
|
-
const answer = (0,
|
|
1779
|
+
const answer = (0, import_react5.useCallback)((toolCallId) => {
|
|
1714
1780
|
const current = latest.current;
|
|
1715
1781
|
const onAnswer = current.options.onAnswer;
|
|
1716
1782
|
if (!onAnswer) {
|
|
@@ -1720,7 +1786,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
1720
1786
|
}, [
|
|
1721
1787
|
settle
|
|
1722
1788
|
]);
|
|
1723
|
-
const skip = (0,
|
|
1789
|
+
const skip = (0, import_react5.useCallback)((toolCallId) => {
|
|
1724
1790
|
const onSkip = latest.current.options.onSkip;
|
|
1725
1791
|
if (onSkip) {
|
|
1726
1792
|
settle(toolCallId, "skip", () => onSkip(toolCallId));
|
|
@@ -1728,7 +1794,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
1728
1794
|
}, [
|
|
1729
1795
|
settle
|
|
1730
1796
|
]);
|
|
1731
|
-
const approve = (0,
|
|
1797
|
+
const approve = (0, import_react5.useCallback)((toolCallId) => {
|
|
1732
1798
|
const onApprove = latest.current.options.onApprove;
|
|
1733
1799
|
if (onApprove) {
|
|
1734
1800
|
settle(toolCallId, "approve", () => onApprove(toolCallId));
|
|
@@ -1736,7 +1802,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
1736
1802
|
}, [
|
|
1737
1803
|
settle
|
|
1738
1804
|
]);
|
|
1739
|
-
const reject = (0,
|
|
1805
|
+
const reject = (0, import_react5.useCallback)((toolCallId) => {
|
|
1740
1806
|
const onReject = latest.current.options.onReject;
|
|
1741
1807
|
if (onReject) {
|
|
1742
1808
|
settle(toolCallId, "reject", () => onReject(toolCallId));
|
|
@@ -1744,7 +1810,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
1744
1810
|
}, [
|
|
1745
1811
|
settle
|
|
1746
1812
|
]);
|
|
1747
|
-
const callbacksFor = (0,
|
|
1813
|
+
const callbacksFor = (0, import_react5.useCallback)((id) => {
|
|
1748
1814
|
const cached = callbackCache.current.get(id);
|
|
1749
1815
|
if (cached) {
|
|
1750
1816
|
return cached;
|
|
@@ -1983,7 +2049,7 @@ function MessageItem({ message, isStreaming = false, editable, onEditSubmit, reg
|
|
|
1983
2049
|
getCreatedAt: /* @__PURE__ */ __name(() => createdAt, "getCreatedAt")
|
|
1984
2050
|
} : {}
|
|
1985
2051
|
});
|
|
1986
|
-
return /* @__PURE__ */
|
|
2052
|
+
return /* @__PURE__ */ import_react6.default.createElement(MessageItemView, {
|
|
1987
2053
|
item,
|
|
1988
2054
|
...slots
|
|
1989
2055
|
});
|
|
@@ -1991,51 +2057,51 @@ function MessageItem({ message, isStreaming = false, editable, onEditSubmit, reg
|
|
|
1991
2057
|
__name(MessageItem, "MessageItem");
|
|
1992
2058
|
function MessageItemView({ item, ...slots }) {
|
|
1993
2059
|
const { classNames } = slots;
|
|
1994
|
-
const actionRow = /* @__PURE__ */
|
|
2060
|
+
const actionRow = /* @__PURE__ */ import_react6.default.createElement("div", {
|
|
1995
2061
|
className: classNames?.actions,
|
|
1996
2062
|
"data-actions-for": item.role
|
|
1997
|
-
}, item.copy.available ? /* @__PURE__ */
|
|
2063
|
+
}, item.copy.available ? /* @__PURE__ */ import_react6.default.createElement("button", {
|
|
1998
2064
|
type: "button",
|
|
1999
2065
|
onClick: item.copy.copy,
|
|
2000
2066
|
className: classNames?.actionButton,
|
|
2001
2067
|
title: item.copy.copied ? "Copied!" : "Copy message text"
|
|
2002
|
-
}, item.copy.copied ? "Copied" : "Copy") : null, item.fork.available ? /* @__PURE__ */
|
|
2068
|
+
}, item.copy.copied ? "Copied" : "Copy") : null, item.fork.available ? /* @__PURE__ */ import_react6.default.createElement("button", {
|
|
2003
2069
|
type: "button",
|
|
2004
2070
|
onClick: item.fork.run,
|
|
2005
2071
|
className: classNames?.actionButton,
|
|
2006
2072
|
title: "Fork thread from this message"
|
|
2007
|
-
}, "Fork") : null, item.regenerate.available ? /* @__PURE__ */
|
|
2073
|
+
}, "Fork") : null, item.regenerate.available ? /* @__PURE__ */ import_react6.default.createElement("button", {
|
|
2008
2074
|
type: "button",
|
|
2009
2075
|
onClick: item.regenerate.run,
|
|
2010
2076
|
className: classNames?.actionButton,
|
|
2011
2077
|
title: "Regenerate response"
|
|
2012
|
-
}, "Regenerate") : null, slots.meta, !item.isUser && item.usage ? /* @__PURE__ */
|
|
2078
|
+
}, "Regenerate") : null, slots.meta, !item.isUser && item.usage ? /* @__PURE__ */ import_react6.default.createElement("span", {
|
|
2013
2079
|
className: classNames?.usage,
|
|
2014
2080
|
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__ */
|
|
2081
|
+
}, item.usage.costLabel, " \xB7 ", item.usage.tokensLabel) : null, item.timestamp ? /* @__PURE__ */ import_react6.default.createElement("span", {
|
|
2016
2082
|
className: classNames?.timestamp,
|
|
2017
2083
|
title: item.timestamp.absolute
|
|
2018
2084
|
}, item.timestamp.relative) : null);
|
|
2019
2085
|
if (item.edit.available) {
|
|
2020
|
-
return /* @__PURE__ */
|
|
2086
|
+
return /* @__PURE__ */ import_react6.default.createElement(EditableUserBubble, {
|
|
2021
2087
|
item,
|
|
2022
2088
|
slots,
|
|
2023
2089
|
actions: actionRow
|
|
2024
2090
|
});
|
|
2025
2091
|
}
|
|
2026
2092
|
const className = joinClasses(classNames?.root, classNames?.byRole?.[item.role]);
|
|
2027
|
-
return /* @__PURE__ */
|
|
2093
|
+
return /* @__PURE__ */ import_react6.default.createElement("div", {
|
|
2028
2094
|
className,
|
|
2029
2095
|
"data-role": item.role,
|
|
2030
2096
|
"data-streaming": item.isStreaming ? "true" : void 0
|
|
2031
|
-
}, /* @__PURE__ */
|
|
2097
|
+
}, /* @__PURE__ */ import_react6.default.createElement("div", null, renderBlocks(item, slots)), actionRow);
|
|
2032
2098
|
}
|
|
2033
2099
|
__name(MessageItemView, "MessageItemView");
|
|
2034
2100
|
function renderBlocks(item, slots) {
|
|
2035
2101
|
const nodes = [];
|
|
2036
2102
|
for (const block of item.blocks) {
|
|
2037
2103
|
if (block.kind === "text") {
|
|
2038
|
-
nodes.push(/* @__PURE__ */
|
|
2104
|
+
nodes.push(/* @__PURE__ */ import_react6.default.createElement("div", {
|
|
2039
2105
|
key: block.key,
|
|
2040
2106
|
className: slots.classNames?.text
|
|
2041
2107
|
}, slots.renderText ? slots.renderText(block.text, {
|
|
@@ -2056,7 +2122,7 @@ function renderBlocks(item, slots) {
|
|
|
2056
2122
|
continue;
|
|
2057
2123
|
}
|
|
2058
2124
|
if (block.kind === "ui" && slots.renderUi) {
|
|
2059
|
-
nodes.push(/* @__PURE__ */
|
|
2125
|
+
nodes.push(/* @__PURE__ */ import_react6.default.createElement("div", {
|
|
2060
2126
|
key: block.key,
|
|
2061
2127
|
"data-slot": "ui",
|
|
2062
2128
|
"data-component": block.component
|
|
@@ -2067,18 +2133,18 @@ function renderBlocks(item, slots) {
|
|
|
2067
2133
|
}
|
|
2068
2134
|
__name(renderBlocks, "renderBlocks");
|
|
2069
2135
|
function renderFilesBlock(block, slots) {
|
|
2070
|
-
return /* @__PURE__ */
|
|
2136
|
+
return /* @__PURE__ */ import_react6.default.createElement("div", {
|
|
2071
2137
|
key: block.key,
|
|
2072
2138
|
className: slots.classNames?.files,
|
|
2073
2139
|
"data-files": "true"
|
|
2074
|
-
}, slots.renderFiles ? slots.renderFiles(block.files) : block.files.map((file) => /* @__PURE__ */
|
|
2140
|
+
}, slots.renderFiles ? slots.renderFiles(block.files) : block.files.map((file) => /* @__PURE__ */ import_react6.default.createElement("a", {
|
|
2075
2141
|
key: file.url,
|
|
2076
2142
|
href: file.url,
|
|
2077
2143
|
target: "_blank",
|
|
2078
2144
|
rel: "noreferrer",
|
|
2079
2145
|
className: slots.classNames?.file,
|
|
2080
2146
|
title: file.filename ?? file.mediaType
|
|
2081
|
-
}, file.isImage ? /* @__PURE__ */
|
|
2147
|
+
}, file.isImage ? /* @__PURE__ */ import_react6.default.createElement("img", {
|
|
2082
2148
|
src: file.url,
|
|
2083
2149
|
alt: file.filename ?? "image",
|
|
2084
2150
|
className: slots.classNames?.fileImage
|
|
@@ -2086,17 +2152,17 @@ function renderFilesBlock(block, slots) {
|
|
|
2086
2152
|
}
|
|
2087
2153
|
__name(renderFilesBlock, "renderFilesBlock");
|
|
2088
2154
|
function renderReasoningBlock(block, slots) {
|
|
2089
|
-
return /* @__PURE__ */
|
|
2155
|
+
return /* @__PURE__ */ import_react6.default.createElement("div", {
|
|
2090
2156
|
key: block.key,
|
|
2091
2157
|
className: slots.classNames?.reasoning,
|
|
2092
2158
|
"data-reasoning": "true",
|
|
2093
2159
|
"data-streaming": block.isStreaming ? "true" : void 0
|
|
2094
|
-
}, /* @__PURE__ */
|
|
2160
|
+
}, /* @__PURE__ */ import_react6.default.createElement("button", {
|
|
2095
2161
|
type: "button",
|
|
2096
2162
|
className: slots.classNames?.reasoningToggle,
|
|
2097
2163
|
onClick: /* @__PURE__ */ __name(() => block.toggle(), "onClick"),
|
|
2098
2164
|
"aria-expanded": block.isOpen
|
|
2099
|
-
}, slots.reasoningLabel ?? "Reasoning"), block.isOpen ? /* @__PURE__ */
|
|
2165
|
+
}, slots.reasoningLabel ?? "Reasoning"), block.isOpen ? /* @__PURE__ */ import_react6.default.createElement("div", {
|
|
2100
2166
|
className: slots.classNames?.reasoningText
|
|
2101
2167
|
}, slots.renderReasoning ? slots.renderReasoning(block.text, {
|
|
2102
2168
|
isStreaming: block.isStreaming,
|
|
@@ -2107,7 +2173,7 @@ __name(renderReasoningBlock, "renderReasoningBlock");
|
|
|
2107
2173
|
function renderToolBlock(item, block, slots) {
|
|
2108
2174
|
if (slots.renderToolGroup) {
|
|
2109
2175
|
return [
|
|
2110
|
-
/* @__PURE__ */
|
|
2176
|
+
/* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, {
|
|
2111
2177
|
key: block.key
|
|
2112
2178
|
}, slots.renderToolGroup(block.parts, block.key))
|
|
2113
2179
|
];
|
|
@@ -2118,7 +2184,7 @@ function renderToolBlock(item, block, slots) {
|
|
|
2118
2184
|
const renderToolPart = slots.renderToolPart;
|
|
2119
2185
|
return block.parts.map((part) => {
|
|
2120
2186
|
const partKey = `${item.id}-${part.toolCallId}`;
|
|
2121
|
-
return /* @__PURE__ */
|
|
2187
|
+
return /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, {
|
|
2122
2188
|
key: partKey
|
|
2123
2189
|
}, renderToolPart(part, partKey));
|
|
2124
2190
|
});
|
|
@@ -2128,14 +2194,14 @@ function EditableUserBubble({ item, slots, actions }) {
|
|
|
2128
2194
|
const { classNames } = slots;
|
|
2129
2195
|
const { edit } = item;
|
|
2130
2196
|
if (!edit.isEditing) {
|
|
2131
|
-
return /* @__PURE__ */
|
|
2197
|
+
return /* @__PURE__ */ import_react6.default.createElement("div", {
|
|
2132
2198
|
className: joinClasses(classNames?.root, classNames?.byRole?.user),
|
|
2133
2199
|
"data-role": "user"
|
|
2134
|
-
}, /* @__PURE__ */
|
|
2200
|
+
}, /* @__PURE__ */ import_react6.default.createElement("div", {
|
|
2135
2201
|
className: classNames?.text
|
|
2136
2202
|
}, slots.renderText ? slots.renderText(item.text, {
|
|
2137
2203
|
isStreaming: false
|
|
2138
|
-
}) : item.text), /* @__PURE__ */
|
|
2204
|
+
}) : item.text), /* @__PURE__ */ import_react6.default.createElement("button", {
|
|
2139
2205
|
type: "button",
|
|
2140
2206
|
onClick: edit.start,
|
|
2141
2207
|
className: classNames?.actionButton,
|
|
@@ -2143,18 +2209,18 @@ function EditableUserBubble({ item, slots, actions }) {
|
|
|
2143
2209
|
}, "Edit"), actions);
|
|
2144
2210
|
}
|
|
2145
2211
|
const textareaProps = edit.getTextareaProps();
|
|
2146
|
-
return /* @__PURE__ */
|
|
2212
|
+
return /* @__PURE__ */ import_react6.default.createElement("div", {
|
|
2147
2213
|
"data-editing": "true"
|
|
2148
|
-
}, /* @__PURE__ */
|
|
2214
|
+
}, /* @__PURE__ */ import_react6.default.createElement("textarea", {
|
|
2149
2215
|
...textareaProps,
|
|
2150
2216
|
rows: Math.min(8, edit.draft.split("\n").length + 1),
|
|
2151
2217
|
className: classNames?.editTextarea
|
|
2152
|
-
}), /* @__PURE__ */
|
|
2218
|
+
}), /* @__PURE__ */ import_react6.default.createElement("div", {
|
|
2153
2219
|
className: classNames?.editActions
|
|
2154
|
-
}, /* @__PURE__ */
|
|
2220
|
+
}, /* @__PURE__ */ import_react6.default.createElement("button", {
|
|
2155
2221
|
type: "button",
|
|
2156
2222
|
onClick: edit.cancel
|
|
2157
|
-
}, "Cancel"), /* @__PURE__ */
|
|
2223
|
+
}, "Cancel"), /* @__PURE__ */ import_react6.default.createElement("button", {
|
|
2158
2224
|
type: "button",
|
|
2159
2225
|
onClick: edit.save,
|
|
2160
2226
|
disabled: !edit.canSave
|
|
@@ -2394,35 +2460,35 @@ function toItem(entry) {
|
|
|
2394
2460
|
__name(toItem, "toItem");
|
|
2395
2461
|
|
|
2396
2462
|
// src/composer/use-composer-autocomplete.ts
|
|
2397
|
-
var
|
|
2463
|
+
var import_react7 = require("react");
|
|
2398
2464
|
function useComposerAutocomplete(options) {
|
|
2399
2465
|
const { value, sources, acceptOnTab = true } = options;
|
|
2400
|
-
const latest = (0,
|
|
2466
|
+
const latest = (0, import_react7.useRef)(options);
|
|
2401
2467
|
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,
|
|
2468
|
+
const inputRef = (0, import_react7.useRef)(null);
|
|
2469
|
+
const [caret, setCaret] = (0, import_react7.useState)(value.length);
|
|
2470
|
+
const [items, setItems] = (0, import_react7.useState)([]);
|
|
2471
|
+
const [isLoading, setLoading] = (0, import_react7.useState)(false);
|
|
2472
|
+
const [error, setError] = (0, import_react7.useState)(null);
|
|
2473
|
+
const [activeIndex, setActiveIndex] = (0, import_react7.useState)(0);
|
|
2474
|
+
const [dismissedIndex, setDismissedIndex] = (0, import_react7.useState)(null);
|
|
2409
2475
|
const safeCaret = Math.min(caret, value.length);
|
|
2410
|
-
const match = (0,
|
|
2476
|
+
const match = (0, import_react7.useMemo)(() => findActiveTrigger(value, safeCaret, sources), [
|
|
2411
2477
|
value,
|
|
2412
2478
|
safeCaret,
|
|
2413
2479
|
sources
|
|
2414
2480
|
]);
|
|
2415
2481
|
const isActive = match !== null && dismissedIndex !== match.index;
|
|
2416
|
-
const matchRef = (0,
|
|
2482
|
+
const matchRef = (0, import_react7.useRef)(match);
|
|
2417
2483
|
matchRef.current = match;
|
|
2418
|
-
const caretRef = (0,
|
|
2484
|
+
const caretRef = (0, import_react7.useRef)(safeCaret);
|
|
2419
2485
|
caretRef.current = safeCaret;
|
|
2420
|
-
const itemsRef = (0,
|
|
2486
|
+
const itemsRef = (0, import_react7.useRef)(items);
|
|
2421
2487
|
itemsRef.current = items;
|
|
2422
|
-
const activeIndexRef = (0,
|
|
2488
|
+
const activeIndexRef = (0, import_react7.useRef)(activeIndex);
|
|
2423
2489
|
activeIndexRef.current = activeIndex;
|
|
2424
2490
|
const requestKey = isActive && match ? `${match.source.id}\0${match.query}` : null;
|
|
2425
|
-
(0,
|
|
2491
|
+
(0, import_react7.useEffect)(() => {
|
|
2426
2492
|
const current = matchRef.current;
|
|
2427
2493
|
if (requestKey === null || current === null) {
|
|
2428
2494
|
setItems([]);
|
|
@@ -2470,25 +2536,25 @@ function useComposerAutocomplete(options) {
|
|
|
2470
2536
|
]);
|
|
2471
2537
|
const isOpen = isActive;
|
|
2472
2538
|
const activeItem = isOpen ? items[activeIndex] ?? null : null;
|
|
2473
|
-
const reactId = (0,
|
|
2539
|
+
const reactId = (0, import_react7.useId)();
|
|
2474
2540
|
const listboxId = options.id ?? `agent-autocomplete-${reactId}`;
|
|
2475
|
-
const optionId = (0,
|
|
2541
|
+
const optionId = (0, import_react7.useCallback)((index) => `${listboxId}-option-${index}`, [
|
|
2476
2542
|
listboxId
|
|
2477
2543
|
]);
|
|
2478
|
-
const highlight = (0,
|
|
2544
|
+
const highlight = (0, import_react7.useCallback)((index) => {
|
|
2479
2545
|
const total = itemsRef.current.length;
|
|
2480
2546
|
if (total === 0) return;
|
|
2481
2547
|
setActiveIndex((index % total + total) % total);
|
|
2482
2548
|
}, []);
|
|
2483
|
-
const moveHighlight = (0,
|
|
2549
|
+
const moveHighlight = (0, import_react7.useCallback)((delta) => highlight(activeIndexRef.current + delta), [
|
|
2484
2550
|
highlight
|
|
2485
2551
|
]);
|
|
2486
|
-
const dismiss = (0,
|
|
2552
|
+
const dismiss = (0, import_react7.useCallback)(() => {
|
|
2487
2553
|
const current = matchRef.current;
|
|
2488
2554
|
if (current) setDismissedIndex(current.index);
|
|
2489
2555
|
}, []);
|
|
2490
|
-
const pendingCaret = (0,
|
|
2491
|
-
const accept = (0,
|
|
2556
|
+
const pendingCaret = (0, import_react7.useRef)(null);
|
|
2557
|
+
const accept = (0, import_react7.useCallback)((item) => {
|
|
2492
2558
|
const current = matchRef.current;
|
|
2493
2559
|
if (!current) return;
|
|
2494
2560
|
const chosen = item ?? itemsRef.current[activeIndexRef.current];
|
|
@@ -2499,16 +2565,16 @@ function useComposerAutocomplete(options) {
|
|
|
2499
2565
|
setDismissedIndex(null);
|
|
2500
2566
|
pendingCaret.current = edit.caret;
|
|
2501
2567
|
}, []);
|
|
2502
|
-
(0,
|
|
2568
|
+
(0, import_react7.useLayoutEffect)(() => {
|
|
2503
2569
|
const position = pendingCaret.current;
|
|
2504
2570
|
if (position === null) return;
|
|
2505
2571
|
pendingCaret.current = null;
|
|
2506
2572
|
inputRef.current?.setSelectionRange(position, position);
|
|
2507
2573
|
});
|
|
2508
|
-
const readCaret = (0,
|
|
2574
|
+
const readCaret = (0, import_react7.useCallback)((element) => {
|
|
2509
2575
|
setCaret(element.selectionStart ?? element.value.length);
|
|
2510
2576
|
}, []);
|
|
2511
|
-
const onKeyDown = (0,
|
|
2577
|
+
const onKeyDown = (0, import_react7.useCallback)((event) => {
|
|
2512
2578
|
if (!isOpen) return;
|
|
2513
2579
|
const hasItems = itemsRef.current.length > 0;
|
|
2514
2580
|
switch (event.key) {
|
|
@@ -2546,23 +2612,23 @@ function useComposerAutocomplete(options) {
|
|
|
2546
2612
|
dismiss,
|
|
2547
2613
|
moveHighlight
|
|
2548
2614
|
]);
|
|
2549
|
-
const onChange = (0,
|
|
2615
|
+
const onChange = (0, import_react7.useCallback)((event) => {
|
|
2550
2616
|
readCaret(event.target);
|
|
2551
2617
|
const next = findActiveTrigger(event.target.value, event.target.selectionStart ?? event.target.value.length, latest.current.sources);
|
|
2552
2618
|
setDismissedIndex((current) => current !== null && next?.index === current ? current : null);
|
|
2553
2619
|
}, [
|
|
2554
2620
|
readCaret
|
|
2555
2621
|
]);
|
|
2556
|
-
const onSelect = (0,
|
|
2622
|
+
const onSelect = (0, import_react7.useCallback)((event) => readCaret(event.currentTarget), [
|
|
2557
2623
|
readCaret
|
|
2558
2624
|
]);
|
|
2559
|
-
const onClick = (0,
|
|
2625
|
+
const onClick = (0, import_react7.useCallback)((event) => readCaret(event.currentTarget), [
|
|
2560
2626
|
readCaret
|
|
2561
2627
|
]);
|
|
2562
|
-
const setInput = (0,
|
|
2628
|
+
const setInput = (0, import_react7.useCallback)((element) => {
|
|
2563
2629
|
inputRef.current = element;
|
|
2564
2630
|
}, []);
|
|
2565
|
-
const getInputProps = (0,
|
|
2631
|
+
const getInputProps = (0, import_react7.useCallback)(() => ({
|
|
2566
2632
|
ref: setInput,
|
|
2567
2633
|
onChange,
|
|
2568
2634
|
onKeyDown,
|
|
@@ -2590,7 +2656,7 @@ function useComposerAutocomplete(options) {
|
|
|
2590
2656
|
activeIndex,
|
|
2591
2657
|
optionId
|
|
2592
2658
|
]);
|
|
2593
|
-
const getListboxProps = (0,
|
|
2659
|
+
const getListboxProps = (0, import_react7.useCallback)(() => ({
|
|
2594
2660
|
id: listboxId,
|
|
2595
2661
|
role: "listbox",
|
|
2596
2662
|
"aria-label": match?.source.label ?? match?.source.id ?? "Suggestions"
|
|
@@ -2598,7 +2664,7 @@ function useComposerAutocomplete(options) {
|
|
|
2598
2664
|
listboxId,
|
|
2599
2665
|
match
|
|
2600
2666
|
]);
|
|
2601
|
-
const getOptionProps = (0,
|
|
2667
|
+
const getOptionProps = (0, import_react7.useCallback)((index) => ({
|
|
2602
2668
|
id: optionId(index),
|
|
2603
2669
|
role: "option",
|
|
2604
2670
|
"aria-selected": index === activeIndex
|
|
@@ -2652,6 +2718,16 @@ function refusalReason(result) {
|
|
|
2652
2718
|
__name(refusalReason, "refusalReason");
|
|
2653
2719
|
function storedMessageToUiMessage(message) {
|
|
2654
2720
|
const parts = [];
|
|
2721
|
+
if (message.reasoning) {
|
|
2722
|
+
parts.push({
|
|
2723
|
+
type: "reasoning",
|
|
2724
|
+
text: message.reasoning,
|
|
2725
|
+
state: "done",
|
|
2726
|
+
...message.reasoningMs !== void 0 ? {
|
|
2727
|
+
providerMetadata: reasoningDurationMetadata(message.reasoningMs)
|
|
2728
|
+
} : {}
|
|
2729
|
+
});
|
|
2730
|
+
}
|
|
2655
2731
|
if (message.content) {
|
|
2656
2732
|
parts.push({
|
|
2657
2733
|
type: "text",
|
|
@@ -2666,6 +2742,20 @@ function storedMessageToUiMessage(message) {
|
|
|
2666
2742
|
url: attachment.url
|
|
2667
2743
|
});
|
|
2668
2744
|
}
|
|
2745
|
+
for (const component of message.ui ?? []) {
|
|
2746
|
+
parts.push({
|
|
2747
|
+
type: "data-ui",
|
|
2748
|
+
id: component.id,
|
|
2749
|
+
data: {
|
|
2750
|
+
id: component.id,
|
|
2751
|
+
component: component.component,
|
|
2752
|
+
props: component.props,
|
|
2753
|
+
...component.version !== void 0 ? {
|
|
2754
|
+
version: component.version
|
|
2755
|
+
} : {}
|
|
2756
|
+
}
|
|
2757
|
+
});
|
|
2758
|
+
}
|
|
2669
2759
|
for (const call of message.toolCalls ?? []) {
|
|
2670
2760
|
const result = message.toolResults?.find((candidate) => candidate.id === call.id);
|
|
2671
2761
|
const toolKind2 = call.kind;
|
|
@@ -2767,21 +2857,21 @@ function sumUsage(rows) {
|
|
|
2767
2857
|
__name(sumUsage, "sumUsage");
|
|
2768
2858
|
|
|
2769
2859
|
// src/use-agent-chat.ts
|
|
2770
|
-
var
|
|
2771
|
-
var
|
|
2860
|
+
var import_react8 = require("@ai-sdk/react");
|
|
2861
|
+
var import_react9 = require("react");
|
|
2772
2862
|
function useAgentChat(options) {
|
|
2773
|
-
const latest = (0,
|
|
2863
|
+
const latest = (0, import_react9.useRef)(options);
|
|
2774
2864
|
latest.current = options;
|
|
2775
|
-
const [runId, setRunId] = (0,
|
|
2776
|
-
const runIdRef = (0,
|
|
2865
|
+
const [runId, setRunId] = (0, import_react9.useState)(options.resumeRunId);
|
|
2866
|
+
const runIdRef = (0, import_react9.useRef)(runId);
|
|
2777
2867
|
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,
|
|
2868
|
+
const settlingRunIdRef = (0, import_react9.useRef)(void 0);
|
|
2869
|
+
const autoResumeRunIdRef = (0, import_react9.useRef)(void 0);
|
|
2870
|
+
const [autoResume, setAutoResume] = (0, import_react9.useState)(false);
|
|
2871
|
+
const [activeRunId, setActiveRunId] = (0, import_react9.useState)(null);
|
|
2872
|
+
const regenerateNext = (0, import_react9.useRef)(false);
|
|
2873
|
+
const createdThreadId = (0, import_react9.useRef)(void 0);
|
|
2874
|
+
const client = (0, import_react9.useMemo)(() => {
|
|
2785
2875
|
if (options.client) return options.client;
|
|
2786
2876
|
return new AgentClient({
|
|
2787
2877
|
...options.baseUrl !== void 0 ? {
|
|
@@ -2796,7 +2886,7 @@ function useAgentChat(options) {
|
|
|
2796
2886
|
getHeaders: /* @__PURE__ */ __name(async () => mergeHeaders(latest.current), "getHeaders")
|
|
2797
2887
|
});
|
|
2798
2888
|
}, []);
|
|
2799
|
-
(0,
|
|
2889
|
+
(0, import_react9.useEffect)(() => {
|
|
2800
2890
|
if (!options.resume || options.threadId === void 0) return;
|
|
2801
2891
|
let cancelled = false;
|
|
2802
2892
|
const threadId = options.threadId;
|
|
@@ -2816,7 +2906,7 @@ function useAgentChat(options) {
|
|
|
2816
2906
|
options.resume,
|
|
2817
2907
|
options.threadId
|
|
2818
2908
|
]);
|
|
2819
|
-
const transport = (0,
|
|
2909
|
+
const transport = (0, import_react9.useMemo)(() => {
|
|
2820
2910
|
function onMeta(meta) {
|
|
2821
2911
|
settlingRunIdRef.current = meta.runId;
|
|
2822
2912
|
setRunId(meta.runId);
|
|
@@ -2865,8 +2955,8 @@ function useAgentChat(options) {
|
|
|
2865
2955
|
}, "onAttemptStart")
|
|
2866
2956
|
});
|
|
2867
2957
|
}, []);
|
|
2868
|
-
const backgroundRef = (0,
|
|
2869
|
-
const chat = (0,
|
|
2958
|
+
const backgroundRef = (0, import_react9.useRef)(() => Promise.resolve());
|
|
2959
|
+
const chat = (0, import_react8.useChat)({
|
|
2870
2960
|
transport,
|
|
2871
2961
|
resume: options.resumeRunId !== void 0 || autoResume,
|
|
2872
2962
|
...options.threadId !== void 0 ? {
|
|
@@ -2896,13 +2986,13 @@ function useAgentChat(options) {
|
|
|
2896
2986
|
}
|
|
2897
2987
|
}, "onFinish")
|
|
2898
2988
|
});
|
|
2899
|
-
const chatRef = (0,
|
|
2989
|
+
const chatRef = (0, import_react9.useRef)(chat);
|
|
2900
2990
|
chatRef.current = chat;
|
|
2901
|
-
const turnInFlight = (0,
|
|
2902
|
-
const isTurnInFlight = (0,
|
|
2991
|
+
const turnInFlight = (0, import_react9.useRef)(false);
|
|
2992
|
+
const isTurnInFlight = (0, import_react9.useCallback)(() => turnInFlight.current || transport.isAttemptLive, [
|
|
2903
2993
|
transport
|
|
2904
2994
|
]);
|
|
2905
|
-
const sendMessage = (0,
|
|
2995
|
+
const sendMessage = (0, import_react9.useCallback)(async (...args) => {
|
|
2906
2996
|
if (isTurnInFlight()) return;
|
|
2907
2997
|
turnInFlight.current = true;
|
|
2908
2998
|
try {
|
|
@@ -2913,15 +3003,15 @@ function useAgentChat(options) {
|
|
|
2913
3003
|
}, [
|
|
2914
3004
|
isTurnInFlight
|
|
2915
3005
|
]);
|
|
2916
|
-
const addToolResult = (0,
|
|
3006
|
+
const addToolResult = (0, import_react9.useCallback)(({ tool, toolCallId, output }) => chatRef.current.addToolResult({
|
|
2917
3007
|
tool,
|
|
2918
3008
|
toolCallId,
|
|
2919
3009
|
output
|
|
2920
3010
|
}), []);
|
|
2921
|
-
const [threads, setThreads] = (0,
|
|
2922
|
-
const [quota, setQuota] = (0,
|
|
2923
|
-
const [backgroundRuns, setBackgroundRuns] = (0,
|
|
2924
|
-
const refreshBackground = (0,
|
|
3011
|
+
const [threads, setThreads] = (0, import_react9.useState)([]);
|
|
3012
|
+
const [quota, setQuota] = (0, import_react9.useState)(null);
|
|
3013
|
+
const [backgroundRuns, setBackgroundRuns] = (0, import_react9.useState)([]);
|
|
3014
|
+
const refreshBackground = (0, import_react9.useCallback)(async () => {
|
|
2925
3015
|
const threadId = latest.current.threadId ?? createdThreadId.current;
|
|
2926
3016
|
if (threadId === void 0) {
|
|
2927
3017
|
return;
|
|
@@ -2946,7 +3036,7 @@ function useAgentChat(options) {
|
|
|
2946
3036
|
]);
|
|
2947
3037
|
backgroundRef.current = refreshBackground;
|
|
2948
3038
|
const isWorking = backgroundRuns.some((run) => run.status === "running");
|
|
2949
|
-
(0,
|
|
3039
|
+
(0, import_react9.useEffect)(() => {
|
|
2950
3040
|
if (options.background !== true || options.threadId === void 0) {
|
|
2951
3041
|
return;
|
|
2952
3042
|
}
|
|
@@ -2956,7 +3046,7 @@ function useAgentChat(options) {
|
|
|
2956
3046
|
options.threadId,
|
|
2957
3047
|
refreshBackground
|
|
2958
3048
|
]);
|
|
2959
|
-
(0,
|
|
3049
|
+
(0, import_react9.useEffect)(() => {
|
|
2960
3050
|
const every = latest.current.backgroundPollMs ?? 5e3;
|
|
2961
3051
|
if (latest.current.background !== true || !isWorking || every <= 0) {
|
|
2962
3052
|
return;
|
|
@@ -2967,26 +3057,26 @@ function useAgentChat(options) {
|
|
|
2967
3057
|
isWorking,
|
|
2968
3058
|
refreshBackground
|
|
2969
3059
|
]);
|
|
2970
|
-
const loadThreads = (0,
|
|
3060
|
+
const loadThreads = (0, import_react9.useCallback)(async () => {
|
|
2971
3061
|
const list = await client.listThreads();
|
|
2972
3062
|
setThreads(list);
|
|
2973
3063
|
return list;
|
|
2974
3064
|
}, [
|
|
2975
3065
|
client
|
|
2976
3066
|
]);
|
|
2977
|
-
const loadThread = (0,
|
|
3067
|
+
const loadThread = (0, import_react9.useCallback)((id) => client.getThread(id), [
|
|
2978
3068
|
client
|
|
2979
3069
|
]);
|
|
2980
|
-
const deleteThread = (0,
|
|
3070
|
+
const deleteThread = (0, import_react9.useCallback)(async (id) => {
|
|
2981
3071
|
await client.deleteThread(id);
|
|
2982
3072
|
setThreads((current) => current.filter((thread) => thread.id !== id));
|
|
2983
3073
|
}, [
|
|
2984
3074
|
client
|
|
2985
3075
|
]);
|
|
2986
|
-
const forkThread = (0,
|
|
3076
|
+
const forkThread = (0, import_react9.useCallback)((threadId, messageId) => client.forkFromMessage(threadId, messageId), [
|
|
2987
3077
|
client
|
|
2988
3078
|
]);
|
|
2989
|
-
const renameThread = (0,
|
|
3079
|
+
const renameThread = (0, import_react9.useCallback)(async (id, title) => {
|
|
2990
3080
|
await client.renameThread(id, title);
|
|
2991
3081
|
setThreads((current) => current.map((thread) => thread.id === id ? {
|
|
2992
3082
|
...thread,
|
|
@@ -2995,24 +3085,24 @@ function useAgentChat(options) {
|
|
|
2995
3085
|
}, [
|
|
2996
3086
|
client
|
|
2997
3087
|
]);
|
|
2998
|
-
const promoteThread = (0,
|
|
3088
|
+
const promoteThread = (0, import_react9.useCallback)(async (id) => {
|
|
2999
3089
|
await client.promoteThread(id);
|
|
3000
3090
|
await loadThreads();
|
|
3001
3091
|
}, [
|
|
3002
3092
|
client,
|
|
3003
3093
|
loadThreads
|
|
3004
3094
|
]);
|
|
3005
|
-
const truncateFromMessage = (0,
|
|
3095
|
+
const truncateFromMessage = (0, import_react9.useCallback)((threadId, messageId) => client.truncateFromMessage(threadId, messageId).then(() => void 0), [
|
|
3006
3096
|
client
|
|
3007
3097
|
]);
|
|
3008
|
-
const loadQuota = (0,
|
|
3098
|
+
const loadQuota = (0, import_react9.useCallback)(async () => {
|
|
3009
3099
|
const today = await client.getQuotaToday();
|
|
3010
3100
|
setQuota(today);
|
|
3011
3101
|
return today;
|
|
3012
3102
|
}, [
|
|
3013
3103
|
client
|
|
3014
3104
|
]);
|
|
3015
|
-
const cancel = (0,
|
|
3105
|
+
const cancel = (0, import_react9.useCallback)(async () => {
|
|
3016
3106
|
chatRef.current.stop();
|
|
3017
3107
|
const activeRunId2 = runIdRef.current;
|
|
3018
3108
|
if (activeRunId2) {
|
|
@@ -3024,14 +3114,14 @@ function useAgentChat(options) {
|
|
|
3024
3114
|
}, [
|
|
3025
3115
|
client
|
|
3026
3116
|
]);
|
|
3027
|
-
const approve = (0,
|
|
3117
|
+
const approve = (0, import_react9.useCallback)(async ({ toolCallId }) => {
|
|
3028
3118
|
await client.approveToolCall({
|
|
3029
3119
|
toolCallId
|
|
3030
3120
|
});
|
|
3031
3121
|
}, [
|
|
3032
3122
|
client
|
|
3033
3123
|
]);
|
|
3034
|
-
const reject = (0,
|
|
3124
|
+
const reject = (0, import_react9.useCallback)(async ({ toolCallId, reason }) => {
|
|
3035
3125
|
await client.rejectToolCall({
|
|
3036
3126
|
toolCallId,
|
|
3037
3127
|
...reason !== void 0 ? {
|
|
@@ -3041,7 +3131,7 @@ function useAgentChat(options) {
|
|
|
3041
3131
|
}, [
|
|
3042
3132
|
client
|
|
3043
3133
|
]);
|
|
3044
|
-
const answer = (0,
|
|
3134
|
+
const answer = (0, import_react9.useCallback)(async ({ toolCallId, answers }) => {
|
|
3045
3135
|
await client.answerToolCall({
|
|
3046
3136
|
toolCallId,
|
|
3047
3137
|
...answers !== void 0 ? {
|
|
@@ -3051,14 +3141,14 @@ function useAgentChat(options) {
|
|
|
3051
3141
|
}, [
|
|
3052
3142
|
client
|
|
3053
3143
|
]);
|
|
3054
|
-
const skip = (0,
|
|
3144
|
+
const skip = (0, import_react9.useCallback)(async ({ toolCallId }) => {
|
|
3055
3145
|
await client.skipToolCall({
|
|
3056
3146
|
toolCallId
|
|
3057
3147
|
});
|
|
3058
3148
|
}, [
|
|
3059
3149
|
client
|
|
3060
3150
|
]);
|
|
3061
|
-
const regenerate = (0,
|
|
3151
|
+
const regenerate = (0, import_react9.useCallback)(() => {
|
|
3062
3152
|
if (isTurnInFlight()) return;
|
|
3063
3153
|
regenerateNext.current = true;
|
|
3064
3154
|
turnInFlight.current = true;
|
|
@@ -3130,14 +3220,17 @@ __name(mergeHeaders, "mergeHeaders");
|
|
|
3130
3220
|
extractMessageText,
|
|
3131
3221
|
filterAutocompleteItems,
|
|
3132
3222
|
findActiveTrigger,
|
|
3223
|
+
formatElapsed,
|
|
3133
3224
|
formatRelativeTime,
|
|
3134
3225
|
loadStoredSpeechLang,
|
|
3135
3226
|
persistSpeechLang,
|
|
3227
|
+
readReasoningMs,
|
|
3136
3228
|
storedMessageToUiMessage,
|
|
3137
3229
|
storedThreadToUiMessages,
|
|
3138
3230
|
useAgentChat,
|
|
3139
3231
|
useChatTranscript,
|
|
3140
3232
|
useComposerAutocomplete,
|
|
3233
|
+
useElapsed,
|
|
3141
3234
|
useSpeechRecognition,
|
|
3142
3235
|
useStickToBottom,
|
|
3143
3236
|
useTranscriptItem
|