@personaai/react 0.1.2 → 0.3.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/index.cjs +240 -47
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +198 -52
- package/dist/index.d.ts +198 -52
- package/dist/index.js +251 -58
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -41,15 +41,61 @@ function usePersonaContext() {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
// src/hooks/useChat.ts
|
|
44
|
-
import { useCallback, useRef, useState } from "react";
|
|
44
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
45
|
+
function isErrorToolContent(content) {
|
|
46
|
+
if (typeof content !== "string" || !content.trim().startsWith("{")) return false;
|
|
47
|
+
try {
|
|
48
|
+
return JSON.parse(content)?.status === "error";
|
|
49
|
+
} catch {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function parsePresentedFile(content) {
|
|
54
|
+
try {
|
|
55
|
+
const parsed = JSON.parse(content);
|
|
56
|
+
if (parsed?.status !== "success" || typeof parsed.filePath !== "string") return null;
|
|
57
|
+
return {
|
|
58
|
+
path: parsed.filePath,
|
|
59
|
+
title: typeof parsed.title === "string" ? parsed.title : parsed.filePath,
|
|
60
|
+
description: typeof parsed.description === "string" ? parsed.description : ""
|
|
61
|
+
};
|
|
62
|
+
} catch {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function normalizePendingInterrupt(pending) {
|
|
67
|
+
if (!pending || typeof pending !== "object") return null;
|
|
68
|
+
const p = pending;
|
|
69
|
+
if (p.kind === "hitl") {
|
|
70
|
+
return {
|
|
71
|
+
kind: "hitl",
|
|
72
|
+
actionRequests: p.value?.actionRequests ?? [],
|
|
73
|
+
reviewConfigs: p.value?.reviewConfigs ?? []
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
if (p.kind === "clarification") {
|
|
77
|
+
return {
|
|
78
|
+
kind: "clarification",
|
|
79
|
+
questions: p.value?.questions ?? []
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
45
84
|
function useChat(options = {}) {
|
|
46
85
|
const { defaultAgentId, fetchWithAuth } = usePersonaContext();
|
|
47
86
|
const agentId = options.agentId || defaultAgentId;
|
|
87
|
+
const threadId = options.threadId;
|
|
48
88
|
const [messages, setMessages] = useState(options.initialMessages || []);
|
|
49
89
|
const [input, setInput] = useState("");
|
|
50
90
|
const [isStreaming, setIsStreaming] = useState(false);
|
|
91
|
+
const [isLoadingHistory, setIsLoadingHistory] = useState(false);
|
|
51
92
|
const [error, setError] = useState(null);
|
|
93
|
+
const [interrupt, setInterrupt] = useState(null);
|
|
94
|
+
const [files, setFiles] = useState({});
|
|
95
|
+
const [todos, setTodos] = useState([]);
|
|
96
|
+
const [presentedFile, setPresentedFile] = useState(null);
|
|
52
97
|
const abortControllerRef = useRef(null);
|
|
98
|
+
const loadedThreadIdRef = useRef(void 0);
|
|
53
99
|
const stop = useCallback(() => {
|
|
54
100
|
if (abortControllerRef.current) {
|
|
55
101
|
abortControllerRef.current.abort();
|
|
@@ -61,7 +107,50 @@ function useChat(options = {}) {
|
|
|
61
107
|
stop();
|
|
62
108
|
setMessages([]);
|
|
63
109
|
setError(null);
|
|
110
|
+
setInterrupt(null);
|
|
111
|
+
setFiles({});
|
|
112
|
+
setTodos([]);
|
|
113
|
+
setPresentedFile(null);
|
|
64
114
|
}, [stop]);
|
|
115
|
+
const loadThreadMessages = useCallback(
|
|
116
|
+
async (id) => {
|
|
117
|
+
setIsLoadingHistory(true);
|
|
118
|
+
setError(null);
|
|
119
|
+
try {
|
|
120
|
+
const res = await fetchWithAuth(`/threads/${id}/messages`);
|
|
121
|
+
if (!res.ok) throw new Error(`Failed to load thread history: ${res.statusText}`);
|
|
122
|
+
const body = await res.json();
|
|
123
|
+
const data = body?.data ?? body;
|
|
124
|
+
const raw = data?.messages ?? [];
|
|
125
|
+
const loaded = raw.map((m, i) => ({
|
|
126
|
+
id: m.id || `history-${id}-${i}`,
|
|
127
|
+
role: m.role,
|
|
128
|
+
content: m.content,
|
|
129
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
130
|
+
toolCalls: m.toolCalls
|
|
131
|
+
}));
|
|
132
|
+
setMessages(loaded);
|
|
133
|
+
setInterrupt(normalizePendingInterrupt(data?.pendingInterrupt));
|
|
134
|
+
setFiles(data?.state?.files ?? {});
|
|
135
|
+
setTodos(data?.state?.todos ?? []);
|
|
136
|
+
return loaded;
|
|
137
|
+
} catch (err) {
|
|
138
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
139
|
+
setError(errorObj);
|
|
140
|
+
return [];
|
|
141
|
+
} finally {
|
|
142
|
+
setIsLoadingHistory(false);
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
[fetchWithAuth]
|
|
146
|
+
);
|
|
147
|
+
useEffect(() => {
|
|
148
|
+
if (!threadId || isStreaming) return;
|
|
149
|
+
if (loadedThreadIdRef.current === threadId) return;
|
|
150
|
+
if (messages.length > 0) return;
|
|
151
|
+
loadedThreadIdRef.current = threadId;
|
|
152
|
+
void loadThreadMessages(threadId);
|
|
153
|
+
}, [threadId, isStreaming, messages.length, loadThreadMessages]);
|
|
65
154
|
const sendMessage = useCallback(
|
|
66
155
|
async (contentToSend, overrideOptions) => {
|
|
67
156
|
const prompt = (contentToSend ?? input).trim();
|
|
@@ -93,6 +182,7 @@ function useChat(options = {}) {
|
|
|
93
182
|
setInput("");
|
|
94
183
|
setIsStreaming(true);
|
|
95
184
|
setError(null);
|
|
185
|
+
setInterrupt(null);
|
|
96
186
|
const controller = new AbortController();
|
|
97
187
|
abortControllerRef.current = controller;
|
|
98
188
|
try {
|
|
@@ -108,7 +198,8 @@ function useChat(options = {}) {
|
|
|
108
198
|
body: JSON.stringify({
|
|
109
199
|
agentId: targetAgentId,
|
|
110
200
|
messages: payloadMessages,
|
|
111
|
-
threadId: overrideOptions?.threadId || options.threadId
|
|
201
|
+
threadId: overrideOptions?.threadId || options.threadId,
|
|
202
|
+
resume: overrideOptions?.resume
|
|
112
203
|
}),
|
|
113
204
|
signal: controller.signal
|
|
114
205
|
});
|
|
@@ -123,7 +214,15 @@ function useChat(options = {}) {
|
|
|
123
214
|
const decoder = new TextDecoder("utf-8");
|
|
124
215
|
let buffer = "";
|
|
125
216
|
let accumulatedText = "";
|
|
217
|
+
let accumulatedReasoning = "";
|
|
126
218
|
const toolCallsMap = /* @__PURE__ */ new Map();
|
|
219
|
+
const patchAssistant = (patch) => {
|
|
220
|
+
setMessages(
|
|
221
|
+
(prev) => prev.map(
|
|
222
|
+
(msg) => msg.id === assistantMessageId ? { ...msg, toolCalls: Array.from(toolCallsMap.values()), ...patch } : msg
|
|
223
|
+
)
|
|
224
|
+
);
|
|
225
|
+
};
|
|
127
226
|
while (true) {
|
|
128
227
|
const { done, value } = await reader.read();
|
|
129
228
|
if (done) break;
|
|
@@ -140,47 +239,56 @@ function useChat(options = {}) {
|
|
|
140
239
|
options.onEvent?.(event);
|
|
141
240
|
if (event.type === "TEXT_MESSAGE_CHUNK" && event.delta) {
|
|
142
241
|
accumulatedText += event.delta;
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
(msg) => msg.id === assistantMessageId ? {
|
|
146
|
-
...msg,
|
|
147
|
-
content: accumulatedText,
|
|
148
|
-
isStreaming: true,
|
|
149
|
-
toolCalls: Array.from(toolCallsMap.values())
|
|
150
|
-
} : msg
|
|
151
|
-
)
|
|
152
|
-
);
|
|
153
|
-
} else if (event.type === "TOOL_CALL_START") {
|
|
154
|
-
toolCallsMap.set(event.toolCallId, {
|
|
155
|
-
toolCallId: event.toolCallId,
|
|
156
|
-
toolName: event.toolName,
|
|
157
|
-
args: ""
|
|
158
|
-
});
|
|
159
|
-
setMessages(
|
|
160
|
-
(prev) => prev.map(
|
|
161
|
-
(msg) => msg.id === assistantMessageId ? { ...msg, toolCalls: Array.from(toolCallsMap.values()) } : msg
|
|
162
|
-
)
|
|
163
|
-
);
|
|
164
|
-
} else if (event.type === "TOOL_CALL_ARGS") {
|
|
242
|
+
patchAssistant({ content: accumulatedText, isStreaming: true });
|
|
243
|
+
} else if (event.type === "TOOL_CALL_CHUNK" && event.toolCallId) {
|
|
165
244
|
const existing = toolCallsMap.get(event.toolCallId);
|
|
166
245
|
if (existing) {
|
|
167
|
-
existing.args = (existing.args || "") + event.delta;
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
246
|
+
existing.args = (existing.args || "") + (event.delta || "");
|
|
247
|
+
} else {
|
|
248
|
+
toolCallsMap.set(event.toolCallId, {
|
|
249
|
+
toolCallId: event.toolCallId,
|
|
250
|
+
toolName: event.toolCallName || "",
|
|
251
|
+
args: event.delta || ""
|
|
252
|
+
});
|
|
173
253
|
}
|
|
254
|
+
patchAssistant({});
|
|
174
255
|
} else if (event.type === "TOOL_CALL_RESULT") {
|
|
175
256
|
const existing = toolCallsMap.get(event.toolCallId);
|
|
176
257
|
if (existing) {
|
|
177
|
-
existing.result = event.
|
|
178
|
-
existing.isError = event.
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
);
|
|
258
|
+
existing.result = event.content;
|
|
259
|
+
existing.isError = isErrorToolContent(event.content);
|
|
260
|
+
if (existing.toolName === "present_file" && !existing.isError) {
|
|
261
|
+
const presented = parsePresentedFile(event.content);
|
|
262
|
+
if (presented) setPresentedFile(presented);
|
|
263
|
+
}
|
|
264
|
+
patchAssistant({});
|
|
265
|
+
}
|
|
266
|
+
} else if (event.type === "STATE_SNAPSHOT") {
|
|
267
|
+
setFiles(event.snapshot.files);
|
|
268
|
+
setTodos(event.snapshot.todos);
|
|
269
|
+
} else if (event.type === "REASONING_MESSAGE_CONTENT") {
|
|
270
|
+
accumulatedReasoning += event.delta;
|
|
271
|
+
patchAssistant({ reasoning: accumulatedReasoning, isReasoning: true });
|
|
272
|
+
} else if (event.type === "REASONING_END") {
|
|
273
|
+
patchAssistant({ isReasoning: false });
|
|
274
|
+
} else if (event.type === "CUSTOM") {
|
|
275
|
+
if (event.name === "hitl_request") {
|
|
276
|
+
const value2 = event.value;
|
|
277
|
+
setInterrupt({
|
|
278
|
+
kind: "hitl",
|
|
279
|
+
actionRequests: value2.actionRequests,
|
|
280
|
+
reviewConfigs: value2.reviewConfigs
|
|
281
|
+
});
|
|
282
|
+
} else if (event.name === "clarification_request") {
|
|
283
|
+
const value2 = event.value;
|
|
284
|
+
setInterrupt({ kind: "clarification", questions: value2.questions });
|
|
285
|
+
} else if (event.name === "subagent_activity") {
|
|
286
|
+
const { toolCallId, ...entry } = event.value;
|
|
287
|
+
const existing = toolCallsMap.get(toolCallId);
|
|
288
|
+
if (existing) {
|
|
289
|
+
existing.subagentActivity = [...existing.subagentActivity || [], entry];
|
|
290
|
+
patchAssistant({});
|
|
291
|
+
}
|
|
184
292
|
}
|
|
185
293
|
} else if (event.type === "RUN_ERROR") {
|
|
186
294
|
throw new Error(event.message || "Stream error from agent");
|
|
@@ -198,7 +306,8 @@ function useChat(options = {}) {
|
|
|
198
306
|
content: accumulatedText,
|
|
199
307
|
createdAt: /* @__PURE__ */ new Date(),
|
|
200
308
|
isStreaming: false,
|
|
201
|
-
toolCalls: Array.from(toolCallsMap.values())
|
|
309
|
+
toolCalls: Array.from(toolCallsMap.values()),
|
|
310
|
+
...accumulatedReasoning ? { reasoning: accumulatedReasoning, isReasoning: false } : {}
|
|
202
311
|
};
|
|
203
312
|
setMessages(
|
|
204
313
|
(prev) => prev.map((msg) => msg.id === assistantMessageId ? finalMessage : msg)
|
|
@@ -256,6 +365,11 @@ function useChat(options = {}) {
|
|
|
256
365
|
setMessages(messages.slice(0, lastUserIndex));
|
|
257
366
|
void sendMessage(lastUserMessage.content);
|
|
258
367
|
}, [isStreaming, messages, sendMessage]);
|
|
368
|
+
const resumeInterrupt = useCallback(
|
|
369
|
+
(resume, displayContent) => sendMessage(displayContent, { resume }),
|
|
370
|
+
[sendMessage]
|
|
371
|
+
);
|
|
372
|
+
const dismissPresentedFile = useCallback(() => setPresentedFile(null), []);
|
|
259
373
|
return {
|
|
260
374
|
messages,
|
|
261
375
|
input,
|
|
@@ -265,19 +379,27 @@ function useChat(options = {}) {
|
|
|
265
379
|
sendMessage,
|
|
266
380
|
isStreaming,
|
|
267
381
|
isLoading: isStreaming,
|
|
382
|
+
isLoadingHistory,
|
|
268
383
|
error,
|
|
384
|
+
interrupt,
|
|
385
|
+
resumeInterrupt,
|
|
386
|
+
files,
|
|
387
|
+
todos,
|
|
388
|
+
presentedFile,
|
|
389
|
+
dismissPresentedFile,
|
|
269
390
|
stop,
|
|
270
391
|
reload,
|
|
271
392
|
clear,
|
|
272
|
-
setMessages
|
|
393
|
+
setMessages,
|
|
394
|
+
loadThreadMessages
|
|
273
395
|
};
|
|
274
396
|
}
|
|
275
397
|
|
|
276
398
|
// src/hooks/useMemory.ts
|
|
277
|
-
import { useCallback as useCallback2, useEffect, useState as useState2 } from "react";
|
|
399
|
+
import { useCallback as useCallback2, useEffect as useEffect2, useState as useState2 } from "react";
|
|
278
400
|
function useMemory(autoFetch = true) {
|
|
279
401
|
const { fetchWithAuth } = usePersonaContext();
|
|
280
|
-
const [memory, setMemory] = useState2({
|
|
402
|
+
const [memory, setMemory] = useState2({ userFiles: [], agentMemories: [] });
|
|
281
403
|
const [isLoading, setIsLoading] = useState2(false);
|
|
282
404
|
const [error, setError] = useState2(null);
|
|
283
405
|
const fetchMemory = useCallback2(async () => {
|
|
@@ -294,7 +416,7 @@ function useMemory(autoFetch = true) {
|
|
|
294
416
|
} catch (err) {
|
|
295
417
|
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
296
418
|
setError(errorObj);
|
|
297
|
-
return {
|
|
419
|
+
return { userFiles: [], agentMemories: [] };
|
|
298
420
|
} finally {
|
|
299
421
|
setIsLoading(false);
|
|
300
422
|
}
|
|
@@ -337,7 +459,7 @@ function useMemory(autoFetch = true) {
|
|
|
337
459
|
},
|
|
338
460
|
[fetchWithAuth, fetchMemory]
|
|
339
461
|
);
|
|
340
|
-
|
|
462
|
+
useEffect2(() => {
|
|
341
463
|
if (autoFetch) {
|
|
342
464
|
void fetchMemory();
|
|
343
465
|
}
|
|
@@ -354,7 +476,7 @@ function useMemory(autoFetch = true) {
|
|
|
354
476
|
}
|
|
355
477
|
|
|
356
478
|
// src/hooks/useThreads.ts
|
|
357
|
-
import { useCallback as useCallback3, useEffect as
|
|
479
|
+
import { useCallback as useCallback3, useEffect as useEffect3, useState as useState3 } from "react";
|
|
358
480
|
function useThreads(autoFetch = true) {
|
|
359
481
|
const { fetchWithAuth, defaultAgentId } = usePersonaContext();
|
|
360
482
|
const [threads, setThreads] = useState3([]);
|
|
@@ -367,7 +489,7 @@ function useThreads(autoFetch = true) {
|
|
|
367
489
|
const res = await fetchWithAuth("/threads");
|
|
368
490
|
if (!res.ok) throw new Error(`Failed to list threads: ${res.statusText}`);
|
|
369
491
|
const data = await res.json();
|
|
370
|
-
const items = Array.isArray(data) ? data : data?.threads || data?.
|
|
492
|
+
const items = Array.isArray(data) ? data : data?.items || data?.threads || (Array.isArray(data?.data) ? data.data : void 0) || [];
|
|
371
493
|
setThreads(items);
|
|
372
494
|
return items;
|
|
373
495
|
} catch (err) {
|
|
@@ -387,7 +509,8 @@ function useThreads(autoFetch = true) {
|
|
|
387
509
|
body: JSON.stringify({ agentId: targetAgentId })
|
|
388
510
|
});
|
|
389
511
|
if (!res.ok) throw new Error(`Failed to create thread: ${res.statusText}`);
|
|
390
|
-
const
|
|
512
|
+
const data = await res.json();
|
|
513
|
+
const created = data?.data ?? data;
|
|
391
514
|
void fetchThreads();
|
|
392
515
|
return created;
|
|
393
516
|
},
|
|
@@ -401,7 +524,57 @@ function useThreads(autoFetch = true) {
|
|
|
401
524
|
},
|
|
402
525
|
[fetchWithAuth]
|
|
403
526
|
);
|
|
404
|
-
|
|
527
|
+
const bulkDeleteThreads = useCallback3(
|
|
528
|
+
async (threadIds) => {
|
|
529
|
+
const res = await fetchWithAuth("/threads/bulk-delete", {
|
|
530
|
+
method: "POST",
|
|
531
|
+
headers: { "Content-Type": "application/json" },
|
|
532
|
+
body: JSON.stringify({ ids: threadIds })
|
|
533
|
+
});
|
|
534
|
+
if (!res.ok) throw new Error(`Failed to bulk-delete threads: ${res.statusText}`);
|
|
535
|
+
const data = await res.json();
|
|
536
|
+
const result = data?.data ?? data;
|
|
537
|
+
const deletedSet = new Set(result.deleted);
|
|
538
|
+
setThreads((prev) => prev.filter((t) => !deletedSet.has(t._id)));
|
|
539
|
+
return result;
|
|
540
|
+
},
|
|
541
|
+
[fetchWithAuth]
|
|
542
|
+
);
|
|
543
|
+
const deleteAllThreads = useCallback3(async () => {
|
|
544
|
+
const ids = threads.map((t) => t._id);
|
|
545
|
+
for (let i = 0; i < ids.length; i += 100) {
|
|
546
|
+
await bulkDeleteThreads(ids.slice(i, i + 100));
|
|
547
|
+
}
|
|
548
|
+
}, [threads, bulkDeleteThreads]);
|
|
549
|
+
const updateThread = useCallback3(
|
|
550
|
+
async (threadId, input) => {
|
|
551
|
+
const res = await fetchWithAuth(`/threads/${threadId}`, {
|
|
552
|
+
method: "PATCH",
|
|
553
|
+
headers: { "Content-Type": "application/json" },
|
|
554
|
+
body: JSON.stringify(input)
|
|
555
|
+
});
|
|
556
|
+
if (!res.ok) throw new Error(`Failed to update thread: ${res.statusText}`);
|
|
557
|
+
const data = await res.json();
|
|
558
|
+
const updated = data?.data ?? data;
|
|
559
|
+
setThreads((prev) => prev.map((t) => t._id === threadId ? { ...t, ...updated } : t));
|
|
560
|
+
return updated;
|
|
561
|
+
},
|
|
562
|
+
[fetchWithAuth]
|
|
563
|
+
);
|
|
564
|
+
const renameThread = useCallback3(
|
|
565
|
+
(threadId, title) => updateThread(threadId, { title }),
|
|
566
|
+
[updateThread]
|
|
567
|
+
);
|
|
568
|
+
const getThread = useCallback3(
|
|
569
|
+
async (threadId) => {
|
|
570
|
+
const res = await fetchWithAuth(`/threads/${threadId}`);
|
|
571
|
+
if (!res.ok) throw new Error(`Failed to fetch thread: ${res.statusText}`);
|
|
572
|
+
const data = await res.json();
|
|
573
|
+
return data?.data ?? data;
|
|
574
|
+
},
|
|
575
|
+
[fetchWithAuth]
|
|
576
|
+
);
|
|
577
|
+
useEffect3(() => {
|
|
405
578
|
if (autoFetch) {
|
|
406
579
|
void fetchThreads();
|
|
407
580
|
}
|
|
@@ -412,12 +585,17 @@ function useThreads(autoFetch = true) {
|
|
|
412
585
|
error,
|
|
413
586
|
refetch: fetchThreads,
|
|
414
587
|
createThread,
|
|
415
|
-
deleteThread
|
|
588
|
+
deleteThread,
|
|
589
|
+
bulkDeleteThreads,
|
|
590
|
+
deleteAllThreads,
|
|
591
|
+
updateThread,
|
|
592
|
+
renameThread,
|
|
593
|
+
getThread
|
|
416
594
|
};
|
|
417
595
|
}
|
|
418
596
|
|
|
419
597
|
// src/hooks/useFiles.ts
|
|
420
|
-
import { useCallback as useCallback4, useEffect as
|
|
598
|
+
import { useCallback as useCallback4, useEffect as useEffect4, useState as useState4 } from "react";
|
|
421
599
|
function useFiles(autoFetch = true) {
|
|
422
600
|
const { fetchWithAuth } = usePersonaContext();
|
|
423
601
|
const [files, setFiles] = useState4([]);
|
|
@@ -431,7 +609,7 @@ function useFiles(autoFetch = true) {
|
|
|
431
609
|
const res = await fetchWithAuth("/files");
|
|
432
610
|
if (!res.ok) throw new Error(`Failed to list files: ${res.statusText}`);
|
|
433
611
|
const data = await res.json();
|
|
434
|
-
const items = Array.isArray(data) ? data : data?.
|
|
612
|
+
const items = Array.isArray(data) ? data : data?.items || data?.files || [];
|
|
435
613
|
setFiles(items);
|
|
436
614
|
return items;
|
|
437
615
|
} catch (err) {
|
|
@@ -479,7 +657,21 @@ function useFiles(autoFetch = true) {
|
|
|
479
657
|
async (fileId) => {
|
|
480
658
|
const res = await fetchWithAuth(`/files/${fileId}`, { method: "DELETE" });
|
|
481
659
|
if (!res.ok) throw new Error(`Failed to delete file: ${res.statusText}`);
|
|
482
|
-
setFiles((prev) => prev.filter((f) => f.
|
|
660
|
+
setFiles((prev) => prev.filter((f) => f.id !== fileId));
|
|
661
|
+
},
|
|
662
|
+
[fetchWithAuth]
|
|
663
|
+
);
|
|
664
|
+
const bulkDeleteFiles = useCallback4(
|
|
665
|
+
async (fileIds) => {
|
|
666
|
+
const res = await fetchWithAuth("/files/bulk-delete", {
|
|
667
|
+
method: "POST",
|
|
668
|
+
headers: { "Content-Type": "application/json" },
|
|
669
|
+
body: JSON.stringify({ ids: fileIds })
|
|
670
|
+
});
|
|
671
|
+
if (!res.ok) throw new Error(`Failed to bulk-delete files: ${res.statusText}`);
|
|
672
|
+
const idSet = new Set(fileIds);
|
|
673
|
+
setFiles((prev) => prev.filter((f) => !idSet.has(f.id)));
|
|
674
|
+
return await res.json();
|
|
483
675
|
},
|
|
484
676
|
[fetchWithAuth]
|
|
485
677
|
);
|
|
@@ -489,7 +681,7 @@ function useFiles(autoFetch = true) {
|
|
|
489
681
|
},
|
|
490
682
|
[]
|
|
491
683
|
);
|
|
492
|
-
|
|
684
|
+
useEffect4(() => {
|
|
493
685
|
if (autoFetch) {
|
|
494
686
|
void fetchFiles();
|
|
495
687
|
}
|
|
@@ -502,12 +694,13 @@ function useFiles(autoFetch = true) {
|
|
|
502
694
|
refetch: fetchFiles,
|
|
503
695
|
uploadFile,
|
|
504
696
|
deleteFile,
|
|
697
|
+
bulkDeleteFiles,
|
|
505
698
|
getDownloadUrl
|
|
506
699
|
};
|
|
507
700
|
}
|
|
508
701
|
|
|
509
702
|
// src/hooks/useAgents.ts
|
|
510
|
-
import { useCallback as useCallback5, useEffect as
|
|
703
|
+
import { useCallback as useCallback5, useEffect as useEffect5, useState as useState5 } from "react";
|
|
511
704
|
function useAgents(autoFetch = true) {
|
|
512
705
|
const { fetchWithAuth } = usePersonaContext();
|
|
513
706
|
const [agents, setAgents] = useState5([]);
|
|
@@ -520,7 +713,7 @@ function useAgents(autoFetch = true) {
|
|
|
520
713
|
const res = await fetchWithAuth("/agents");
|
|
521
714
|
if (!res.ok) throw new Error(`Failed to list agents: ${res.statusText}`);
|
|
522
715
|
const data = await res.json();
|
|
523
|
-
const items = Array.isArray(data) ? data : data?.
|
|
716
|
+
const items = Array.isArray(data) ? data : data?.items || data?.agents || [];
|
|
524
717
|
setAgents(items);
|
|
525
718
|
return items;
|
|
526
719
|
} catch (err) {
|
|
@@ -531,7 +724,7 @@ function useAgents(autoFetch = true) {
|
|
|
531
724
|
setIsLoading(false);
|
|
532
725
|
}
|
|
533
726
|
}, [fetchWithAuth]);
|
|
534
|
-
|
|
727
|
+
useEffect5(() => {
|
|
535
728
|
if (autoFetch) {
|
|
536
729
|
void fetchAgents();
|
|
537
730
|
}
|
|
@@ -545,7 +738,7 @@ function useAgents(autoFetch = true) {
|
|
|
545
738
|
}
|
|
546
739
|
|
|
547
740
|
// src/hooks/useConnection.ts
|
|
548
|
-
import { useCallback as useCallback6, useEffect as
|
|
741
|
+
import { useCallback as useCallback6, useEffect as useEffect6, useState as useState6 } from "react";
|
|
549
742
|
function useConnection(autoCheck = true) {
|
|
550
743
|
const { fetchWithAuth } = usePersonaContext();
|
|
551
744
|
const [health, setHealth] = useState6(null);
|
|
@@ -570,7 +763,7 @@ function useConnection(autoCheck = true) {
|
|
|
570
763
|
setIsLoading(false);
|
|
571
764
|
}
|
|
572
765
|
}, [fetchWithAuth]);
|
|
573
|
-
|
|
766
|
+
useEffect6(() => {
|
|
574
767
|
if (autoCheck) {
|
|
575
768
|
void checkHealth();
|
|
576
769
|
}
|
|
@@ -584,7 +777,7 @@ function useConnection(autoCheck = true) {
|
|
|
584
777
|
}
|
|
585
778
|
|
|
586
779
|
// src/index.ts
|
|
587
|
-
var VERSION = "0.
|
|
780
|
+
var VERSION = "0.2.0";
|
|
588
781
|
export {
|
|
589
782
|
PersonaProvider,
|
|
590
783
|
VERSION,
|