@sinas/sdk 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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 +301 -87
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -8
- package/dist/index.d.ts +19 -8
- package/dist/index.js +208 -88
- package/dist/index.js.map +1 -1
- package/dist/sinas-sdk.umd.js +296 -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,235 @@ 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([]);
|
|
537
637
|
const abortRef = import_react5.default.useRef(null);
|
|
638
|
+
const chatIdRef = import_react5.default.useRef(chatId);
|
|
639
|
+
chatIdRef.current = chatId;
|
|
640
|
+
import_react5.default.useEffect(() => {
|
|
641
|
+
if (!options?.chatId) return;
|
|
642
|
+
let cancelled = false;
|
|
643
|
+
setLoading(true);
|
|
644
|
+
getChat(client, options.chatId).then((detail) => {
|
|
645
|
+
if (cancelled) return;
|
|
646
|
+
setChatId(detail.id);
|
|
647
|
+
setMessages(detail.messages);
|
|
648
|
+
}).catch((e) => {
|
|
649
|
+
if (cancelled) return;
|
|
650
|
+
setError(e.message);
|
|
651
|
+
}).finally(() => {
|
|
652
|
+
if (!cancelled) setLoading(false);
|
|
653
|
+
});
|
|
654
|
+
return () => {
|
|
655
|
+
cancelled = true;
|
|
656
|
+
};
|
|
657
|
+
}, [client, options?.chatId]);
|
|
538
658
|
import_react5.default.useEffect(() => {
|
|
539
659
|
return () => {
|
|
540
660
|
abortRef.current?.abort();
|
|
541
661
|
};
|
|
542
662
|
}, []);
|
|
543
|
-
const
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
663
|
+
const handleStreamChunks = import_react5.default.useCallback(
|
|
664
|
+
(assistantId) => (chunk) => {
|
|
665
|
+
if (chunk.event === "message") {
|
|
666
|
+
try {
|
|
667
|
+
const parsed = JSON.parse(chunk.data);
|
|
668
|
+
if (parsed.content) {
|
|
669
|
+
setMessages(
|
|
670
|
+
(prev) => prev.map(
|
|
671
|
+
(m) => m.id === assistantId ? { ...m, content: (m.content || "") + parsed.content } : m
|
|
672
|
+
)
|
|
673
|
+
);
|
|
674
|
+
}
|
|
675
|
+
} catch {
|
|
676
|
+
setMessages(
|
|
677
|
+
(prev) => prev.map(
|
|
678
|
+
(m) => m.id === assistantId ? { ...m, content: (m.content || "") + chunk.data } : m
|
|
679
|
+
)
|
|
680
|
+
);
|
|
681
|
+
}
|
|
682
|
+
} else if (chunk.event === "approval_required") {
|
|
683
|
+
try {
|
|
684
|
+
const parsed = JSON.parse(chunk.data);
|
|
685
|
+
setPendingApprovals((prev) => [...prev, parsed]);
|
|
686
|
+
} catch {
|
|
687
|
+
}
|
|
688
|
+
} else if (chunk.event === "error") {
|
|
689
|
+
try {
|
|
690
|
+
const parsed = JSON.parse(chunk.data);
|
|
691
|
+
setError(parsed.error || "Stream error");
|
|
692
|
+
} catch {
|
|
693
|
+
setError(chunk.data || "Stream error");
|
|
694
|
+
}
|
|
556
695
|
}
|
|
557
696
|
},
|
|
558
|
-
[
|
|
697
|
+
[]
|
|
559
698
|
);
|
|
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]);
|
|
699
|
+
const refreshMessages = import_react5.default.useCallback(
|
|
700
|
+
async (id) => {
|
|
576
701
|
try {
|
|
577
|
-
const
|
|
578
|
-
setMessages(
|
|
579
|
-
|
|
580
|
-
} catch (e) {
|
|
581
|
-
setError(e.message);
|
|
582
|
-
} finally {
|
|
583
|
-
setLoading(false);
|
|
702
|
+
const detail = await getChat(client, id);
|
|
703
|
+
setMessages(detail.messages);
|
|
704
|
+
} catch {
|
|
584
705
|
}
|
|
585
706
|
},
|
|
586
|
-
[client
|
|
707
|
+
[client]
|
|
587
708
|
);
|
|
588
|
-
const
|
|
709
|
+
const send = import_react5.default.useCallback(
|
|
589
710
|
(content) => {
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
711
|
+
const doSend = async () => {
|
|
712
|
+
let activeChatId = chatIdRef.current;
|
|
713
|
+
if (!activeChatId) {
|
|
714
|
+
setLoading(true);
|
|
715
|
+
setError(null);
|
|
716
|
+
try {
|
|
717
|
+
const result = await createChat(client, agentRef, options?.input);
|
|
718
|
+
activeChatId = result.id;
|
|
719
|
+
setChatId(result.id);
|
|
720
|
+
chatIdRef.current = result.id;
|
|
721
|
+
} catch (e) {
|
|
722
|
+
setError(e.message);
|
|
723
|
+
setLoading(false);
|
|
724
|
+
return;
|
|
725
|
+
}
|
|
726
|
+
setLoading(false);
|
|
727
|
+
}
|
|
728
|
+
abortRef.current?.abort();
|
|
729
|
+
setStreaming(true);
|
|
730
|
+
setError(null);
|
|
731
|
+
setPendingApprovals([]);
|
|
732
|
+
const displayContent = typeof content === "string" ? content : JSON.stringify(content);
|
|
733
|
+
const userMsg = {
|
|
734
|
+
id: `tmp-user-${Date.now()}`,
|
|
735
|
+
chatId: activeChatId,
|
|
736
|
+
role: "user",
|
|
737
|
+
content: displayContent,
|
|
738
|
+
toolCalls: null,
|
|
739
|
+
toolCallId: null,
|
|
740
|
+
name: null,
|
|
741
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
742
|
+
};
|
|
743
|
+
setMessages((prev) => [...prev, userMsg]);
|
|
744
|
+
const assistantId = `tmp-assistant-${Date.now()}`;
|
|
745
|
+
const assistantMsg = {
|
|
746
|
+
id: assistantId,
|
|
747
|
+
chatId: activeChatId,
|
|
748
|
+
role: "assistant",
|
|
749
|
+
content: "",
|
|
750
|
+
toolCalls: null,
|
|
751
|
+
toolCallId: null,
|
|
752
|
+
name: null,
|
|
753
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
754
|
+
streaming: true
|
|
755
|
+
};
|
|
756
|
+
setMessages((prev) => [...prev, assistantMsg]);
|
|
757
|
+
const controller = streamMessage(
|
|
758
|
+
client,
|
|
759
|
+
activeChatId,
|
|
760
|
+
content,
|
|
761
|
+
handleStreamChunks(assistantId),
|
|
762
|
+
() => {
|
|
763
|
+
setStreaming(false);
|
|
764
|
+
refreshMessages(activeChatId);
|
|
765
|
+
},
|
|
766
|
+
(err) => {
|
|
767
|
+
setError(err.message);
|
|
768
|
+
setStreaming(false);
|
|
769
|
+
}
|
|
770
|
+
);
|
|
771
|
+
abortRef.current = controller;
|
|
772
|
+
};
|
|
773
|
+
doSend();
|
|
774
|
+
},
|
|
775
|
+
[client, agentRef, options?.input, handleStreamChunks, refreshMessages]
|
|
776
|
+
);
|
|
777
|
+
const handleApproval = import_react5.default.useCallback(
|
|
778
|
+
(toolCallId, approved) => {
|
|
779
|
+
const currentChatId = chatIdRef.current;
|
|
780
|
+
if (!currentChatId) return;
|
|
781
|
+
setPendingApprovals((prev) => prev.filter((a) => a.toolCallId !== toolCallId));
|
|
595
782
|
setStreaming(true);
|
|
596
783
|
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
|
-
if (chunk.event === "content" || chunk.event === "message") {
|
|
620
|
-
setMessages(
|
|
621
|
-
(prev) => prev.map(
|
|
622
|
-
(m) => m.id === assistantId ? { ...m, content: m.content + chunk.data } : m
|
|
623
|
-
)
|
|
624
|
-
);
|
|
784
|
+
const assistantId = `tmp-resume-${Date.now()}`;
|
|
785
|
+
if (approved) {
|
|
786
|
+
const assistantMsg = {
|
|
787
|
+
id: assistantId,
|
|
788
|
+
chatId: currentChatId,
|
|
789
|
+
role: "assistant",
|
|
790
|
+
content: "",
|
|
791
|
+
toolCalls: null,
|
|
792
|
+
toolCallId: null,
|
|
793
|
+
name: null,
|
|
794
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
795
|
+
streaming: true
|
|
796
|
+
};
|
|
797
|
+
setMessages((prev) => [...prev, assistantMsg]);
|
|
798
|
+
}
|
|
799
|
+
(async () => {
|
|
800
|
+
try {
|
|
801
|
+
const result = await approveToolCall(client, currentChatId, toolCallId, approved);
|
|
802
|
+
if (!approved) {
|
|
803
|
+
setStreaming(false);
|
|
804
|
+
refreshMessages(currentChatId);
|
|
805
|
+
return;
|
|
625
806
|
}
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
807
|
+
const controller = streamFromChannel(
|
|
808
|
+
client,
|
|
809
|
+
currentChatId,
|
|
810
|
+
result.channelId,
|
|
811
|
+
handleStreamChunks(assistantId),
|
|
812
|
+
() => {
|
|
813
|
+
setStreaming(false);
|
|
814
|
+
refreshMessages(currentChatId);
|
|
815
|
+
},
|
|
816
|
+
(err) => {
|
|
817
|
+
setError(err.message);
|
|
818
|
+
setStreaming(false);
|
|
819
|
+
}
|
|
820
|
+
);
|
|
821
|
+
abortRef.current = controller;
|
|
822
|
+
} catch (e) {
|
|
823
|
+
setError(e.message);
|
|
632
824
|
setStreaming(false);
|
|
633
825
|
}
|
|
634
|
-
);
|
|
635
|
-
abortRef.current = controller;
|
|
636
|
-
return controller;
|
|
826
|
+
})();
|
|
637
827
|
},
|
|
638
|
-
[client,
|
|
828
|
+
[client, handleStreamChunks, refreshMessages]
|
|
829
|
+
);
|
|
830
|
+
const approve = import_react5.default.useCallback(
|
|
831
|
+
(toolCallId) => handleApproval(toolCallId, true),
|
|
832
|
+
[handleApproval]
|
|
639
833
|
);
|
|
834
|
+
const reject = import_react5.default.useCallback(
|
|
835
|
+
(toolCallId) => handleApproval(toolCallId, false),
|
|
836
|
+
[handleApproval]
|
|
837
|
+
);
|
|
838
|
+
const stop = import_react5.default.useCallback(() => {
|
|
839
|
+
abortRef.current?.abort();
|
|
840
|
+
abortRef.current = null;
|
|
841
|
+
setStreaming(false);
|
|
842
|
+
}, []);
|
|
843
|
+
const clearError = import_react5.default.useCallback(() => {
|
|
844
|
+
setError(null);
|
|
845
|
+
}, []);
|
|
640
846
|
return {
|
|
641
847
|
chatId,
|
|
642
848
|
messages,
|
|
643
849
|
loading,
|
|
644
850
|
streaming,
|
|
645
851
|
error,
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
852
|
+
pendingApprovals,
|
|
853
|
+
send,
|
|
854
|
+
approve,
|
|
855
|
+
reject,
|
|
856
|
+
stop,
|
|
857
|
+
clearError
|
|
649
858
|
};
|
|
650
859
|
}
|
|
651
860
|
|