@sinas/sdk 0.2.3 → 0.5.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-Z6NVKMMG.js → chunk-IABVF56L.js} +189 -18
- package/dist/chunk-IABVF56L.js.map +1 -0
- package/dist/client.cjs +198 -19
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +118 -5
- package/dist/client.d.ts +118 -5
- package/dist/client.js +19 -3
- package/dist/index.cjs +331 -102
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +41 -4
- package/dist/index.d.ts +41 -4
- package/dist/index.js +151 -86
- package/dist/index.js.map +1 -1
- package/dist/sinas-sdk.umd.js +321 -101
- package/dist/sinas-sdk.umd.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-Z6NVKMMG.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -32,19 +32,26 @@ var src_exports = {};
|
|
|
32
32
|
__export(src_exports, {
|
|
33
33
|
SinasAuthError: () => SinasAuthError,
|
|
34
34
|
SinasClient: () => SinasClient,
|
|
35
|
+
SinasClientAuth: () => SinasClientAuth,
|
|
35
36
|
SinasError: () => SinasError,
|
|
36
37
|
SinasNotFoundError: () => SinasNotFoundError,
|
|
37
38
|
SinasPermissionError: () => SinasPermissionError,
|
|
38
39
|
SinasProvider: () => SinasProvider,
|
|
39
40
|
SinasTimeoutError: () => SinasTimeoutError,
|
|
40
41
|
approveToolCall: () => approveToolCall,
|
|
42
|
+
checkPermissions: () => checkPermissions,
|
|
41
43
|
createChat: () => createChat,
|
|
42
44
|
executeFunction: () => executeFunction,
|
|
43
45
|
executeQuery: () => executeQuery,
|
|
44
46
|
generateFileUrl: () => generateFileUrl,
|
|
45
47
|
getChat: () => getChat,
|
|
48
|
+
getInfo: () => getInfo,
|
|
49
|
+
getMe: () => getMe,
|
|
46
50
|
listCollections: () => listCollections,
|
|
47
51
|
listFiles: () => listFiles,
|
|
52
|
+
login: () => login,
|
|
53
|
+
logout: () => logout,
|
|
54
|
+
refresh: () => refresh,
|
|
48
55
|
sendMessage: () => sendMessage,
|
|
49
56
|
stateDelete: () => stateDelete,
|
|
50
57
|
stateGet: () => stateGet,
|
|
@@ -53,12 +60,14 @@ __export(src_exports, {
|
|
|
53
60
|
streamFromChannel: () => streamFromChannel,
|
|
54
61
|
streamMessage: () => streamMessage,
|
|
55
62
|
uploadFile: () => uploadFile,
|
|
63
|
+
useAuth: () => useAuth,
|
|
56
64
|
useChat: () => useChat,
|
|
57
65
|
useClient: () => useClient,
|
|
58
66
|
useExecute: () => useExecute,
|
|
59
67
|
useQuery: () => useQuery,
|
|
60
68
|
useSinas: () => useSinas,
|
|
61
|
-
useStateStore: () => useStateStore
|
|
69
|
+
useStateStore: () => useStateStore,
|
|
70
|
+
verifyOTP: () => verifyOTP
|
|
62
71
|
});
|
|
63
72
|
module.exports = __toCommonJS(src_exports);
|
|
64
73
|
|
|
@@ -96,16 +105,131 @@ var SinasTimeoutError = class extends SinasError {
|
|
|
96
105
|
}
|
|
97
106
|
};
|
|
98
107
|
|
|
108
|
+
// src/client/auth.ts
|
|
109
|
+
function trimBase(baseUrl) {
|
|
110
|
+
return baseUrl.replace(/\/+$/, "");
|
|
111
|
+
}
|
|
112
|
+
async function authFetch(baseUrl, path, init = {}, accessToken) {
|
|
113
|
+
const headers = new Headers(init.headers);
|
|
114
|
+
if (!headers.has("Content-Type") && init.body !== void 0) {
|
|
115
|
+
headers.set("Content-Type", "application/json");
|
|
116
|
+
}
|
|
117
|
+
if (accessToken) headers.set("Authorization", `Bearer ${accessToken}`);
|
|
118
|
+
const res = await fetch(`${trimBase(baseUrl)}${path}`, { ...init, headers });
|
|
119
|
+
if (res.ok || res.status === 204) return res;
|
|
120
|
+
let detail = res.statusText;
|
|
121
|
+
try {
|
|
122
|
+
const body = await res.clone().json();
|
|
123
|
+
detail = body.detail || body.message || detail;
|
|
124
|
+
} catch {
|
|
125
|
+
}
|
|
126
|
+
if (res.status === 401) throw new SinasAuthError(detail);
|
|
127
|
+
if (res.status === 403) throw new SinasPermissionError(detail);
|
|
128
|
+
if (res.status === 404) throw new SinasNotFoundError(detail);
|
|
129
|
+
throw new SinasError(detail, res.status, detail);
|
|
130
|
+
}
|
|
131
|
+
async function getInfo(baseUrl) {
|
|
132
|
+
const res = await authFetch(baseUrl, "/info");
|
|
133
|
+
return await res.json();
|
|
134
|
+
}
|
|
135
|
+
async function login(baseUrl, request) {
|
|
136
|
+
const res = await authFetch(baseUrl, "/auth/login", {
|
|
137
|
+
method: "POST",
|
|
138
|
+
body: JSON.stringify(request)
|
|
139
|
+
});
|
|
140
|
+
return await res.json();
|
|
141
|
+
}
|
|
142
|
+
async function verifyOTP(baseUrl, request) {
|
|
143
|
+
const res = await authFetch(baseUrl, "/auth/verify-otp", {
|
|
144
|
+
method: "POST",
|
|
145
|
+
body: JSON.stringify(request)
|
|
146
|
+
});
|
|
147
|
+
return await res.json();
|
|
148
|
+
}
|
|
149
|
+
async function refresh(baseUrl, refreshToken) {
|
|
150
|
+
const res = await authFetch(baseUrl, "/auth/refresh", {
|
|
151
|
+
method: "POST",
|
|
152
|
+
body: JSON.stringify({ refresh_token: refreshToken })
|
|
153
|
+
});
|
|
154
|
+
return await res.json();
|
|
155
|
+
}
|
|
156
|
+
async function logout(baseUrl, refreshToken) {
|
|
157
|
+
try {
|
|
158
|
+
await authFetch(baseUrl, "/auth/logout", {
|
|
159
|
+
method: "POST",
|
|
160
|
+
body: JSON.stringify({ refresh_token: refreshToken })
|
|
161
|
+
});
|
|
162
|
+
} catch (e) {
|
|
163
|
+
if (e instanceof SinasNotFoundError) return;
|
|
164
|
+
throw e;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
async function getMe(baseUrl, accessToken) {
|
|
168
|
+
const res = await authFetch(baseUrl, "/auth/me", { method: "GET" }, accessToken);
|
|
169
|
+
return await res.json();
|
|
170
|
+
}
|
|
171
|
+
async function checkPermissions(baseUrl, accessToken, request) {
|
|
172
|
+
const res = await authFetch(
|
|
173
|
+
baseUrl,
|
|
174
|
+
"/auth/check-permissions",
|
|
175
|
+
{
|
|
176
|
+
method: "POST",
|
|
177
|
+
body: JSON.stringify({ logic: "AND", ...request })
|
|
178
|
+
},
|
|
179
|
+
accessToken
|
|
180
|
+
);
|
|
181
|
+
return await res.json();
|
|
182
|
+
}
|
|
183
|
+
|
|
99
184
|
// src/client/SinasClient.ts
|
|
185
|
+
function hasWindow() {
|
|
186
|
+
return typeof window !== "undefined";
|
|
187
|
+
}
|
|
188
|
+
function trim(url) {
|
|
189
|
+
return url.replace(/\/+$/, "");
|
|
190
|
+
}
|
|
191
|
+
var SinasClientAuth = class {
|
|
192
|
+
constructor(client) {
|
|
193
|
+
this.client = client;
|
|
194
|
+
}
|
|
195
|
+
getInfo() {
|
|
196
|
+
return getInfo(this.client.requireBaseUrl());
|
|
197
|
+
}
|
|
198
|
+
login(request) {
|
|
199
|
+
return login(this.client.requireBaseUrl(), request);
|
|
200
|
+
}
|
|
201
|
+
verifyOTP(request) {
|
|
202
|
+
return verifyOTP(this.client.requireBaseUrl(), request);
|
|
203
|
+
}
|
|
204
|
+
refresh(refreshToken) {
|
|
205
|
+
return refresh(this.client.requireBaseUrl(), refreshToken);
|
|
206
|
+
}
|
|
207
|
+
logout(refreshToken) {
|
|
208
|
+
return logout(this.client.requireBaseUrl(), refreshToken);
|
|
209
|
+
}
|
|
210
|
+
getMe() {
|
|
211
|
+
const token = this.client.getAccessToken();
|
|
212
|
+
if (!token) throw new SinasAuthError("No access token available");
|
|
213
|
+
return getMe(this.client.requireBaseUrl(), token);
|
|
214
|
+
}
|
|
215
|
+
checkPermissions(request) {
|
|
216
|
+
const token = this.client.getAccessToken();
|
|
217
|
+
if (!token) throw new SinasAuthError("No access token available");
|
|
218
|
+
return checkPermissions(this.client.requireBaseUrl(), token, request);
|
|
219
|
+
}
|
|
220
|
+
};
|
|
100
221
|
var SinasClient = class {
|
|
101
|
-
constructor(
|
|
102
|
-
this.
|
|
222
|
+
constructor(options = {}) {
|
|
223
|
+
this.refreshInFlight = null;
|
|
224
|
+
this.options = options;
|
|
225
|
+
this.auth = new SinasClientAuth(this);
|
|
103
226
|
}
|
|
227
|
+
// ─── Config / base URL ───
|
|
104
228
|
getConfig() {
|
|
105
|
-
const config = this.
|
|
229
|
+
const config = this.options.config || (hasWindow() ? window.__SINAS_CONFIG__ : void 0);
|
|
106
230
|
if (!config) {
|
|
107
231
|
return {
|
|
108
|
-
apiBase: "",
|
|
232
|
+
apiBase: this.options.baseUrl ? `${trim(this.options.baseUrl)}/api/v1` : "",
|
|
109
233
|
component: { namespace: "", name: "", version: "" },
|
|
110
234
|
resources: {
|
|
111
235
|
enabledAgents: [],
|
|
@@ -122,12 +246,56 @@ var SinasClient = class {
|
|
|
122
246
|
getInput() {
|
|
123
247
|
return this.getConfig().input || {};
|
|
124
248
|
}
|
|
249
|
+
/** Workspace base URL (root of the Sinas instance). Throws if unset. */
|
|
250
|
+
requireBaseUrl() {
|
|
251
|
+
const url = this.getBaseUrl();
|
|
252
|
+
if (!url) {
|
|
253
|
+
throw new SinasError(
|
|
254
|
+
"No baseUrl configured. Construct with `new SinasClient({ baseUrl })` for standalone use.",
|
|
255
|
+
0
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
return url;
|
|
259
|
+
}
|
|
260
|
+
getBaseUrl() {
|
|
261
|
+
if (this.options.baseUrl) return trim(this.options.baseUrl);
|
|
262
|
+
const apiBase = this.getConfig().apiBase;
|
|
263
|
+
if (!apiBase) return null;
|
|
264
|
+
return trim(apiBase).replace(/\/api\/v1$/, "");
|
|
265
|
+
}
|
|
266
|
+
// ─── Tokens ───
|
|
267
|
+
getAccessToken() {
|
|
268
|
+
if (this.options.getAccessToken) return this.options.getAccessToken();
|
|
269
|
+
if (hasWindow()) return window.__SINAS_AUTH_TOKEN__ ?? null;
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
getRefreshToken() {
|
|
273
|
+
return this.options.getRefreshToken ? this.options.getRefreshToken() : null;
|
|
274
|
+
}
|
|
275
|
+
async tryRefresh() {
|
|
276
|
+
const refreshToken = this.getRefreshToken();
|
|
277
|
+
if (!refreshToken) return null;
|
|
278
|
+
if (this.refreshInFlight) return this.refreshInFlight;
|
|
279
|
+
const baseUrl = this.getBaseUrl();
|
|
280
|
+
if (!baseUrl) return null;
|
|
281
|
+
this.refreshInFlight = (async () => {
|
|
282
|
+
try {
|
|
283
|
+
const resp = await refresh(baseUrl, refreshToken);
|
|
284
|
+
this.options.onTokenRefresh?.(resp.access_token);
|
|
285
|
+
return resp.access_token;
|
|
286
|
+
} catch {
|
|
287
|
+
return null;
|
|
288
|
+
} finally {
|
|
289
|
+
this.refreshInFlight = null;
|
|
290
|
+
}
|
|
291
|
+
})();
|
|
292
|
+
return this.refreshInFlight;
|
|
293
|
+
}
|
|
294
|
+
// ─── Headers / proxy ───
|
|
125
295
|
getAuthHeaders() {
|
|
126
|
-
const token =
|
|
296
|
+
const token = this.getAccessToken();
|
|
127
297
|
const headers = { "Content-Type": "application/json" };
|
|
128
|
-
if (token) {
|
|
129
|
-
headers["Authorization"] = `Bearer ${token}`;
|
|
130
|
-
}
|
|
298
|
+
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
131
299
|
return headers;
|
|
132
300
|
}
|
|
133
301
|
getProxyBase() {
|
|
@@ -135,7 +303,8 @@ var SinasClient = class {
|
|
|
135
303
|
const comp = config.component;
|
|
136
304
|
return `${config.apiBase}/components/${comp.namespace}/${comp.name}/proxy`;
|
|
137
305
|
}
|
|
138
|
-
|
|
306
|
+
// ─── Fetch with refresh-on-401 ───
|
|
307
|
+
async fetch(url, options = {}, _retried = false) {
|
|
139
308
|
const res = await fetch(url, {
|
|
140
309
|
...options,
|
|
141
310
|
headers: {
|
|
@@ -143,15 +312,18 @@ var SinasClient = class {
|
|
|
143
312
|
...options.headers || {}
|
|
144
313
|
}
|
|
145
314
|
});
|
|
146
|
-
if (
|
|
147
|
-
|
|
148
|
-
const
|
|
149
|
-
if (
|
|
150
|
-
|
|
151
|
-
if (res.status === 404) throw new SinasNotFoundError(message);
|
|
152
|
-
throw new SinasError(message, res.status);
|
|
315
|
+
if (res.ok || res.status === 204) return res;
|
|
316
|
+
if (res.status === 401 && !_retried) {
|
|
317
|
+
const newToken = await this.tryRefresh();
|
|
318
|
+
if (newToken) return this.fetch(url, options, true);
|
|
319
|
+
this.options.onUnauthenticated?.();
|
|
153
320
|
}
|
|
154
|
-
|
|
321
|
+
const body = await res.json().catch(() => ({ detail: res.statusText }));
|
|
322
|
+
const message = body.detail || body.message || res.statusText;
|
|
323
|
+
if (res.status === 401) throw new SinasAuthError(message);
|
|
324
|
+
if (res.status === 403) throw new SinasPermissionError(message);
|
|
325
|
+
if (res.status === 404) throw new SinasNotFoundError(message);
|
|
326
|
+
throw new SinasError(message, res.status);
|
|
155
327
|
}
|
|
156
328
|
};
|
|
157
329
|
|
|
@@ -475,8 +647,14 @@ var import_react2 = __toESM(require("react"), 1);
|
|
|
475
647
|
// src/hooks/context.ts
|
|
476
648
|
var import_react = __toESM(require("react"), 1);
|
|
477
649
|
var SinasContext = import_react.default.createContext(null);
|
|
478
|
-
function SinasProvider({ client, children }) {
|
|
479
|
-
const value = import_react.default.useMemo(
|
|
650
|
+
function SinasProvider({ client, options, children }) {
|
|
651
|
+
const value = import_react.default.useMemo(
|
|
652
|
+
() => client || new SinasClient(options),
|
|
653
|
+
// We intentionally only re-create when `client` reference changes; `options`
|
|
654
|
+
// is expected to be a stable object (callbacks reading from localStorage).
|
|
655
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
656
|
+
[client]
|
|
657
|
+
);
|
|
480
658
|
return import_react.default.createElement(SinasContext.Provider, { value }, children);
|
|
481
659
|
}
|
|
482
660
|
function useClient() {
|
|
@@ -656,8 +834,6 @@ function useChat(agentRef, options) {
|
|
|
656
834
|
const abortRef = import_react5.default.useRef(null);
|
|
657
835
|
const chatIdRef = import_react5.default.useRef(chatId);
|
|
658
836
|
chatIdRef.current = chatId;
|
|
659
|
-
const activeAssistantIdRef = import_react5.default.useRef("");
|
|
660
|
-
const activeToolCallMsgIdRef = import_react5.default.useRef("");
|
|
661
837
|
import_react5.default.useEffect(() => {
|
|
662
838
|
if (!options?.chatId) return;
|
|
663
839
|
let cancelled = false;
|
|
@@ -687,24 +863,34 @@ function useChat(agentRef, options) {
|
|
|
687
863
|
const handleStreamChunks = import_react5.default.useCallback(
|
|
688
864
|
(chunk) => {
|
|
689
865
|
if (chunk.event === "message") {
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
(m) => m.id === targetId ? { ...m, content: (m.content || "") + parsed.content } : m
|
|
697
|
-
)
|
|
698
|
-
);
|
|
866
|
+
const newContent = (() => {
|
|
867
|
+
try {
|
|
868
|
+
const parsed = JSON.parse(chunk.data);
|
|
869
|
+
return parsed.content || "";
|
|
870
|
+
} catch {
|
|
871
|
+
return chunk.data;
|
|
699
872
|
}
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
873
|
+
})();
|
|
874
|
+
if (!newContent) return;
|
|
875
|
+
setMessages((prev) => {
|
|
876
|
+
const last = prev[prev.length - 1];
|
|
877
|
+
if (last && last.role === "assistant" && !last.toolCalls && last.streaming) {
|
|
878
|
+
const next = [...prev];
|
|
879
|
+
next[next.length - 1] = { ...last, content: (last.content || "") + newContent };
|
|
880
|
+
return next;
|
|
881
|
+
}
|
|
882
|
+
return [...prev, {
|
|
883
|
+
id: `tmp-text-${Date.now()}`,
|
|
884
|
+
chatId: chatIdRef.current || "",
|
|
885
|
+
role: "assistant",
|
|
886
|
+
content: newContent,
|
|
887
|
+
toolCalls: null,
|
|
888
|
+
toolCallId: null,
|
|
889
|
+
name: null,
|
|
890
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
891
|
+
streaming: true
|
|
892
|
+
}];
|
|
893
|
+
});
|
|
708
894
|
} else if (chunk.event === "tool_start") {
|
|
709
895
|
try {
|
|
710
896
|
const parsed = JSON.parse(chunk.data);
|
|
@@ -712,35 +898,29 @@ function useChat(agentRef, options) {
|
|
|
712
898
|
...prev,
|
|
713
899
|
{ toolCallId: parsed.tool_call_id, name: parsed.name, description: parsed.description, status: "running" }
|
|
714
900
|
]);
|
|
715
|
-
const placeholderId = activeAssistantIdRef.current;
|
|
716
|
-
const toolCallMsg = {
|
|
717
|
-
id: `tmp-tc-${parsed.tool_call_id}`,
|
|
718
|
-
chatId: chatIdRef.current || "",
|
|
719
|
-
role: "assistant",
|
|
720
|
-
content: null,
|
|
721
|
-
toolCalls: [{
|
|
722
|
-
id: parsed.tool_call_id,
|
|
723
|
-
type: "function",
|
|
724
|
-
function: { name: parsed.name, arguments: parsed.arguments || "{}" },
|
|
725
|
-
description: parsed.description
|
|
726
|
-
}],
|
|
727
|
-
toolCallId: null,
|
|
728
|
-
name: null,
|
|
729
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
730
|
-
streaming: true
|
|
731
|
-
};
|
|
732
901
|
setMessages((prev) => {
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
);
|
|
736
|
-
if (alreadyExists) return prev;
|
|
737
|
-
const idx = prev.findIndex((m) => m.id === placeholderId);
|
|
738
|
-
if (idx >= 0) {
|
|
739
|
-
const next = [...prev];
|
|
740
|
-
next.splice(idx, 0, toolCallMsg);
|
|
741
|
-
return next;
|
|
902
|
+
if (prev.some((m) => m.toolCalls?.some((tc) => tc.id === parsed.tool_call_id))) {
|
|
903
|
+
return prev;
|
|
742
904
|
}
|
|
743
|
-
|
|
905
|
+
const next = prev.map(
|
|
906
|
+
(m, i) => i === prev.length - 1 && m.streaming && m.role === "assistant" && !m.toolCalls ? { ...m, streaming: false } : m
|
|
907
|
+
);
|
|
908
|
+
return [...next, {
|
|
909
|
+
id: `tmp-tc-${parsed.tool_call_id}`,
|
|
910
|
+
chatId: chatIdRef.current || "",
|
|
911
|
+
role: "assistant",
|
|
912
|
+
content: null,
|
|
913
|
+
toolCalls: [{
|
|
914
|
+
id: parsed.tool_call_id,
|
|
915
|
+
type: "function",
|
|
916
|
+
function: { name: parsed.name, arguments: parsed.arguments || "{}" },
|
|
917
|
+
description: parsed.description
|
|
918
|
+
}],
|
|
919
|
+
toolCallId: null,
|
|
920
|
+
name: null,
|
|
921
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
922
|
+
streaming: true
|
|
923
|
+
}];
|
|
744
924
|
});
|
|
745
925
|
} catch {
|
|
746
926
|
}
|
|
@@ -842,20 +1022,6 @@ function useChat(agentRef, options) {
|
|
|
842
1022
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
843
1023
|
};
|
|
844
1024
|
setMessages((prev) => [...prev, userMsg]);
|
|
845
|
-
const assistantId = `tmp-assistant-${Date.now()}`;
|
|
846
|
-
activeAssistantIdRef.current = assistantId;
|
|
847
|
-
const assistantMsg = {
|
|
848
|
-
id: assistantId,
|
|
849
|
-
chatId: activeChatId,
|
|
850
|
-
role: "assistant",
|
|
851
|
-
content: "",
|
|
852
|
-
toolCalls: null,
|
|
853
|
-
toolCallId: null,
|
|
854
|
-
name: null,
|
|
855
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
856
|
-
streaming: true
|
|
857
|
-
};
|
|
858
|
-
setMessages((prev) => [...prev, assistantMsg]);
|
|
859
1025
|
const controller = streamMessage(
|
|
860
1026
|
client,
|
|
861
1027
|
activeChatId,
|
|
@@ -864,11 +1030,6 @@ function useChat(agentRef, options) {
|
|
|
864
1030
|
() => {
|
|
865
1031
|
setStreaming(false);
|
|
866
1032
|
setToolStatus([]);
|
|
867
|
-
setMessages(
|
|
868
|
-
(prev) => prev.filter(
|
|
869
|
-
(m) => !(m.streaming && m.role === "assistant" && !m.content && !m.toolCalls)
|
|
870
|
-
)
|
|
871
|
-
);
|
|
872
1033
|
refreshMessages(activeChatId);
|
|
873
1034
|
},
|
|
874
1035
|
(err) => {
|
|
@@ -890,22 +1051,6 @@ function useChat(agentRef, options) {
|
|
|
890
1051
|
setPendingApprovals((prev) => prev.filter((a) => a.toolCallId !== toolCallId));
|
|
891
1052
|
setStreaming(true);
|
|
892
1053
|
setError(null);
|
|
893
|
-
const assistantId = `tmp-resume-${Date.now()}`;
|
|
894
|
-
activeAssistantIdRef.current = assistantId;
|
|
895
|
-
if (approved) {
|
|
896
|
-
const assistantMsg = {
|
|
897
|
-
id: assistantId,
|
|
898
|
-
chatId: currentChatId,
|
|
899
|
-
role: "assistant",
|
|
900
|
-
content: "",
|
|
901
|
-
toolCalls: null,
|
|
902
|
-
toolCallId: null,
|
|
903
|
-
name: null,
|
|
904
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
905
|
-
streaming: true
|
|
906
|
-
};
|
|
907
|
-
setMessages((prev) => [...prev, assistantMsg]);
|
|
908
|
-
}
|
|
909
1054
|
(async () => {
|
|
910
1055
|
try {
|
|
911
1056
|
const result = await approveToolCall(client, currentChatId, toolCallId, approved);
|
|
@@ -984,23 +1129,105 @@ function useSinas() {
|
|
|
984
1129
|
useChat
|
|
985
1130
|
};
|
|
986
1131
|
}
|
|
1132
|
+
|
|
1133
|
+
// src/hooks/useAuth.ts
|
|
1134
|
+
var import_react6 = __toESM(require("react"), 1);
|
|
1135
|
+
function useAuth(options = {}) {
|
|
1136
|
+
const { autoRefresh = true } = options;
|
|
1137
|
+
const client = useClient();
|
|
1138
|
+
const [status, setStatus] = import_react6.default.useState("loading");
|
|
1139
|
+
const [user, setUser] = import_react6.default.useState(null);
|
|
1140
|
+
const [info, setInfo] = import_react6.default.useState(null);
|
|
1141
|
+
const [error, setError] = import_react6.default.useState(null);
|
|
1142
|
+
const refresh2 = import_react6.default.useCallback(async () => {
|
|
1143
|
+
setError(null);
|
|
1144
|
+
try {
|
|
1145
|
+
const [infoResp, meResp] = await Promise.all([
|
|
1146
|
+
client.auth.getInfo().catch(() => null),
|
|
1147
|
+
client.getAccessToken() ? client.auth.getMe().catch(() => null) : Promise.resolve(null)
|
|
1148
|
+
]);
|
|
1149
|
+
if (infoResp) setInfo(infoResp);
|
|
1150
|
+
if (meResp) {
|
|
1151
|
+
setUser(meResp);
|
|
1152
|
+
setStatus("authenticated");
|
|
1153
|
+
} else {
|
|
1154
|
+
setUser(null);
|
|
1155
|
+
setStatus("unauthenticated");
|
|
1156
|
+
}
|
|
1157
|
+
} catch (e) {
|
|
1158
|
+
setError(e instanceof Error ? e.message : String(e));
|
|
1159
|
+
setStatus("unauthenticated");
|
|
1160
|
+
}
|
|
1161
|
+
}, [client]);
|
|
1162
|
+
import_react6.default.useEffect(() => {
|
|
1163
|
+
if (autoRefresh) void refresh2();
|
|
1164
|
+
}, [autoRefresh, refresh2]);
|
|
1165
|
+
const login2 = import_react6.default.useCallback(
|
|
1166
|
+
async (email, password) => {
|
|
1167
|
+
setError(null);
|
|
1168
|
+
try {
|
|
1169
|
+
return await client.auth.login({ email, password });
|
|
1170
|
+
} catch (e) {
|
|
1171
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
1172
|
+
setError(msg);
|
|
1173
|
+
throw e;
|
|
1174
|
+
}
|
|
1175
|
+
},
|
|
1176
|
+
[client]
|
|
1177
|
+
);
|
|
1178
|
+
const verifyOTP2 = import_react6.default.useCallback(
|
|
1179
|
+
async (sessionId, otpCode) => {
|
|
1180
|
+
setError(null);
|
|
1181
|
+
try {
|
|
1182
|
+
return await client.auth.verifyOTP({ session_id: sessionId, otp_code: otpCode });
|
|
1183
|
+
} catch (e) {
|
|
1184
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
1185
|
+
setError(msg);
|
|
1186
|
+
throw e;
|
|
1187
|
+
}
|
|
1188
|
+
},
|
|
1189
|
+
[client]
|
|
1190
|
+
);
|
|
1191
|
+
const logout2 = import_react6.default.useCallback(
|
|
1192
|
+
async (refreshToken) => {
|
|
1193
|
+
if (refreshToken) {
|
|
1194
|
+
try {
|
|
1195
|
+
await client.auth.logout(refreshToken);
|
|
1196
|
+
} catch (e) {
|
|
1197
|
+
if (!(e instanceof SinasAuthError)) throw e;
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
setUser(null);
|
|
1201
|
+
setStatus("unauthenticated");
|
|
1202
|
+
},
|
|
1203
|
+
[client]
|
|
1204
|
+
);
|
|
1205
|
+
return { status, user, info, error, refresh: refresh2, login: login2, verifyOTP: verifyOTP2, logout: logout2 };
|
|
1206
|
+
}
|
|
987
1207
|
// Annotate the CommonJS export names for ESM import in node:
|
|
988
1208
|
0 && (module.exports = {
|
|
989
1209
|
SinasAuthError,
|
|
990
1210
|
SinasClient,
|
|
1211
|
+
SinasClientAuth,
|
|
991
1212
|
SinasError,
|
|
992
1213
|
SinasNotFoundError,
|
|
993
1214
|
SinasPermissionError,
|
|
994
1215
|
SinasProvider,
|
|
995
1216
|
SinasTimeoutError,
|
|
996
1217
|
approveToolCall,
|
|
1218
|
+
checkPermissions,
|
|
997
1219
|
createChat,
|
|
998
1220
|
executeFunction,
|
|
999
1221
|
executeQuery,
|
|
1000
1222
|
generateFileUrl,
|
|
1001
1223
|
getChat,
|
|
1224
|
+
getInfo,
|
|
1225
|
+
getMe,
|
|
1002
1226
|
listCollections,
|
|
1003
1227
|
listFiles,
|
|
1228
|
+
login,
|
|
1229
|
+
logout,
|
|
1230
|
+
refresh,
|
|
1004
1231
|
sendMessage,
|
|
1005
1232
|
stateDelete,
|
|
1006
1233
|
stateGet,
|
|
@@ -1009,11 +1236,13 @@ function useSinas() {
|
|
|
1009
1236
|
streamFromChannel,
|
|
1010
1237
|
streamMessage,
|
|
1011
1238
|
uploadFile,
|
|
1239
|
+
useAuth,
|
|
1012
1240
|
useChat,
|
|
1013
1241
|
useClient,
|
|
1014
1242
|
useExecute,
|
|
1015
1243
|
useQuery,
|
|
1016
1244
|
useSinas,
|
|
1017
|
-
useStateStore
|
|
1245
|
+
useStateStore,
|
|
1246
|
+
verifyOTP
|
|
1018
1247
|
});
|
|
1019
1248
|
//# sourceMappingURL=index.cjs.map
|