@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/client.js
CHANGED
|
@@ -5,16 +5,21 @@ import {
|
|
|
5
5
|
SinasNotFoundError,
|
|
6
6
|
SinasPermissionError,
|
|
7
7
|
SinasTimeoutError,
|
|
8
|
+
approveToolCall,
|
|
8
9
|
createChat,
|
|
9
10
|
executeFunction,
|
|
10
11
|
executeQuery,
|
|
12
|
+
getChat,
|
|
13
|
+
listCollections,
|
|
14
|
+
listFiles,
|
|
11
15
|
sendMessage,
|
|
12
16
|
stateDelete,
|
|
13
17
|
stateGet,
|
|
14
18
|
stateList,
|
|
15
19
|
stateSet,
|
|
20
|
+
streamFromChannel,
|
|
16
21
|
streamMessage
|
|
17
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-EV5ARSUJ.js";
|
|
18
23
|
export {
|
|
19
24
|
SinasAuthError,
|
|
20
25
|
SinasClient,
|
|
@@ -22,14 +27,19 @@ export {
|
|
|
22
27
|
SinasNotFoundError,
|
|
23
28
|
SinasPermissionError,
|
|
24
29
|
SinasTimeoutError,
|
|
30
|
+
approveToolCall,
|
|
25
31
|
createChat,
|
|
26
32
|
executeFunction,
|
|
27
33
|
executeQuery,
|
|
34
|
+
getChat,
|
|
35
|
+
listCollections,
|
|
36
|
+
listFiles,
|
|
28
37
|
sendMessage,
|
|
29
38
|
stateDelete,
|
|
30
39
|
stateGet,
|
|
31
40
|
stateList,
|
|
32
41
|
stateSet,
|
|
42
|
+
streamFromChannel,
|
|
33
43
|
streamMessage
|
|
34
44
|
};
|
|
35
45
|
//# sourceMappingURL=client.js.map
|
package/dist/index.cjs
CHANGED
|
@@ -37,14 +37,19 @@ __export(src_exports, {
|
|
|
37
37
|
SinasPermissionError: () => SinasPermissionError,
|
|
38
38
|
SinasProvider: () => SinasProvider,
|
|
39
39
|
SinasTimeoutError: () => SinasTimeoutError,
|
|
40
|
+
approveToolCall: () => approveToolCall,
|
|
40
41
|
createChat: () => createChat,
|
|
41
42
|
executeFunction: () => executeFunction,
|
|
42
43
|
executeQuery: () => executeQuery,
|
|
44
|
+
getChat: () => getChat,
|
|
45
|
+
listCollections: () => listCollections,
|
|
46
|
+
listFiles: () => listFiles,
|
|
43
47
|
sendMessage: () => sendMessage,
|
|
44
48
|
stateDelete: () => stateDelete,
|
|
45
49
|
stateGet: () => stateGet,
|
|
46
50
|
stateList: () => stateList,
|
|
47
51
|
stateSet: () => stateSet,
|
|
52
|
+
streamFromChannel: () => streamFromChannel,
|
|
48
53
|
streamMessage: () => streamMessage,
|
|
49
54
|
useChat: () => useChat,
|
|
50
55
|
useExecute: () => useExecute,
|
|
@@ -268,6 +273,88 @@ async function sendMessage(client, chatId, content) {
|
|
|
268
273
|
createdAt: data.created_at
|
|
269
274
|
};
|
|
270
275
|
}
|
|
276
|
+
function mapMessage(data) {
|
|
277
|
+
const toolCalls = data.tool_calls;
|
|
278
|
+
return {
|
|
279
|
+
id: data.id,
|
|
280
|
+
chatId: data.chat_id,
|
|
281
|
+
role: data.role,
|
|
282
|
+
content: data.content ?? null,
|
|
283
|
+
toolCalls: toolCalls ?? null,
|
|
284
|
+
toolCallId: data.tool_call_id ?? null,
|
|
285
|
+
name: data.name ?? null,
|
|
286
|
+
createdAt: data.created_at
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
async function getChat(client, chatId) {
|
|
290
|
+
const config = client.getConfig();
|
|
291
|
+
const res = await client.fetch(`${config.apiBase}/chats/${chatId}`);
|
|
292
|
+
const data = await res.json();
|
|
293
|
+
return {
|
|
294
|
+
id: data.id,
|
|
295
|
+
agentNamespace: data.agent_namespace,
|
|
296
|
+
agentName: data.agent_name,
|
|
297
|
+
title: data.title,
|
|
298
|
+
messages: (data.messages || []).map(mapMessage)
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
async function approveToolCall(client, chatId, toolCallId, approved) {
|
|
302
|
+
const config = client.getConfig();
|
|
303
|
+
const res = await client.fetch(
|
|
304
|
+
`${config.apiBase}/chats/${chatId}/approve-tool/${toolCallId}`,
|
|
305
|
+
{ method: "POST", body: JSON.stringify({ approved }) }
|
|
306
|
+
);
|
|
307
|
+
const data = await res.json();
|
|
308
|
+
return {
|
|
309
|
+
status: data.status,
|
|
310
|
+
toolCallId: data.tool_call_id,
|
|
311
|
+
channelId: data.channel_id
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
function streamFromChannel(client, chatId, channelId, onChunk, onDone, onError) {
|
|
315
|
+
const controller = new AbortController();
|
|
316
|
+
const config = client.getConfig();
|
|
317
|
+
(async () => {
|
|
318
|
+
try {
|
|
319
|
+
const res = await fetch(
|
|
320
|
+
`${config.apiBase}/chats/${chatId}/stream/${channelId}?last_id=0`,
|
|
321
|
+
{ headers: client.getAuthHeaders(), signal: controller.signal }
|
|
322
|
+
);
|
|
323
|
+
if (!res.ok) {
|
|
324
|
+
const body = await res.json().catch(() => ({ detail: res.statusText }));
|
|
325
|
+
throw new Error(body.detail || "Stream reconnect failed");
|
|
326
|
+
}
|
|
327
|
+
const reader = res.body.getReader();
|
|
328
|
+
const decoder = new TextDecoder();
|
|
329
|
+
let buffer = "";
|
|
330
|
+
while (true) {
|
|
331
|
+
const { done, value } = await reader.read();
|
|
332
|
+
if (done) break;
|
|
333
|
+
buffer += decoder.decode(value, { stream: true });
|
|
334
|
+
const { chunks, remaining } = parseSSE(buffer);
|
|
335
|
+
buffer = remaining;
|
|
336
|
+
for (const chunk of chunks) {
|
|
337
|
+
onChunk(chunk);
|
|
338
|
+
if (chunk.event === "done") {
|
|
339
|
+
onDone?.();
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
if (buffer.trim()) {
|
|
345
|
+
const { chunks } = parseSSE(buffer + "\n\n");
|
|
346
|
+
for (const chunk of chunks) {
|
|
347
|
+
onChunk(chunk);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
onDone?.();
|
|
351
|
+
} catch (err) {
|
|
352
|
+
if (err.name === "AbortError") return;
|
|
353
|
+
onError?.(err);
|
|
354
|
+
}
|
|
355
|
+
})();
|
|
356
|
+
return controller;
|
|
357
|
+
}
|
|
271
358
|
function parseSSE(buffer) {
|
|
272
359
|
const chunks = [];
|
|
273
360
|
const lines = buffer.split("\n");
|
|
@@ -341,6 +428,18 @@ function streamMessage(client, chatId, content, onChunk, onDone, onError) {
|
|
|
341
428
|
return controller;
|
|
342
429
|
}
|
|
343
430
|
|
|
431
|
+
// src/client/collections.ts
|
|
432
|
+
async function listCollections(client) {
|
|
433
|
+
const base = client.getProxyBase();
|
|
434
|
+
const res = await client.fetch(`${base}/collections`);
|
|
435
|
+
return res.json();
|
|
436
|
+
}
|
|
437
|
+
async function listFiles(client, namespace, collection) {
|
|
438
|
+
const base = client.getProxyBase();
|
|
439
|
+
const res = await client.fetch(`${base}/files/${namespace}/${collection}`);
|
|
440
|
+
return res.json();
|
|
441
|
+
}
|
|
442
|
+
|
|
344
443
|
// src/hooks/useQuery.ts
|
|
345
444
|
var import_react2 = __toESM(require("react"), 1);
|
|
346
445
|
|
|
@@ -516,125 +615,318 @@ function useStateStore(ns, key) {
|
|
|
516
615
|
|
|
517
616
|
// src/hooks/useChat.ts
|
|
518
617
|
var import_react5 = __toESM(require("react"), 1);
|
|
519
|
-
function useChat(agentRef) {
|
|
618
|
+
function useChat(agentRef, options) {
|
|
520
619
|
const client = useClient();
|
|
521
|
-
const [chatId, setChatId] = import_react5.default.useState(null);
|
|
620
|
+
const [chatId, setChatId] = import_react5.default.useState(options?.chatId ?? null);
|
|
522
621
|
const [messages, setMessages] = import_react5.default.useState([]);
|
|
523
622
|
const [loading, setLoading] = import_react5.default.useState(false);
|
|
524
623
|
const [streaming, setStreaming] = import_react5.default.useState(false);
|
|
525
624
|
const [error, setError] = import_react5.default.useState(null);
|
|
625
|
+
const [pendingApprovals, setPendingApprovals] = import_react5.default.useState([]);
|
|
626
|
+
const [toolStatus, setToolStatus] = import_react5.default.useState([]);
|
|
526
627
|
const abortRef = import_react5.default.useRef(null);
|
|
628
|
+
const chatIdRef = import_react5.default.useRef(chatId);
|
|
629
|
+
chatIdRef.current = chatId;
|
|
630
|
+
const activeAssistantIdRef = import_react5.default.useRef("");
|
|
631
|
+
import_react5.default.useEffect(() => {
|
|
632
|
+
if (!options?.chatId) return;
|
|
633
|
+
let cancelled = false;
|
|
634
|
+
setLoading(true);
|
|
635
|
+
getChat(client, options.chatId).then((detail) => {
|
|
636
|
+
if (cancelled) return;
|
|
637
|
+
setChatId(detail.id);
|
|
638
|
+
setMessages(detail.messages);
|
|
639
|
+
}).catch((e) => {
|
|
640
|
+
if (cancelled) return;
|
|
641
|
+
setError(e.message);
|
|
642
|
+
}).finally(() => {
|
|
643
|
+
if (!cancelled) setLoading(false);
|
|
644
|
+
});
|
|
645
|
+
return () => {
|
|
646
|
+
cancelled = true;
|
|
647
|
+
};
|
|
648
|
+
}, [client, options?.chatId]);
|
|
527
649
|
import_react5.default.useEffect(() => {
|
|
528
650
|
return () => {
|
|
529
651
|
abortRef.current?.abort();
|
|
530
652
|
};
|
|
531
653
|
}, []);
|
|
532
|
-
const
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
654
|
+
const handleStreamChunks = import_react5.default.useCallback(
|
|
655
|
+
(chunk) => {
|
|
656
|
+
if (chunk.event === "message") {
|
|
657
|
+
try {
|
|
658
|
+
const parsed = JSON.parse(chunk.data);
|
|
659
|
+
if (parsed.content) {
|
|
660
|
+
const targetId = activeAssistantIdRef.current;
|
|
661
|
+
setMessages(
|
|
662
|
+
(prev) => prev.map(
|
|
663
|
+
(m) => m.id === targetId ? { ...m, content: (m.content || "") + parsed.content } : m
|
|
664
|
+
)
|
|
665
|
+
);
|
|
666
|
+
}
|
|
667
|
+
} catch {
|
|
668
|
+
const targetId = activeAssistantIdRef.current;
|
|
669
|
+
setMessages(
|
|
670
|
+
(prev) => prev.map(
|
|
671
|
+
(m) => m.id === targetId ? { ...m, content: (m.content || "") + chunk.data } : m
|
|
672
|
+
)
|
|
673
|
+
);
|
|
674
|
+
}
|
|
675
|
+
} else if (chunk.event === "tool_start") {
|
|
676
|
+
try {
|
|
677
|
+
const parsed = JSON.parse(chunk.data);
|
|
678
|
+
setToolStatus((prev) => [
|
|
679
|
+
...prev,
|
|
680
|
+
{ toolCallId: parsed.tool_call_id, name: parsed.name, description: parsed.description, status: "running" }
|
|
681
|
+
]);
|
|
682
|
+
const placeholderId = activeAssistantIdRef.current;
|
|
683
|
+
const toolCallMsg = {
|
|
684
|
+
id: `tmp-tc-${parsed.tool_call_id}`,
|
|
685
|
+
chatId: chatIdRef.current || "",
|
|
686
|
+
role: "assistant",
|
|
687
|
+
content: null,
|
|
688
|
+
toolCalls: [{
|
|
689
|
+
id: parsed.tool_call_id,
|
|
690
|
+
type: "function",
|
|
691
|
+
function: { name: parsed.name, arguments: parsed.arguments || "{}" }
|
|
692
|
+
}],
|
|
693
|
+
toolCallId: null,
|
|
694
|
+
name: null,
|
|
695
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
696
|
+
};
|
|
697
|
+
setMessages((prev) => {
|
|
698
|
+
const filtered = prev.filter(
|
|
699
|
+
(m) => !(m.id === placeholderId && m.streaming && !m.content)
|
|
700
|
+
);
|
|
701
|
+
return [...filtered, toolCallMsg];
|
|
702
|
+
});
|
|
703
|
+
} catch {
|
|
704
|
+
}
|
|
705
|
+
} else if (chunk.event === "tool_end") {
|
|
706
|
+
try {
|
|
707
|
+
const parsed = JSON.parse(chunk.data);
|
|
708
|
+
setToolStatus(
|
|
709
|
+
(prev) => prev.map((t) => t.toolCallId === parsed.tool_call_id ? { ...t, status: "complete" } : t)
|
|
710
|
+
);
|
|
711
|
+
if (parsed.result !== void 0) {
|
|
712
|
+
const toolResultMsg = {
|
|
713
|
+
id: `tmp-tr-${parsed.tool_call_id}`,
|
|
714
|
+
chatId: chatIdRef.current || "",
|
|
715
|
+
role: "tool",
|
|
716
|
+
content: typeof parsed.result === "string" ? parsed.result : JSON.stringify(parsed.result),
|
|
717
|
+
toolCalls: null,
|
|
718
|
+
toolCallId: parsed.tool_call_id,
|
|
719
|
+
name: parsed.name,
|
|
720
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
721
|
+
};
|
|
722
|
+
setMessages((prev) => [...prev, toolResultMsg]);
|
|
723
|
+
}
|
|
724
|
+
setToolStatus((currentStatus) => {
|
|
725
|
+
const stillRunning = currentStatus.filter((t) => t.status === "running");
|
|
726
|
+
if (stillRunning.length === 0) {
|
|
727
|
+
const newAssistantId = `tmp-assistant-${Date.now()}`;
|
|
728
|
+
activeAssistantIdRef.current = newAssistantId;
|
|
729
|
+
const newMsg = {
|
|
730
|
+
id: newAssistantId,
|
|
731
|
+
chatId: chatIdRef.current || "",
|
|
732
|
+
role: "assistant",
|
|
733
|
+
content: "",
|
|
734
|
+
toolCalls: null,
|
|
735
|
+
toolCallId: null,
|
|
736
|
+
name: null,
|
|
737
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
738
|
+
streaming: true
|
|
739
|
+
};
|
|
740
|
+
setMessages((prev) => [...prev, newMsg]);
|
|
741
|
+
}
|
|
742
|
+
return currentStatus;
|
|
743
|
+
});
|
|
744
|
+
} catch {
|
|
745
|
+
}
|
|
746
|
+
} else if (chunk.event === "approval_required") {
|
|
747
|
+
try {
|
|
748
|
+
const parsed = JSON.parse(chunk.data);
|
|
749
|
+
setPendingApprovals((prev) => [...prev, parsed]);
|
|
750
|
+
} catch {
|
|
751
|
+
}
|
|
752
|
+
} else if (chunk.event === "error") {
|
|
753
|
+
try {
|
|
754
|
+
const parsed = JSON.parse(chunk.data);
|
|
755
|
+
setError(parsed.error || "Stream error");
|
|
756
|
+
} catch {
|
|
757
|
+
setError(chunk.data || "Stream error");
|
|
758
|
+
}
|
|
545
759
|
}
|
|
546
760
|
},
|
|
547
|
-
[
|
|
761
|
+
[]
|
|
548
762
|
);
|
|
549
|
-
const
|
|
550
|
-
async (
|
|
551
|
-
if (!chatId) {
|
|
552
|
-
setError("No active chat. Call createChat first.");
|
|
553
|
-
return;
|
|
554
|
-
}
|
|
555
|
-
setLoading(true);
|
|
556
|
-
setError(null);
|
|
557
|
-
const userMsg = {
|
|
558
|
-
id: `tmp-${Date.now()}`,
|
|
559
|
-
chatId,
|
|
560
|
-
role: "user",
|
|
561
|
-
content,
|
|
562
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
563
|
-
};
|
|
564
|
-
setMessages((prev) => [...prev, userMsg]);
|
|
763
|
+
const refreshMessages = import_react5.default.useCallback(
|
|
764
|
+
async (id) => {
|
|
565
765
|
try {
|
|
566
|
-
const
|
|
567
|
-
setMessages(
|
|
568
|
-
|
|
569
|
-
} catch (e) {
|
|
570
|
-
setError(e.message);
|
|
571
|
-
} finally {
|
|
572
|
-
setLoading(false);
|
|
766
|
+
const detail = await getChat(client, id);
|
|
767
|
+
setMessages(detail.messages);
|
|
768
|
+
} catch {
|
|
573
769
|
}
|
|
574
770
|
},
|
|
575
|
-
[client
|
|
771
|
+
[client]
|
|
576
772
|
);
|
|
577
|
-
const
|
|
773
|
+
const send = import_react5.default.useCallback(
|
|
578
774
|
(content) => {
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
775
|
+
const doSend = async () => {
|
|
776
|
+
let activeChatId = chatIdRef.current;
|
|
777
|
+
if (!activeChatId) {
|
|
778
|
+
setLoading(true);
|
|
779
|
+
setError(null);
|
|
780
|
+
try {
|
|
781
|
+
const result = await createChat(client, agentRef, options?.input);
|
|
782
|
+
activeChatId = result.id;
|
|
783
|
+
setChatId(result.id);
|
|
784
|
+
chatIdRef.current = result.id;
|
|
785
|
+
} catch (e) {
|
|
786
|
+
setError(e.message);
|
|
787
|
+
setLoading(false);
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
setLoading(false);
|
|
791
|
+
}
|
|
792
|
+
abortRef.current?.abort();
|
|
793
|
+
setStreaming(true);
|
|
794
|
+
setError(null);
|
|
795
|
+
setPendingApprovals([]);
|
|
796
|
+
setToolStatus([]);
|
|
797
|
+
const displayContent = typeof content === "string" ? content : JSON.stringify(content);
|
|
798
|
+
const userMsg = {
|
|
799
|
+
id: `tmp-user-${Date.now()}`,
|
|
800
|
+
chatId: activeChatId,
|
|
801
|
+
role: "user",
|
|
802
|
+
content: displayContent,
|
|
803
|
+
toolCalls: null,
|
|
804
|
+
toolCallId: null,
|
|
805
|
+
name: null,
|
|
806
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
807
|
+
};
|
|
808
|
+
setMessages((prev) => [...prev, userMsg]);
|
|
809
|
+
const assistantId = `tmp-assistant-${Date.now()}`;
|
|
810
|
+
activeAssistantIdRef.current = assistantId;
|
|
811
|
+
const assistantMsg = {
|
|
812
|
+
id: assistantId,
|
|
813
|
+
chatId: activeChatId,
|
|
814
|
+
role: "assistant",
|
|
815
|
+
content: "",
|
|
816
|
+
toolCalls: null,
|
|
817
|
+
toolCallId: null,
|
|
818
|
+
name: null,
|
|
819
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
820
|
+
streaming: true
|
|
821
|
+
};
|
|
822
|
+
setMessages((prev) => [...prev, assistantMsg]);
|
|
823
|
+
const controller = streamMessage(
|
|
824
|
+
client,
|
|
825
|
+
activeChatId,
|
|
826
|
+
content,
|
|
827
|
+
handleStreamChunks,
|
|
828
|
+
() => {
|
|
829
|
+
setStreaming(false);
|
|
830
|
+
setToolStatus([]);
|
|
831
|
+
refreshMessages(activeChatId);
|
|
832
|
+
},
|
|
833
|
+
(err) => {
|
|
834
|
+
setError(err.message);
|
|
835
|
+
setStreaming(false);
|
|
836
|
+
setToolStatus([]);
|
|
837
|
+
}
|
|
838
|
+
);
|
|
839
|
+
abortRef.current = controller;
|
|
840
|
+
};
|
|
841
|
+
doSend();
|
|
842
|
+
},
|
|
843
|
+
[client, agentRef, options?.input, handleStreamChunks, refreshMessages]
|
|
844
|
+
);
|
|
845
|
+
const handleApproval = import_react5.default.useCallback(
|
|
846
|
+
(toolCallId, approved) => {
|
|
847
|
+
const currentChatId = chatIdRef.current;
|
|
848
|
+
if (!currentChatId) return;
|
|
849
|
+
setPendingApprovals((prev) => prev.filter((a) => a.toolCallId !== toolCallId));
|
|
584
850
|
setStreaming(true);
|
|
585
851
|
setError(null);
|
|
586
|
-
const
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
setMessages(
|
|
610
|
-
(prev) => prev.map(
|
|
611
|
-
(m) => m.id === assistantId ? { ...m, content: m.content + chunk.data } : m
|
|
612
|
-
)
|
|
613
|
-
);
|
|
852
|
+
const assistantId = `tmp-resume-${Date.now()}`;
|
|
853
|
+
activeAssistantIdRef.current = assistantId;
|
|
854
|
+
if (approved) {
|
|
855
|
+
const assistantMsg = {
|
|
856
|
+
id: assistantId,
|
|
857
|
+
chatId: currentChatId,
|
|
858
|
+
role: "assistant",
|
|
859
|
+
content: "",
|
|
860
|
+
toolCalls: null,
|
|
861
|
+
toolCallId: null,
|
|
862
|
+
name: null,
|
|
863
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
864
|
+
streaming: true
|
|
865
|
+
};
|
|
866
|
+
setMessages((prev) => [...prev, assistantMsg]);
|
|
867
|
+
}
|
|
868
|
+
(async () => {
|
|
869
|
+
try {
|
|
870
|
+
const result = await approveToolCall(client, currentChatId, toolCallId, approved);
|
|
871
|
+
if (!approved) {
|
|
872
|
+
setStreaming(false);
|
|
873
|
+
refreshMessages(currentChatId);
|
|
874
|
+
return;
|
|
614
875
|
}
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
876
|
+
const controller = streamFromChannel(
|
|
877
|
+
client,
|
|
878
|
+
currentChatId,
|
|
879
|
+
result.channelId,
|
|
880
|
+
handleStreamChunks,
|
|
881
|
+
() => {
|
|
882
|
+
setStreaming(false);
|
|
883
|
+
setToolStatus([]);
|
|
884
|
+
refreshMessages(currentChatId);
|
|
885
|
+
},
|
|
886
|
+
(err) => {
|
|
887
|
+
setError(err.message);
|
|
888
|
+
setStreaming(false);
|
|
889
|
+
setToolStatus([]);
|
|
890
|
+
}
|
|
891
|
+
);
|
|
892
|
+
abortRef.current = controller;
|
|
893
|
+
} catch (e) {
|
|
894
|
+
setError(e.message);
|
|
621
895
|
setStreaming(false);
|
|
622
896
|
}
|
|
623
|
-
);
|
|
624
|
-
abortRef.current = controller;
|
|
625
|
-
return controller;
|
|
897
|
+
})();
|
|
626
898
|
},
|
|
627
|
-
[client,
|
|
899
|
+
[client, handleStreamChunks, refreshMessages]
|
|
900
|
+
);
|
|
901
|
+
const approve = import_react5.default.useCallback(
|
|
902
|
+
(toolCallId) => handleApproval(toolCallId, true),
|
|
903
|
+
[handleApproval]
|
|
628
904
|
);
|
|
905
|
+
const reject = import_react5.default.useCallback(
|
|
906
|
+
(toolCallId) => handleApproval(toolCallId, false),
|
|
907
|
+
[handleApproval]
|
|
908
|
+
);
|
|
909
|
+
const stop = import_react5.default.useCallback(() => {
|
|
910
|
+
abortRef.current?.abort();
|
|
911
|
+
abortRef.current = null;
|
|
912
|
+
setStreaming(false);
|
|
913
|
+
}, []);
|
|
914
|
+
const clearError = import_react5.default.useCallback(() => {
|
|
915
|
+
setError(null);
|
|
916
|
+
}, []);
|
|
629
917
|
return {
|
|
630
918
|
chatId,
|
|
631
919
|
messages,
|
|
632
920
|
loading,
|
|
633
921
|
streaming,
|
|
634
922
|
error,
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
923
|
+
pendingApprovals,
|
|
924
|
+
toolStatus,
|
|
925
|
+
send,
|
|
926
|
+
approve,
|
|
927
|
+
reject,
|
|
928
|
+
stop,
|
|
929
|
+
clearError
|
|
638
930
|
};
|
|
639
931
|
}
|
|
640
932
|
|
|
@@ -660,14 +952,19 @@ function useSinas() {
|
|
|
660
952
|
SinasPermissionError,
|
|
661
953
|
SinasProvider,
|
|
662
954
|
SinasTimeoutError,
|
|
955
|
+
approveToolCall,
|
|
663
956
|
createChat,
|
|
664
957
|
executeFunction,
|
|
665
958
|
executeQuery,
|
|
959
|
+
getChat,
|
|
960
|
+
listCollections,
|
|
961
|
+
listFiles,
|
|
666
962
|
sendMessage,
|
|
667
963
|
stateDelete,
|
|
668
964
|
stateGet,
|
|
669
965
|
stateList,
|
|
670
966
|
stateSet,
|
|
967
|
+
streamFromChannel,
|
|
671
968
|
streamMessage,
|
|
672
969
|
useChat,
|
|
673
970
|
useExecute,
|