@sinas/sdk 0.1.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-M7YHE5Y6.js → chunk-EV5ARSUJ.js} +101 -2
- package/dist/chunk-EV5ARSUJ.js.map +1 -0
- package/dist/client.cjs +104 -0
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +89 -3
- package/dist/client.d.ts +89 -3
- package/dist/client.js +11 -1
- package/dist/index.cjs +384 -87
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -8
- package/dist/index.d.ts +26 -8
- package/dist/index.js +291 -88
- package/dist/index.js.map +1 -1
- package/dist/sinas-sdk.umd.js +379 -87
- package/dist/sinas-sdk.umd.js.map +1 -1
- package/package.json +7 -2
- package/dist/chunk-M7YHE5Y6.js.map +0 -1
package/dist/sinas-sdk.umd.js
CHANGED
|
@@ -49,14 +49,19 @@ var SinasSDK = (() => {
|
|
|
49
49
|
SinasPermissionError: () => SinasPermissionError,
|
|
50
50
|
SinasProvider: () => SinasProvider,
|
|
51
51
|
SinasTimeoutError: () => SinasTimeoutError,
|
|
52
|
+
approveToolCall: () => approveToolCall,
|
|
52
53
|
createChat: () => createChat,
|
|
53
54
|
executeFunction: () => executeFunction,
|
|
54
55
|
executeQuery: () => executeQuery,
|
|
56
|
+
getChat: () => getChat,
|
|
57
|
+
listCollections: () => listCollections,
|
|
58
|
+
listFiles: () => listFiles,
|
|
55
59
|
sendMessage: () => sendMessage,
|
|
56
60
|
stateDelete: () => stateDelete,
|
|
57
61
|
stateGet: () => stateGet,
|
|
58
62
|
stateList: () => stateList,
|
|
59
63
|
stateSet: () => stateSet,
|
|
64
|
+
streamFromChannel: () => streamFromChannel,
|
|
60
65
|
streamMessage: () => streamMessage,
|
|
61
66
|
useChat: () => useChat,
|
|
62
67
|
useExecute: () => useExecute,
|
|
@@ -279,6 +284,88 @@ var SinasSDK = (() => {
|
|
|
279
284
|
createdAt: data.created_at
|
|
280
285
|
};
|
|
281
286
|
}
|
|
287
|
+
function mapMessage(data) {
|
|
288
|
+
const toolCalls = data.tool_calls;
|
|
289
|
+
return {
|
|
290
|
+
id: data.id,
|
|
291
|
+
chatId: data.chat_id,
|
|
292
|
+
role: data.role,
|
|
293
|
+
content: data.content ?? null,
|
|
294
|
+
toolCalls: toolCalls ?? null,
|
|
295
|
+
toolCallId: data.tool_call_id ?? null,
|
|
296
|
+
name: data.name ?? null,
|
|
297
|
+
createdAt: data.created_at
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
async function getChat(client, chatId) {
|
|
301
|
+
const config = client.getConfig();
|
|
302
|
+
const res = await client.fetch(`${config.apiBase}/chats/${chatId}`);
|
|
303
|
+
const data = await res.json();
|
|
304
|
+
return {
|
|
305
|
+
id: data.id,
|
|
306
|
+
agentNamespace: data.agent_namespace,
|
|
307
|
+
agentName: data.agent_name,
|
|
308
|
+
title: data.title,
|
|
309
|
+
messages: (data.messages || []).map(mapMessage)
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
async function approveToolCall(client, chatId, toolCallId, approved) {
|
|
313
|
+
const config = client.getConfig();
|
|
314
|
+
const res = await client.fetch(
|
|
315
|
+
`${config.apiBase}/chats/${chatId}/approve-tool/${toolCallId}`,
|
|
316
|
+
{ method: "POST", body: JSON.stringify({ approved }) }
|
|
317
|
+
);
|
|
318
|
+
const data = await res.json();
|
|
319
|
+
return {
|
|
320
|
+
status: data.status,
|
|
321
|
+
toolCallId: data.tool_call_id,
|
|
322
|
+
channelId: data.channel_id
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
function streamFromChannel(client, chatId, channelId, onChunk, onDone, onError) {
|
|
326
|
+
const controller = new AbortController();
|
|
327
|
+
const config = client.getConfig();
|
|
328
|
+
(async () => {
|
|
329
|
+
try {
|
|
330
|
+
const res = await fetch(
|
|
331
|
+
`${config.apiBase}/chats/${chatId}/stream/${channelId}?last_id=0`,
|
|
332
|
+
{ headers: client.getAuthHeaders(), signal: controller.signal }
|
|
333
|
+
);
|
|
334
|
+
if (!res.ok) {
|
|
335
|
+
const body = await res.json().catch(() => ({ detail: res.statusText }));
|
|
336
|
+
throw new Error(body.detail || "Stream reconnect failed");
|
|
337
|
+
}
|
|
338
|
+
const reader = res.body.getReader();
|
|
339
|
+
const decoder = new TextDecoder();
|
|
340
|
+
let buffer = "";
|
|
341
|
+
while (true) {
|
|
342
|
+
const { done, value } = await reader.read();
|
|
343
|
+
if (done) break;
|
|
344
|
+
buffer += decoder.decode(value, { stream: true });
|
|
345
|
+
const { chunks, remaining } = parseSSE(buffer);
|
|
346
|
+
buffer = remaining;
|
|
347
|
+
for (const chunk of chunks) {
|
|
348
|
+
onChunk(chunk);
|
|
349
|
+
if (chunk.event === "done") {
|
|
350
|
+
onDone?.();
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
if (buffer.trim()) {
|
|
356
|
+
const { chunks } = parseSSE(buffer + "\n\n");
|
|
357
|
+
for (const chunk of chunks) {
|
|
358
|
+
onChunk(chunk);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
onDone?.();
|
|
362
|
+
} catch (err) {
|
|
363
|
+
if (err.name === "AbortError") return;
|
|
364
|
+
onError?.(err);
|
|
365
|
+
}
|
|
366
|
+
})();
|
|
367
|
+
return controller;
|
|
368
|
+
}
|
|
282
369
|
function parseSSE(buffer) {
|
|
283
370
|
const chunks = [];
|
|
284
371
|
const lines = buffer.split("\n");
|
|
@@ -352,6 +439,18 @@ var SinasSDK = (() => {
|
|
|
352
439
|
return controller;
|
|
353
440
|
}
|
|
354
441
|
|
|
442
|
+
// src/client/collections.ts
|
|
443
|
+
async function listCollections(client) {
|
|
444
|
+
const base = client.getProxyBase();
|
|
445
|
+
const res = await client.fetch(`${base}/collections`);
|
|
446
|
+
return res.json();
|
|
447
|
+
}
|
|
448
|
+
async function listFiles(client, namespace, collection) {
|
|
449
|
+
const base = client.getProxyBase();
|
|
450
|
+
const res = await client.fetch(`${base}/files/${namespace}/${collection}`);
|
|
451
|
+
return res.json();
|
|
452
|
+
}
|
|
453
|
+
|
|
355
454
|
// src/hooks/useQuery.ts
|
|
356
455
|
var import_react2 = __toESM(require_react(), 1);
|
|
357
456
|
|
|
@@ -527,125 +626,318 @@ var SinasSDK = (() => {
|
|
|
527
626
|
|
|
528
627
|
// src/hooks/useChat.ts
|
|
529
628
|
var import_react5 = __toESM(require_react(), 1);
|
|
530
|
-
function useChat(agentRef) {
|
|
629
|
+
function useChat(agentRef, options) {
|
|
531
630
|
const client = useClient();
|
|
532
|
-
const [chatId, setChatId] = import_react5.default.useState(null);
|
|
631
|
+
const [chatId, setChatId] = import_react5.default.useState(options?.chatId ?? null);
|
|
533
632
|
const [messages, setMessages] = import_react5.default.useState([]);
|
|
534
633
|
const [loading, setLoading] = import_react5.default.useState(false);
|
|
535
634
|
const [streaming, setStreaming] = import_react5.default.useState(false);
|
|
536
635
|
const [error, setError] = import_react5.default.useState(null);
|
|
636
|
+
const [pendingApprovals, setPendingApprovals] = import_react5.default.useState([]);
|
|
637
|
+
const [toolStatus, setToolStatus] = import_react5.default.useState([]);
|
|
537
638
|
const abortRef = import_react5.default.useRef(null);
|
|
639
|
+
const chatIdRef = import_react5.default.useRef(chatId);
|
|
640
|
+
chatIdRef.current = chatId;
|
|
641
|
+
const activeAssistantIdRef = import_react5.default.useRef("");
|
|
642
|
+
import_react5.default.useEffect(() => {
|
|
643
|
+
if (!options?.chatId) return;
|
|
644
|
+
let cancelled = false;
|
|
645
|
+
setLoading(true);
|
|
646
|
+
getChat(client, options.chatId).then((detail) => {
|
|
647
|
+
if (cancelled) return;
|
|
648
|
+
setChatId(detail.id);
|
|
649
|
+
setMessages(detail.messages);
|
|
650
|
+
}).catch((e) => {
|
|
651
|
+
if (cancelled) return;
|
|
652
|
+
setError(e.message);
|
|
653
|
+
}).finally(() => {
|
|
654
|
+
if (!cancelled) setLoading(false);
|
|
655
|
+
});
|
|
656
|
+
return () => {
|
|
657
|
+
cancelled = true;
|
|
658
|
+
};
|
|
659
|
+
}, [client, options?.chatId]);
|
|
538
660
|
import_react5.default.useEffect(() => {
|
|
539
661
|
return () => {
|
|
540
662
|
abortRef.current?.abort();
|
|
541
663
|
};
|
|
542
664
|
}, []);
|
|
543
|
-
const
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
665
|
+
const handleStreamChunks = import_react5.default.useCallback(
|
|
666
|
+
(chunk) => {
|
|
667
|
+
if (chunk.event === "message") {
|
|
668
|
+
try {
|
|
669
|
+
const parsed = JSON.parse(chunk.data);
|
|
670
|
+
if (parsed.content) {
|
|
671
|
+
const targetId = activeAssistantIdRef.current;
|
|
672
|
+
setMessages(
|
|
673
|
+
(prev) => prev.map(
|
|
674
|
+
(m) => m.id === targetId ? { ...m, content: (m.content || "") + parsed.content } : m
|
|
675
|
+
)
|
|
676
|
+
);
|
|
677
|
+
}
|
|
678
|
+
} catch {
|
|
679
|
+
const targetId = activeAssistantIdRef.current;
|
|
680
|
+
setMessages(
|
|
681
|
+
(prev) => prev.map(
|
|
682
|
+
(m) => m.id === targetId ? { ...m, content: (m.content || "") + chunk.data } : m
|
|
683
|
+
)
|
|
684
|
+
);
|
|
685
|
+
}
|
|
686
|
+
} else if (chunk.event === "tool_start") {
|
|
687
|
+
try {
|
|
688
|
+
const parsed = JSON.parse(chunk.data);
|
|
689
|
+
setToolStatus((prev) => [
|
|
690
|
+
...prev,
|
|
691
|
+
{ toolCallId: parsed.tool_call_id, name: parsed.name, description: parsed.description, status: "running" }
|
|
692
|
+
]);
|
|
693
|
+
const placeholderId = activeAssistantIdRef.current;
|
|
694
|
+
const toolCallMsg = {
|
|
695
|
+
id: `tmp-tc-${parsed.tool_call_id}`,
|
|
696
|
+
chatId: chatIdRef.current || "",
|
|
697
|
+
role: "assistant",
|
|
698
|
+
content: null,
|
|
699
|
+
toolCalls: [{
|
|
700
|
+
id: parsed.tool_call_id,
|
|
701
|
+
type: "function",
|
|
702
|
+
function: { name: parsed.name, arguments: parsed.arguments || "{}" }
|
|
703
|
+
}],
|
|
704
|
+
toolCallId: null,
|
|
705
|
+
name: null,
|
|
706
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
707
|
+
};
|
|
708
|
+
setMessages((prev) => {
|
|
709
|
+
const filtered = prev.filter(
|
|
710
|
+
(m) => !(m.id === placeholderId && m.streaming && !m.content)
|
|
711
|
+
);
|
|
712
|
+
return [...filtered, toolCallMsg];
|
|
713
|
+
});
|
|
714
|
+
} catch {
|
|
715
|
+
}
|
|
716
|
+
} else if (chunk.event === "tool_end") {
|
|
717
|
+
try {
|
|
718
|
+
const parsed = JSON.parse(chunk.data);
|
|
719
|
+
setToolStatus(
|
|
720
|
+
(prev) => prev.map((t) => t.toolCallId === parsed.tool_call_id ? { ...t, status: "complete" } : t)
|
|
721
|
+
);
|
|
722
|
+
if (parsed.result !== void 0) {
|
|
723
|
+
const toolResultMsg = {
|
|
724
|
+
id: `tmp-tr-${parsed.tool_call_id}`,
|
|
725
|
+
chatId: chatIdRef.current || "",
|
|
726
|
+
role: "tool",
|
|
727
|
+
content: typeof parsed.result === "string" ? parsed.result : JSON.stringify(parsed.result),
|
|
728
|
+
toolCalls: null,
|
|
729
|
+
toolCallId: parsed.tool_call_id,
|
|
730
|
+
name: parsed.name,
|
|
731
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
732
|
+
};
|
|
733
|
+
setMessages((prev) => [...prev, toolResultMsg]);
|
|
734
|
+
}
|
|
735
|
+
setToolStatus((currentStatus) => {
|
|
736
|
+
const stillRunning = currentStatus.filter((t) => t.status === "running");
|
|
737
|
+
if (stillRunning.length === 0) {
|
|
738
|
+
const newAssistantId = `tmp-assistant-${Date.now()}`;
|
|
739
|
+
activeAssistantIdRef.current = newAssistantId;
|
|
740
|
+
const newMsg = {
|
|
741
|
+
id: newAssistantId,
|
|
742
|
+
chatId: chatIdRef.current || "",
|
|
743
|
+
role: "assistant",
|
|
744
|
+
content: "",
|
|
745
|
+
toolCalls: null,
|
|
746
|
+
toolCallId: null,
|
|
747
|
+
name: null,
|
|
748
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
749
|
+
streaming: true
|
|
750
|
+
};
|
|
751
|
+
setMessages((prev) => [...prev, newMsg]);
|
|
752
|
+
}
|
|
753
|
+
return currentStatus;
|
|
754
|
+
});
|
|
755
|
+
} catch {
|
|
756
|
+
}
|
|
757
|
+
} else if (chunk.event === "approval_required") {
|
|
758
|
+
try {
|
|
759
|
+
const parsed = JSON.parse(chunk.data);
|
|
760
|
+
setPendingApprovals((prev) => [...prev, parsed]);
|
|
761
|
+
} catch {
|
|
762
|
+
}
|
|
763
|
+
} else if (chunk.event === "error") {
|
|
764
|
+
try {
|
|
765
|
+
const parsed = JSON.parse(chunk.data);
|
|
766
|
+
setError(parsed.error || "Stream error");
|
|
767
|
+
} catch {
|
|
768
|
+
setError(chunk.data || "Stream error");
|
|
769
|
+
}
|
|
556
770
|
}
|
|
557
771
|
},
|
|
558
|
-
[
|
|
772
|
+
[]
|
|
559
773
|
);
|
|
560
|
-
const
|
|
561
|
-
async (
|
|
562
|
-
if (!chatId) {
|
|
563
|
-
setError("No active chat. Call createChat first.");
|
|
564
|
-
return;
|
|
565
|
-
}
|
|
566
|
-
setLoading(true);
|
|
567
|
-
setError(null);
|
|
568
|
-
const userMsg = {
|
|
569
|
-
id: `tmp-${Date.now()}`,
|
|
570
|
-
chatId,
|
|
571
|
-
role: "user",
|
|
572
|
-
content,
|
|
573
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
574
|
-
};
|
|
575
|
-
setMessages((prev) => [...prev, userMsg]);
|
|
774
|
+
const refreshMessages = import_react5.default.useCallback(
|
|
775
|
+
async (id) => {
|
|
576
776
|
try {
|
|
577
|
-
const
|
|
578
|
-
setMessages(
|
|
579
|
-
|
|
580
|
-
} catch (e) {
|
|
581
|
-
setError(e.message);
|
|
582
|
-
} finally {
|
|
583
|
-
setLoading(false);
|
|
777
|
+
const detail = await getChat(client, id);
|
|
778
|
+
setMessages(detail.messages);
|
|
779
|
+
} catch {
|
|
584
780
|
}
|
|
585
781
|
},
|
|
586
|
-
[client
|
|
782
|
+
[client]
|
|
587
783
|
);
|
|
588
|
-
const
|
|
784
|
+
const send = import_react5.default.useCallback(
|
|
589
785
|
(content) => {
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
786
|
+
const doSend = async () => {
|
|
787
|
+
let activeChatId = chatIdRef.current;
|
|
788
|
+
if (!activeChatId) {
|
|
789
|
+
setLoading(true);
|
|
790
|
+
setError(null);
|
|
791
|
+
try {
|
|
792
|
+
const result = await createChat(client, agentRef, options?.input);
|
|
793
|
+
activeChatId = result.id;
|
|
794
|
+
setChatId(result.id);
|
|
795
|
+
chatIdRef.current = result.id;
|
|
796
|
+
} catch (e) {
|
|
797
|
+
setError(e.message);
|
|
798
|
+
setLoading(false);
|
|
799
|
+
return;
|
|
800
|
+
}
|
|
801
|
+
setLoading(false);
|
|
802
|
+
}
|
|
803
|
+
abortRef.current?.abort();
|
|
804
|
+
setStreaming(true);
|
|
805
|
+
setError(null);
|
|
806
|
+
setPendingApprovals([]);
|
|
807
|
+
setToolStatus([]);
|
|
808
|
+
const displayContent = typeof content === "string" ? content : JSON.stringify(content);
|
|
809
|
+
const userMsg = {
|
|
810
|
+
id: `tmp-user-${Date.now()}`,
|
|
811
|
+
chatId: activeChatId,
|
|
812
|
+
role: "user",
|
|
813
|
+
content: displayContent,
|
|
814
|
+
toolCalls: null,
|
|
815
|
+
toolCallId: null,
|
|
816
|
+
name: null,
|
|
817
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
818
|
+
};
|
|
819
|
+
setMessages((prev) => [...prev, userMsg]);
|
|
820
|
+
const assistantId = `tmp-assistant-${Date.now()}`;
|
|
821
|
+
activeAssistantIdRef.current = assistantId;
|
|
822
|
+
const assistantMsg = {
|
|
823
|
+
id: assistantId,
|
|
824
|
+
chatId: activeChatId,
|
|
825
|
+
role: "assistant",
|
|
826
|
+
content: "",
|
|
827
|
+
toolCalls: null,
|
|
828
|
+
toolCallId: null,
|
|
829
|
+
name: null,
|
|
830
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
831
|
+
streaming: true
|
|
832
|
+
};
|
|
833
|
+
setMessages((prev) => [...prev, assistantMsg]);
|
|
834
|
+
const controller = streamMessage(
|
|
835
|
+
client,
|
|
836
|
+
activeChatId,
|
|
837
|
+
content,
|
|
838
|
+
handleStreamChunks,
|
|
839
|
+
() => {
|
|
840
|
+
setStreaming(false);
|
|
841
|
+
setToolStatus([]);
|
|
842
|
+
refreshMessages(activeChatId);
|
|
843
|
+
},
|
|
844
|
+
(err) => {
|
|
845
|
+
setError(err.message);
|
|
846
|
+
setStreaming(false);
|
|
847
|
+
setToolStatus([]);
|
|
848
|
+
}
|
|
849
|
+
);
|
|
850
|
+
abortRef.current = controller;
|
|
851
|
+
};
|
|
852
|
+
doSend();
|
|
853
|
+
},
|
|
854
|
+
[client, agentRef, options?.input, handleStreamChunks, refreshMessages]
|
|
855
|
+
);
|
|
856
|
+
const handleApproval = import_react5.default.useCallback(
|
|
857
|
+
(toolCallId, approved) => {
|
|
858
|
+
const currentChatId = chatIdRef.current;
|
|
859
|
+
if (!currentChatId) return;
|
|
860
|
+
setPendingApprovals((prev) => prev.filter((a) => a.toolCallId !== toolCallId));
|
|
595
861
|
setStreaming(true);
|
|
596
862
|
setError(null);
|
|
597
|
-
const
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
setMessages(
|
|
621
|
-
(prev) => prev.map(
|
|
622
|
-
(m) => m.id === assistantId ? { ...m, content: m.content + chunk.data } : m
|
|
623
|
-
)
|
|
624
|
-
);
|
|
863
|
+
const assistantId = `tmp-resume-${Date.now()}`;
|
|
864
|
+
activeAssistantIdRef.current = assistantId;
|
|
865
|
+
if (approved) {
|
|
866
|
+
const assistantMsg = {
|
|
867
|
+
id: assistantId,
|
|
868
|
+
chatId: currentChatId,
|
|
869
|
+
role: "assistant",
|
|
870
|
+
content: "",
|
|
871
|
+
toolCalls: null,
|
|
872
|
+
toolCallId: null,
|
|
873
|
+
name: null,
|
|
874
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
875
|
+
streaming: true
|
|
876
|
+
};
|
|
877
|
+
setMessages((prev) => [...prev, assistantMsg]);
|
|
878
|
+
}
|
|
879
|
+
(async () => {
|
|
880
|
+
try {
|
|
881
|
+
const result = await approveToolCall(client, currentChatId, toolCallId, approved);
|
|
882
|
+
if (!approved) {
|
|
883
|
+
setStreaming(false);
|
|
884
|
+
refreshMessages(currentChatId);
|
|
885
|
+
return;
|
|
625
886
|
}
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
887
|
+
const controller = streamFromChannel(
|
|
888
|
+
client,
|
|
889
|
+
currentChatId,
|
|
890
|
+
result.channelId,
|
|
891
|
+
handleStreamChunks,
|
|
892
|
+
() => {
|
|
893
|
+
setStreaming(false);
|
|
894
|
+
setToolStatus([]);
|
|
895
|
+
refreshMessages(currentChatId);
|
|
896
|
+
},
|
|
897
|
+
(err) => {
|
|
898
|
+
setError(err.message);
|
|
899
|
+
setStreaming(false);
|
|
900
|
+
setToolStatus([]);
|
|
901
|
+
}
|
|
902
|
+
);
|
|
903
|
+
abortRef.current = controller;
|
|
904
|
+
} catch (e) {
|
|
905
|
+
setError(e.message);
|
|
632
906
|
setStreaming(false);
|
|
633
907
|
}
|
|
634
|
-
);
|
|
635
|
-
abortRef.current = controller;
|
|
636
|
-
return controller;
|
|
908
|
+
})();
|
|
637
909
|
},
|
|
638
|
-
[client,
|
|
910
|
+
[client, handleStreamChunks, refreshMessages]
|
|
911
|
+
);
|
|
912
|
+
const approve = import_react5.default.useCallback(
|
|
913
|
+
(toolCallId) => handleApproval(toolCallId, true),
|
|
914
|
+
[handleApproval]
|
|
639
915
|
);
|
|
916
|
+
const reject = import_react5.default.useCallback(
|
|
917
|
+
(toolCallId) => handleApproval(toolCallId, false),
|
|
918
|
+
[handleApproval]
|
|
919
|
+
);
|
|
920
|
+
const stop = import_react5.default.useCallback(() => {
|
|
921
|
+
abortRef.current?.abort();
|
|
922
|
+
abortRef.current = null;
|
|
923
|
+
setStreaming(false);
|
|
924
|
+
}, []);
|
|
925
|
+
const clearError = import_react5.default.useCallback(() => {
|
|
926
|
+
setError(null);
|
|
927
|
+
}, []);
|
|
640
928
|
return {
|
|
641
929
|
chatId,
|
|
642
930
|
messages,
|
|
643
931
|
loading,
|
|
644
932
|
streaming,
|
|
645
933
|
error,
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
934
|
+
pendingApprovals,
|
|
935
|
+
toolStatus,
|
|
936
|
+
send,
|
|
937
|
+
approve,
|
|
938
|
+
reject,
|
|
939
|
+
stop,
|
|
940
|
+
clearError
|
|
649
941
|
};
|
|
650
942
|
}
|
|
651
943
|
|