@blade-hq/agent-kit 0.5.2 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{SkillStatusBar-DpbkD4Jx.d.ts → SkillStatusBar-BKAGU9tr.d.ts} +5 -3
- package/dist/{blade-client-CFvmjs5R.d.ts → blade-client-R3cLVOYs.d.ts} +25 -3
- package/dist/{chunk-YW2THJUX.js → chunk-BFF6D2XV.js} +2 -2
- package/dist/{chunk-4ZEOWH6U.js → chunk-IRCXJHXT.js} +2 -2
- package/dist/{chunk-7JX26TWV.js → chunk-Q6CSM5DE.js} +60 -4
- package/dist/chunk-Q6CSM5DE.js.map +1 -0
- package/dist/{chunk-EV225FLR.js → chunk-RTBAPZIO.js} +216 -189
- package/dist/chunk-RTBAPZIO.js.map +1 -0
- package/dist/{chunk-PTMCGZFG.js → chunk-UQEXX57F.js} +15 -3
- package/dist/{chunk-PTMCGZFG.js.map → chunk-UQEXX57F.js.map} +1 -1
- package/dist/{chunk-LVLGDM76.js → chunk-ZQQNSKQS.js} +2 -2
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.js +1 -1
- package/dist/react/api/vibe-coding.d.ts +2 -2
- package/dist/react/api/vibe-coding.js +2 -2
- package/dist/react/components/chat/index.d.ts +3 -3
- package/dist/react/components/chat/index.js +5 -5
- package/dist/react/components/plan/index.js +3 -3
- package/dist/react/components/session/index.js +3 -3
- package/dist/react/components/workspace/index.js +32 -4
- package/dist/react/components/workspace/index.js.map +1 -1
- package/dist/react/index.d.ts +9 -7
- package/dist/react/index.js +6 -6
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/dist/chunk-7JX26TWV.js.map +0 -1
- package/dist/chunk-EV225FLR.js.map +0 -1
- /package/dist/{chunk-YW2THJUX.js.map → chunk-BFF6D2XV.js.map} +0 -0
- /package/dist/{chunk-4ZEOWH6U.js.map → chunk-IRCXJHXT.js.map} +0 -0
- /package/dist/{chunk-LVLGDM76.js.map → chunk-ZQQNSKQS.js.map} +0 -0
|
@@ -8,13 +8,13 @@ import {
|
|
|
8
8
|
getCodeLanguageFromFilename,
|
|
9
9
|
parseAskUserQuestion,
|
|
10
10
|
useHighlightedCodeHtml
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-ZQQNSKQS.js";
|
|
12
12
|
import {
|
|
13
13
|
Collapsible,
|
|
14
14
|
CollapsibleContent,
|
|
15
15
|
CollapsibleTrigger,
|
|
16
16
|
resolveSessionFilePreviewTarget
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-IRCXJHXT.js";
|
|
18
18
|
import {
|
|
19
19
|
buildMessageContent,
|
|
20
20
|
buildToolPreviewKey,
|
|
@@ -57,7 +57,7 @@ import {
|
|
|
57
57
|
useUiBridgeStore,
|
|
58
58
|
useUiStore,
|
|
59
59
|
writeFile
|
|
60
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-UQEXX57F.js";
|
|
61
61
|
import {
|
|
62
62
|
registerBridgeIframe,
|
|
63
63
|
tapBridgeEvent
|
|
@@ -66,7 +66,7 @@ import {
|
|
|
66
66
|
ModelOption,
|
|
67
67
|
ModelsConfig,
|
|
68
68
|
ModelsResource
|
|
69
|
-
} from "./chunk-
|
|
69
|
+
} from "./chunk-Q6CSM5DE.js";
|
|
70
70
|
import {
|
|
71
71
|
cn,
|
|
72
72
|
copyToClipboard
|
|
@@ -80,13 +80,15 @@ import { Eye } from "lucide-react";
|
|
|
80
80
|
import { useCallback as useCallback13 } from "react";
|
|
81
81
|
|
|
82
82
|
// src/react/hooks/use-chat.ts
|
|
83
|
-
import { useCallback, useEffect } from "react";
|
|
83
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
84
84
|
var EMPTY_MESSAGES = [];
|
|
85
85
|
function useChat(sessionId) {
|
|
86
86
|
const messages = useChatStore((s) => s.messages[sessionId] ?? EMPTY_MESSAGES);
|
|
87
87
|
const isStreaming = useChatStore((s) => s.isStreaming[sessionId] ?? false);
|
|
88
88
|
const mode = useSessionStore((s) => s.modes[sessionId] ?? "executing");
|
|
89
89
|
const setAnswerCallback = useAnswerCallbackStore((s) => s.setAnswerCallback);
|
|
90
|
+
const [isStopping, setIsStopping] = useState(false);
|
|
91
|
+
const previousSessionIdRef = useRef(sessionId);
|
|
90
92
|
const send = useCallback(
|
|
91
93
|
(msg, mode2, askuserAnswer, options) => {
|
|
92
94
|
const synthesizedAnswer = askuserAnswer ?? buildPendingAskUserAnswer(sessionId, msg);
|
|
@@ -94,9 +96,27 @@ function useChat(sessionId) {
|
|
|
94
96
|
},
|
|
95
97
|
[sessionId]
|
|
96
98
|
);
|
|
97
|
-
const stop = useCallback(() => {
|
|
98
|
-
|
|
99
|
-
|
|
99
|
+
const stop = useCallback(async () => {
|
|
100
|
+
if (isStopping) return;
|
|
101
|
+
setIsStopping(true);
|
|
102
|
+
try {
|
|
103
|
+
await getSocket().stop(sessionId);
|
|
104
|
+
} catch (error) {
|
|
105
|
+
console.error("[chat] stop request failed", error);
|
|
106
|
+
} finally {
|
|
107
|
+
setIsStopping(false);
|
|
108
|
+
}
|
|
109
|
+
}, [isStopping, sessionId]);
|
|
110
|
+
useEffect(() => {
|
|
111
|
+
if (previousSessionIdRef.current !== sessionId) {
|
|
112
|
+
previousSessionIdRef.current = sessionId;
|
|
113
|
+
setIsStopping(false);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (!isStreaming) {
|
|
117
|
+
setIsStopping(false);
|
|
118
|
+
}
|
|
119
|
+
}, [isStreaming, sessionId]);
|
|
100
120
|
const answer = useCallback(
|
|
101
121
|
(msg, toolCallId, answerData) => {
|
|
102
122
|
send(msg, mode, { tool_call_id: toolCallId, ...answerData });
|
|
@@ -107,7 +127,7 @@ function useChat(sessionId) {
|
|
|
107
127
|
setAnswerCallback(sessionId, answer);
|
|
108
128
|
return () => setAnswerCallback(sessionId, void 0);
|
|
109
129
|
}, [answer, sessionId, setAnswerCallback]);
|
|
110
|
-
return { messages, isStreaming, send, stop };
|
|
130
|
+
return { messages, isStreaming, isStopping, send, stop };
|
|
111
131
|
}
|
|
112
132
|
function buildPendingAskUserAnswer(sessionId, message) {
|
|
113
133
|
const session = useSessionStore.getState().sessions.find((item) => item.id === sessionId);
|
|
@@ -180,17 +200,17 @@ import {
|
|
|
180
200
|
useEffect as useEffect7,
|
|
181
201
|
useEffectEvent as useEffectEvent2,
|
|
182
202
|
useMemo as useMemo7,
|
|
183
|
-
useRef as
|
|
184
|
-
useState as
|
|
203
|
+
useRef as useRef5,
|
|
204
|
+
useState as useState8
|
|
185
205
|
} from "react";
|
|
186
206
|
import { createRoot } from "react-dom/client";
|
|
187
207
|
import { toast } from "sonner";
|
|
188
208
|
|
|
189
209
|
// src/react/asr/use-tiptap-voice-input.ts
|
|
190
|
-
import { useCallback as useCallback3, useEffect as useEffect3, useEffectEvent, useRef as
|
|
210
|
+
import { useCallback as useCallback3, useEffect as useEffect3, useEffectEvent, useRef as useRef3 } from "react";
|
|
191
211
|
|
|
192
212
|
// src/react/asr/use-voice-input.ts
|
|
193
|
-
import { useCallback as useCallback2, useEffect as useEffect2, useRef, useState } from "react";
|
|
213
|
+
import { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
|
|
194
214
|
|
|
195
215
|
// src/react/asr/voice-input-support.ts
|
|
196
216
|
function isIpHost(hostname) {
|
|
@@ -237,14 +257,14 @@ function matchesRequest(data, requestId) {
|
|
|
237
257
|
return !rid || rid === requestId;
|
|
238
258
|
}
|
|
239
259
|
function useVoiceInput(options) {
|
|
240
|
-
const [status, setStatus] =
|
|
241
|
-
const [error, setError] =
|
|
242
|
-
const [level, setLevel] =
|
|
243
|
-
const sessionRef =
|
|
244
|
-
const startingRef =
|
|
245
|
-
const stoppingRef =
|
|
246
|
-
const unmountedRef =
|
|
247
|
-
const optionsRef =
|
|
260
|
+
const [status, setStatus] = useState2("idle");
|
|
261
|
+
const [error, setError] = useState2(null);
|
|
262
|
+
const [level, setLevel] = useState2(0);
|
|
263
|
+
const sessionRef = useRef2(null);
|
|
264
|
+
const startingRef = useRef2(false);
|
|
265
|
+
const stoppingRef = useRef2(false);
|
|
266
|
+
const unmountedRef = useRef2(false);
|
|
267
|
+
const optionsRef = useRef2(options);
|
|
248
268
|
optionsRef.current = options;
|
|
249
269
|
const reportError = useCallback2((err) => {
|
|
250
270
|
const payload = typeof err === "string" ? { title: err } : err;
|
|
@@ -499,8 +519,8 @@ function useVoiceInput(options) {
|
|
|
499
519
|
// src/react/asr/use-tiptap-voice-input.ts
|
|
500
520
|
function useTiptapVoiceInput(options) {
|
|
501
521
|
const { editorRef, workletUrl, onError } = options;
|
|
502
|
-
const partialRangeRef =
|
|
503
|
-
const lastPartialLenRef =
|
|
522
|
+
const partialRangeRef = useRef3(null);
|
|
523
|
+
const lastPartialLenRef = useRef3(0);
|
|
504
524
|
const handlePartial = useEffectEvent((text) => {
|
|
505
525
|
const ed = editorRef.current;
|
|
506
526
|
if (!ed) return;
|
|
@@ -619,7 +639,7 @@ function VoiceWaveform({ level, color = "currentColor", size = 16 }) {
|
|
|
619
639
|
|
|
620
640
|
// src/react/components/model/ModelSelector.tsx
|
|
621
641
|
import { Loader2, Sparkles } from "lucide-react";
|
|
622
|
-
import { useEffect as useEffect4, useMemo, useRef as
|
|
642
|
+
import { useEffect as useEffect4, useMemo, useRef as useRef4, useState as useState3 } from "react";
|
|
623
643
|
|
|
624
644
|
// src/react/hooks/use-model-preferences.ts
|
|
625
645
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
@@ -727,9 +747,9 @@ function ModelSelector({
|
|
|
727
747
|
placement = "bottom"
|
|
728
748
|
}) {
|
|
729
749
|
const { models, defaultModel, isLoading } = useModelConfig();
|
|
730
|
-
const [isOpen, setIsOpen] =
|
|
731
|
-
const [query, setQuery] =
|
|
732
|
-
const rootRef =
|
|
750
|
+
const [isOpen, setIsOpen] = useState3(false);
|
|
751
|
+
const [query, setQuery] = useState3("");
|
|
752
|
+
const rootRef = useRef4(null);
|
|
733
753
|
useEffect4(() => {
|
|
734
754
|
if (!isOpen) return;
|
|
735
755
|
const closeOnPointerDown = (event) => {
|
|
@@ -838,7 +858,7 @@ function ModelSelector({
|
|
|
838
858
|
}
|
|
839
859
|
|
|
840
860
|
// src/react/hooks/use-input-history.ts
|
|
841
|
-
import { useCallback as useCallback4, useEffect as useEffect5, useMemo as useMemo2, useState as
|
|
861
|
+
import { useCallback as useCallback4, useEffect as useEffect5, useMemo as useMemo2, useState as useState4 } from "react";
|
|
842
862
|
var MAX_HISTORY_ENTRIES = 50;
|
|
843
863
|
function getStorageKey(sessionId) {
|
|
844
864
|
return sessionId ? `input-history:${sessionId}` : null;
|
|
@@ -863,9 +883,9 @@ function readEntries(storageKey) {
|
|
|
863
883
|
}
|
|
864
884
|
function useInputHistory(sessionId) {
|
|
865
885
|
const storageKey = useMemo2(() => getStorageKey(sessionId), [sessionId]);
|
|
866
|
-
const [entries, setEntries] =
|
|
867
|
-
const [cursor, setCursor] =
|
|
868
|
-
const [draft, setDraft] =
|
|
886
|
+
const [entries, setEntries] = useState4([]);
|
|
887
|
+
const [cursor, setCursor] = useState4(null);
|
|
888
|
+
const [draft, setDraft] = useState4("");
|
|
869
889
|
useEffect5(() => {
|
|
870
890
|
setEntries(readEntries(storageKey));
|
|
871
891
|
setCursor(null);
|
|
@@ -1004,7 +1024,7 @@ function skillDisplayName(skill) {
|
|
|
1004
1024
|
|
|
1005
1025
|
// src/react/components/chat/FileCompletionMenu.tsx
|
|
1006
1026
|
import { ChevronRight, File, Folder } from "lucide-react";
|
|
1007
|
-
import { forwardRef, useCallback as useCallback5, useImperativeHandle, useMemo as useMemo4, useState as
|
|
1027
|
+
import { forwardRef, useCallback as useCallback5, useImperativeHandle, useMemo as useMemo4, useState as useState5 } from "react";
|
|
1008
1028
|
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1009
1029
|
var ROOT_DIR = ".";
|
|
1010
1030
|
function isVisibleEntry(entry) {
|
|
@@ -1108,7 +1128,7 @@ var FileCompletionMenu = forwardRef(
|
|
|
1108
1128
|
}
|
|
1109
1129
|
);
|
|
1110
1130
|
var FileCompletionMenuContent = forwardRef(function FileCompletionMenuContent2({ command, editor, filterQuery, items, onExit, range, sessionId }, ref) {
|
|
1111
|
-
const [rawSelectedIndex, setRawSelectedIndex] =
|
|
1131
|
+
const [rawSelectedIndex, setRawSelectedIndex] = useState5(0);
|
|
1112
1132
|
const filteredEntries = useMemo4(() => filterEntries(items, filterQuery), [filterQuery, items]);
|
|
1113
1133
|
const selectedIndex = filteredEntries.length === 0 ? 0 : Math.min(rawSelectedIndex, filteredEntries.length - 1);
|
|
1114
1134
|
const handleSelect = useCallback5(
|
|
@@ -1189,11 +1209,11 @@ var FileCompletionMenuContent = forwardRef(function FileCompletionMenuContent2({
|
|
|
1189
1209
|
});
|
|
1190
1210
|
|
|
1191
1211
|
// src/react/components/chat/SkillCompletionMenu.tsx
|
|
1192
|
-
import { forwardRef as forwardRef2, useCallback as useCallback6, useImperativeHandle as useImperativeHandle2, useState as
|
|
1212
|
+
import { forwardRef as forwardRef2, useCallback as useCallback6, useImperativeHandle as useImperativeHandle2, useState as useState6 } from "react";
|
|
1193
1213
|
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1194
1214
|
var SkillCompletionMenu = forwardRef2(
|
|
1195
1215
|
function SkillCompletionMenu2({ command, items }, ref) {
|
|
1196
|
-
const [rawSelectedIndex, setRawSelectedIndex] =
|
|
1216
|
+
const [rawSelectedIndex, setRawSelectedIndex] = useState6(0);
|
|
1197
1217
|
const selectedIndex = items.length === 0 ? 0 : Math.min(rawSelectedIndex, items.length - 1);
|
|
1198
1218
|
const handleSelect = useCallback6(
|
|
1199
1219
|
(item) => {
|
|
@@ -1298,7 +1318,7 @@ var SkillCompletionMenu = forwardRef2(
|
|
|
1298
1318
|
|
|
1299
1319
|
// src/react/components/chat/BackgroundTasksPill.tsx
|
|
1300
1320
|
import { FileText, Square, Terminal } from "lucide-react";
|
|
1301
|
-
import { useState as
|
|
1321
|
+
import { useState as useState7 } from "react";
|
|
1302
1322
|
|
|
1303
1323
|
// src/react/hooks/use-background-tasks.ts
|
|
1304
1324
|
import { useQuery as useQuery2 } from "@tanstack/react-query";
|
|
@@ -1347,8 +1367,8 @@ function statusClass(status) {
|
|
|
1347
1367
|
}
|
|
1348
1368
|
function BackgroundTasksPill({ sessionId }) {
|
|
1349
1369
|
const { data: tasks } = useBackgroundTasks(sessionId);
|
|
1350
|
-
const [open, setOpen] =
|
|
1351
|
-
const [logTask, setLogTask] =
|
|
1370
|
+
const [open, setOpen] = useState7(false);
|
|
1371
|
+
const [logTask, setLogTask] = useState7(null);
|
|
1352
1372
|
if (tasks.length === 0) return null;
|
|
1353
1373
|
const runningCount = tasks.filter((task) => task.status === "running").length;
|
|
1354
1374
|
const openTaskLog = async (task) => {
|
|
@@ -2131,20 +2151,38 @@ function ComposerFilePill({
|
|
|
2131
2151
|
const isFile = attachment.kind === "file";
|
|
2132
2152
|
const isFailed = isFile && attachment.status === "failed";
|
|
2133
2153
|
const isUploading = isFile && attachment.status === "uploading";
|
|
2154
|
+
const uploadPercent = isUploading && typeof attachment.uploadProgress === "number" ? Math.max(0, Math.min(100, Math.round(attachment.uploadProgress * 100))) : null;
|
|
2134
2155
|
return /* @__PURE__ */ jsxs8(
|
|
2135
2156
|
"div",
|
|
2136
2157
|
{
|
|
2137
|
-
className: `flex shrink-0 items-center gap-1.5 rounded-full border px-2.5 py-1 text-[11px] ${isFailed ? "border-red-500/30 bg-red-500/5 text-red-400" : "border-[hsl(var(--border))] bg-[hsl(var(--card))] text-[hsl(var(--foreground))]"}`,
|
|
2158
|
+
className: `relative flex shrink-0 items-center gap-1.5 overflow-hidden rounded-full border px-2.5 py-1 text-[11px] ${isFailed ? "border-red-500/30 bg-red-500/5 text-red-400" : "border-[hsl(var(--border))] bg-[hsl(var(--card))] text-[hsl(var(--foreground))]"}`,
|
|
2138
2159
|
children: [
|
|
2139
|
-
|
|
2140
|
-
|
|
2160
|
+
uploadPercent !== null ? /* @__PURE__ */ jsx9(
|
|
2161
|
+
"span",
|
|
2162
|
+
{
|
|
2163
|
+
className: "absolute inset-y-0 left-0 bg-[hsl(var(--primary))]/10 transition-[width]",
|
|
2164
|
+
style: { width: `${uploadPercent}%` }
|
|
2165
|
+
}
|
|
2166
|
+
) : null,
|
|
2167
|
+
isUploading ? /* @__PURE__ */ jsx9(
|
|
2168
|
+
Loader22,
|
|
2169
|
+
{
|
|
2170
|
+
size: 12,
|
|
2171
|
+
className: "relative z-10 shrink-0 animate-spin text-[hsl(var(--muted-foreground))]"
|
|
2172
|
+
}
|
|
2173
|
+
) : /* @__PURE__ */ jsx9(Icon, { size: 12, className: "relative z-10 shrink-0 text-[hsl(var(--muted-foreground))]" }),
|
|
2174
|
+
/* @__PURE__ */ jsx9("span", { className: "relative z-10 max-w-32 truncate", children: attachment.name }),
|
|
2175
|
+
uploadPercent !== null ? /* @__PURE__ */ jsxs8("span", { className: "relative z-10 font-mono text-[10px] tabular-nums text-[hsl(var(--muted-foreground))]", children: [
|
|
2176
|
+
uploadPercent,
|
|
2177
|
+
"%"
|
|
2178
|
+
] }) : null,
|
|
2141
2179
|
/* @__PURE__ */ jsx9(
|
|
2142
2180
|
"button",
|
|
2143
2181
|
{
|
|
2144
2182
|
type: "button",
|
|
2145
2183
|
onClick: () => onRemove(attachment.id),
|
|
2146
2184
|
"aria-label": `\u79FB\u9664 ${attachment.name}`,
|
|
2147
|
-
className: "ml-0.5 inline-flex shrink-0 items-center justify-center rounded-full text-[hsl(var(--muted-foreground))] transition hover:text-rose-400",
|
|
2185
|
+
className: "relative z-10 ml-0.5 inline-flex shrink-0 items-center justify-center rounded-full text-[hsl(var(--muted-foreground))] transition hover:text-rose-400",
|
|
2148
2186
|
children: /* @__PURE__ */ jsx9(X2, { size: 10 })
|
|
2149
2187
|
}
|
|
2150
2188
|
)
|
|
@@ -2158,13 +2196,13 @@ function AddContextDialog({
|
|
|
2158
2196
|
onAdd
|
|
2159
2197
|
}) {
|
|
2160
2198
|
const CONTEXT_INLINE_THRESHOLD = 200;
|
|
2161
|
-
const [label, setLabel] =
|
|
2162
|
-
const [content, setContent] =
|
|
2163
|
-
const [showSessionPicker, setShowSessionPicker] =
|
|
2164
|
-
const [sessions, setSessions] =
|
|
2165
|
-
const [loadingSessions, setLoadingSessions] =
|
|
2166
|
-
const [importingId, setImportingId] =
|
|
2167
|
-
const [isImportProcessing, setIsImportProcessing] =
|
|
2199
|
+
const [label, setLabel] = useState8("");
|
|
2200
|
+
const [content, setContent] = useState8("");
|
|
2201
|
+
const [showSessionPicker, setShowSessionPicker] = useState8(false);
|
|
2202
|
+
const [sessions, setSessions] = useState8([]);
|
|
2203
|
+
const [loadingSessions, setLoadingSessions] = useState8(false);
|
|
2204
|
+
const [importingId, setImportingId] = useState8(null);
|
|
2205
|
+
const [isImportProcessing, setIsImportProcessing] = useState8(false);
|
|
2168
2206
|
const sanitizeContextFolderName = (raw) => {
|
|
2169
2207
|
const normalized = raw.trim().toLowerCase();
|
|
2170
2208
|
const safe = normalized.replace(/[^\w\-.\u4e00-\u9fa5]+/g, "_").replace(/^_+|_+$/g, "");
|
|
@@ -2394,7 +2432,7 @@ function ComposerContextPill({
|
|
|
2394
2432
|
content,
|
|
2395
2433
|
onRemove
|
|
2396
2434
|
}) {
|
|
2397
|
-
const [showDetail, setShowDetail] =
|
|
2435
|
+
const [showDetail, setShowDetail] = useState8(false);
|
|
2398
2436
|
const tokenK = formatTokenK(content);
|
|
2399
2437
|
return /* @__PURE__ */ jsxs8(Fragment2, { children: [
|
|
2400
2438
|
/* @__PURE__ */ jsxs8("div", { className: "flex shrink-0 items-center gap-1.5 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--accent))] px-2.5 py-1 text-[11px] text-[hsl(var(--foreground))]", children: [
|
|
@@ -2589,6 +2627,7 @@ function ChatInput({
|
|
|
2589
2627
|
onSend,
|
|
2590
2628
|
onStop,
|
|
2591
2629
|
isStreaming,
|
|
2630
|
+
isStopping = false,
|
|
2592
2631
|
mode = "executing",
|
|
2593
2632
|
onToggleMode,
|
|
2594
2633
|
renderAttachments,
|
|
@@ -2608,13 +2647,13 @@ function ChatInput({
|
|
|
2608
2647
|
onResyncSkills,
|
|
2609
2648
|
isResyncingSkills = false
|
|
2610
2649
|
}) {
|
|
2611
|
-
const [input, setInputInternal] =
|
|
2650
|
+
const [input, setInputInternal] = useState8(externalDraft?.value ?? "");
|
|
2612
2651
|
const setInput = useEffectEvent2((value) => {
|
|
2613
2652
|
setInputInternal(value);
|
|
2614
2653
|
externalDraft?.setValue(value);
|
|
2615
2654
|
});
|
|
2616
2655
|
const externalDraftValue = externalDraft?.value;
|
|
2617
|
-
const inputRef =
|
|
2656
|
+
const inputRef = useRef5(input);
|
|
2618
2657
|
inputRef.current = input;
|
|
2619
2658
|
useEffect7(() => {
|
|
2620
2659
|
if (externalDraftValue == null) return;
|
|
@@ -2624,7 +2663,7 @@ function ChatInput({
|
|
|
2624
2663
|
}
|
|
2625
2664
|
setInputInternal(externalDraftValue);
|
|
2626
2665
|
}, [externalDraftValue]);
|
|
2627
|
-
const [composerAttachments, setComposerAttachmentsInternal] =
|
|
2666
|
+
const [composerAttachments, setComposerAttachmentsInternal] = useState8(
|
|
2628
2667
|
externalAttachments?.value ?? []
|
|
2629
2668
|
);
|
|
2630
2669
|
const setComposerAttachments = useEffectEvent2(
|
|
@@ -2637,24 +2676,24 @@ function ChatInput({
|
|
|
2637
2676
|
}
|
|
2638
2677
|
);
|
|
2639
2678
|
const externalAttachmentsValue = externalAttachments?.value;
|
|
2640
|
-
const composerAttachmentsRef =
|
|
2679
|
+
const composerAttachmentsRef = useRef5(composerAttachments);
|
|
2641
2680
|
composerAttachmentsRef.current = composerAttachments;
|
|
2642
2681
|
useEffect7(() => {
|
|
2643
2682
|
if (externalAttachmentsValue == null) return;
|
|
2644
2683
|
if (composerAttachmentsRef.current === externalAttachmentsValue) return;
|
|
2645
2684
|
setComposerAttachmentsInternal(externalAttachmentsValue);
|
|
2646
2685
|
}, [externalAttachmentsValue]);
|
|
2647
|
-
const [dragging, setDragging] =
|
|
2648
|
-
const [isEditorFocused, setIsEditorFocused] =
|
|
2649
|
-
const [oversizedFiles, setOversizedFiles] =
|
|
2650
|
-
const [selectedModel, setSelectedModel] =
|
|
2686
|
+
const [dragging, setDragging] = useState8(false);
|
|
2687
|
+
const [isEditorFocused, setIsEditorFocused] = useState8(false);
|
|
2688
|
+
const [oversizedFiles, setOversizedFiles] = useState8([]);
|
|
2689
|
+
const [selectedModel, setSelectedModel] = useState8("");
|
|
2651
2690
|
const { setPreferredModel } = usePreferredModel();
|
|
2652
2691
|
const queryClient = useQueryClient2();
|
|
2653
|
-
const actionMenuRef =
|
|
2654
|
-
const fileInputRef =
|
|
2655
|
-
const folderInputRef =
|
|
2656
|
-
const editorRef =
|
|
2657
|
-
const localImageUrlsRef =
|
|
2692
|
+
const actionMenuRef = useRef5(null);
|
|
2693
|
+
const fileInputRef = useRef5(null);
|
|
2694
|
+
const folderInputRef = useRef5(null);
|
|
2695
|
+
const editorRef = useRef5(null);
|
|
2696
|
+
const localImageUrlsRef = useRef5(/* @__PURE__ */ new Map());
|
|
2658
2697
|
const activeSessionId = useSessionStore((state) => state.activeSessionId);
|
|
2659
2698
|
const sessions = useSessionStore((state) => state.sessions);
|
|
2660
2699
|
const activeSessionModel = useMemo7(
|
|
@@ -2687,7 +2726,7 @@ function ChatInput({
|
|
|
2687
2726
|
const inputHistory = useInputHistory(activeSessionId);
|
|
2688
2727
|
const getSessionId = useEffectEvent2(() => activeSessionId);
|
|
2689
2728
|
const handleSlashCommand = useEffectEvent2((commandId) => onCommand?.(commandId));
|
|
2690
|
-
const [localImageUrls, setLocalImageUrls] =
|
|
2729
|
+
const [localImageUrls, setLocalImageUrls] = useState8({});
|
|
2691
2730
|
useEffect7(() => {
|
|
2692
2731
|
const closeActionMenu = (event) => {
|
|
2693
2732
|
const menu = actionMenuRef.current;
|
|
@@ -3016,7 +3055,7 @@ function ChatInput({
|
|
|
3016
3055
|
editor.commands.focus("end");
|
|
3017
3056
|
setRewindDraft(activeSessionId, null);
|
|
3018
3057
|
}, [activeSessionId, editor, rewindDraft, setRewindDraft]);
|
|
3019
|
-
const submittingRef =
|
|
3058
|
+
const submittingRef = useRef5(false);
|
|
3020
3059
|
useEffect7(() => {
|
|
3021
3060
|
let changed = false;
|
|
3022
3061
|
const nextLocalIds = /* @__PURE__ */ new Set();
|
|
@@ -3095,14 +3134,14 @@ function ChatInput({
|
|
|
3095
3134
|
});
|
|
3096
3135
|
const { isRecording, level: voiceLevel } = voice;
|
|
3097
3136
|
const handleMicDisabledClick = () => toast.info("\u8BED\u97F3\u8F93\u5165\u529F\u80FD\u672A\u5F00\u542F\uFF0C\u8BF7\u5728\u540E\u7AEF .env \u914D\u7F6E ASR_API_KEY");
|
|
3098
|
-
const voiceStopRef =
|
|
3137
|
+
const voiceStopRef = useRef5(voice.stop);
|
|
3099
3138
|
voiceStopRef.current = voice.stop;
|
|
3100
3139
|
useEffect7(() => {
|
|
3101
3140
|
if (isStreaming && isRecording) {
|
|
3102
3141
|
void voiceStopRef.current();
|
|
3103
3142
|
}
|
|
3104
3143
|
}, [isStreaming, isRecording]);
|
|
3105
|
-
const prevSessionIdRef =
|
|
3144
|
+
const prevSessionIdRef = useRef5(activeSessionId);
|
|
3106
3145
|
useEffect7(() => {
|
|
3107
3146
|
if (prevSessionIdRef.current !== activeSessionId) {
|
|
3108
3147
|
prevSessionIdRef.current = activeSessionId;
|
|
@@ -3153,14 +3192,24 @@ function ChatInput({
|
|
|
3153
3192
|
if (pendingFiles.length > 0) {
|
|
3154
3193
|
setComposerAttachments(
|
|
3155
3194
|
(prev) => prev.map(
|
|
3156
|
-
(a) => a.kind === "file" && a.status === "pending" ? { ...a, status: "uploading" } : a
|
|
3195
|
+
(a) => a.kind === "file" && a.status === "pending" ? { ...a, status: "uploading", uploadProgress: 0 } : a
|
|
3157
3196
|
)
|
|
3158
3197
|
);
|
|
3159
3198
|
try {
|
|
3160
3199
|
const result = await uploadFiles(
|
|
3161
3200
|
uploadSessionId,
|
|
3162
3201
|
".",
|
|
3163
|
-
pendingFiles.map((a) => ({ file: a.file, name: a.name }))
|
|
3202
|
+
pendingFiles.map((a) => ({ file: a.file, name: a.name })),
|
|
3203
|
+
{
|
|
3204
|
+
onProgress: (progress) => {
|
|
3205
|
+
if (typeof progress.percent !== "number") return;
|
|
3206
|
+
setComposerAttachments(
|
|
3207
|
+
(prev) => prev.map(
|
|
3208
|
+
(a) => pendingFiles.some((pending) => pending.id === a.id) && a.kind === "file" && a.status === "uploading" ? { ...a, uploadProgress: progress.percent } : a
|
|
3209
|
+
)
|
|
3210
|
+
);
|
|
3211
|
+
}
|
|
3212
|
+
}
|
|
3164
3213
|
);
|
|
3165
3214
|
const uploadResultById = /* @__PURE__ */ new Map();
|
|
3166
3215
|
const failedSet = new Set(result.failed);
|
|
@@ -3176,9 +3225,15 @@ function ChatInput({
|
|
|
3176
3225
|
updatedAttachments = composerAttachments.map((a) => {
|
|
3177
3226
|
if (!uploadResultById.has(a.id)) return a;
|
|
3178
3227
|
const uploadedPath = uploadResultById.get(a.id);
|
|
3179
|
-
if (!uploadedPath) return { ...a, status: "failed" };
|
|
3228
|
+
if (!uploadedPath) return { ...a, status: "failed", uploadProgress: null };
|
|
3180
3229
|
const actualName = uploadedPath.split("/").pop() || a.name;
|
|
3181
|
-
return {
|
|
3230
|
+
return {
|
|
3231
|
+
...a,
|
|
3232
|
+
name: actualName,
|
|
3233
|
+
status: "uploaded",
|
|
3234
|
+
uploadedPath,
|
|
3235
|
+
uploadProgress: null
|
|
3236
|
+
};
|
|
3182
3237
|
});
|
|
3183
3238
|
setComposerAttachments(updatedAttachments);
|
|
3184
3239
|
if (result.uploaded.length > 0) {
|
|
@@ -3220,7 +3275,7 @@ function ChatInput({
|
|
|
3220
3275
|
const removeAttachment = (id) => {
|
|
3221
3276
|
setComposerAttachments((prev) => prev.filter((attachment) => attachment.id !== id));
|
|
3222
3277
|
};
|
|
3223
|
-
const [showAddContext, setShowAddContext] =
|
|
3278
|
+
const [showAddContext, setShowAddContext] = useState8(false);
|
|
3224
3279
|
const isPlanning = mode === "planning";
|
|
3225
3280
|
const placeholder = isPlanning ? "\u89C4\u5212\u8FDB\u884C\u4E2D\u2026 \u53EF\u8F93\u5165\u8865\u5145\u9700\u6C42\u6216\u7B49\u5F85\u5B8C\u6210" : "\u8F93\u5165\u6D88\u606F\u2026";
|
|
3226
3281
|
const attachments = renderAttachments?.() ?? null;
|
|
@@ -3596,10 +3651,11 @@ function ChatInput({
|
|
|
3596
3651
|
"button",
|
|
3597
3652
|
{
|
|
3598
3653
|
type: "button",
|
|
3599
|
-
onClick: onStop,
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3654
|
+
onClick: () => void onStop(),
|
|
3655
|
+
disabled: isStopping,
|
|
3656
|
+
"aria-label": isStopping ? "\u6B63\u5728\u505C\u6B62" : "\u505C\u6B62\u751F\u6210",
|
|
3657
|
+
className: "flex h-7 w-7 items-center justify-center rounded-lg bg-[hsl(var(--destructive))] text-[hsl(var(--destructive-foreground))] transition-opacity hover:opacity-80 disabled:cursor-wait disabled:opacity-70",
|
|
3658
|
+
children: isStopping ? /* @__PURE__ */ jsx9(Loader22, { size: 13, className: "animate-spin" }) : /* @__PURE__ */ jsx9(Square2, { size: 13 })
|
|
3603
3659
|
}
|
|
3604
3660
|
) : /* @__PURE__ */ jsx9(
|
|
3605
3661
|
"button",
|
|
@@ -3689,12 +3745,12 @@ import {
|
|
|
3689
3745
|
useEffect as useEffect16,
|
|
3690
3746
|
useEffectEvent as useEffectEvent4,
|
|
3691
3747
|
useMemo as useMemo17,
|
|
3692
|
-
useRef as
|
|
3693
|
-
useState as
|
|
3748
|
+
useRef as useRef12,
|
|
3749
|
+
useState as useState21
|
|
3694
3750
|
} from "react";
|
|
3695
3751
|
|
|
3696
3752
|
// ../../node_modules/.pnpm/use-stick-to-bottom@1.1.3_react@19.2.4/node_modules/use-stick-to-bottom/dist/useStickToBottom.js
|
|
3697
|
-
import { useCallback as useCallback7, useMemo as useMemo8, useRef as
|
|
3753
|
+
import { useCallback as useCallback7, useMemo as useMemo8, useRef as useRef6, useState as useState9 } from "react";
|
|
3698
3754
|
var DEFAULT_SPRING_ANIMATION = {
|
|
3699
3755
|
/**
|
|
3700
3756
|
* A value from 0 to 1, on how much to damp the animation.
|
|
@@ -3731,10 +3787,10 @@ globalThis.document?.addEventListener("click", () => {
|
|
|
3731
3787
|
mouseDown = false;
|
|
3732
3788
|
});
|
|
3733
3789
|
var useStickToBottom = (options = {}) => {
|
|
3734
|
-
const [escapedFromLock, updateEscapedFromLock] =
|
|
3735
|
-
const [isAtBottom, updateIsAtBottom] =
|
|
3736
|
-
const [isNearBottom, setIsNearBottom] =
|
|
3737
|
-
const optionsRef =
|
|
3790
|
+
const [escapedFromLock, updateEscapedFromLock] = useState9(false);
|
|
3791
|
+
const [isAtBottom, updateIsAtBottom] = useState9(options.initial !== false);
|
|
3792
|
+
const [isNearBottom, setIsNearBottom] = useState9(false);
|
|
3793
|
+
const optionsRef = useRef6(null);
|
|
3738
3794
|
optionsRef.current = options;
|
|
3739
3795
|
const isSelecting = useCallback7(() => {
|
|
3740
3796
|
if (!mouseDown) {
|
|
@@ -4038,11 +4094,11 @@ function mergeAnimations(...animations) {
|
|
|
4038
4094
|
|
|
4039
4095
|
// ../../node_modules/.pnpm/use-stick-to-bottom@1.1.3_react@19.2.4/node_modules/use-stick-to-bottom/dist/StickToBottom.js
|
|
4040
4096
|
import * as React from "react";
|
|
4041
|
-
import { createContext, useContext, useEffect as useEffect8, useImperativeHandle as useImperativeHandle3, useLayoutEffect, useMemo as useMemo9, useRef as
|
|
4097
|
+
import { createContext, useContext, useEffect as useEffect8, useImperativeHandle as useImperativeHandle3, useLayoutEffect, useMemo as useMemo9, useRef as useRef7 } from "react";
|
|
4042
4098
|
var StickToBottomContext = createContext(null);
|
|
4043
4099
|
var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect8;
|
|
4044
4100
|
function StickToBottom({ instance, children, resize, initial, mass, damping, stiffness, targetScrollTop: currentTargetScrollTop, contextRef, ...props }) {
|
|
4045
|
-
const customTargetScrollTop =
|
|
4101
|
+
const customTargetScrollTop = useRef7(null);
|
|
4046
4102
|
const targetScrollTop = React.useCallback((target, elements) => {
|
|
4047
4103
|
const get = context?.targetScrollTop ?? currentTargetScrollTop;
|
|
4048
4104
|
return get?.(target, elements) ?? target;
|
|
@@ -4119,7 +4175,7 @@ function useStickToBottomContext() {
|
|
|
4119
4175
|
|
|
4120
4176
|
// src/react/components/chat/AssistantTurnBlock.tsx
|
|
4121
4177
|
import { AlertCircle, BookOpen, Check as Check4, ChevronRight as ChevronRight5 } from "lucide-react";
|
|
4122
|
-
import { useCallback as useCallback11, useEffect as useEffect14, useMemo as useMemo15, useRef as
|
|
4178
|
+
import { useCallback as useCallback11, useEffect as useEffect14, useMemo as useMemo15, useRef as useRef11, useState as useState18 } from "react";
|
|
4123
4179
|
|
|
4124
4180
|
// src/react/routes.ts
|
|
4125
4181
|
var MEMORIES_ROUTE = "/memories";
|
|
@@ -4137,8 +4193,8 @@ import {
|
|
|
4137
4193
|
useContext as useContext2,
|
|
4138
4194
|
useEffect as useEffect9,
|
|
4139
4195
|
useMemo as useMemo11,
|
|
4140
|
-
useRef as
|
|
4141
|
-
useState as
|
|
4196
|
+
useRef as useRef8,
|
|
4197
|
+
useState as useState10
|
|
4142
4198
|
} from "react";
|
|
4143
4199
|
import { createPortal as createPortal2 } from "react-dom";
|
|
4144
4200
|
import { Streamdown } from "streamdown";
|
|
@@ -4205,7 +4261,6 @@ var useReasoning = () => {
|
|
|
4205
4261
|
}
|
|
4206
4262
|
return context;
|
|
4207
4263
|
};
|
|
4208
|
-
var AUTO_CLOSE_DELAY = 3e3;
|
|
4209
4264
|
var MS_IN_S = 1e3;
|
|
4210
4265
|
var Reasoning = memo2(
|
|
4211
4266
|
({
|
|
@@ -4218,10 +4273,8 @@ var Reasoning = memo2(
|
|
|
4218
4273
|
children,
|
|
4219
4274
|
...props
|
|
4220
4275
|
}) => {
|
|
4221
|
-
const resolvedDefaultOpen = defaultOpen ?? isStreaming;
|
|
4222
|
-
const isExplicitlyClosed = defaultOpen === false;
|
|
4223
4276
|
const [isOpen, setIsOpen] = useControllableState({
|
|
4224
|
-
defaultProp:
|
|
4277
|
+
defaultProp: defaultOpen ?? false,
|
|
4225
4278
|
onChange: onOpenChange,
|
|
4226
4279
|
prop: open
|
|
4227
4280
|
});
|
|
@@ -4229,12 +4282,9 @@ var Reasoning = memo2(
|
|
|
4229
4282
|
defaultProp: void 0,
|
|
4230
4283
|
prop: durationProp
|
|
4231
4284
|
});
|
|
4232
|
-
const
|
|
4233
|
-
const [hasAutoClosed, setHasAutoClosed] = useState9(false);
|
|
4234
|
-
const startTimeRef = useRef7(null);
|
|
4285
|
+
const startTimeRef = useRef8(null);
|
|
4235
4286
|
useEffect9(() => {
|
|
4236
4287
|
if (isStreaming) {
|
|
4237
|
-
hasEverStreamedRef.current = true;
|
|
4238
4288
|
if (startTimeRef.current === null) {
|
|
4239
4289
|
startTimeRef.current = Date.now();
|
|
4240
4290
|
}
|
|
@@ -4243,20 +4293,6 @@ var Reasoning = memo2(
|
|
|
4243
4293
|
startTimeRef.current = null;
|
|
4244
4294
|
}
|
|
4245
4295
|
}, [isStreaming, setDuration]);
|
|
4246
|
-
useEffect9(() => {
|
|
4247
|
-
if (isStreaming && !isOpen && !isExplicitlyClosed) {
|
|
4248
|
-
setIsOpen(true);
|
|
4249
|
-
}
|
|
4250
|
-
}, [isStreaming, isOpen, setIsOpen, isExplicitlyClosed]);
|
|
4251
|
-
useEffect9(() => {
|
|
4252
|
-
if (hasEverStreamedRef.current && !isStreaming && isOpen && !hasAutoClosed) {
|
|
4253
|
-
const timer = setTimeout(() => {
|
|
4254
|
-
setIsOpen(false);
|
|
4255
|
-
setHasAutoClosed(true);
|
|
4256
|
-
}, AUTO_CLOSE_DELAY);
|
|
4257
|
-
return () => clearTimeout(timer);
|
|
4258
|
-
}
|
|
4259
|
-
}, [isStreaming, isOpen, setIsOpen, hasAutoClosed]);
|
|
4260
4296
|
const handleOpenChange = useCallback9(
|
|
4261
4297
|
(newOpen) => {
|
|
4262
4298
|
setIsOpen(newOpen);
|
|
@@ -4270,7 +4306,7 @@ var Reasoning = memo2(
|
|
|
4270
4306
|
return /* @__PURE__ */ jsx12(ReasoningContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx12(
|
|
4271
4307
|
Collapsible,
|
|
4272
4308
|
{
|
|
4273
|
-
className: cn("not-prose
|
|
4309
|
+
className: cn("not-prose", className),
|
|
4274
4310
|
onOpenChange: handleOpenChange,
|
|
4275
4311
|
open: isOpen,
|
|
4276
4312
|
...props,
|
|
@@ -4279,38 +4315,36 @@ var Reasoning = memo2(
|
|
|
4279
4315
|
) });
|
|
4280
4316
|
}
|
|
4281
4317
|
);
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
}
|
|
4286
|
-
if (duration === void 0) {
|
|
4287
|
-
return /* @__PURE__ */ jsx12("p", { children: "\u5DF2\u6DF1\u5EA6\u601D\u8003" });
|
|
4288
|
-
}
|
|
4289
|
-
return /* @__PURE__ */ jsxs10("p", { children: [
|
|
4290
|
-
"\u5DF2\u6DF1\u5EA6\u601D\u8003 ",
|
|
4291
|
-
duration,
|
|
4292
|
-
" \u79D2"
|
|
4293
|
-
] });
|
|
4294
|
-
};
|
|
4318
|
+
function formatWordCount(value) {
|
|
4319
|
+
return new Intl.NumberFormat("zh-CN").format(value);
|
|
4320
|
+
}
|
|
4295
4321
|
var ReasoningTrigger = memo2(
|
|
4296
4322
|
({
|
|
4297
4323
|
className,
|
|
4298
4324
|
children,
|
|
4299
|
-
|
|
4325
|
+
wordCount,
|
|
4300
4326
|
...props
|
|
4301
4327
|
}) => {
|
|
4302
4328
|
const { isStreaming, isOpen, duration } = useReasoning();
|
|
4329
|
+
const status = isStreaming || duration === 0 ? "\u6B63\u5728\u601D\u8003" : "\u5DF2\u601D\u8003";
|
|
4330
|
+
const detail = `${formatWordCount(wordCount)} \u5B57`;
|
|
4303
4331
|
return /* @__PURE__ */ jsx12(
|
|
4304
4332
|
CollapsibleTrigger,
|
|
4305
4333
|
{
|
|
4306
4334
|
className: cn(
|
|
4307
|
-
"flex w-
|
|
4335
|
+
"flex w-fit items-center gap-2 rounded-full px-1 py-0.5 text-muted-foreground text-sm transition-colors hover:text-foreground",
|
|
4308
4336
|
className
|
|
4309
4337
|
),
|
|
4310
4338
|
...props,
|
|
4311
4339
|
children: children ?? /* @__PURE__ */ jsxs10(Fragment3, { children: [
|
|
4312
4340
|
/* @__PURE__ */ jsx12(BrainIcon, { className: "size-4" }),
|
|
4313
|
-
|
|
4341
|
+
/* @__PURE__ */ jsxs10("span", { className: "inline-flex items-center gap-1.5", children: [
|
|
4342
|
+
isStreaming || duration === 0 ? /* @__PURE__ */ jsx12(Shimmer, { duration: 1, children: status }) : /* @__PURE__ */ jsx12("span", { children: status }),
|
|
4343
|
+
/* @__PURE__ */ jsxs10("span", { className: "text-[hsl(var(--muted-foreground))]/70", children: [
|
|
4344
|
+
"\xB7 ",
|
|
4345
|
+
detail
|
|
4346
|
+
] })
|
|
4347
|
+
] }),
|
|
4314
4348
|
/* @__PURE__ */ jsx12(
|
|
4315
4349
|
ChevronDownIcon,
|
|
4316
4350
|
{
|
|
@@ -4332,7 +4366,7 @@ var ReasoningContent = memo2(
|
|
|
4332
4366
|
CollapsibleContent,
|
|
4333
4367
|
{
|
|
4334
4368
|
className: cn(
|
|
4335
|
-
"mt-
|
|
4369
|
+
"mt-2 max-h-60 overflow-auto rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20 px-3 py-2 text-sm",
|
|
4336
4370
|
"data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-muted-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in",
|
|
4337
4371
|
className
|
|
4338
4372
|
),
|
|
@@ -4346,7 +4380,7 @@ function compactReasoningText(text) {
|
|
|
4346
4380
|
}
|
|
4347
4381
|
function ThinkingBadge({ reasoning, variant = "inline", onClick }) {
|
|
4348
4382
|
const compactReasoning = compactReasoningText(reasoning);
|
|
4349
|
-
const [open, setOpen] =
|
|
4383
|
+
const [open, setOpen] = useState10(false);
|
|
4350
4384
|
return /* @__PURE__ */ jsxs10(
|
|
4351
4385
|
"span",
|
|
4352
4386
|
{
|
|
@@ -4423,10 +4457,10 @@ ReasoningContent.displayName = "ReasoningContent";
|
|
|
4423
4457
|
|
|
4424
4458
|
// src/react/components/chat/AgentLoopBlock.tsx
|
|
4425
4459
|
import { Bot, Check as Check3, ChevronRight as ChevronRight4, FileText as FileText6, Loader2 as Loader24, MessageSquareMore as MessageSquareMore2 } from "lucide-react";
|
|
4426
|
-
import { useEffect as useEffect13, useMemo as useMemo14, useState as
|
|
4460
|
+
import { useEffect as useEffect13, useMemo as useMemo14, useState as useState17 } from "react";
|
|
4427
4461
|
|
|
4428
4462
|
// src/react/components/chat/ResourceIframe.tsx
|
|
4429
|
-
import { useEffect as useEffect10, useEffectEvent as useEffectEvent3, useRef as
|
|
4463
|
+
import { useEffect as useEffect10, useEffectEvent as useEffectEvent3, useRef as useRef9, useState as useState11 } from "react";
|
|
4430
4464
|
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
4431
4465
|
function isResourceBridgeMessage(value) {
|
|
4432
4466
|
return typeof value === "object" && value !== null && value.__resourceBridge === true && typeof value.action === "string";
|
|
@@ -4435,8 +4469,8 @@ var INLINE_HEIGHT_MIN = 80;
|
|
|
4435
4469
|
var INLINE_HEIGHT_MAX = 6e3;
|
|
4436
4470
|
var INLINE_HEIGHT_PADDING = 8;
|
|
4437
4471
|
function ResourceIframe({ ui, sessionId }) {
|
|
4438
|
-
const iframeRef =
|
|
4439
|
-
const iframeKeyRef =
|
|
4472
|
+
const iframeRef = useRef9(null);
|
|
4473
|
+
const iframeKeyRef = useRef9(
|
|
4440
4474
|
`iframe-${Math.random().toString(36).slice(2, 10)}`
|
|
4441
4475
|
);
|
|
4442
4476
|
const activeSessionId = useSessionStore((state) => state.activeSessionId);
|
|
@@ -4444,7 +4478,7 @@ function ResourceIframe({ ui, sessionId }) {
|
|
|
4444
4478
|
const theme = useUiStore((state) => state.theme);
|
|
4445
4479
|
const resourceUri = ui.resourceUri ?? ui.resourceURI;
|
|
4446
4480
|
const iframeLabel = ui.title ?? resourceUri ?? "\u5DE5\u5177\u754C\u9762";
|
|
4447
|
-
const [autoHeight, setAutoHeight] =
|
|
4481
|
+
const [autoHeight, setAutoHeight] = useState11(null);
|
|
4448
4482
|
useEffect10(() => {
|
|
4449
4483
|
setAutoHeight(null);
|
|
4450
4484
|
}, [ui.resourceHTML, resourceUri]);
|
|
@@ -4555,7 +4589,7 @@ function ResourceIframe({ ui, sessionId }) {
|
|
|
4555
4589
|
|
|
4556
4590
|
// src/react/components/chat/ToolCallBlock.tsx
|
|
4557
4591
|
import { Check, ChevronRight as ChevronRight3, Loader2 as Loader23, MessageSquareMore, PanelRightOpen, X as X4 } from "lucide-react";
|
|
4558
|
-
import { useMemo as useMemo12, useState as
|
|
4592
|
+
import { useMemo as useMemo12, useState as useState14 } from "react";
|
|
4559
4593
|
|
|
4560
4594
|
// src/react/components/chat/tool-renderers/shared.tsx
|
|
4561
4595
|
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
@@ -4882,21 +4916,21 @@ function FileEditRenderer({ toolCall }) {
|
|
|
4882
4916
|
}
|
|
4883
4917
|
|
|
4884
4918
|
// src/react/components/chat/tool-renderers/FileReadRenderer.tsx
|
|
4885
|
-
import { useState as
|
|
4919
|
+
import { useState as useState13 } from "react";
|
|
4886
4920
|
|
|
4887
4921
|
// src/react/components/chat/ImageLightbox.tsx
|
|
4888
4922
|
import { ChevronLeft, ChevronRight as ChevronRight2, Download as Download2, ExternalLink, Minus, Plus as Plus2, RotateCcw, X as X3 } from "lucide-react";
|
|
4889
|
-
import { useCallback as useCallback10, useEffect as useEffect11, useRef as
|
|
4923
|
+
import { useCallback as useCallback10, useEffect as useEffect11, useRef as useRef10, useState as useState12 } from "react";
|
|
4890
4924
|
import { createPortal as createPortal3 } from "react-dom";
|
|
4891
4925
|
import { Fragment as Fragment4, jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
4892
4926
|
function ImageLightbox({ open, onOpenChange, images, initialIndex = 0 }) {
|
|
4893
|
-
const [currentIndex, setCurrentIndex] =
|
|
4894
|
-
const [scale, setScale] =
|
|
4895
|
-
const [translate, setTranslate] =
|
|
4896
|
-
const dragging =
|
|
4897
|
-
const dragStart =
|
|
4898
|
-
const translateStart =
|
|
4899
|
-
const imgRef =
|
|
4927
|
+
const [currentIndex, setCurrentIndex] = useState12(initialIndex);
|
|
4928
|
+
const [scale, setScale] = useState12(1);
|
|
4929
|
+
const [translate, setTranslate] = useState12({ x: 0, y: 0 });
|
|
4930
|
+
const dragging = useRef10(false);
|
|
4931
|
+
const dragStart = useRef10({ x: 0, y: 0 });
|
|
4932
|
+
const translateStart = useRef10({ x: 0, y: 0 });
|
|
4933
|
+
const imgRef = useRef10(null);
|
|
4900
4934
|
const reset = useCallback10(() => {
|
|
4901
4935
|
setScale(1);
|
|
4902
4936
|
setTranslate({ x: 0, y: 0 });
|
|
@@ -4915,7 +4949,7 @@ function ImageLightbox({ open, onOpenChange, images, initialIndex = 0 }) {
|
|
|
4915
4949
|
setCurrentIndex((i) => Math.min(images.length - 1, i + 1));
|
|
4916
4950
|
reset();
|
|
4917
4951
|
}, [images.length, reset]);
|
|
4918
|
-
const prevOpenRef =
|
|
4952
|
+
const prevOpenRef = useRef10(false);
|
|
4919
4953
|
useEffect11(() => {
|
|
4920
4954
|
if (open && !prevOpenRef.current) {
|
|
4921
4955
|
setCurrentIndex(initialIndex);
|
|
@@ -5205,7 +5239,7 @@ function formatLineRange(startLine, endLine) {
|
|
|
5205
5239
|
return startLine === endLine ? `\u7B2C ${startLine} \u884C` : `\u7B2C ${startLine}-${endLine} \u884C`;
|
|
5206
5240
|
}
|
|
5207
5241
|
function FileReadRenderer({ toolCall }) {
|
|
5208
|
-
const [lightboxIndex, setLightboxIndex] =
|
|
5242
|
+
const [lightboxIndex, setLightboxIndex] = useState13(null);
|
|
5209
5243
|
const argsValue = parseJsonValue(toolCall.arguments);
|
|
5210
5244
|
const args = isPlainObject(argsValue) ? argsValue : null;
|
|
5211
5245
|
const filePath = extractToolFilePath(toolCall);
|
|
@@ -5503,7 +5537,7 @@ function ToolCallBlock({
|
|
|
5503
5537
|
reasoning,
|
|
5504
5538
|
customization
|
|
5505
5539
|
}) {
|
|
5506
|
-
const [expanded, setExpanded] =
|
|
5540
|
+
const [expanded, setExpanded] = useState14(false);
|
|
5507
5541
|
const activeSessionId = useSessionStore((s) => s.activeSessionId);
|
|
5508
5542
|
const sessions = useSessionStore((s) => s.sessions);
|
|
5509
5543
|
const pushArtifact = useUiStore((s) => s.pushArtifact);
|
|
@@ -5707,7 +5741,7 @@ function buildAskUserPayload(argumentsJson) {
|
|
|
5707
5741
|
}
|
|
5708
5742
|
|
|
5709
5743
|
// src/react/components/chat/UserMessageBubble.tsx
|
|
5710
|
-
import { useState as
|
|
5744
|
+
import { useState as useState16 } from "react";
|
|
5711
5745
|
|
|
5712
5746
|
// src/react/lib/preview-dispatch.ts
|
|
5713
5747
|
var IMAGE_EXTS = [
|
|
@@ -6040,10 +6074,10 @@ function MessageFileAttachmentList({
|
|
|
6040
6074
|
|
|
6041
6075
|
// src/react/components/chat/MessageActions.tsx
|
|
6042
6076
|
import { Check as Check2, Copy } from "lucide-react";
|
|
6043
|
-
import { useState as
|
|
6077
|
+
import { useState as useState15 } from "react";
|
|
6044
6078
|
import { jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
6045
6079
|
function MessageActions({ content, className }) {
|
|
6046
|
-
const [copied, setCopied] =
|
|
6080
|
+
const [copied, setCopied] = useState15(false);
|
|
6047
6081
|
const handleCopy = async () => {
|
|
6048
6082
|
const ok = await copyToClipboard(content);
|
|
6049
6083
|
if (ok) {
|
|
@@ -6233,8 +6267,8 @@ function UserMessageBubble({ message, className }) {
|
|
|
6233
6267
|
alt: attachment.name || "\u7528\u6237\u4E0A\u4F20\u7684\u56FE\u7247"
|
|
6234
6268
|
}))
|
|
6235
6269
|
];
|
|
6236
|
-
const [lightboxIndex, setLightboxIndex] =
|
|
6237
|
-
const [preview, setPreview] =
|
|
6270
|
+
const [lightboxIndex, setLightboxIndex] = useState16(null);
|
|
6271
|
+
const [preview, setPreview] = useState16(null);
|
|
6238
6272
|
const handleTextAttachmentPreview = (attachment) => {
|
|
6239
6273
|
if (!activeSessionId) return;
|
|
6240
6274
|
const pathForUrl = attachment.uploadedPath ?? attachment.name;
|
|
@@ -6401,7 +6435,7 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
|
|
|
6401
6435
|
() => visibleLoopToolCalls.some((childToolCall) => childToolCall.status === "awaiting_answer"),
|
|
6402
6436
|
[visibleLoopToolCalls]
|
|
6403
6437
|
);
|
|
6404
|
-
const [expanded, setExpanded] =
|
|
6438
|
+
const [expanded, setExpanded] = useState17(hasAwaitingAnswer);
|
|
6405
6439
|
const completedToolLabels = useMemo14(
|
|
6406
6440
|
() => visibleLoopToolCalls.flatMap((childToolCall) => {
|
|
6407
6441
|
const isCompleted = childToolCall.status === "done" || childToolCall.status !== "pending" && childToolCall.status !== "awaiting_answer" && childToolCall.status !== "error" && childToolCall.status !== "cancelled";
|
|
@@ -6653,12 +6687,9 @@ function ExpandedChildAssistantMessage({
|
|
|
6653
6687
|
const text = typeof message.content === "string" ? message.content.trim() : message.content.filter((part) => part.type === "text").map((part) => part.text).join("").trim();
|
|
6654
6688
|
const toolCalls = message.tool_calls ?? [];
|
|
6655
6689
|
const hasToolCalls = toolCalls.length > 0;
|
|
6656
|
-
const firstToolCallId = toolCalls[0]?.id;
|
|
6657
|
-
const toolReasoning = !isStreaming && !text && hasToolCalls ? message.reasoning : void 0;
|
|
6658
|
-
const standaloneReasoning = !isStreaming && !text && !hasToolCalls ? message.reasoning : void 0;
|
|
6659
6690
|
return /* @__PURE__ */ jsxs24("div", { className: "flex flex-col gap-2", children: [
|
|
6660
|
-
message.reasoning &&
|
|
6661
|
-
/* @__PURE__ */ jsx29(ReasoningTrigger, {}),
|
|
6691
|
+
message.reasoning && /* @__PURE__ */ jsxs24(Reasoning, { isStreaming, children: [
|
|
6692
|
+
/* @__PURE__ */ jsx29(ReasoningTrigger, { wordCount: message.reasoning.length }),
|
|
6662
6693
|
/* @__PURE__ */ jsx29(ReasoningContent, { children: message.reasoning })
|
|
6663
6694
|
] }),
|
|
6664
6695
|
text ? /* @__PURE__ */ jsx29(
|
|
@@ -6667,18 +6698,17 @@ function ExpandedChildAssistantMessage({
|
|
|
6667
6698
|
text,
|
|
6668
6699
|
isStreaming,
|
|
6669
6700
|
sessionId,
|
|
6670
|
-
reasoning:
|
|
6701
|
+
reasoning: void 0
|
|
6671
6702
|
}
|
|
6672
6703
|
) : null,
|
|
6673
6704
|
!text && isStreaming && /* @__PURE__ */ jsx29("span", { className: "pl-8 text-[12px] text-[hsl(var(--muted-foreground))]", children: "\u6B63\u5728\u751F\u6210..." }),
|
|
6674
|
-
standaloneReasoning ? /* @__PURE__ */ jsx29("div", { className: "pl-8", children: /* @__PURE__ */ jsx29(ThinkingBadge, { reasoning: standaloneReasoning, variant: "block" }) }) : null,
|
|
6675
6705
|
hasToolCalls && /* @__PURE__ */ jsx29("div", { className: "flex flex-col gap-2", children: toolCalls.map(
|
|
6676
|
-
(toolCall
|
|
6706
|
+
(toolCall) => formatToolName(toolCall.name) === "Agent" ? /* @__PURE__ */ jsx29(
|
|
6677
6707
|
AgentLoopBlock,
|
|
6678
6708
|
{
|
|
6679
6709
|
toolCall,
|
|
6680
6710
|
sessionId,
|
|
6681
|
-
reasoning:
|
|
6711
|
+
reasoning: void 0
|
|
6682
6712
|
},
|
|
6683
6713
|
toolCall.id
|
|
6684
6714
|
) : /* @__PURE__ */ jsx29(
|
|
@@ -6688,7 +6718,7 @@ function ExpandedChildAssistantMessage({
|
|
|
6688
6718
|
sessionId,
|
|
6689
6719
|
level: 2,
|
|
6690
6720
|
turnBlocks: message.blocks,
|
|
6691
|
-
reasoning:
|
|
6721
|
+
reasoning: void 0
|
|
6692
6722
|
},
|
|
6693
6723
|
toolCall.id
|
|
6694
6724
|
)
|
|
@@ -6910,10 +6940,10 @@ function AssistantTurnBlock({
|
|
|
6910
6940
|
),
|
|
6911
6941
|
[allToolCalls]
|
|
6912
6942
|
);
|
|
6913
|
-
const [displayMode, setDisplayMode] =
|
|
6943
|
+
const [displayMode, setDisplayMode] = useState18(
|
|
6914
6944
|
defaultTurnDisplayMode({ forceExpanded, hasActionableToolCall })
|
|
6915
6945
|
);
|
|
6916
|
-
const wasStreamingRef =
|
|
6946
|
+
const wasStreamingRef = useRef11(isStreaming);
|
|
6917
6947
|
useEffect14(() => {
|
|
6918
6948
|
if (wasStreamingRef.current && !isStreaming && !forceExpanded) {
|
|
6919
6949
|
setDisplayMode(defaultTurnDisplayMode({ forceExpanded, hasActionableToolCall }));
|
|
@@ -7012,23 +7042,18 @@ function AssistantMessages({
|
|
|
7012
7042
|
return messages.map(
|
|
7013
7043
|
(message, index) => isRenderableAssistantMessage(message, isStreaming && index === messages.length - 1) ? (() => {
|
|
7014
7044
|
const isStreamingLastMessage = isStreaming && index === messages.length - 1;
|
|
7015
|
-
const hasText = !!getMessageText(message);
|
|
7016
7045
|
const reasoning = message.reasoning;
|
|
7017
7046
|
const hasReasoning = !!reasoning;
|
|
7018
|
-
const hasAttachments = getImageParts(message.content).length > 0 || getFileParts(message.content).length > 0;
|
|
7019
7047
|
const toolCalls = message.tool_calls ?? [];
|
|
7020
7048
|
const hasToolCalls = toolCalls.length > 0;
|
|
7021
|
-
const firstToolCallId = toolCalls[0]?.id;
|
|
7022
7049
|
const toolRenderItems = groupDetailedToolCalls(toolCalls);
|
|
7023
|
-
const toolReasoning = hasReasoning && !hasText && !hasAttachments && hasToolCalls && !isStreamingLastMessage ? reasoning : void 0;
|
|
7024
|
-
const contentReasoning = hasReasoning && !isStreamingLastMessage && (hasText || hasAttachments || !hasToolCalls) ? reasoning : void 0;
|
|
7025
7050
|
return /* @__PURE__ */ jsxs25(
|
|
7026
7051
|
"div",
|
|
7027
7052
|
{
|
|
7028
7053
|
className: "flex flex-col gap-3",
|
|
7029
7054
|
children: [
|
|
7030
|
-
hasReasoning &&
|
|
7031
|
-
/* @__PURE__ */ jsx30(ReasoningTrigger, {}),
|
|
7055
|
+
hasReasoning && /* @__PURE__ */ jsxs25(Reasoning, { isStreaming: isStreamingLastMessage, children: [
|
|
7056
|
+
/* @__PURE__ */ jsx30(ReasoningTrigger, { wordCount: reasoning.length }),
|
|
7032
7057
|
/* @__PURE__ */ jsx30(ReasoningContent, { children: reasoning })
|
|
7033
7058
|
] }),
|
|
7034
7059
|
/* @__PURE__ */ jsx30(
|
|
@@ -7037,7 +7062,7 @@ function AssistantMessages({
|
|
|
7037
7062
|
message,
|
|
7038
7063
|
isStreaming: isStreamingLastMessage,
|
|
7039
7064
|
sessionId,
|
|
7040
|
-
reasoning:
|
|
7065
|
+
reasoning: void 0,
|
|
7041
7066
|
className: customization?.classNames?.assistantText
|
|
7042
7067
|
}
|
|
7043
7068
|
),
|
|
@@ -7048,7 +7073,7 @@ function AssistantMessages({
|
|
|
7048
7073
|
{
|
|
7049
7074
|
toolCalls: item.toolCalls,
|
|
7050
7075
|
kind: item.kind,
|
|
7051
|
-
reasoning:
|
|
7076
|
+
reasoning: void 0,
|
|
7052
7077
|
sessionId,
|
|
7053
7078
|
sessionStatus,
|
|
7054
7079
|
askAnswers,
|
|
@@ -7066,7 +7091,7 @@ function AssistantMessages({
|
|
|
7066
7091
|
{
|
|
7067
7092
|
toolCall,
|
|
7068
7093
|
sessionId,
|
|
7069
|
-
reasoning:
|
|
7094
|
+
reasoning: void 0
|
|
7070
7095
|
},
|
|
7071
7096
|
toolCall.id
|
|
7072
7097
|
) : customization?.components?.ToolCall ? /* @__PURE__ */ jsx30(
|
|
@@ -7080,7 +7105,7 @@ function AssistantMessages({
|
|
|
7080
7105
|
sessionStatus,
|
|
7081
7106
|
level,
|
|
7082
7107
|
turnBlocks: message.blocks,
|
|
7083
|
-
reasoning:
|
|
7108
|
+
reasoning: void 0,
|
|
7084
7109
|
customization
|
|
7085
7110
|
},
|
|
7086
7111
|
toolCall.id
|
|
@@ -7095,7 +7120,7 @@ function AssistantMessages({
|
|
|
7095
7120
|
sessionStatus,
|
|
7096
7121
|
level,
|
|
7097
7122
|
turnBlocks: message.blocks,
|
|
7098
|
-
reasoning:
|
|
7123
|
+
reasoning: void 0,
|
|
7099
7124
|
customization
|
|
7100
7125
|
},
|
|
7101
7126
|
toolCall.id
|
|
@@ -7137,7 +7162,7 @@ function CompactToolGroupBlock({
|
|
|
7137
7162
|
level,
|
|
7138
7163
|
customization
|
|
7139
7164
|
}) {
|
|
7140
|
-
const [expanded, setExpanded] =
|
|
7165
|
+
const [expanded, setExpanded] = useState18(false);
|
|
7141
7166
|
const indentClass = level === 2 ? "ml-3" : "ml-4";
|
|
7142
7167
|
const hasError = toolCalls.some(
|
|
7143
7168
|
(tc) => tc.status === "error" || tc.status === "cancelled"
|
|
@@ -7303,7 +7328,7 @@ function AssistantText({
|
|
|
7303
7328
|
}
|
|
7304
7329
|
function MemoryRefsHint({ refs: rawRefs }) {
|
|
7305
7330
|
const refs = Array.isArray(rawRefs) ? rawRefs : [];
|
|
7306
|
-
const [expanded, setExpanded] =
|
|
7331
|
+
const [expanded, setExpanded] = useState18(false);
|
|
7307
7332
|
const hasSkill = refs.some((r3) => r3.skill_name);
|
|
7308
7333
|
const label = hasSkill ? "\u53C2\u8003\u4E86\u8BE5\u6280\u80FD\u7684\u5386\u53F2\u7ECF\u9A8C" : "\u53C2\u8003\u4E86\u5386\u53F2\u7ECF\u9A8C";
|
|
7309
7334
|
return /* @__PURE__ */ jsxs25("div", { className: "ml-4", children: [
|
|
@@ -7351,7 +7376,7 @@ function MemoryRefsHint({ refs: rawRefs }) {
|
|
|
7351
7376
|
|
|
7352
7377
|
// src/react/components/chat/CompactionCard.tsx
|
|
7353
7378
|
import { ChevronDown as ChevronDown2, ChevronRight as ChevronRight6, Loader2 as Loader25, Square as Square3, XCircle } from "lucide-react";
|
|
7354
|
-
import { useState as
|
|
7379
|
+
import { useState as useState19 } from "react";
|
|
7355
7380
|
import { jsx as jsx31, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
7356
7381
|
var PERCENT_FORMATTER = new Intl.NumberFormat("zh-CN", {
|
|
7357
7382
|
style: "percent",
|
|
@@ -7411,7 +7436,7 @@ function CompactionCard({
|
|
|
7411
7436
|
...compaction,
|
|
7412
7437
|
status: status ?? "completed"
|
|
7413
7438
|
} : activeCompaction;
|
|
7414
|
-
const [expanded, setExpanded] =
|
|
7439
|
+
const [expanded, setExpanded] = useState19(false);
|
|
7415
7440
|
if (!source || !source.compaction_id) {
|
|
7416
7441
|
return null;
|
|
7417
7442
|
}
|
|
@@ -7453,7 +7478,7 @@ function CompactionCard({
|
|
|
7453
7478
|
"button",
|
|
7454
7479
|
{
|
|
7455
7480
|
type: "button",
|
|
7456
|
-
onClick: () => getSocket().stop(sessionId),
|
|
7481
|
+
onClick: () => void getSocket().stop(sessionId),
|
|
7457
7482
|
className: "shrink-0 rounded-md border border-current/15 px-2 py-0.5 text-[11px] transition-opacity hover:opacity-80",
|
|
7458
7483
|
children: "\u53D6\u6D88\u6574\u7406"
|
|
7459
7484
|
}
|
|
@@ -7572,7 +7597,7 @@ import {
|
|
|
7572
7597
|
TerminalSquare,
|
|
7573
7598
|
WandSparkles
|
|
7574
7599
|
} from "lucide-react";
|
|
7575
|
-
import { useEffect as useEffect15, useMemo as useMemo16, useState as
|
|
7600
|
+
import { useEffect as useEffect15, useMemo as useMemo16, useState as useState20 } from "react";
|
|
7576
7601
|
import { jsx as jsx33, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
7577
7602
|
var EMPTY_EVENTS = [];
|
|
7578
7603
|
function formatElapsedDuration(durationMs) {
|
|
@@ -7651,7 +7676,7 @@ function getTurnStartedAt(events) {
|
|
|
7651
7676
|
return null;
|
|
7652
7677
|
}
|
|
7653
7678
|
function useElapsedDuration(startedAt, active) {
|
|
7654
|
-
const [now, setNow] =
|
|
7679
|
+
const [now, setNow] = useState20(() => Date.now());
|
|
7655
7680
|
useEffect15(() => {
|
|
7656
7681
|
if (!active || startedAt == null) {
|
|
7657
7682
|
return;
|
|
@@ -7943,10 +7968,10 @@ function MessageList({
|
|
|
7943
7968
|
) ?? null,
|
|
7944
7969
|
[lastTurnId, renderBlocks]
|
|
7945
7970
|
);
|
|
7946
|
-
const containerRef =
|
|
7947
|
-
const scrollContainerRef =
|
|
7948
|
-
const frameRef =
|
|
7949
|
-
const [activeTurnId, setActiveTurnId] =
|
|
7971
|
+
const containerRef = useRef12(null);
|
|
7972
|
+
const scrollContainerRef = useRef12(null);
|
|
7973
|
+
const frameRef = useRef12(null);
|
|
7974
|
+
const [activeTurnId, setActiveTurnId] = useState21(lastTurnId);
|
|
7950
7975
|
const layoutSignature = useMemo17(
|
|
7951
7976
|
() => getMessagesMeasureSignature(messages),
|
|
7952
7977
|
[messages]
|
|
@@ -8244,6 +8269,7 @@ function ChatView({
|
|
|
8244
8269
|
const {
|
|
8245
8270
|
messages,
|
|
8246
8271
|
isStreaming,
|
|
8272
|
+
isStopping,
|
|
8247
8273
|
send,
|
|
8248
8274
|
stop
|
|
8249
8275
|
} = useChat(sessionId);
|
|
@@ -8291,6 +8317,7 @@ function ChatView({
|
|
|
8291
8317
|
onSend: (msg, _targetSessionId, model) => send(msg, mode, void 0, { model: model || void 0 }),
|
|
8292
8318
|
onStop: stop,
|
|
8293
8319
|
isStreaming,
|
|
8320
|
+
isStopping,
|
|
8294
8321
|
mode,
|
|
8295
8322
|
onToggleMode: toggleMode,
|
|
8296
8323
|
renderAttachments,
|
|
@@ -8360,4 +8387,4 @@ use-stick-to-bottom/dist/StickToBottom.js:
|
|
|
8360
8387
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
8361
8388
|
*--------------------------------------------------------------------------------------------*)
|
|
8362
8389
|
*/
|
|
8363
|
-
//# sourceMappingURL=chunk-
|
|
8390
|
+
//# sourceMappingURL=chunk-RTBAPZIO.js.map
|