@dudousxd/nestjs-agent-react 0.7.5 → 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 +35 -2
- package/dist/index.cjs +451 -179
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +119 -12
- package/dist/index.d.ts +119 -12
- package/dist/index.js +358 -89
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,6 +1,65 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
3
|
|
|
4
|
+
// src/reasoning/timing.ts
|
|
5
|
+
import { useEffect, useRef, useState } from "react";
|
|
6
|
+
var REASONING_METADATA_KEY = "agent";
|
|
7
|
+
function reasoningDurationMetadata(reasoningMs) {
|
|
8
|
+
return {
|
|
9
|
+
[REASONING_METADATA_KEY]: {
|
|
10
|
+
reasoningMs
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
__name(reasoningDurationMetadata, "reasoningDurationMetadata");
|
|
15
|
+
function readReasoningMs(part) {
|
|
16
|
+
const metadata = part.providerMetadata;
|
|
17
|
+
if (typeof metadata !== "object" || metadata === null) return null;
|
|
18
|
+
const scoped = metadata[REASONING_METADATA_KEY];
|
|
19
|
+
if (typeof scoped !== "object" || scoped === null) return null;
|
|
20
|
+
const value = scoped.reasoningMs;
|
|
21
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : null;
|
|
22
|
+
}
|
|
23
|
+
__name(readReasoningMs, "readReasoningMs");
|
|
24
|
+
function useElapsed(running, options = {}) {
|
|
25
|
+
const { intervalMs = 1e3 } = options;
|
|
26
|
+
const nowRef = useRef(options.now ?? Date.now);
|
|
27
|
+
nowRef.current = options.now ?? Date.now;
|
|
28
|
+
const startedAt = useRef(null);
|
|
29
|
+
const [elapsed, setElapsed] = useState(0);
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
if (!running) {
|
|
32
|
+
if (startedAt.current !== null) {
|
|
33
|
+
setElapsed(nowRef.current() - startedAt.current);
|
|
34
|
+
startedAt.current = null;
|
|
35
|
+
}
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
startedAt.current = nowRef.current();
|
|
39
|
+
setElapsed(0);
|
|
40
|
+
const timer = setInterval(() => {
|
|
41
|
+
if (startedAt.current !== null) setElapsed(nowRef.current() - startedAt.current);
|
|
42
|
+
}, intervalMs);
|
|
43
|
+
return () => clearInterval(timer);
|
|
44
|
+
}, [
|
|
45
|
+
running,
|
|
46
|
+
intervalMs
|
|
47
|
+
]);
|
|
48
|
+
return elapsed;
|
|
49
|
+
}
|
|
50
|
+
__name(useElapsed, "useElapsed");
|
|
51
|
+
function formatElapsed(ms) {
|
|
52
|
+
if (!Number.isFinite(ms) || ms < 1e3) return "<1s";
|
|
53
|
+
const totalSeconds = Math.floor(ms / 1e3);
|
|
54
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
55
|
+
const minutes = Math.floor(totalSeconds % 3600 / 60);
|
|
56
|
+
const seconds = totalSeconds % 60;
|
|
57
|
+
if (hours > 0) return minutes > 0 ? `${hours}h ${minutes}m` : `${hours}h`;
|
|
58
|
+
if (minutes > 0) return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;
|
|
59
|
+
return `${seconds}s`;
|
|
60
|
+
}
|
|
61
|
+
__name(formatElapsed, "formatElapsed");
|
|
62
|
+
|
|
4
63
|
// src/agent-chat-transport.ts
|
|
5
64
|
var HEADER_RUN_ID = "x-agent-run-id";
|
|
6
65
|
var HEADER_THREAD_ID = "x-agent-thread-id";
|
|
@@ -140,7 +199,8 @@ var AgentChatTransport = class {
|
|
|
140
199
|
* Parse the backend's SSE byte stream and re-emit it as a valid v7 UI-message chunk stream.
|
|
141
200
|
* Recognized frames:
|
|
142
201
|
* - `event: meta` `data: {"runId","threadId"}` → records identity
|
|
143
|
-
* - `data: <AgentStreamEvent JSON>` → mapped to UI chunks (text / reasoning / tool
|
|
202
|
+
* - `data: <AgentStreamEvent JSON>` → mapped to UI chunks (text / reasoning / tool /
|
|
203
|
+
* `data-*`; see {@link AgentChatTransport} docs)
|
|
144
204
|
* - `event: done` `data: {}` → terminates
|
|
145
205
|
* - `event: error` `data: {code,message}` → error chunk
|
|
146
206
|
*
|
|
@@ -157,7 +217,11 @@ var AgentChatTransport = class {
|
|
|
157
217
|
let stepIndex = 0;
|
|
158
218
|
let textId = null;
|
|
159
219
|
let reasoningId = null;
|
|
220
|
+
let reasoningStartedAt = 0;
|
|
221
|
+
let textSeq = 0;
|
|
222
|
+
let reasoningSeq = 0;
|
|
160
223
|
const announced = /* @__PURE__ */ new Set();
|
|
224
|
+
const toolMetadata = /* @__PURE__ */ new Map();
|
|
161
225
|
const record = /* @__PURE__ */ __name((meta) => this.recordMeta(meta), "record");
|
|
162
226
|
const endAttempt = /* @__PURE__ */ __name(() => {
|
|
163
227
|
this.attemptLive = false;
|
|
@@ -179,6 +243,8 @@ var AgentChatTransport = class {
|
|
|
179
243
|
stepIndex += 1;
|
|
180
244
|
textId = null;
|
|
181
245
|
reasoningId = null;
|
|
246
|
+
textSeq = 0;
|
|
247
|
+
reasoningSeq = 0;
|
|
182
248
|
controller.enqueue({
|
|
183
249
|
type: "start-step"
|
|
184
250
|
});
|
|
@@ -188,8 +254,7 @@ var AgentChatTransport = class {
|
|
|
188
254
|
if (!stepOpen) openStep();
|
|
189
255
|
}
|
|
190
256
|
__name(ensureStep, "ensureStep");
|
|
191
|
-
function
|
|
192
|
-
if (!stepOpen) return;
|
|
257
|
+
function closeRuns(reasoningMs) {
|
|
193
258
|
if (textId !== null) {
|
|
194
259
|
controller.enqueue({
|
|
195
260
|
type: "text-end",
|
|
@@ -200,23 +265,55 @@ var AgentChatTransport = class {
|
|
|
200
265
|
if (reasoningId !== null) {
|
|
201
266
|
controller.enqueue({
|
|
202
267
|
type: "reasoning-end",
|
|
203
|
-
id: reasoningId
|
|
268
|
+
id: reasoningId,
|
|
269
|
+
providerMetadata: reasoningDurationMetadata(reasoningMs ?? Math.max(0, Date.now() - reasoningStartedAt))
|
|
204
270
|
});
|
|
205
271
|
reasoningId = null;
|
|
206
272
|
}
|
|
273
|
+
}
|
|
274
|
+
__name(closeRuns, "closeRuns");
|
|
275
|
+
function closeStep(reasoningMs) {
|
|
276
|
+
if (!stepOpen) return;
|
|
277
|
+
closeRuns(reasoningMs);
|
|
207
278
|
controller.enqueue({
|
|
208
279
|
type: "finish-step"
|
|
209
280
|
});
|
|
210
281
|
stepOpen = false;
|
|
211
282
|
}
|
|
212
283
|
__name(closeStep, "closeStep");
|
|
284
|
+
function metadataFor(id, toolKind2, parentId) {
|
|
285
|
+
const merged = {
|
|
286
|
+
...toolMetadata.get(id)
|
|
287
|
+
};
|
|
288
|
+
if (toolKind2 !== void 0) merged.toolKind = toolKind2;
|
|
289
|
+
if (parentId !== void 0 && merged.parentId === void 0) merged.parentId = parentId;
|
|
290
|
+
if (Object.keys(merged).length === 0) return void 0;
|
|
291
|
+
toolMetadata.set(id, merged);
|
|
292
|
+
return merged;
|
|
293
|
+
}
|
|
294
|
+
__name(metadataFor, "metadataFor");
|
|
295
|
+
function forwardAsData(event, transient) {
|
|
296
|
+
ensureStarted();
|
|
297
|
+
const { kind, ...data } = event;
|
|
298
|
+
controller.enqueue({
|
|
299
|
+
type: `data-${kind}`,
|
|
300
|
+
...typeof data.id === "string" ? {
|
|
301
|
+
id: data.id
|
|
302
|
+
} : {},
|
|
303
|
+
data,
|
|
304
|
+
...transient ? {
|
|
305
|
+
transient: true
|
|
306
|
+
} : {}
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
__name(forwardAsData, "forwardAsData");
|
|
213
310
|
function emit(event) {
|
|
214
311
|
switch (event.kind) {
|
|
215
312
|
case "step-start":
|
|
216
313
|
openStep();
|
|
217
314
|
break;
|
|
218
315
|
case "step-finish":
|
|
219
|
-
closeStep();
|
|
316
|
+
closeStep(event.reasoningMs);
|
|
220
317
|
if (event.costUsd !== void 0) {
|
|
221
318
|
controller.enqueue({
|
|
222
319
|
type: "message-metadata",
|
|
@@ -229,7 +326,8 @@ var AgentChatTransport = class {
|
|
|
229
326
|
case "text":
|
|
230
327
|
ensureStep();
|
|
231
328
|
if (textId === null) {
|
|
232
|
-
textId = `txt-${stepIndex}`;
|
|
329
|
+
textId = textSeq === 0 ? `txt-${stepIndex}` : `txt-${stepIndex}.${textSeq}`;
|
|
330
|
+
textSeq += 1;
|
|
233
331
|
controller.enqueue({
|
|
234
332
|
type: "text-start",
|
|
235
333
|
id: textId
|
|
@@ -244,7 +342,9 @@ var AgentChatTransport = class {
|
|
|
244
342
|
case "reasoning":
|
|
245
343
|
ensureStep();
|
|
246
344
|
if (reasoningId === null) {
|
|
247
|
-
reasoningId = `rsn-${stepIndex}`;
|
|
345
|
+
reasoningId = reasoningSeq === 0 ? `rsn-${stepIndex}` : `rsn-${stepIndex}.${reasoningSeq}`;
|
|
346
|
+
reasoningSeq += 1;
|
|
347
|
+
reasoningStartedAt = Date.now();
|
|
248
348
|
controller.enqueue({
|
|
249
349
|
type: "reasoning-start",
|
|
250
350
|
id: reasoningId
|
|
@@ -256,23 +356,20 @@ var AgentChatTransport = class {
|
|
|
256
356
|
delta: event.text
|
|
257
357
|
});
|
|
258
358
|
break;
|
|
259
|
-
case "tool-input-start":
|
|
359
|
+
case "tool-input-start": {
|
|
260
360
|
ensureStep();
|
|
261
361
|
announced.add(event.id);
|
|
362
|
+
const metadata = metadataFor(event.id, event.toolKind, event.parentId);
|
|
262
363
|
controller.enqueue({
|
|
263
364
|
type: "tool-input-start",
|
|
264
365
|
toolCallId: event.id,
|
|
265
366
|
toolName: event.name,
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
// UI gate approval affordances on `kind === 'action'` without hardcoding tool names.
|
|
269
|
-
...event.toolKind !== void 0 ? {
|
|
270
|
-
toolMetadata: {
|
|
271
|
-
toolKind: event.toolKind
|
|
272
|
-
}
|
|
367
|
+
...metadata !== void 0 ? {
|
|
368
|
+
toolMetadata: metadata
|
|
273
369
|
} : {}
|
|
274
370
|
});
|
|
275
371
|
break;
|
|
372
|
+
}
|
|
276
373
|
case "tool-input-delta":
|
|
277
374
|
ensureStep();
|
|
278
375
|
controller.enqueue({
|
|
@@ -281,21 +378,21 @@ var AgentChatTransport = class {
|
|
|
281
378
|
inputTextDelta: event.delta
|
|
282
379
|
});
|
|
283
380
|
break;
|
|
284
|
-
case "tool-input-available":
|
|
381
|
+
case "tool-input-available": {
|
|
285
382
|
ensureStep();
|
|
286
383
|
announced.add(event.id);
|
|
384
|
+
const metadata = metadataFor(event.id, event.toolKind, event.parentId);
|
|
287
385
|
controller.enqueue({
|
|
288
386
|
type: "tool-input-available",
|
|
289
387
|
toolCallId: event.id,
|
|
290
388
|
toolName: event.name,
|
|
291
389
|
input: event.input,
|
|
292
|
-
...
|
|
293
|
-
toolMetadata:
|
|
294
|
-
toolKind: event.toolKind
|
|
295
|
-
}
|
|
390
|
+
...metadata !== void 0 ? {
|
|
391
|
+
toolMetadata: metadata
|
|
296
392
|
} : {}
|
|
297
393
|
});
|
|
298
394
|
break;
|
|
395
|
+
}
|
|
299
396
|
case "elicitation":
|
|
300
397
|
ensureStep();
|
|
301
398
|
if (!announced.has(event.id)) {
|
|
@@ -336,7 +433,39 @@ var AgentChatTransport = class {
|
|
|
336
433
|
toolCallId: event.id
|
|
337
434
|
});
|
|
338
435
|
break;
|
|
436
|
+
case "approval-requested":
|
|
437
|
+
ensureStep();
|
|
438
|
+
forwardAsData(event, false);
|
|
439
|
+
if (announced.has(event.id)) {
|
|
440
|
+
controller.enqueue({
|
|
441
|
+
type: "tool-approval-request",
|
|
442
|
+
approvalId: event.id,
|
|
443
|
+
toolCallId: event.id
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
break;
|
|
447
|
+
case "ui":
|
|
448
|
+
ensureStep();
|
|
449
|
+
closeRuns();
|
|
450
|
+
controller.enqueue({
|
|
451
|
+
type: "data-ui",
|
|
452
|
+
id: event.id,
|
|
453
|
+
data: {
|
|
454
|
+
id: event.id,
|
|
455
|
+
component: event.component,
|
|
456
|
+
props: event.props,
|
|
457
|
+
...event.version !== void 0 ? {
|
|
458
|
+
version: event.version
|
|
459
|
+
} : {}
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
break;
|
|
463
|
+
case "title":
|
|
464
|
+
case "cancelled":
|
|
465
|
+
forwardAsData(event, true);
|
|
466
|
+
break;
|
|
339
467
|
default:
|
|
468
|
+
forwardAsData(event, false);
|
|
340
469
|
break;
|
|
341
470
|
}
|
|
342
471
|
}
|
|
@@ -663,10 +792,10 @@ var AgentClient = class {
|
|
|
663
792
|
};
|
|
664
793
|
|
|
665
794
|
// src/components/chat-input.tsx
|
|
666
|
-
import React2, { useEffect as
|
|
795
|
+
import React2, { useEffect as useEffect3, useState as useState3 } from "react";
|
|
667
796
|
|
|
668
797
|
// src/components/use-speech-recognition.ts
|
|
669
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
798
|
+
import { useCallback, useEffect as useEffect2, useMemo, useRef as useRef2, useState as useState2 } from "react";
|
|
670
799
|
function getRecognitionCtor() {
|
|
671
800
|
if (typeof window === "undefined") return null;
|
|
672
801
|
const scope = window;
|
|
@@ -674,15 +803,15 @@ function getRecognitionCtor() {
|
|
|
674
803
|
}
|
|
675
804
|
__name(getRecognitionCtor, "getRecognitionCtor");
|
|
676
805
|
function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTranscript }) {
|
|
677
|
-
const recognitionRef =
|
|
678
|
-
const [isListening, setIsListening] =
|
|
806
|
+
const recognitionRef = useRef2(null);
|
|
807
|
+
const [isListening, setIsListening] = useState2(false);
|
|
679
808
|
const ctor = useMemo(() => getRecognitionCtor(), []);
|
|
680
809
|
const isSupported = ctor !== null;
|
|
681
|
-
const finalRef =
|
|
682
|
-
const interimRef =
|
|
810
|
+
const finalRef = useRef2(onFinalTranscript);
|
|
811
|
+
const interimRef = useRef2(onInterimTranscript);
|
|
683
812
|
finalRef.current = onFinalTranscript;
|
|
684
813
|
interimRef.current = onInterimTranscript;
|
|
685
|
-
|
|
814
|
+
useEffect2(() => {
|
|
686
815
|
if (!ctor) return;
|
|
687
816
|
const recognition = new ctor();
|
|
688
817
|
recognition.lang = lang;
|
|
@@ -750,8 +879,8 @@ __name(useSpeechRecognition, "useSpeechRecognition");
|
|
|
750
879
|
|
|
751
880
|
// src/components/chat-input.tsx
|
|
752
881
|
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 }) {
|
|
753
|
-
const [value, setValue] =
|
|
754
|
-
const [interim, setInterim] =
|
|
882
|
+
const [value, setValue] = useState3("");
|
|
883
|
+
const [interim, setInterim] = useState3("");
|
|
755
884
|
const speech = useSpeechRecognition({
|
|
756
885
|
lang: speechLang,
|
|
757
886
|
onFinalTranscript: /* @__PURE__ */ __name((text) => {
|
|
@@ -762,7 +891,7 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
|
|
|
762
891
|
}, "onFinalTranscript"),
|
|
763
892
|
onInterimTranscript: /* @__PURE__ */ __name((text) => setInterim(text), "onInterimTranscript")
|
|
764
893
|
});
|
|
765
|
-
|
|
894
|
+
useEffect3(() => {
|
|
766
895
|
if (!speech.isListening) setInterim("");
|
|
767
896
|
}, [
|
|
768
897
|
speech.isListening
|
|
@@ -829,10 +958,10 @@ __name(ChatInput, "ChatInput");
|
|
|
829
958
|
import React3 from "react";
|
|
830
959
|
|
|
831
960
|
// src/transcript/use-chat-transcript.ts
|
|
832
|
-
import { useCallback as useCallback3, useEffect as
|
|
961
|
+
import { useCallback as useCallback3, useEffect as useEffect5, useRef as useRef4, useState as useState5 } from "react";
|
|
833
962
|
|
|
834
963
|
// src/transcript/model.ts
|
|
835
|
-
import { getToolName, isFileUIPart, isReasoningUIPart, isTextUIPart, isToolUIPart } from "ai";
|
|
964
|
+
import { getToolName, isDataUIPart, isFileUIPart, isReasoningUIPart, isTextUIPart, isToolUIPart } from "ai";
|
|
836
965
|
function buildTranscriptBlocks(message, options) {
|
|
837
966
|
const blocks = [];
|
|
838
967
|
let toolBuffer = [];
|
|
@@ -844,15 +973,18 @@ function buildTranscriptBlocks(message, options) {
|
|
|
844
973
|
let reasoningCounter = 0;
|
|
845
974
|
let sourcesCounter = 0;
|
|
846
975
|
let elicitationCounter = 0;
|
|
976
|
+
const approvals = readApprovals(message.parts ?? []);
|
|
847
977
|
function flushTools() {
|
|
848
978
|
if (toolBuffer.length === 0) {
|
|
849
979
|
return;
|
|
850
980
|
}
|
|
981
|
+
const calls = toolBuffer.map((part) => buildToolCall(part, options.approval, approvals.get(part.toolCallId) ?? null));
|
|
851
982
|
blocks.push({
|
|
852
983
|
kind: "tools",
|
|
853
984
|
key: `${message.id}-tools-${toolCounter++}`,
|
|
854
985
|
parts: toolBuffer,
|
|
855
|
-
calls
|
|
986
|
+
calls,
|
|
987
|
+
roots: nestToolCalls(calls)
|
|
856
988
|
});
|
|
857
989
|
toolBuffer = [];
|
|
858
990
|
}
|
|
@@ -915,7 +1047,21 @@ function buildTranscriptBlocks(message, options) {
|
|
|
915
1047
|
fileBuffer.push(part);
|
|
916
1048
|
continue;
|
|
917
1049
|
}
|
|
1050
|
+
if (part.type === APPROVAL_PART) {
|
|
1051
|
+
continue;
|
|
1052
|
+
}
|
|
918
1053
|
flushAll();
|
|
1054
|
+
if (isDataUIPart(part)) {
|
|
1055
|
+
const ui = part.type === UI_PART ? readUiComponent(part) : null;
|
|
1056
|
+
if (ui !== null) {
|
|
1057
|
+
blocks.push({
|
|
1058
|
+
kind: "ui",
|
|
1059
|
+
key: `${message.id}-ui-${ui.id}`,
|
|
1060
|
+
...ui
|
|
1061
|
+
});
|
|
1062
|
+
}
|
|
1063
|
+
continue;
|
|
1064
|
+
}
|
|
919
1065
|
if (isTextUIPart(part)) {
|
|
920
1066
|
blocks.push({
|
|
921
1067
|
kind: "text",
|
|
@@ -933,6 +1079,7 @@ function buildTranscriptBlocks(message, options) {
|
|
|
933
1079
|
key,
|
|
934
1080
|
text: part.text,
|
|
935
1081
|
isStreaming,
|
|
1082
|
+
durationMs: readReasoningMs(part),
|
|
936
1083
|
isOpen: options.isReasoningOpen(key, isStreaming),
|
|
937
1084
|
toggle: /* @__PURE__ */ __name((open) => options.toggleReasoning(key, open), "toggle")
|
|
938
1085
|
});
|
|
@@ -999,7 +1146,42 @@ function isAwaitingApproval(part) {
|
|
|
999
1146
|
return toolKind(part) === "action" && readElicitationRequest(part) === null;
|
|
1000
1147
|
}
|
|
1001
1148
|
__name(isAwaitingApproval, "isAwaitingApproval");
|
|
1002
|
-
function
|
|
1149
|
+
function toolParentId(part) {
|
|
1150
|
+
const metadata = part.toolMetadata;
|
|
1151
|
+
return isRecord(metadata) && typeof metadata.parentId === "string" ? metadata.parentId : null;
|
|
1152
|
+
}
|
|
1153
|
+
__name(toolParentId, "toolParentId");
|
|
1154
|
+
function nestToolCalls(calls) {
|
|
1155
|
+
const byId = new Map(calls.map((call) => [
|
|
1156
|
+
call.toolCallId,
|
|
1157
|
+
call
|
|
1158
|
+
]));
|
|
1159
|
+
const roots = [];
|
|
1160
|
+
for (const call of calls) {
|
|
1161
|
+
const parent = call.parentId !== null ? byId.get(call.parentId) : void 0;
|
|
1162
|
+
if (parent === void 0 || isAncestor(call, parent, byId)) {
|
|
1163
|
+
roots.push(call);
|
|
1164
|
+
continue;
|
|
1165
|
+
}
|
|
1166
|
+
parent.children.push(call);
|
|
1167
|
+
}
|
|
1168
|
+
return roots;
|
|
1169
|
+
}
|
|
1170
|
+
__name(nestToolCalls, "nestToolCalls");
|
|
1171
|
+
function isAncestor(call, candidate, byId) {
|
|
1172
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1173
|
+
let current = candidate;
|
|
1174
|
+
while (current !== void 0 && !seen.has(current.toolCallId)) {
|
|
1175
|
+
if (current.toolCallId === call.toolCallId) {
|
|
1176
|
+
return true;
|
|
1177
|
+
}
|
|
1178
|
+
seen.add(current.toolCallId);
|
|
1179
|
+
current = current.parentId !== null ? byId.get(current.parentId) : void 0;
|
|
1180
|
+
}
|
|
1181
|
+
return false;
|
|
1182
|
+
}
|
|
1183
|
+
__name(isAncestor, "isAncestor");
|
|
1184
|
+
function buildToolCall(part, options, approval) {
|
|
1003
1185
|
const toolCallId = part.toolCallId;
|
|
1004
1186
|
const awaiting = isAwaitingApproval(part);
|
|
1005
1187
|
const sending = awaiting ? options?.submitting(toolCallId) ?? null : null;
|
|
@@ -1007,6 +1189,10 @@ function buildToolCall(part, options) {
|
|
|
1007
1189
|
part,
|
|
1008
1190
|
toolCallId,
|
|
1009
1191
|
name: getToolName(part),
|
|
1192
|
+
toolKind: toolKind(part) ?? null,
|
|
1193
|
+
parentId: toolParentId(part),
|
|
1194
|
+
children: [],
|
|
1195
|
+
approval,
|
|
1010
1196
|
isAwaitingApproval: awaiting,
|
|
1011
1197
|
approve: {
|
|
1012
1198
|
available: awaiting && options?.canApprove === true,
|
|
@@ -1137,6 +1323,44 @@ function buildElicitationBlock(key, part, request, options) {
|
|
|
1137
1323
|
};
|
|
1138
1324
|
}
|
|
1139
1325
|
__name(buildElicitationBlock, "buildElicitationBlock");
|
|
1326
|
+
var UI_PART = "data-ui";
|
|
1327
|
+
var APPROVAL_PART = "data-approval-requested";
|
|
1328
|
+
function readApprovals(parts) {
|
|
1329
|
+
const out = /* @__PURE__ */ new Map();
|
|
1330
|
+
for (const part of parts) {
|
|
1331
|
+
if (part.type !== APPROVAL_PART) {
|
|
1332
|
+
continue;
|
|
1333
|
+
}
|
|
1334
|
+
const data = part.data;
|
|
1335
|
+
if (!isRecord(data) || typeof data.id !== "string" || typeof data.approver !== "string") {
|
|
1336
|
+
continue;
|
|
1337
|
+
}
|
|
1338
|
+
out.set(data.id, {
|
|
1339
|
+
approver: data.approver,
|
|
1340
|
+
expiresAt: typeof data.expiresAt === "string" ? data.expiresAt : null,
|
|
1341
|
+
reason: typeof data.reason === "string" ? data.reason : null
|
|
1342
|
+
});
|
|
1343
|
+
}
|
|
1344
|
+
return out;
|
|
1345
|
+
}
|
|
1346
|
+
__name(readApprovals, "readApprovals");
|
|
1347
|
+
function readUiComponent(part) {
|
|
1348
|
+
const data = part.data;
|
|
1349
|
+
if (!isRecord(data) || typeof data.component !== "string") {
|
|
1350
|
+
return null;
|
|
1351
|
+
}
|
|
1352
|
+
const id = typeof data.id === "string" ? data.id : part.id;
|
|
1353
|
+
if (id === void 0) {
|
|
1354
|
+
return null;
|
|
1355
|
+
}
|
|
1356
|
+
return {
|
|
1357
|
+
id,
|
|
1358
|
+
component: data.component,
|
|
1359
|
+
props: isRecord(data.props) ? data.props : {},
|
|
1360
|
+
version: typeof data.version === "number" ? data.version : null
|
|
1361
|
+
};
|
|
1362
|
+
}
|
|
1363
|
+
__name(readUiComponent, "readUiComponent");
|
|
1140
1364
|
function isRecord(value) {
|
|
1141
1365
|
return typeof value === "object" && value !== null;
|
|
1142
1366
|
}
|
|
@@ -1268,10 +1492,10 @@ function formatCostUsd(cost) {
|
|
|
1268
1492
|
__name(formatCostUsd, "formatCostUsd");
|
|
1269
1493
|
|
|
1270
1494
|
// src/transcript/use-stick-to-bottom.ts
|
|
1271
|
-
import { useCallback as useCallback2, useEffect as
|
|
1495
|
+
import { useCallback as useCallback2, useEffect as useEffect4, useRef as useRef3, useState as useState4 } from "react";
|
|
1272
1496
|
function useStickToBottom({ contentKey, threshold = 32 }) {
|
|
1273
|
-
const containerRef =
|
|
1274
|
-
const [isAtBottom, setIsAtBottom] =
|
|
1497
|
+
const containerRef = useRef3(null);
|
|
1498
|
+
const [isAtBottom, setIsAtBottom] = useState4(true);
|
|
1275
1499
|
const measure = useCallback2(() => {
|
|
1276
1500
|
const element = containerRef.current;
|
|
1277
1501
|
if (!element) {
|
|
@@ -1298,7 +1522,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
|
|
|
1298
1522
|
}, [
|
|
1299
1523
|
measure
|
|
1300
1524
|
]);
|
|
1301
|
-
|
|
1525
|
+
useEffect4(() => {
|
|
1302
1526
|
if (isAtBottom) {
|
|
1303
1527
|
scrollToBottom();
|
|
1304
1528
|
}
|
|
@@ -1329,14 +1553,14 @@ var DEFAULT_LOAD_EARLIER_STEP = 50;
|
|
|
1329
1553
|
var DEFAULT_COPY_RESET_MS = 1500;
|
|
1330
1554
|
function useChatTranscript(options) {
|
|
1331
1555
|
const { messages, status, initialVisibleCount = DEFAULT_VISIBLE_COUNT, loadEarlierStep = DEFAULT_LOAD_EARLIER_STEP, followUps, stickToBottomThreshold } = options;
|
|
1332
|
-
const latest =
|
|
1556
|
+
const latest = useRef4(options);
|
|
1333
1557
|
latest.current = options;
|
|
1334
|
-
const [visibleCount, setVisibleCount] =
|
|
1335
|
-
const [stopRequested, setStopRequested] =
|
|
1558
|
+
const [visibleCount, setVisibleCount] = useState5(initialVisibleCount);
|
|
1559
|
+
const [stopRequested, setStopRequested] = useState5(false);
|
|
1336
1560
|
const isStreaming = status === "streaming";
|
|
1337
1561
|
const isBusy = status === "submitted" || isStreaming;
|
|
1338
1562
|
const isEmpty = messages.length === 0;
|
|
1339
|
-
|
|
1563
|
+
useEffect5(() => {
|
|
1340
1564
|
if (!isBusy) {
|
|
1341
1565
|
setStopRequested(false);
|
|
1342
1566
|
}
|
|
@@ -1398,7 +1622,7 @@ function useChatTranscript(options) {
|
|
|
1398
1622
|
__name(useChatTranscript, "useChatTranscript");
|
|
1399
1623
|
function useTranscriptItem(options) {
|
|
1400
1624
|
const { message, isStreaming = false } = options;
|
|
1401
|
-
const messagesRef =
|
|
1625
|
+
const messagesRef = useRef4([
|
|
1402
1626
|
message
|
|
1403
1627
|
]);
|
|
1404
1628
|
if (messagesRef.current[0] !== message) {
|
|
@@ -1416,13 +1640,13 @@ function useTranscriptItem(options) {
|
|
|
1416
1640
|
}
|
|
1417
1641
|
__name(useTranscriptItem, "useTranscriptItem");
|
|
1418
1642
|
function useTranscriptItems({ messages, visibleStart, streamingMessageId, options }) {
|
|
1419
|
-
const [drafts, setDrafts] =
|
|
1420
|
-
const [copied, setCopied] =
|
|
1421
|
-
const [openReasoning, setOpenReasoning] =
|
|
1422
|
-
const [picks, setPicks] =
|
|
1423
|
-
const [settling, setSettling] =
|
|
1424
|
-
const [settleErrors, setSettleErrors] =
|
|
1425
|
-
const latest =
|
|
1643
|
+
const [drafts, setDrafts] = useState5(() => /* @__PURE__ */ new Map());
|
|
1644
|
+
const [copied, setCopied] = useState5(() => /* @__PURE__ */ new Set());
|
|
1645
|
+
const [openReasoning, setOpenReasoning] = useState5(() => /* @__PURE__ */ new Map());
|
|
1646
|
+
const [picks, setPicks] = useState5(() => /* @__PURE__ */ new Map());
|
|
1647
|
+
const [settling, setSettling] = useState5(() => /* @__PURE__ */ new Map());
|
|
1648
|
+
const [settleErrors, setSettleErrors] = useState5(() => /* @__PURE__ */ new Map());
|
|
1649
|
+
const latest = useRef4({
|
|
1426
1650
|
options,
|
|
1427
1651
|
drafts,
|
|
1428
1652
|
picks,
|
|
@@ -1434,15 +1658,15 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
1434
1658
|
picks,
|
|
1435
1659
|
messages
|
|
1436
1660
|
};
|
|
1437
|
-
const copyTimers =
|
|
1438
|
-
|
|
1661
|
+
const copyTimers = useRef4(/* @__PURE__ */ new Map());
|
|
1662
|
+
useEffect5(() => () => {
|
|
1439
1663
|
for (const timer of copyTimers.current.values()) {
|
|
1440
1664
|
clearTimeout(timer);
|
|
1441
1665
|
}
|
|
1442
1666
|
copyTimers.current.clear();
|
|
1443
1667
|
}, []);
|
|
1444
|
-
const callbackCache =
|
|
1445
|
-
const reasoningToggleCache =
|
|
1668
|
+
const callbackCache = useRef4(/* @__PURE__ */ new Map());
|
|
1669
|
+
const reasoningToggleCache = useRef4(/* @__PURE__ */ new Map());
|
|
1446
1670
|
const toggleReasoning = useCallback3((key, open) => {
|
|
1447
1671
|
setOpenReasoning((current) => {
|
|
1448
1672
|
const next = new Map(current);
|
|
@@ -1830,6 +2054,14 @@ function renderBlocks(item, slots) {
|
|
|
1830
2054
|
}
|
|
1831
2055
|
if (block.kind === "tools") {
|
|
1832
2056
|
nodes.push(...renderToolBlock(item, block, slots));
|
|
2057
|
+
continue;
|
|
2058
|
+
}
|
|
2059
|
+
if (block.kind === "ui" && slots.renderUi) {
|
|
2060
|
+
nodes.push(/* @__PURE__ */ React3.createElement("div", {
|
|
2061
|
+
key: block.key,
|
|
2062
|
+
"data-slot": "ui",
|
|
2063
|
+
"data-component": block.component
|
|
2064
|
+
}, slots.renderUi(block)));
|
|
1833
2065
|
}
|
|
1834
2066
|
}
|
|
1835
2067
|
return nodes;
|
|
@@ -1937,7 +2169,7 @@ function joinClasses(...entries) {
|
|
|
1937
2169
|
__name(joinClasses, "joinClasses");
|
|
1938
2170
|
|
|
1939
2171
|
// src/components/message-list.tsx
|
|
1940
|
-
function MessageList({ messages, status, renderToolPart, renderToolGroup, renderText, renderReasoning, renderFiles, reasoningLabel, getMeta, onFork, editable, onEditSubmit, regeneratable, onRegenerate, getUsage, getCreatedAt, emptyState, typingIndicator, followUps, onFollowUpClick, error, onRetry, classNames }) {
|
|
2172
|
+
function MessageList({ messages, status, renderToolPart, renderToolGroup, renderText, renderReasoning, renderFiles, renderUi, reasoningLabel, getMeta, onFork, editable, onEditSubmit, regeneratable, onRegenerate, getUsage, getCreatedAt, emptyState, typingIndicator, followUps, onFollowUpClick, error, onRetry, classNames }) {
|
|
1941
2173
|
const transcript = useChatTranscript({
|
|
1942
2174
|
messages,
|
|
1943
2175
|
status,
|
|
@@ -1987,6 +2219,9 @@ function MessageList({ messages, status, renderToolPart, renderToolGroup, render
|
|
|
1987
2219
|
...renderFiles ? {
|
|
1988
2220
|
renderFiles
|
|
1989
2221
|
} : {},
|
|
2222
|
+
...renderUi ? {
|
|
2223
|
+
renderUi
|
|
2224
|
+
} : {},
|
|
1990
2225
|
...reasoningLabel !== void 0 ? {
|
|
1991
2226
|
reasoningLabel
|
|
1992
2227
|
} : {},
|
|
@@ -2160,18 +2395,18 @@ function toItem(entry) {
|
|
|
2160
2395
|
__name(toItem, "toItem");
|
|
2161
2396
|
|
|
2162
2397
|
// src/composer/use-composer-autocomplete.ts
|
|
2163
|
-
import { useCallback as useCallback4, useEffect as
|
|
2398
|
+
import { useCallback as useCallback4, useEffect as useEffect6, useId, useLayoutEffect, useMemo as useMemo2, useRef as useRef5, useState as useState6 } from "react";
|
|
2164
2399
|
function useComposerAutocomplete(options) {
|
|
2165
2400
|
const { value, sources, acceptOnTab = true } = options;
|
|
2166
|
-
const latest =
|
|
2401
|
+
const latest = useRef5(options);
|
|
2167
2402
|
latest.current = options;
|
|
2168
|
-
const inputRef =
|
|
2169
|
-
const [caret, setCaret] =
|
|
2170
|
-
const [items, setItems] =
|
|
2171
|
-
const [isLoading, setLoading] =
|
|
2172
|
-
const [error, setError] =
|
|
2173
|
-
const [activeIndex, setActiveIndex] =
|
|
2174
|
-
const [dismissedIndex, setDismissedIndex] =
|
|
2403
|
+
const inputRef = useRef5(null);
|
|
2404
|
+
const [caret, setCaret] = useState6(value.length);
|
|
2405
|
+
const [items, setItems] = useState6([]);
|
|
2406
|
+
const [isLoading, setLoading] = useState6(false);
|
|
2407
|
+
const [error, setError] = useState6(null);
|
|
2408
|
+
const [activeIndex, setActiveIndex] = useState6(0);
|
|
2409
|
+
const [dismissedIndex, setDismissedIndex] = useState6(null);
|
|
2175
2410
|
const safeCaret = Math.min(caret, value.length);
|
|
2176
2411
|
const match = useMemo2(() => findActiveTrigger(value, safeCaret, sources), [
|
|
2177
2412
|
value,
|
|
@@ -2179,16 +2414,16 @@ function useComposerAutocomplete(options) {
|
|
|
2179
2414
|
sources
|
|
2180
2415
|
]);
|
|
2181
2416
|
const isActive = match !== null && dismissedIndex !== match.index;
|
|
2182
|
-
const matchRef =
|
|
2417
|
+
const matchRef = useRef5(match);
|
|
2183
2418
|
matchRef.current = match;
|
|
2184
|
-
const caretRef =
|
|
2419
|
+
const caretRef = useRef5(safeCaret);
|
|
2185
2420
|
caretRef.current = safeCaret;
|
|
2186
|
-
const itemsRef =
|
|
2421
|
+
const itemsRef = useRef5(items);
|
|
2187
2422
|
itemsRef.current = items;
|
|
2188
|
-
const activeIndexRef =
|
|
2423
|
+
const activeIndexRef = useRef5(activeIndex);
|
|
2189
2424
|
activeIndexRef.current = activeIndex;
|
|
2190
2425
|
const requestKey = isActive && match ? `${match.source.id}\0${match.query}` : null;
|
|
2191
|
-
|
|
2426
|
+
useEffect6(() => {
|
|
2192
2427
|
const current = matchRef.current;
|
|
2193
2428
|
if (requestKey === null || current === null) {
|
|
2194
2429
|
setItems([]);
|
|
@@ -2253,7 +2488,7 @@ function useComposerAutocomplete(options) {
|
|
|
2253
2488
|
const current = matchRef.current;
|
|
2254
2489
|
if (current) setDismissedIndex(current.index);
|
|
2255
2490
|
}, []);
|
|
2256
|
-
const pendingCaret =
|
|
2491
|
+
const pendingCaret = useRef5(null);
|
|
2257
2492
|
const accept = useCallback4((item) => {
|
|
2258
2493
|
const current = matchRef.current;
|
|
2259
2494
|
if (!current) return;
|
|
@@ -2418,6 +2653,16 @@ function refusalReason(result) {
|
|
|
2418
2653
|
__name(refusalReason, "refusalReason");
|
|
2419
2654
|
function storedMessageToUiMessage(message) {
|
|
2420
2655
|
const parts = [];
|
|
2656
|
+
if (message.reasoning) {
|
|
2657
|
+
parts.push({
|
|
2658
|
+
type: "reasoning",
|
|
2659
|
+
text: message.reasoning,
|
|
2660
|
+
state: "done",
|
|
2661
|
+
...message.reasoningMs !== void 0 ? {
|
|
2662
|
+
providerMetadata: reasoningDurationMetadata(message.reasoningMs)
|
|
2663
|
+
} : {}
|
|
2664
|
+
});
|
|
2665
|
+
}
|
|
2421
2666
|
if (message.content) {
|
|
2422
2667
|
parts.push({
|
|
2423
2668
|
type: "text",
|
|
@@ -2432,6 +2677,20 @@ function storedMessageToUiMessage(message) {
|
|
|
2432
2677
|
url: attachment.url
|
|
2433
2678
|
});
|
|
2434
2679
|
}
|
|
2680
|
+
for (const component of message.ui ?? []) {
|
|
2681
|
+
parts.push({
|
|
2682
|
+
type: "data-ui",
|
|
2683
|
+
id: component.id,
|
|
2684
|
+
data: {
|
|
2685
|
+
id: component.id,
|
|
2686
|
+
component: component.component,
|
|
2687
|
+
props: component.props,
|
|
2688
|
+
...component.version !== void 0 ? {
|
|
2689
|
+
version: component.version
|
|
2690
|
+
} : {}
|
|
2691
|
+
}
|
|
2692
|
+
});
|
|
2693
|
+
}
|
|
2435
2694
|
for (const call of message.toolCalls ?? []) {
|
|
2436
2695
|
const result = message.toolResults?.find((candidate) => candidate.id === call.id);
|
|
2437
2696
|
const toolKind2 = call.kind;
|
|
@@ -2534,19 +2793,19 @@ __name(sumUsage, "sumUsage");
|
|
|
2534
2793
|
|
|
2535
2794
|
// src/use-agent-chat.ts
|
|
2536
2795
|
import { useChat } from "@ai-sdk/react";
|
|
2537
|
-
import { useCallback as useCallback5, useEffect as
|
|
2796
|
+
import { useCallback as useCallback5, useEffect as useEffect7, useMemo as useMemo3, useRef as useRef6, useState as useState7 } from "react";
|
|
2538
2797
|
function useAgentChat(options) {
|
|
2539
|
-
const latest =
|
|
2798
|
+
const latest = useRef6(options);
|
|
2540
2799
|
latest.current = options;
|
|
2541
|
-
const [runId, setRunId] =
|
|
2542
|
-
const runIdRef =
|
|
2800
|
+
const [runId, setRunId] = useState7(options.resumeRunId);
|
|
2801
|
+
const runIdRef = useRef6(runId);
|
|
2543
2802
|
runIdRef.current = runId;
|
|
2544
|
-
const settlingRunIdRef =
|
|
2545
|
-
const autoResumeRunIdRef =
|
|
2546
|
-
const [autoResume, setAutoResume] =
|
|
2547
|
-
const [activeRunId, setActiveRunId] =
|
|
2548
|
-
const regenerateNext =
|
|
2549
|
-
const createdThreadId =
|
|
2803
|
+
const settlingRunIdRef = useRef6(void 0);
|
|
2804
|
+
const autoResumeRunIdRef = useRef6(void 0);
|
|
2805
|
+
const [autoResume, setAutoResume] = useState7(false);
|
|
2806
|
+
const [activeRunId, setActiveRunId] = useState7(null);
|
|
2807
|
+
const regenerateNext = useRef6(false);
|
|
2808
|
+
const createdThreadId = useRef6(void 0);
|
|
2550
2809
|
const client = useMemo3(() => {
|
|
2551
2810
|
if (options.client) return options.client;
|
|
2552
2811
|
return new AgentClient({
|
|
@@ -2562,7 +2821,7 @@ function useAgentChat(options) {
|
|
|
2562
2821
|
getHeaders: /* @__PURE__ */ __name(async () => mergeHeaders(latest.current), "getHeaders")
|
|
2563
2822
|
});
|
|
2564
2823
|
}, []);
|
|
2565
|
-
|
|
2824
|
+
useEffect7(() => {
|
|
2566
2825
|
if (!options.resume || options.threadId === void 0) return;
|
|
2567
2826
|
let cancelled = false;
|
|
2568
2827
|
const threadId = options.threadId;
|
|
@@ -2631,7 +2890,7 @@ function useAgentChat(options) {
|
|
|
2631
2890
|
}, "onAttemptStart")
|
|
2632
2891
|
});
|
|
2633
2892
|
}, []);
|
|
2634
|
-
const backgroundRef =
|
|
2893
|
+
const backgroundRef = useRef6(() => Promise.resolve());
|
|
2635
2894
|
const chat = useChat({
|
|
2636
2895
|
transport,
|
|
2637
2896
|
resume: options.resumeRunId !== void 0 || autoResume,
|
|
@@ -2641,6 +2900,13 @@ function useAgentChat(options) {
|
|
|
2641
2900
|
...options.initialMessages !== void 0 ? {
|
|
2642
2901
|
messages: options.initialMessages
|
|
2643
2902
|
} : {},
|
|
2903
|
+
onData: /* @__PURE__ */ __name((part) => {
|
|
2904
|
+
latest.current.onData?.(part);
|
|
2905
|
+
if (part.type === "data-title") {
|
|
2906
|
+
const title = part.data?.title;
|
|
2907
|
+
if (typeof title === "string") latest.current.onTitle?.(title);
|
|
2908
|
+
}
|
|
2909
|
+
}, "onData"),
|
|
2644
2910
|
onFinish: /* @__PURE__ */ __name(({ isError }) => {
|
|
2645
2911
|
latest.current.onFinish?.();
|
|
2646
2912
|
if (latest.current.background === true) {
|
|
@@ -2655,9 +2921,9 @@ function useAgentChat(options) {
|
|
|
2655
2921
|
}
|
|
2656
2922
|
}, "onFinish")
|
|
2657
2923
|
});
|
|
2658
|
-
const chatRef =
|
|
2924
|
+
const chatRef = useRef6(chat);
|
|
2659
2925
|
chatRef.current = chat;
|
|
2660
|
-
const turnInFlight =
|
|
2926
|
+
const turnInFlight = useRef6(false);
|
|
2661
2927
|
const isTurnInFlight = useCallback5(() => turnInFlight.current || transport.isAttemptLive, [
|
|
2662
2928
|
transport
|
|
2663
2929
|
]);
|
|
@@ -2677,9 +2943,9 @@ function useAgentChat(options) {
|
|
|
2677
2943
|
toolCallId,
|
|
2678
2944
|
output
|
|
2679
2945
|
}), []);
|
|
2680
|
-
const [threads, setThreads] =
|
|
2681
|
-
const [quota, setQuota] =
|
|
2682
|
-
const [backgroundRuns, setBackgroundRuns] =
|
|
2946
|
+
const [threads, setThreads] = useState7([]);
|
|
2947
|
+
const [quota, setQuota] = useState7(null);
|
|
2948
|
+
const [backgroundRuns, setBackgroundRuns] = useState7([]);
|
|
2683
2949
|
const refreshBackground = useCallback5(async () => {
|
|
2684
2950
|
const threadId = latest.current.threadId ?? createdThreadId.current;
|
|
2685
2951
|
if (threadId === void 0) {
|
|
@@ -2705,7 +2971,7 @@ function useAgentChat(options) {
|
|
|
2705
2971
|
]);
|
|
2706
2972
|
backgroundRef.current = refreshBackground;
|
|
2707
2973
|
const isWorking = backgroundRuns.some((run) => run.status === "running");
|
|
2708
|
-
|
|
2974
|
+
useEffect7(() => {
|
|
2709
2975
|
if (options.background !== true || options.threadId === void 0) {
|
|
2710
2976
|
return;
|
|
2711
2977
|
}
|
|
@@ -2715,7 +2981,7 @@ function useAgentChat(options) {
|
|
|
2715
2981
|
options.threadId,
|
|
2716
2982
|
refreshBackground
|
|
2717
2983
|
]);
|
|
2718
|
-
|
|
2984
|
+
useEffect7(() => {
|
|
2719
2985
|
const every = latest.current.backgroundPollMs ?? 5e3;
|
|
2720
2986
|
if (latest.current.background !== true || !isWorking || every <= 0) {
|
|
2721
2987
|
return;
|
|
@@ -2888,14 +3154,17 @@ export {
|
|
|
2888
3154
|
extractMessageText,
|
|
2889
3155
|
filterAutocompleteItems,
|
|
2890
3156
|
findActiveTrigger,
|
|
3157
|
+
formatElapsed,
|
|
2891
3158
|
formatRelativeTime,
|
|
2892
3159
|
loadStoredSpeechLang,
|
|
2893
3160
|
persistSpeechLang,
|
|
3161
|
+
readReasoningMs,
|
|
2894
3162
|
storedMessageToUiMessage,
|
|
2895
3163
|
storedThreadToUiMessages,
|
|
2896
3164
|
useAgentChat,
|
|
2897
3165
|
useChatTranscript,
|
|
2898
3166
|
useComposerAutocomplete,
|
|
3167
|
+
useElapsed,
|
|
2899
3168
|
useSpeechRecognition,
|
|
2900
3169
|
useStickToBottom,
|
|
2901
3170
|
useTranscriptItem
|