@agents24/chat-react 0.1.9 → 0.1.10
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 +16 -4
- package/dist/controller-actions.d.ts +45 -0
- package/dist/controller-helpers.d.ts +27 -0
- package/dist/controller.d.ts +2 -7
- package/dist/index.cjs +568 -207
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +511 -157
- package/dist/index.js.map +1 -1
- package/dist/message-lifecycle.d.ts +15 -0
- package/dist/model.d.ts +2 -0
- package/dist/renderers.d.ts +1 -1
- package/dist/sse.d.ts +3 -1
- package/dist/templates/agent-chat-shell.d.ts +13 -1
- package/dist/templates/index.cjs +90 -24
- package/dist/templates/index.cjs.map +1 -1
- package/dist/templates/index.js +88 -23
- package/dist/templates/index.js.map +1 -1
- package/dist/transport.d.ts +14 -0
- package/dist/types.d.ts +61 -4
- package/dist/ui/adapters.d.ts +1 -2
- package/dist/ui/agent-chat-actions.d.ts +16 -0
- package/dist/ui/agent-chat-composer.d.ts +28 -0
- package/dist/ui/agent-chat-message.d.ts +40 -0
- package/dist/ui/agent-response-timeline.d.ts +24 -0
- package/dist/ui/index.cjs +944 -206
- package/dist/ui/index.cjs.map +1 -1
- package/dist/ui/index.d.ts +5 -0
- package/dist/ui/index.js +932 -202
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/mcp-connect-required-card.d.ts +13 -0
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
ChatTransportError: () => ChatTransportError,
|
|
33
34
|
DEFAULT_THREAD_PAGE_SIZE: () => DEFAULT_THREAD_PAGE_SIZE,
|
|
34
35
|
DefaultChatPart: () => DefaultChatPart,
|
|
35
36
|
DefaultToolPart: () => DefaultToolPart,
|
|
@@ -44,21 +45,26 @@ __export(index_exports, {
|
|
|
44
45
|
MessageScroller: () => import_message_scroller2.MessageScroller,
|
|
45
46
|
activeRunIdFromThread: () => activeRunIdFromThread,
|
|
46
47
|
activeRunIdFromThreadDetail: () => activeRunIdFromThreadDetail,
|
|
48
|
+
appendStableStreamingTurn: () => appendStableStreamingTurn,
|
|
47
49
|
assistantTextFromParts: () => assistantTextFromParts,
|
|
48
50
|
assistantTextFromResponseBlocks: () => assistantTextFromResponseBlocks,
|
|
51
|
+
autoAttachRunIdFromThread: () => autoAttachRunIdFromThread,
|
|
49
52
|
compressionFromContextWindow: () => compressionFromContextWindow,
|
|
50
53
|
consumeSseResponse: () => consumeSseResponse,
|
|
51
54
|
createChatId: () => createChatId,
|
|
52
55
|
createFetchChatTransport: () => createFetchChatTransport,
|
|
56
|
+
findStableAssistantMessageIndex: () => findStableAssistantMessageIndex,
|
|
53
57
|
getActiveStreamingTextPartId: () => getActiveStreamingTextPartId,
|
|
54
58
|
hasStaleUnfinishedAssistantCache: () => hasStaleUnfinishedAssistantCache,
|
|
55
59
|
hasUnfinishedAssistantMessage: () => hasUnfinishedAssistantMessage,
|
|
56
60
|
isActiveStreamingTextPart: () => isActiveStreamingTextPart,
|
|
61
|
+
isAutoAttachThreadStatus: () => isAutoAttachThreadStatus,
|
|
57
62
|
isRunningThreadStatus: () => isRunningThreadStatus,
|
|
58
63
|
latestContextWindowFromThread: () => latestContextWindowFromThread,
|
|
59
64
|
mergeContextWindow: () => mergeContextWindow,
|
|
60
65
|
mergeContextWindowUpdate: () => mergeContextWindowUpdate,
|
|
61
66
|
mergeReasoningSteps: () => mergeReasoningSteps,
|
|
67
|
+
mergeStoredThreadsForRefresh: () => mergeStoredThreadsForRefresh,
|
|
62
68
|
normalizeContextCompression: () => normalizeContextCompression,
|
|
63
69
|
normalizeContextWindow: () => normalizeContextWindow,
|
|
64
70
|
parseSseBlock: () => parseSseBlock,
|
|
@@ -71,6 +77,7 @@ __export(index_exports, {
|
|
|
71
77
|
threadPaging: () => threadPaging,
|
|
72
78
|
titleFromMessage: () => titleFromMessage,
|
|
73
79
|
toolStateFromStatus: () => toolStateFromStatus,
|
|
80
|
+
upsertStableAssistantMessage: () => upsertStableAssistantMessage,
|
|
74
81
|
useAgents24ChatController: () => useAgents24ChatController,
|
|
75
82
|
useMessageScroller: () => import_message_scroller2.useMessageScroller,
|
|
76
83
|
useMessageScrollerScrollable: () => import_message_scroller2.useMessageScrollerScrollable,
|
|
@@ -80,7 +87,79 @@ __export(index_exports, {
|
|
|
80
87
|
module.exports = __toCommonJS(index_exports);
|
|
81
88
|
|
|
82
89
|
// src/controller.ts
|
|
90
|
+
var import_react2 = require("react");
|
|
91
|
+
|
|
92
|
+
// src/controller-actions.ts
|
|
83
93
|
var import_react = require("react");
|
|
94
|
+
function useControllerMessageActions(input) {
|
|
95
|
+
const handleCopy = (0, import_react.useCallback)((content, messageId) => {
|
|
96
|
+
navigator.clipboard?.writeText(content);
|
|
97
|
+
input.setCopiedMessageId(messageId);
|
|
98
|
+
setTimeout(() => input.setCopiedMessageId(null), 200);
|
|
99
|
+
}, [input]);
|
|
100
|
+
const handleLike = (0, import_react.useCallback)(async (msg) => {
|
|
101
|
+
const nextLiked = !input.liked[msg.id];
|
|
102
|
+
input.setLiked((prev) => ({ ...prev, [msg.id]: nextLiked }));
|
|
103
|
+
if (nextLiked) input.setDisliked((prev) => ({ ...prev, [msg.id]: false }));
|
|
104
|
+
}, [input]);
|
|
105
|
+
const handleDislike = (0, import_react.useCallback)(async (msg) => {
|
|
106
|
+
const nextDisliked = !input.disliked[msg.id];
|
|
107
|
+
input.setDisliked((prev) => ({ ...prev, [msg.id]: nextDisliked }));
|
|
108
|
+
if (nextDisliked) input.setLiked((prev) => ({ ...prev, [msg.id]: false }));
|
|
109
|
+
}, [input]);
|
|
110
|
+
const handleRetry = (0, import_react.useCallback)(async (msg) => {
|
|
111
|
+
const index = input.messagesRef.current.findIndex((message) => message.id === msg.id);
|
|
112
|
+
if (index <= 0) return;
|
|
113
|
+
const userMessage = input.messagesRef.current[index - 1];
|
|
114
|
+
if (userMessage.role !== "user") return;
|
|
115
|
+
const trimmed = input.messagesRef.current.slice(0, index);
|
|
116
|
+
input.setMessages(trimmed);
|
|
117
|
+
input.messagesRef.current = trimmed;
|
|
118
|
+
if (input.activeThreadIdRef.current) input.persistThread(input.activeThreadIdRef.current, trimmed);
|
|
119
|
+
await input.handleSubmit({ text: userMessage.content, files: userMessage.attachments || [] });
|
|
120
|
+
}, [input]);
|
|
121
|
+
const upsertLiveVoiceMessage = (0, import_react.useCallback)((payload) => {
|
|
122
|
+
const content = payload.content?.trim() ?? "";
|
|
123
|
+
if (!content && !payload.citations?.length && !payload.reasoningSteps?.length) return;
|
|
124
|
+
input.setMessages((prev) => {
|
|
125
|
+
const currentId = input.liveVoiceIdsRef.current[payload.role];
|
|
126
|
+
const index = currentId ? prev.findIndex((message) => message.id === currentId) : -1;
|
|
127
|
+
const nextMessage = {
|
|
128
|
+
id: currentId || input.createId(),
|
|
129
|
+
role: payload.role,
|
|
130
|
+
content,
|
|
131
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
132
|
+
isFinal: Boolean(payload.isFinal),
|
|
133
|
+
isVoice: payload.role === "user",
|
|
134
|
+
parts: content ? [{ id: input.createId(), type: "text", kind: "text", text: content }] : [],
|
|
135
|
+
citations: payload.citations,
|
|
136
|
+
reasoningSteps: payload.reasoningSteps
|
|
137
|
+
};
|
|
138
|
+
const next = index === -1 ? [...prev, nextMessage] : prev.map((message, itemIndex) => itemIndex === index ? { ...message, ...nextMessage } : message);
|
|
139
|
+
input.liveVoiceIdsRef.current[payload.role] = payload.isFinal ? void 0 : nextMessage.id;
|
|
140
|
+
input.messagesRef.current = next;
|
|
141
|
+
if (input.activeThreadIdRef.current) input.persistThread(input.activeThreadIdRef.current, next);
|
|
142
|
+
return next;
|
|
143
|
+
});
|
|
144
|
+
}, [input]);
|
|
145
|
+
const startNewThread = (0, import_react.useCallback)(() => {
|
|
146
|
+
input.detachActiveStream();
|
|
147
|
+
input.requestSeqRef.current += 1;
|
|
148
|
+
input.activeThreadIdRef.current = null;
|
|
149
|
+
input.loadedThreadIdRef.current = null;
|
|
150
|
+
input.nextBeforeTurnIndexRef.current = null;
|
|
151
|
+
input.hasOlderTurnsRef.current = false;
|
|
152
|
+
input.storage.setActiveThreadId?.(null);
|
|
153
|
+
input.onActiveThreadIdChange?.(null);
|
|
154
|
+
input.setMessages([]);
|
|
155
|
+
input.messagesRef.current = [];
|
|
156
|
+
input.setHasOlderTurns(false);
|
|
157
|
+
input.setIsLoadingOlder(false);
|
|
158
|
+
input.setContextStatus(null);
|
|
159
|
+
input.setLoadingHistory(false);
|
|
160
|
+
}, [input]);
|
|
161
|
+
return { handleCopy, handleDislike, handleLike, handleRetry, startNewThread, upsertLiveVoiceMessage };
|
|
162
|
+
}
|
|
84
163
|
|
|
85
164
|
// src/context-window.ts
|
|
86
165
|
var SOURCE_PRIORITY = {
|
|
@@ -203,7 +282,8 @@ function compressionFromContextWindow(contextWindow) {
|
|
|
203
282
|
|
|
204
283
|
// src/model.ts
|
|
205
284
|
var DEFAULT_THREAD_PAGE_SIZE = 5;
|
|
206
|
-
var isRunningThreadStatus = (status) => (/* @__PURE__ */ new Set(["queued", "running", "cancelling"])).has(String(status || "").toLowerCase());
|
|
285
|
+
var isRunningThreadStatus = (status) => (/* @__PURE__ */ new Set(["queued", "running", "cancelling", "paused"])).has(String(status || "").toLowerCase());
|
|
286
|
+
var isAutoAttachThreadStatus = (status) => (/* @__PURE__ */ new Set(["queued", "running", "cancelling"])).has(String(status || "").toLowerCase());
|
|
207
287
|
var createChatId = () => {
|
|
208
288
|
if (typeof crypto !== "undefined" && "randomUUID" in crypto) return crypto.randomUUID();
|
|
209
289
|
return `chat-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
|
|
@@ -369,8 +449,17 @@ var partsFromResponseBlocks = (blocks, fallbackText) => {
|
|
|
369
449
|
});
|
|
370
450
|
return;
|
|
371
451
|
}
|
|
372
|
-
if (block.kind === "
|
|
373
|
-
|
|
452
|
+
if (block.kind === "hitl_request") {
|
|
453
|
+
const hitl = asRecord(block.hitl) || block;
|
|
454
|
+
parts.push({
|
|
455
|
+
id,
|
|
456
|
+
type: "hitl",
|
|
457
|
+
kind: "hitl",
|
|
458
|
+
hitl,
|
|
459
|
+
interruptId: optionalString(block.interruptId) || optionalString(hitl.interrupt_id) || null,
|
|
460
|
+
hitlKind: optionalString(block.hitlKind) || optionalString(hitl.kind) || null,
|
|
461
|
+
raw: block
|
|
462
|
+
});
|
|
374
463
|
return;
|
|
375
464
|
}
|
|
376
465
|
if (block.kind === "error") {
|
|
@@ -496,6 +585,23 @@ var activeRunIdFromThread = (thread) => {
|
|
|
496
585
|
const lastRunId = hasCamelLastRunId ? thread?.lastRunId : thread?.last_run_id || thread?.lastRunId;
|
|
497
586
|
return lastRunId && isRunningThreadStatus(lastRunStatus) ? String(lastRunId) : null;
|
|
498
587
|
};
|
|
588
|
+
var autoAttachRunIdFromThread = (thread) => {
|
|
589
|
+
const hasCamelActiveRun = Boolean(
|
|
590
|
+
thread && Object.prototype.hasOwnProperty.call(thread, "activeRun")
|
|
591
|
+
);
|
|
592
|
+
const hasCamelLastRunStatus = Boolean(
|
|
593
|
+
thread && Object.prototype.hasOwnProperty.call(thread, "lastRunStatus")
|
|
594
|
+
);
|
|
595
|
+
const hasCamelLastRunId = Boolean(
|
|
596
|
+
thread && Object.prototype.hasOwnProperty.call(thread, "lastRunId")
|
|
597
|
+
);
|
|
598
|
+
const activeRun = hasCamelActiveRun ? thread?.activeRun || null : thread?.active_run || null;
|
|
599
|
+
const lastRunStatus = hasCamelLastRunStatus ? thread?.lastRunStatus || null : thread?.last_run_status || thread?.lastRunStatus || null;
|
|
600
|
+
const activeRunId = activeRun?.run_id ? String(activeRun.run_id) : "";
|
|
601
|
+
if (activeRunId && isAutoAttachThreadStatus(activeRun?.status || lastRunStatus)) return activeRunId;
|
|
602
|
+
const lastRunId = hasCamelLastRunId ? thread?.lastRunId : thread?.last_run_id || thread?.lastRunId;
|
|
603
|
+
return lastRunId && isAutoAttachThreadStatus(lastRunStatus) ? String(lastRunId) : null;
|
|
604
|
+
};
|
|
499
605
|
var hasUnfinishedAssistantMessage = (messages) => Boolean(messages?.some((message) => message.role === "assistant" && message.isFinal === false));
|
|
500
606
|
var hasStaleUnfinishedAssistantCache = (thread) => hasUnfinishedAssistantMessage(thread?.messages) && !activeRunIdFromThread(thread);
|
|
501
607
|
var activeRunIdFromThreadDetail = (thread) => {
|
|
@@ -505,7 +611,7 @@ var activeRunIdFromThreadDetail = (thread) => {
|
|
|
505
611
|
return runningTurn?.run_id ? String(runningTurn.run_id) : null;
|
|
506
612
|
};
|
|
507
613
|
|
|
508
|
-
// src/controller.ts
|
|
614
|
+
// src/controller-helpers.ts
|
|
509
615
|
var threadSummaryToStored = (thread) => ({
|
|
510
616
|
...thread,
|
|
511
617
|
id: String(thread.id),
|
|
@@ -514,6 +620,121 @@ var threadSummaryToStored = (thread) => ({
|
|
|
514
620
|
messages: [],
|
|
515
621
|
isHydrated: false
|
|
516
622
|
});
|
|
623
|
+
var isThreadNotFoundError = (error) => {
|
|
624
|
+
if (!error || typeof error !== "object" || !("status" in error)) return false;
|
|
625
|
+
return Number(error.status) === 404;
|
|
626
|
+
};
|
|
627
|
+
var isAbortError = (error) => {
|
|
628
|
+
if (!error || typeof error !== "object") return false;
|
|
629
|
+
const maybe = error;
|
|
630
|
+
return maybe.name === "AbortError" || String(maybe.message || "").toLowerCase().includes("aborted");
|
|
631
|
+
};
|
|
632
|
+
var abortDetachedStream = (controller) => {
|
|
633
|
+
if (!controller || controller.signal.aborted) return;
|
|
634
|
+
try {
|
|
635
|
+
const reason = typeof DOMException !== "undefined" ? new DOMException("Chat stream detached.", "AbortError") : new Error("Chat stream detached.");
|
|
636
|
+
controller.abort(reason);
|
|
637
|
+
} catch {
|
|
638
|
+
}
|
|
639
|
+
};
|
|
640
|
+
var hasRunState = (thread) => Boolean(
|
|
641
|
+
thread.active_run || thread.activeRun || thread.last_run_id || thread.lastRunId || thread.last_run_status || thread.lastRunStatus || thread.isRunning
|
|
642
|
+
);
|
|
643
|
+
var mergeStoredThreadsForRefresh = (currentThreads, serverThreads) => {
|
|
644
|
+
const currentById = new Map(currentThreads.map((thread) => [thread.id, thread]));
|
|
645
|
+
const serverIds = new Set(serverThreads.map((thread) => thread.id));
|
|
646
|
+
const mergedServerThreads = serverThreads.map((serverThread) => {
|
|
647
|
+
const current = currentById.get(serverThread.id);
|
|
648
|
+
if (!current) return serverThread;
|
|
649
|
+
const incomingHasRunState = hasRunState(serverThread);
|
|
650
|
+
return {
|
|
651
|
+
...current,
|
|
652
|
+
...serverThread,
|
|
653
|
+
messages: current.messages || [],
|
|
654
|
+
isHydrated: current.isHydrated,
|
|
655
|
+
hasOlderTurns: current.hasOlderTurns,
|
|
656
|
+
nextBeforeTurnIndex: current.nextBeforeTurnIndex,
|
|
657
|
+
active_run: incomingHasRunState ? serverThread.active_run : current.active_run,
|
|
658
|
+
activeRun: incomingHasRunState ? serverThread.activeRun : current.activeRun,
|
|
659
|
+
last_run_id: incomingHasRunState ? serverThread.last_run_id : current.last_run_id,
|
|
660
|
+
lastRunId: incomingHasRunState ? serverThread.lastRunId : current.lastRunId,
|
|
661
|
+
last_run_status: incomingHasRunState ? serverThread.last_run_status : current.last_run_status,
|
|
662
|
+
lastRunStatus: incomingHasRunState ? serverThread.lastRunStatus : current.lastRunStatus,
|
|
663
|
+
lastEventSeq: incomingHasRunState ? serverThread.lastEventSeq : current.lastEventSeq,
|
|
664
|
+
isRunning: incomingHasRunState ? serverThread.isRunning : current.isRunning
|
|
665
|
+
};
|
|
666
|
+
});
|
|
667
|
+
const localOnlyThreads = currentThreads.filter((thread) => {
|
|
668
|
+
if (serverIds.has(thread.id)) return false;
|
|
669
|
+
return Boolean(thread.isHydrated || thread.messages?.length || thread.isRunning || thread.activeRun || thread.active_run);
|
|
670
|
+
});
|
|
671
|
+
return [...mergedServerThreads, ...localOnlyThreads];
|
|
672
|
+
};
|
|
673
|
+
var stableStringify = (value) => JSON.stringify(value ?? null);
|
|
674
|
+
var sameStoredThread = (left, right) => {
|
|
675
|
+
if (left === right) return true;
|
|
676
|
+
if (!left || !right) return false;
|
|
677
|
+
return stableStringify(left) === stableStringify(right);
|
|
678
|
+
};
|
|
679
|
+
var applyThreadSummaryEvent = (currentThreads, event) => {
|
|
680
|
+
if (event.event === "snapshot_required") return currentThreads;
|
|
681
|
+
if (event.event === "thread.deleted") {
|
|
682
|
+
const next2 = currentThreads.filter((thread) => thread.id !== event.thread_id);
|
|
683
|
+
return next2.length === currentThreads.length ? currentThreads : next2;
|
|
684
|
+
}
|
|
685
|
+
const incoming = threadSummaryToStored(event.thread);
|
|
686
|
+
const index = currentThreads.findIndex((thread) => thread.id === incoming.id);
|
|
687
|
+
const sortByActivity = (threads) => [...threads].sort((a, b) => {
|
|
688
|
+
const left = Date.parse(String(a.updated_at || a.last_activity_at || a.created_at || ""));
|
|
689
|
+
const right = Date.parse(String(b.updated_at || b.last_activity_at || b.created_at || ""));
|
|
690
|
+
return (Number.isFinite(right) ? right : 0) - (Number.isFinite(left) ? left : 0);
|
|
691
|
+
});
|
|
692
|
+
if (index === -1) return sortByActivity([...currentThreads, incoming]);
|
|
693
|
+
const [merged] = mergeStoredThreadsForRefresh([currentThreads[index]], [incoming]);
|
|
694
|
+
if (sameStoredThread(currentThreads[index], merged)) return currentThreads;
|
|
695
|
+
const next = [...currentThreads];
|
|
696
|
+
next[index] = merged;
|
|
697
|
+
return sortByActivity(next);
|
|
698
|
+
};
|
|
699
|
+
|
|
700
|
+
// src/message-lifecycle.ts
|
|
701
|
+
function findStableAssistantMessageIndex(messages, input) {
|
|
702
|
+
return messages.findIndex(
|
|
703
|
+
(message) => message.role === "assistant" && (input.messageId && message.id === input.messageId || Boolean(input.runId && message.runId === input.runId))
|
|
704
|
+
);
|
|
705
|
+
}
|
|
706
|
+
function appendStableStreamingTurn(messages, userMessage, assistantMessage) {
|
|
707
|
+
const next = [...messages];
|
|
708
|
+
if (!next.some((message) => message.id === userMessage.id)) {
|
|
709
|
+
next.push(userMessage);
|
|
710
|
+
}
|
|
711
|
+
if (!next.some(
|
|
712
|
+
(message) => message.id === assistantMessage.id || Boolean(
|
|
713
|
+
assistantMessage.runId && message.role === "assistant" && message.runId === assistantMessage.runId
|
|
714
|
+
)
|
|
715
|
+
)) {
|
|
716
|
+
next.push(assistantMessage);
|
|
717
|
+
}
|
|
718
|
+
return next;
|
|
719
|
+
}
|
|
720
|
+
function upsertStableAssistantMessage(messages, input) {
|
|
721
|
+
const next = [...messages];
|
|
722
|
+
for (const baseMessage of input.baseMessages || []) {
|
|
723
|
+
const matchesTarget = baseMessage.role === "assistant" && (input.messageId && baseMessage.id === input.messageId || Boolean(input.runId && baseMessage.runId === input.runId));
|
|
724
|
+
if (!matchesTarget && !next.some((message) => message.id === baseMessage.id)) {
|
|
725
|
+
next.push(baseMessage);
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
const index = findStableAssistantMessageIndex(next, input);
|
|
729
|
+
if (index === -1) {
|
|
730
|
+
next.push(input.create());
|
|
731
|
+
return next;
|
|
732
|
+
}
|
|
733
|
+
next[index] = input.update(next[index]);
|
|
734
|
+
return next;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
// src/controller.ts
|
|
517
738
|
function useAgents24ChatController({
|
|
518
739
|
transport,
|
|
519
740
|
storage,
|
|
@@ -529,56 +750,59 @@ function useAgents24ChatController({
|
|
|
529
750
|
}) {
|
|
530
751
|
const activeThreadId = controlledActiveThreadId ?? storage.getActiveThreadId?.() ?? null;
|
|
531
752
|
const initialCached = activeThreadId ? storage.getThread(activeThreadId) : void 0;
|
|
532
|
-
const [messages, setMessages] = (0,
|
|
533
|
-
const [isLoading, setIsLoading] = (0,
|
|
534
|
-
const [isLoadingHistory, setIsLoadingHistory] = (0,
|
|
535
|
-
const [isLoadingOlder, setIsLoadingOlder] = (0,
|
|
536
|
-
const [hasOlderTurns, setHasOlderTurns] = (0,
|
|
537
|
-
const [streamingContent, setStreamingContent] = (0,
|
|
538
|
-
const [streamingMessageId, setStreamingMessageId] = (0,
|
|
539
|
-
const [contextStatus, setContextStatus] = (0,
|
|
540
|
-
const [currentReasoning, setCurrentReasoning] = (0,
|
|
541
|
-
const [liked, setLiked] = (0,
|
|
542
|
-
const [disliked, setDisliked] = (0,
|
|
543
|
-
const [copiedMessageId, setCopiedMessageId] = (0,
|
|
544
|
-
const [lastThinkingDurationMs, setLastThinkingDurationMs] = (0,
|
|
545
|
-
const [threads, setThreads] = (0,
|
|
546
|
-
const [isRefreshingThreads, setIsRefreshingThreads] = (0,
|
|
547
|
-
const [
|
|
548
|
-
const
|
|
549
|
-
const
|
|
550
|
-
const
|
|
551
|
-
const
|
|
552
|
-
const
|
|
553
|
-
const
|
|
554
|
-
const
|
|
555
|
-
const
|
|
556
|
-
const
|
|
557
|
-
const
|
|
558
|
-
const
|
|
559
|
-
const
|
|
560
|
-
const
|
|
561
|
-
const
|
|
562
|
-
const
|
|
563
|
-
const
|
|
564
|
-
const
|
|
753
|
+
const [messages, setMessages] = (0, import_react2.useState)(() => initialCached?.messages || []);
|
|
754
|
+
const [isLoading, setIsLoading] = (0, import_react2.useState)(false);
|
|
755
|
+
const [isLoadingHistory, setIsLoadingHistory] = (0, import_react2.useState)(() => Boolean(activeThreadId) && !initialCached?.messages?.length);
|
|
756
|
+
const [isLoadingOlder, setIsLoadingOlder] = (0, import_react2.useState)(false);
|
|
757
|
+
const [hasOlderTurns, setHasOlderTurns] = (0, import_react2.useState)(Boolean(initialCached?.hasOlderTurns));
|
|
758
|
+
const [streamingContent, setStreamingContent] = (0, import_react2.useState)("");
|
|
759
|
+
const [streamingMessageId, setStreamingMessageId] = (0, import_react2.useState)(null);
|
|
760
|
+
const [contextStatus, setContextStatus] = (0, import_react2.useState)(null);
|
|
761
|
+
const [currentReasoning, setCurrentReasoning] = (0, import_react2.useState)([]);
|
|
762
|
+
const [liked, setLiked] = (0, import_react2.useState)({});
|
|
763
|
+
const [disliked, setDisliked] = (0, import_react2.useState)({});
|
|
764
|
+
const [copiedMessageId, setCopiedMessageId] = (0, import_react2.useState)(null);
|
|
765
|
+
const [lastThinkingDurationMs, setLastThinkingDurationMs] = (0, import_react2.useState)(null);
|
|
766
|
+
const [threads, setThreads] = (0, import_react2.useState)(() => storage.listThreads());
|
|
767
|
+
const [isRefreshingThreads, setIsRefreshingThreads] = (0, import_react2.useState)(false);
|
|
768
|
+
const [isSelectingThread, setIsSelectingThread] = (0, import_react2.useState)(false);
|
|
769
|
+
const [activeRunId, setActiveRunId] = (0, import_react2.useState)(null);
|
|
770
|
+
const textareaRef = (0, import_react2.useRef)(null);
|
|
771
|
+
const activeThreadIdRef = (0, import_react2.useRef)(activeThreadId);
|
|
772
|
+
const messagesRef = (0, import_react2.useRef)(messages);
|
|
773
|
+
const nextBeforeTurnIndexRef = (0, import_react2.useRef)(initialCached?.nextBeforeTurnIndex ?? null);
|
|
774
|
+
const hasOlderTurnsRef = (0, import_react2.useRef)(Boolean(initialCached?.hasOlderTurns));
|
|
775
|
+
const isLoadingOlderRef = (0, import_react2.useRef)(false);
|
|
776
|
+
const loadedThreadIdRef = (0, import_react2.useRef)(initialCached?.messages?.length ? activeThreadId : null);
|
|
777
|
+
const requestSeqRef = (0, import_react2.useRef)(0);
|
|
778
|
+
const isLoadingHistoryRef = (0, import_react2.useRef)(isLoadingHistory);
|
|
779
|
+
const activeRunIdRef = (0, import_react2.useRef)(null);
|
|
780
|
+
const reattachedRunIdRef = (0, import_react2.useRef)(null);
|
|
781
|
+
const abortControllerRef = (0, import_react2.useRef)(null);
|
|
782
|
+
const streamingContentRef = (0, import_react2.useRef)("");
|
|
783
|
+
const streamingMessageIdRef = (0, import_react2.useRef)(null);
|
|
784
|
+
const reasoningRef = (0, import_react2.useRef)([]);
|
|
785
|
+
const liveVoiceIdsRef = (0, import_react2.useRef)({});
|
|
786
|
+
const refreshSeqRef = (0, import_react2.useRef)(0);
|
|
787
|
+
const threadEventsCursorRef = (0, import_react2.useRef)(null);
|
|
788
|
+
const setActiveRunIdValue = (0, import_react2.useCallback)((runId) => {
|
|
565
789
|
activeRunIdRef.current = runId;
|
|
566
790
|
setActiveRunId(runId);
|
|
567
791
|
}, []);
|
|
568
|
-
const syncThreadsFromStorage = (0,
|
|
792
|
+
const syncThreadsFromStorage = (0, import_react2.useCallback)(() => {
|
|
569
793
|
setThreads(storage.listThreads());
|
|
570
794
|
}, [storage]);
|
|
571
|
-
const upsertStoredThread = (0,
|
|
795
|
+
const upsertStoredThread = (0, import_react2.useCallback)(
|
|
572
796
|
(thread) => {
|
|
573
797
|
storage.upsertThread(thread);
|
|
574
798
|
syncThreadsFromStorage();
|
|
575
799
|
},
|
|
576
800
|
[storage, syncThreadsFromStorage]
|
|
577
801
|
);
|
|
578
|
-
(0,
|
|
802
|
+
(0, import_react2.useEffect)(() => {
|
|
579
803
|
messagesRef.current = messages;
|
|
580
804
|
}, [messages]);
|
|
581
|
-
const persistThread = (0,
|
|
805
|
+
const persistThread = (0, import_react2.useCallback)(
|
|
582
806
|
(threadId, nextMessages, paging, options) => {
|
|
583
807
|
const existing = storage.getThread(threadId);
|
|
584
808
|
const firstUser = nextMessages.find((message) => message.role === "user");
|
|
@@ -595,7 +819,7 @@ function useAgents24ChatController({
|
|
|
595
819
|
},
|
|
596
820
|
[storage, upsertStoredThread]
|
|
597
821
|
);
|
|
598
|
-
const markThreadRunStatus = (0,
|
|
822
|
+
const markThreadRunStatus = (0, import_react2.useCallback)(
|
|
599
823
|
(threadId, runId, status, lastEventSeq) => {
|
|
600
824
|
const existing = storage.getThread(threadId);
|
|
601
825
|
if (!existing || !runId) return;
|
|
@@ -625,18 +849,20 @@ function useAgents24ChatController({
|
|
|
625
849
|
},
|
|
626
850
|
[storage, upsertStoredThread]
|
|
627
851
|
);
|
|
628
|
-
const refresh = (0,
|
|
852
|
+
const refresh = (0, import_react2.useCallback)(async () => {
|
|
853
|
+
const seq = ++refreshSeqRef.current;
|
|
629
854
|
setIsRefreshingThreads(true);
|
|
630
855
|
try {
|
|
631
856
|
const data = await transport.listThreads();
|
|
857
|
+
if (seq !== refreshSeqRef.current) return;
|
|
632
858
|
const nextThreads = (data.items || []).map((item) => threadSummaryToStored(item));
|
|
633
|
-
storage.setThreads(nextThreads);
|
|
859
|
+
storage.setThreads(mergeStoredThreadsForRefresh(storage.listThreads(), nextThreads));
|
|
634
860
|
setThreads(storage.listThreads());
|
|
635
861
|
} finally {
|
|
636
|
-
setIsRefreshingThreads(false);
|
|
862
|
+
if (seq === refreshSeqRef.current) setIsRefreshingThreads(false);
|
|
637
863
|
}
|
|
638
864
|
}, [storage, transport]);
|
|
639
|
-
const applyThreadId = (0,
|
|
865
|
+
const applyThreadId = (0, import_react2.useCallback)(
|
|
640
866
|
(threadId, baseMessages) => {
|
|
641
867
|
if (!threadId || activeThreadIdRef.current === threadId) return;
|
|
642
868
|
activeThreadIdRef.current = threadId;
|
|
@@ -650,18 +876,18 @@ function useAgents24ChatController({
|
|
|
650
876
|
streamingContentRef.current = value;
|
|
651
877
|
setStreamingContent(value);
|
|
652
878
|
};
|
|
653
|
-
const setLoadingHistory = (0,
|
|
879
|
+
const setLoadingHistory = (0, import_react2.useCallback)((value) => {
|
|
654
880
|
isLoadingHistoryRef.current = value;
|
|
655
881
|
setIsLoadingHistory(value);
|
|
656
882
|
}, []);
|
|
657
|
-
const setReasoningSteps = (0,
|
|
883
|
+
const setReasoningSteps = (0, import_react2.useCallback)((value) => {
|
|
658
884
|
reasoningRef.current = value || [];
|
|
659
885
|
setCurrentReasoning(value || []);
|
|
660
886
|
}, []);
|
|
661
|
-
const detachActiveStream = (0,
|
|
887
|
+
const detachActiveStream = (0, import_react2.useCallback)(() => {
|
|
662
888
|
const controller = abortControllerRef.current;
|
|
663
889
|
abortControllerRef.current = null;
|
|
664
|
-
controller
|
|
890
|
+
abortDetachedStream(controller);
|
|
665
891
|
setActiveRunIdValue(null);
|
|
666
892
|
reattachedRunIdRef.current = null;
|
|
667
893
|
streamingMessageIdRef.current = null;
|
|
@@ -672,21 +898,36 @@ function useAgents24ChatController({
|
|
|
672
898
|
setStreamingContent("");
|
|
673
899
|
setCurrentReasoning([]);
|
|
674
900
|
}, [setActiveRunIdValue]);
|
|
675
|
-
const
|
|
901
|
+
const clearMissingThread = (0, import_react2.useCallback)(
|
|
902
|
+
(threadId) => {
|
|
903
|
+
storage.deleteThread?.(threadId);
|
|
904
|
+
syncThreadsFromStorage();
|
|
905
|
+
if (activeThreadIdRef.current !== threadId) return;
|
|
906
|
+
requestSeqRef.current += 1;
|
|
907
|
+
detachActiveStream();
|
|
908
|
+
activeThreadIdRef.current = null;
|
|
909
|
+
loadedThreadIdRef.current = null;
|
|
910
|
+
nextBeforeTurnIndexRef.current = null;
|
|
911
|
+
hasOlderTurnsRef.current = false;
|
|
912
|
+
storage.setActiveThreadId?.(null);
|
|
913
|
+
onActiveThreadIdChange?.(null);
|
|
914
|
+
setMessages([]);
|
|
915
|
+
messagesRef.current = [];
|
|
916
|
+
setHasOlderTurns(false);
|
|
917
|
+
setIsLoadingOlder(false);
|
|
918
|
+
setContextStatus(null);
|
|
919
|
+
setLoadingHistory(false);
|
|
920
|
+
},
|
|
921
|
+
[detachActiveStream, onActiveThreadIdChange, setLoadingHistory, storage, syncThreadsFromStorage]
|
|
922
|
+
);
|
|
923
|
+
const setLiveAssistantMessage = (0, import_react2.useCallback)(
|
|
676
924
|
(input) => {
|
|
677
925
|
setMessages((prev) => {
|
|
678
|
-
const
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
(input.baseMessages || []).forEach((message) => {
|
|
684
|
-
const isSameAssistant = message.id === input.messageId || Boolean(input.runId && message.role === "assistant" && message.runId === input.runId);
|
|
685
|
-
if (!isSameAssistant && !next2.some((item) => item.id === message.id)) {
|
|
686
|
-
next2.push(message);
|
|
687
|
-
}
|
|
688
|
-
});
|
|
689
|
-
next2.push({
|
|
926
|
+
const next = upsertStableAssistantMessage(prev, {
|
|
927
|
+
baseMessages: input.baseMessages,
|
|
928
|
+
messageId: input.messageId,
|
|
929
|
+
runId: input.runId,
|
|
930
|
+
create: () => ({
|
|
690
931
|
id: input.messageId,
|
|
691
932
|
role: "assistant",
|
|
692
933
|
runId: input.runId ?? null,
|
|
@@ -695,26 +936,23 @@ function useAgents24ChatController({
|
|
|
695
936
|
reasoningSteps: input.reasoning,
|
|
696
937
|
isFinal: false,
|
|
697
938
|
parts: input.parts || []
|
|
698
|
-
})
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
isFinal: false,
|
|
709
|
-
parts: input.parts ?? next[index].parts
|
|
710
|
-
};
|
|
939
|
+
}),
|
|
940
|
+
update: (message) => ({
|
|
941
|
+
...message,
|
|
942
|
+
runId: input.runId ?? message.runId ?? null,
|
|
943
|
+
content: input.content,
|
|
944
|
+
reasoningSteps: input.reasoning,
|
|
945
|
+
isFinal: false,
|
|
946
|
+
parts: input.parts ?? message.parts
|
|
947
|
+
})
|
|
948
|
+
});
|
|
711
949
|
messagesRef.current = next;
|
|
712
950
|
return next;
|
|
713
951
|
});
|
|
714
952
|
},
|
|
715
953
|
[]
|
|
716
954
|
);
|
|
717
|
-
const finalizeAssistantMessage = (0,
|
|
955
|
+
const finalizeAssistantMessage = (0, import_react2.useCallback)(
|
|
718
956
|
(input) => {
|
|
719
957
|
const content = input.error || input.assistantText.trim();
|
|
720
958
|
if (!content) return input.baseMessages;
|
|
@@ -734,7 +972,17 @@ function useAgents24ChatController({
|
|
|
734
972
|
reasoningSteps: mergeReasoningSteps(input.reasoning, { finalize: true }),
|
|
735
973
|
thinkingDurationMs: input.thinkingDurationMs
|
|
736
974
|
};
|
|
737
|
-
const completed =
|
|
975
|
+
const completed = upsertStableAssistantMessage(input.baseMessages, {
|
|
976
|
+
messageId: input.messageId,
|
|
977
|
+
runId: input.runId,
|
|
978
|
+
create: () => assistant,
|
|
979
|
+
update: (message) => ({
|
|
980
|
+
...message,
|
|
981
|
+
...assistant,
|
|
982
|
+
id: message.id,
|
|
983
|
+
createdAt: message.createdAt
|
|
984
|
+
})
|
|
985
|
+
});
|
|
738
986
|
setMessages(completed);
|
|
739
987
|
messagesRef.current = completed;
|
|
740
988
|
if (input.threadId) {
|
|
@@ -758,7 +1006,7 @@ function useAgents24ChatController({
|
|
|
758
1006
|
},
|
|
759
1007
|
[createId, persistThread, storage, upsertStoredThread]
|
|
760
1008
|
);
|
|
761
|
-
const loadThread = (0,
|
|
1009
|
+
const loadThread = (0, import_react2.useCallback)(
|
|
762
1010
|
async (threadId) => {
|
|
763
1011
|
const seq = ++requestSeqRef.current;
|
|
764
1012
|
setLoadingHistory(true);
|
|
@@ -789,13 +1037,20 @@ function useAgents24ChatController({
|
|
|
789
1037
|
nextBeforeTurnIndex: paging.nextBeforeTurnIndex,
|
|
790
1038
|
updated_at: threadActivityDate(detail)
|
|
791
1039
|
});
|
|
1040
|
+
} catch (error) {
|
|
1041
|
+
if (isAbortError(error)) return;
|
|
1042
|
+
if (isThreadNotFoundError(error)) {
|
|
1043
|
+
clearMissingThread(threadId);
|
|
1044
|
+
return;
|
|
1045
|
+
}
|
|
1046
|
+
throw error;
|
|
792
1047
|
} finally {
|
|
793
|
-
if (activeThreadIdRef.current === threadId) setLoadingHistory(false);
|
|
1048
|
+
if (activeThreadIdRef.current === threadId && seq === requestSeqRef.current) setLoadingHistory(false);
|
|
794
1049
|
}
|
|
795
1050
|
},
|
|
796
|
-
[onThreadDetailLoaded, pageSize, setLoadingHistory, transport, upsertStoredThread]
|
|
1051
|
+
[clearMissingThread, onThreadDetailLoaded, pageSize, setLoadingHistory, transport, upsertStoredThread]
|
|
797
1052
|
);
|
|
798
|
-
const loadOlderTurns = (0,
|
|
1053
|
+
const loadOlderTurns = (0, import_react2.useCallback)(async () => {
|
|
799
1054
|
const threadId = activeThreadIdRef.current;
|
|
800
1055
|
const beforeTurnIndex = nextBeforeTurnIndexRef.current;
|
|
801
1056
|
if (!threadId || beforeTurnIndex === null || isLoadingOlderRef.current) return;
|
|
@@ -818,12 +1073,19 @@ function useAgents24ChatController({
|
|
|
818
1073
|
hasOlderTurnsRef.current = paging.hasOlderTurns;
|
|
819
1074
|
nextBeforeTurnIndexRef.current = paging.nextBeforeTurnIndex;
|
|
820
1075
|
persistThread(threadId, next, paging);
|
|
1076
|
+
} catch (error) {
|
|
1077
|
+
if (isAbortError(error)) return;
|
|
1078
|
+
if (isThreadNotFoundError(error)) {
|
|
1079
|
+
clearMissingThread(threadId);
|
|
1080
|
+
return;
|
|
1081
|
+
}
|
|
1082
|
+
throw error;
|
|
821
1083
|
} finally {
|
|
822
1084
|
if (activeThreadIdRef.current === threadId) setIsLoadingOlder(false);
|
|
823
1085
|
isLoadingOlderRef.current = false;
|
|
824
1086
|
}
|
|
825
|
-
}, [pageSize, persistThread, transport]);
|
|
826
|
-
const handleStreamEvent = (0,
|
|
1087
|
+
}, [clearMissingThread, pageSize, persistThread, transport]);
|
|
1088
|
+
const handleStreamEvent = (0, import_react2.useCallback)(
|
|
827
1089
|
(input) => {
|
|
828
1090
|
const { mode, event, assistantMessageId, startedAt, streamThreadIdRef, baseMessages } = input;
|
|
829
1091
|
const payload = event.payload || {};
|
|
@@ -884,7 +1146,7 @@ function useAgents24ChatController({
|
|
|
884
1146
|
},
|
|
885
1147
|
[applyThreadId, finalizeAssistantMessage, markThreadRunStatus, onRuntimeEvent, onStreamErrorMessage, setActiveRunIdValue, setLiveAssistantMessage, setReasoningSteps]
|
|
886
1148
|
);
|
|
887
|
-
const runStream = (0,
|
|
1149
|
+
const runStream = (0, import_react2.useCallback)(
|
|
888
1150
|
async (input) => {
|
|
889
1151
|
const startedAt = Date.now();
|
|
890
1152
|
const controller = new AbortController();
|
|
@@ -943,19 +1205,28 @@ function useAgents24ChatController({
|
|
|
943
1205
|
);
|
|
944
1206
|
}
|
|
945
1207
|
try {
|
|
1208
|
+
let streamResult = null;
|
|
946
1209
|
if (input.mode === "attach") {
|
|
947
1210
|
setActiveRunIdValue(input.runId);
|
|
948
1211
|
reattachedRunIdRef.current = input.runId;
|
|
949
|
-
await transport.attachRun(
|
|
1212
|
+
streamResult = await transport.attachRun(
|
|
950
1213
|
{ runId: input.runId, signal: controller.signal },
|
|
951
1214
|
(event) => handleStreamEvent({ mode: "attach", event, assistantMessageId, startedAt, streamThreadIdRef, baseMessages })
|
|
952
1215
|
);
|
|
953
1216
|
} else {
|
|
954
|
-
await transport.streamMessage(
|
|
1217
|
+
streamResult = await transport.streamMessage(
|
|
955
1218
|
{ ...input.message, files: input.message.files || [], threadId: activeThreadIdRef.current, signal: controller.signal },
|
|
956
1219
|
(event) => handleStreamEvent({ mode: "submit", event, assistantMessageId, startedAt, streamThreadIdRef, baseMessages })
|
|
957
1220
|
);
|
|
958
1221
|
}
|
|
1222
|
+
if (streamResult?.runId) setActiveRunIdValue(streamResult.runId);
|
|
1223
|
+
if (streamResult?.threadId) {
|
|
1224
|
+
streamThreadIdRef.current = streamResult.threadId;
|
|
1225
|
+
applyThreadId(streamResult.threadId, baseMessages);
|
|
1226
|
+
if (streamResult.runId) {
|
|
1227
|
+
markThreadRunStatus(streamResult.threadId, streamResult.runId, "running");
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
959
1230
|
if (streamingContentRef.current.trim() && streamingMessageIdRef.current) {
|
|
960
1231
|
finalizeAssistantMessage({
|
|
961
1232
|
threadId: streamThreadIdRef.current,
|
|
@@ -969,7 +1240,7 @@ function useAgents24ChatController({
|
|
|
969
1240
|
}
|
|
970
1241
|
await refresh().catch(() => void 0);
|
|
971
1242
|
} catch (error) {
|
|
972
|
-
if (error
|
|
1243
|
+
if (!isAbortError(error)) {
|
|
973
1244
|
finalizeAssistantMessage({
|
|
974
1245
|
threadId: streamThreadIdRef.current,
|
|
975
1246
|
baseMessages: messagesRef.current,
|
|
@@ -998,18 +1269,22 @@ function useAgents24ChatController({
|
|
|
998
1269
|
},
|
|
999
1270
|
[createId, finalizeAssistantMessage, handleStreamEvent, onStreamErrorMessage, persistThread, refresh, setActiveRunIdValue, setReasoningSteps, transport]
|
|
1000
1271
|
);
|
|
1001
|
-
const handleSubmit = (0,
|
|
1272
|
+
const handleSubmit = (0, import_react2.useCallback)(
|
|
1002
1273
|
async (message) => {
|
|
1003
1274
|
if (!message.text.trim() && !(message.files || []).length) return;
|
|
1004
1275
|
await runStream({ mode: "submit", message });
|
|
1005
1276
|
},
|
|
1006
1277
|
[runStream]
|
|
1007
1278
|
);
|
|
1008
|
-
const
|
|
1279
|
+
const attachRun = (0, import_react2.useCallback)(async (runId, threadId) => {
|
|
1280
|
+
const resolvedThreadId = threadId ?? activeThreadIdRef.current;
|
|
1281
|
+
if (runId && resolvedThreadId) await runStream({ mode: "attach", runId, threadId: resolvedThreadId });
|
|
1282
|
+
}, [runStream]);
|
|
1283
|
+
const handleStop = (0, import_react2.useCallback)(() => {
|
|
1009
1284
|
const runId = activeRunIdRef.current;
|
|
1010
1285
|
const partial = streamingContentRef.current;
|
|
1011
1286
|
const liveMessageId = streamingMessageIdRef.current;
|
|
1012
|
-
abortControllerRef.current
|
|
1287
|
+
abortDetachedStream(abortControllerRef.current);
|
|
1013
1288
|
abortControllerRef.current = null;
|
|
1014
1289
|
setActiveRunIdValue(null);
|
|
1015
1290
|
streamingMessageIdRef.current = null;
|
|
@@ -1029,16 +1304,45 @@ function useAgents24ChatController({
|
|
|
1029
1304
|
});
|
|
1030
1305
|
}
|
|
1031
1306
|
}, [finalizeAssistantMessage, lastThinkingDurationMs, setActiveRunIdValue, setReasoningSteps, transport]);
|
|
1032
|
-
(0,
|
|
1033
|
-
refresh().catch(() =>
|
|
1034
|
-
storage.setThreads([]);
|
|
1035
|
-
setThreads([]);
|
|
1036
|
-
});
|
|
1307
|
+
(0, import_react2.useEffect)(() => {
|
|
1308
|
+
refresh().catch(() => setThreads(storage.listThreads()));
|
|
1037
1309
|
}, [refresh, storage]);
|
|
1038
|
-
(0,
|
|
1310
|
+
(0, import_react2.useEffect)(() => {
|
|
1311
|
+
if (!transport.subscribeThreadEvents) return;
|
|
1312
|
+
let cancelled = false;
|
|
1313
|
+
let retryTimeout = null;
|
|
1314
|
+
let controller = null;
|
|
1315
|
+
const connect = () => {
|
|
1316
|
+
if (cancelled) return;
|
|
1317
|
+
controller = new AbortController();
|
|
1318
|
+
transport.subscribeThreadEvents?.(
|
|
1319
|
+
{ cursor: threadEventsCursorRef.current, signal: controller.signal },
|
|
1320
|
+
async (event) => {
|
|
1321
|
+
if (typeof event.cursor === "number") threadEventsCursorRef.current = event.cursor;
|
|
1322
|
+
if (event.event === "snapshot_required") {
|
|
1323
|
+
await refresh().catch(() => void 0);
|
|
1324
|
+
return;
|
|
1325
|
+
}
|
|
1326
|
+
const next = applyThreadSummaryEvent(storage.listThreads(), event);
|
|
1327
|
+
storage.setThreads(next);
|
|
1328
|
+
setThreads(storage.listThreads());
|
|
1329
|
+
}
|
|
1330
|
+
).catch((error) => {
|
|
1331
|
+
if (cancelled || isAbortError(error)) return;
|
|
1332
|
+
retryTimeout = setTimeout(connect, 1500);
|
|
1333
|
+
});
|
|
1334
|
+
};
|
|
1335
|
+
connect();
|
|
1336
|
+
return () => {
|
|
1337
|
+
cancelled = true;
|
|
1338
|
+
if (retryTimeout) clearTimeout(retryTimeout);
|
|
1339
|
+
controller?.abort();
|
|
1340
|
+
};
|
|
1341
|
+
}, [refresh, storage, transport]);
|
|
1342
|
+
(0, import_react2.useEffect)(() => {
|
|
1039
1343
|
syncThreadsFromStorage();
|
|
1040
1344
|
}, [storageKey, syncThreadsFromStorage]);
|
|
1041
|
-
(0,
|
|
1345
|
+
(0, import_react2.useEffect)(() => {
|
|
1042
1346
|
const previous = activeThreadIdRef.current;
|
|
1043
1347
|
activeThreadIdRef.current = activeThreadId;
|
|
1044
1348
|
if (activeThreadId && previous === activeThreadId && (activeRunIdRef.current || streamingMessageIdRef.current)) {
|
|
@@ -1048,6 +1352,9 @@ function useAgents24ChatController({
|
|
|
1048
1352
|
detachActiveStream();
|
|
1049
1353
|
}
|
|
1050
1354
|
if (!activeThreadId) {
|
|
1355
|
+
if (previous === null && loadedThreadIdRef.current === null && messagesRef.current.length === 0 && !hasOlderTurnsRef.current && !isLoadingHistoryRef.current && !isLoadingOlderRef.current && nextBeforeTurnIndexRef.current === null) {
|
|
1356
|
+
return;
|
|
1357
|
+
}
|
|
1051
1358
|
requestSeqRef.current += 1;
|
|
1052
1359
|
loadedThreadIdRef.current = null;
|
|
1053
1360
|
setMessages([]);
|
|
@@ -1079,14 +1386,14 @@ function useAgents24ChatController({
|
|
|
1079
1386
|
}
|
|
1080
1387
|
void loadThread(activeThreadId).catch(() => setLoadingHistory(false));
|
|
1081
1388
|
}, [activeThreadId, detachActiveStream, loadThread, setLoadingHistory, storage]);
|
|
1082
|
-
(0,
|
|
1389
|
+
(0, import_react2.useEffect)(() => {
|
|
1083
1390
|
const threadId = activeThreadId;
|
|
1084
1391
|
if (!threadId || isLoadingHistory || loadedThreadIdRef.current !== threadId || activeRunIdRef.current) return;
|
|
1085
|
-
const runId =
|
|
1392
|
+
const runId = autoAttachRunIdFromThread(storage.getThread(threadId));
|
|
1086
1393
|
if (!runId || reattachedRunIdRef.current === runId) return;
|
|
1087
1394
|
void runStream({ mode: "attach", threadId, runId });
|
|
1088
1395
|
}, [activeThreadId, isLoadingHistory, runStream, storage, storageKey]);
|
|
1089
|
-
(0,
|
|
1396
|
+
(0, import_react2.useEffect)(() => {
|
|
1090
1397
|
const threadId = activeThreadId;
|
|
1091
1398
|
if (!threadId || isLoadingHistoryRef.current || activeRunIdRef.current || streamingMessageIdRef.current) {
|
|
1092
1399
|
return;
|
|
@@ -1095,87 +1402,58 @@ function useAgents24ChatController({
|
|
|
1095
1402
|
if (!hasStaleUnfinishedAssistantCache(cached)) return;
|
|
1096
1403
|
void loadThread(threadId).catch(() => setLoadingHistory(false));
|
|
1097
1404
|
}, [activeThreadId, loadThread, setLoadingHistory, storage, storageKey]);
|
|
1098
|
-
const
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
setMessages
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
id: currentId || createId(),
|
|
1132
|
-
role: input.role,
|
|
1133
|
-
content,
|
|
1134
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
1135
|
-
isFinal: Boolean(input.isFinal),
|
|
1136
|
-
isVoice: input.role === "user",
|
|
1137
|
-
parts: content ? [{ id: createId(), type: "text", kind: "text", text: content }] : [],
|
|
1138
|
-
citations: input.citations,
|
|
1139
|
-
reasoningSteps: input.reasoningSteps
|
|
1140
|
-
};
|
|
1141
|
-
const next = index === -1 ? [...prev, nextMessage] : prev.map((message, itemIndex) => itemIndex === index ? { ...message, ...nextMessage } : message);
|
|
1142
|
-
liveVoiceIdsRef.current[input.role] = input.isFinal ? void 0 : nextMessage.id;
|
|
1143
|
-
messagesRef.current = next;
|
|
1144
|
-
if (activeThreadIdRef.current) persistThread(activeThreadIdRef.current, next);
|
|
1145
|
-
return next;
|
|
1146
|
-
});
|
|
1147
|
-
}, [createId, persistThread]);
|
|
1148
|
-
const startNewThread = (0, import_react.useCallback)(() => {
|
|
1149
|
-
detachActiveStream();
|
|
1150
|
-
requestSeqRef.current += 1;
|
|
1151
|
-
activeThreadIdRef.current = null;
|
|
1152
|
-
loadedThreadIdRef.current = null;
|
|
1153
|
-
nextBeforeTurnIndexRef.current = null;
|
|
1154
|
-
hasOlderTurnsRef.current = false;
|
|
1155
|
-
storage.setActiveThreadId?.(null);
|
|
1156
|
-
onActiveThreadIdChange?.(null);
|
|
1157
|
-
setMessages([]);
|
|
1158
|
-
messagesRef.current = [];
|
|
1159
|
-
setHasOlderTurns(false);
|
|
1160
|
-
setIsLoadingOlder(false);
|
|
1161
|
-
setContextStatus(null);
|
|
1162
|
-
setLoadingHistory(false);
|
|
1163
|
-
}, [detachActiveStream, onActiveThreadIdChange, setLoadingHistory, storage]);
|
|
1164
|
-
const loadThreadById = (0, import_react.useCallback)(
|
|
1405
|
+
const {
|
|
1406
|
+
handleCopy,
|
|
1407
|
+
handleDislike,
|
|
1408
|
+
handleLike,
|
|
1409
|
+
handleRetry,
|
|
1410
|
+
startNewThread,
|
|
1411
|
+
upsertLiveVoiceMessage
|
|
1412
|
+
} = useControllerMessageActions({
|
|
1413
|
+
activeThreadIdRef,
|
|
1414
|
+
createId,
|
|
1415
|
+
detachActiveStream,
|
|
1416
|
+
disliked,
|
|
1417
|
+
handleSubmit,
|
|
1418
|
+
hasOlderTurnsRef,
|
|
1419
|
+
liked,
|
|
1420
|
+
liveVoiceIdsRef,
|
|
1421
|
+
loadedThreadIdRef,
|
|
1422
|
+
messagesRef,
|
|
1423
|
+
nextBeforeTurnIndexRef,
|
|
1424
|
+
onActiveThreadIdChange,
|
|
1425
|
+
persistThread,
|
|
1426
|
+
requestSeqRef,
|
|
1427
|
+
setContextStatus,
|
|
1428
|
+
setCopiedMessageId,
|
|
1429
|
+
setDisliked,
|
|
1430
|
+
setHasOlderTurns,
|
|
1431
|
+
setIsLoadingOlder,
|
|
1432
|
+
setLiked,
|
|
1433
|
+
setLoadingHistory,
|
|
1434
|
+
setMessages,
|
|
1435
|
+
storage
|
|
1436
|
+
});
|
|
1437
|
+
const loadThreadById = (0, import_react2.useCallback)(
|
|
1165
1438
|
async (threadId) => {
|
|
1166
1439
|
if (!threadId) return;
|
|
1440
|
+
setIsSelectingThread(true);
|
|
1167
1441
|
if (activeThreadIdRef.current !== threadId) {
|
|
1168
1442
|
if (abortControllerRef.current) detachActiveStream();
|
|
1169
1443
|
activeThreadIdRef.current = threadId;
|
|
1170
1444
|
storage.setActiveThreadId?.(threadId);
|
|
1171
1445
|
onActiveThreadIdChange?.(threadId);
|
|
1172
1446
|
}
|
|
1173
|
-
|
|
1447
|
+
try {
|
|
1448
|
+
await loadThread(threadId);
|
|
1449
|
+
} finally {
|
|
1450
|
+
if (activeThreadIdRef.current === threadId) setIsSelectingThread(false);
|
|
1451
|
+
}
|
|
1174
1452
|
},
|
|
1175
1453
|
[detachActiveStream, loadThread, onActiveThreadIdChange, storage]
|
|
1176
1454
|
);
|
|
1177
1455
|
const activeThread = activeThreadId ? storage.getThread(activeThreadId) || threads.find((thread) => thread.id === activeThreadId) || null : null;
|
|
1178
|
-
return (0,
|
|
1456
|
+
return (0, import_react2.useMemo)(() => ({
|
|
1179
1457
|
threads,
|
|
1180
1458
|
activeThreadId,
|
|
1181
1459
|
activeThread,
|
|
@@ -1188,6 +1466,7 @@ function useAgents24ChatController({
|
|
|
1188
1466
|
isLoadingHistory,
|
|
1189
1467
|
isLoadingOlder,
|
|
1190
1468
|
isRefreshingThreads,
|
|
1469
|
+
isSelectingThread,
|
|
1191
1470
|
hasOlderTurns,
|
|
1192
1471
|
liked,
|
|
1193
1472
|
disliked,
|
|
@@ -1195,6 +1474,7 @@ function useAgents24ChatController({
|
|
|
1195
1474
|
lastThinkingDurationMs,
|
|
1196
1475
|
activeRunId,
|
|
1197
1476
|
handleSubmit,
|
|
1477
|
+
attachRun,
|
|
1198
1478
|
handleStop,
|
|
1199
1479
|
handleCopy,
|
|
1200
1480
|
handleLike,
|
|
@@ -1212,6 +1492,7 @@ function useAgents24ChatController({
|
|
|
1212
1492
|
activeRunId,
|
|
1213
1493
|
activeThread,
|
|
1214
1494
|
activeThreadId,
|
|
1495
|
+
attachRun,
|
|
1215
1496
|
contextStatus,
|
|
1216
1497
|
currentReasoning,
|
|
1217
1498
|
disliked,
|
|
@@ -1226,6 +1507,7 @@ function useAgents24ChatController({
|
|
|
1226
1507
|
isLoadingHistory,
|
|
1227
1508
|
isLoadingOlder,
|
|
1228
1509
|
isRefreshingThreads,
|
|
1510
|
+
isSelectingThread,
|
|
1229
1511
|
lastThinkingDurationMs,
|
|
1230
1512
|
liked,
|
|
1231
1513
|
loadThreadById,
|
|
@@ -1613,13 +1895,16 @@ var DefaultChatPart = ({
|
|
|
1613
1895
|
if (part.kind === "ui-blocks") {
|
|
1614
1896
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { "data-agents24-ui-blocks-part": true, "data-state": part.state });
|
|
1615
1897
|
}
|
|
1616
|
-
if (part.kind === "
|
|
1617
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { "data-agents24-
|
|
1898
|
+
if (part.kind === "hitl") {
|
|
1899
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { "data-agents24-hitl-part": part.interruptId || "" });
|
|
1618
1900
|
}
|
|
1619
1901
|
if (part.kind === "error") {
|
|
1620
1902
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { "data-agents24-error-part": true, children: part.errorText });
|
|
1621
1903
|
}
|
|
1622
|
-
|
|
1904
|
+
if (part.kind === "data") {
|
|
1905
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { "data-agents24-data-part": part.name });
|
|
1906
|
+
}
|
|
1907
|
+
return null;
|
|
1623
1908
|
};
|
|
1624
1909
|
var renderChatPart = (part, message, renderOptions) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1625
1910
|
DefaultChatPart,
|
|
@@ -1632,12 +1917,17 @@ var renderChatPart = (part, message, renderOptions) => /* @__PURE__ */ (0, impor
|
|
|
1632
1917
|
);
|
|
1633
1918
|
|
|
1634
1919
|
// src/sse.ts
|
|
1920
|
+
var isAbortError2 = (error) => {
|
|
1921
|
+
if (!error || typeof error !== "object") return false;
|
|
1922
|
+
const maybe = error;
|
|
1923
|
+
return maybe.name === "AbortError" || String(maybe.message || "").toLowerCase().includes("aborted");
|
|
1924
|
+
};
|
|
1635
1925
|
var parseSseBlock = (block) => {
|
|
1636
1926
|
const data = block.split("\n").filter((line) => line.startsWith("data:")).map((line) => line.replace(/^data:\s?/, "")).join("\n").trim();
|
|
1637
1927
|
if (!data) return null;
|
|
1638
1928
|
return JSON.parse(data);
|
|
1639
1929
|
};
|
|
1640
|
-
var consumeSseResponse = async (response, onEvent) => {
|
|
1930
|
+
var consumeSseResponse = async (response, onEvent, options = {}) => {
|
|
1641
1931
|
if (!response.ok) {
|
|
1642
1932
|
let message = response.statusText || "Failed to open chat stream.";
|
|
1643
1933
|
try {
|
|
@@ -1651,30 +1941,47 @@ var consumeSseResponse = async (response, onEvent) => {
|
|
|
1651
1941
|
if (!reader) throw new Error("The chat stream did not return a readable body.");
|
|
1652
1942
|
const decoder = new TextDecoder();
|
|
1653
1943
|
let buffer = "";
|
|
1654
|
-
let threadId = null;
|
|
1655
|
-
let runId = null;
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1944
|
+
let threadId = response.headers.get("X-Thread-ID") || null;
|
|
1945
|
+
let runId = response.headers.get("X-Run-ID") || null;
|
|
1946
|
+
let closed = false;
|
|
1947
|
+
const closeReader = () => {
|
|
1948
|
+
closed = true;
|
|
1949
|
+
void reader.cancel().catch(() => {
|
|
1950
|
+
});
|
|
1951
|
+
};
|
|
1952
|
+
if (options.signal?.aborted) {
|
|
1953
|
+
closeReader();
|
|
1954
|
+
return { threadId, runId };
|
|
1955
|
+
}
|
|
1956
|
+
options.signal?.addEventListener("abort", closeReader, { once: true });
|
|
1957
|
+
try {
|
|
1958
|
+
while (!closed) {
|
|
1959
|
+
const { value, done } = await reader.read();
|
|
1960
|
+
if (done) break;
|
|
1961
|
+
buffer += decoder.decode(value, { stream: true });
|
|
1962
|
+
let boundary = buffer.indexOf("\n\n");
|
|
1963
|
+
while (boundary !== -1) {
|
|
1964
|
+
const block = buffer.slice(0, boundary);
|
|
1965
|
+
buffer = buffer.slice(boundary + 2);
|
|
1966
|
+
boundary = buffer.indexOf("\n\n");
|
|
1967
|
+
const event = parseSseBlock(block);
|
|
1968
|
+
if (!event) continue;
|
|
1969
|
+
if (event.run_id) runId = event.run_id;
|
|
1970
|
+
const payloadThreadId = event.payload?.thread_id;
|
|
1971
|
+
if (payloadThreadId) threadId = String(payloadThreadId);
|
|
1972
|
+
await onEvent(event);
|
|
1973
|
+
}
|
|
1671
1974
|
}
|
|
1975
|
+
} catch (error) {
|
|
1976
|
+
if (!isAbortError2(error)) throw error;
|
|
1977
|
+
} finally {
|
|
1978
|
+
options.signal?.removeEventListener("abort", closeReader);
|
|
1672
1979
|
}
|
|
1673
1980
|
return { threadId, runId };
|
|
1674
1981
|
};
|
|
1675
1982
|
|
|
1676
1983
|
// src/streaming-text.ts
|
|
1677
|
-
var
|
|
1984
|
+
var import_react3 = require("react");
|
|
1678
1985
|
var DEFAULT_COMPLETED_TEXT_CACHE_SIZE = 200;
|
|
1679
1986
|
var defaultCompletedTextCache = /* @__PURE__ */ new Map();
|
|
1680
1987
|
var defaultStreamingTextCache = {
|
|
@@ -1702,24 +2009,24 @@ function useStreamingText({
|
|
|
1702
2009
|
maxCatchupChars = 20
|
|
1703
2010
|
}) {
|
|
1704
2011
|
const cacheAdapter = cache === false ? null : cache;
|
|
1705
|
-
const [displayedText, setDisplayedText] = (0,
|
|
2012
|
+
const [displayedText, setDisplayedText] = (0, import_react3.useState)(() => {
|
|
1706
2013
|
const cachedText = cacheAdapter?.get(id);
|
|
1707
2014
|
return isStreaming && cachedText !== text ? "" : text;
|
|
1708
2015
|
});
|
|
1709
|
-
const targetRef = (0,
|
|
1710
|
-
const displayedRef = (0,
|
|
1711
|
-
const rafRef = (0,
|
|
1712
|
-
const lastFrameAtRef = (0,
|
|
1713
|
-
const idRef = (0,
|
|
1714
|
-
const shouldAnimateRef = (0,
|
|
1715
|
-
(0,
|
|
2016
|
+
const targetRef = (0, import_react3.useRef)(text);
|
|
2017
|
+
const displayedRef = (0, import_react3.useRef)(displayedText);
|
|
2018
|
+
const rafRef = (0, import_react3.useRef)(null);
|
|
2019
|
+
const lastFrameAtRef = (0, import_react3.useRef)(null);
|
|
2020
|
+
const idRef = (0, import_react3.useRef)(id);
|
|
2021
|
+
const shouldAnimateRef = (0, import_react3.useRef)(isStreaming);
|
|
2022
|
+
(0, import_react3.useEffect)(() => {
|
|
1716
2023
|
if (isStreaming || !text) return;
|
|
1717
2024
|
cacheAdapter?.set(id, text);
|
|
1718
2025
|
}, [cacheAdapter, id, isStreaming, text]);
|
|
1719
|
-
(0,
|
|
2026
|
+
(0, import_react3.useEffect)(() => {
|
|
1720
2027
|
targetRef.current = text;
|
|
1721
2028
|
}, [text]);
|
|
1722
|
-
(0,
|
|
2029
|
+
(0, import_react3.useEffect)(() => {
|
|
1723
2030
|
if (idRef.current === id) return;
|
|
1724
2031
|
idRef.current = id;
|
|
1725
2032
|
const cachedText = cacheAdapter?.get(id);
|
|
@@ -1733,7 +2040,7 @@ function useStreamingText({
|
|
|
1733
2040
|
}
|
|
1734
2041
|
lastFrameAtRef.current = null;
|
|
1735
2042
|
}, [cacheAdapter, id, isStreaming, text]);
|
|
1736
|
-
(0,
|
|
2043
|
+
(0, import_react3.useEffect)(() => {
|
|
1737
2044
|
if (typeof window === "undefined") {
|
|
1738
2045
|
displayedRef.current = text;
|
|
1739
2046
|
setDisplayedText(text);
|
|
@@ -1818,6 +2125,14 @@ var streamHeaders = (headers) => ({
|
|
|
1818
2125
|
Accept: "text/event-stream",
|
|
1819
2126
|
"Content-Type": "application/json"
|
|
1820
2127
|
});
|
|
2128
|
+
var ChatTransportError = class extends Error {
|
|
2129
|
+
constructor(message, status) {
|
|
2130
|
+
super(message);
|
|
2131
|
+
this.name = "ChatTransportError";
|
|
2132
|
+
this.status = status;
|
|
2133
|
+
}
|
|
2134
|
+
};
|
|
2135
|
+
var transportError = (response, fallback) => new ChatTransportError(response.statusText || fallback, response.status);
|
|
1821
2136
|
var createFetchChatTransport = ({
|
|
1822
2137
|
routes,
|
|
1823
2138
|
fetchImpl = fetch,
|
|
@@ -1831,7 +2146,7 @@ var createFetchChatTransport = ({
|
|
|
1831
2146
|
signal: input?.signal,
|
|
1832
2147
|
headers: jsonHeaders(await loadHeaders())
|
|
1833
2148
|
});
|
|
1834
|
-
if (!response.ok) throw
|
|
2149
|
+
if (!response.ok) throw transportError(response, "Failed to list chat threads.");
|
|
1835
2150
|
return response.json();
|
|
1836
2151
|
},
|
|
1837
2152
|
async getThread(input) {
|
|
@@ -1839,7 +2154,7 @@ var createFetchChatTransport = ({
|
|
|
1839
2154
|
signal: input.signal,
|
|
1840
2155
|
headers: jsonHeaders(await loadHeaders())
|
|
1841
2156
|
});
|
|
1842
|
-
if (!response.ok) throw
|
|
2157
|
+
if (!response.ok) throw transportError(response, "Failed to load chat thread.");
|
|
1843
2158
|
return response.json();
|
|
1844
2159
|
},
|
|
1845
2160
|
async streamMessage(input, onEvent) {
|
|
@@ -1872,7 +2187,7 @@ var createFetchChatTransport = ({
|
|
|
1872
2187
|
headers: jsonHeaders(await loadHeaders()),
|
|
1873
2188
|
body: JSON.stringify({ assistant_output_text: input.assistantOutputText || void 0 })
|
|
1874
2189
|
});
|
|
1875
|
-
if (!response.ok) throw
|
|
2190
|
+
if (!response.ok) throw transportError(response, "Failed to cancel chat run.");
|
|
1876
2191
|
return response.json();
|
|
1877
2192
|
},
|
|
1878
2193
|
async deleteThread(input) {
|
|
@@ -1881,7 +2196,46 @@ var createFetchChatTransport = ({
|
|
|
1881
2196
|
method: "DELETE",
|
|
1882
2197
|
headers: jsonHeaders(await loadHeaders())
|
|
1883
2198
|
});
|
|
1884
|
-
if (!response.ok) throw
|
|
2199
|
+
if (!response.ok) throw transportError(response, "Failed to delete chat thread.");
|
|
2200
|
+
return response.json();
|
|
2201
|
+
},
|
|
2202
|
+
async subscribeThreadEvents(input, onEvent) {
|
|
2203
|
+
if (!routes.threadEvents) return;
|
|
2204
|
+
const response = await fetchImpl(routes.threadEvents({ cursor: input.cursor }), {
|
|
2205
|
+
method: "GET",
|
|
2206
|
+
signal: input.signal,
|
|
2207
|
+
headers: streamHeaders(await loadHeaders())
|
|
2208
|
+
});
|
|
2209
|
+
await consumeSseResponse(response, (event) => onEvent(event));
|
|
2210
|
+
},
|
|
2211
|
+
async resumeHitl(input) {
|
|
2212
|
+
if (!routes.resumeRun) throw new ChatTransportError("HITL resume is not configured.", 501);
|
|
2213
|
+
const response = await fetchImpl(routes.resumeRun({ runId: input.runId }), {
|
|
2214
|
+
method: "POST",
|
|
2215
|
+
headers: jsonHeaders(await loadHeaders()),
|
|
2216
|
+
body: JSON.stringify({
|
|
2217
|
+
schema_version: "agents24.hitl.resume.v1",
|
|
2218
|
+
interrupt_id: input.interruptId,
|
|
2219
|
+
decisions: input.decisions,
|
|
2220
|
+
client: input.client
|
|
2221
|
+
})
|
|
2222
|
+
});
|
|
2223
|
+
if (!response.ok) throw transportError(response, "Failed to resume chat run.");
|
|
2224
|
+
return response.json();
|
|
2225
|
+
},
|
|
2226
|
+
async startMcpAuth(input) {
|
|
2227
|
+
if (!routes.startMcpAuth) throw new ChatTransportError("MCP auth is not configured.", 501);
|
|
2228
|
+
const response = await fetchImpl(routes.startMcpAuth({ runId: input.runId, serverId: input.serverId }), {
|
|
2229
|
+
method: "POST",
|
|
2230
|
+
headers: jsonHeaders(await loadHeaders()),
|
|
2231
|
+
body: JSON.stringify({
|
|
2232
|
+
interrupt_id: input.interruptId || void 0,
|
|
2233
|
+
principal_type: input.principalType || void 0,
|
|
2234
|
+
principal_id: input.principalId || void 0,
|
|
2235
|
+
client: input.client
|
|
2236
|
+
})
|
|
2237
|
+
});
|
|
2238
|
+
if (!response.ok) throw transportError(response, "Failed to start MCP authorization.");
|
|
1885
2239
|
return response.json();
|
|
1886
2240
|
}
|
|
1887
2241
|
};
|
|
@@ -1891,6 +2245,7 @@ var createFetchChatTransport = ({
|
|
|
1891
2245
|
var import_message_scroller2 = require("@shadcn/react/message-scroller");
|
|
1892
2246
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1893
2247
|
0 && (module.exports = {
|
|
2248
|
+
ChatTransportError,
|
|
1894
2249
|
DEFAULT_THREAD_PAGE_SIZE,
|
|
1895
2250
|
DefaultChatPart,
|
|
1896
2251
|
DefaultToolPart,
|
|
@@ -1905,21 +2260,26 @@ var import_message_scroller2 = require("@shadcn/react/message-scroller");
|
|
|
1905
2260
|
MessageScroller,
|
|
1906
2261
|
activeRunIdFromThread,
|
|
1907
2262
|
activeRunIdFromThreadDetail,
|
|
2263
|
+
appendStableStreamingTurn,
|
|
1908
2264
|
assistantTextFromParts,
|
|
1909
2265
|
assistantTextFromResponseBlocks,
|
|
2266
|
+
autoAttachRunIdFromThread,
|
|
1910
2267
|
compressionFromContextWindow,
|
|
1911
2268
|
consumeSseResponse,
|
|
1912
2269
|
createChatId,
|
|
1913
2270
|
createFetchChatTransport,
|
|
2271
|
+
findStableAssistantMessageIndex,
|
|
1914
2272
|
getActiveStreamingTextPartId,
|
|
1915
2273
|
hasStaleUnfinishedAssistantCache,
|
|
1916
2274
|
hasUnfinishedAssistantMessage,
|
|
1917
2275
|
isActiveStreamingTextPart,
|
|
2276
|
+
isAutoAttachThreadStatus,
|
|
1918
2277
|
isRunningThreadStatus,
|
|
1919
2278
|
latestContextWindowFromThread,
|
|
1920
2279
|
mergeContextWindow,
|
|
1921
2280
|
mergeContextWindowUpdate,
|
|
1922
2281
|
mergeReasoningSteps,
|
|
2282
|
+
mergeStoredThreadsForRefresh,
|
|
1923
2283
|
normalizeContextCompression,
|
|
1924
2284
|
normalizeContextWindow,
|
|
1925
2285
|
parseSseBlock,
|
|
@@ -1932,6 +2292,7 @@ var import_message_scroller2 = require("@shadcn/react/message-scroller");
|
|
|
1932
2292
|
threadPaging,
|
|
1933
2293
|
titleFromMessage,
|
|
1934
2294
|
toolStateFromStatus,
|
|
2295
|
+
upsertStableAssistantMessage,
|
|
1935
2296
|
useAgents24ChatController,
|
|
1936
2297
|
useMessageScroller,
|
|
1937
2298
|
useMessageScrollerScrollable,
|