@personaai/react 0.1.0 → 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/index.cjs +793 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +341 -0
- package/dist/index.d.ts +341 -0
- package/dist/index.js +758 -0
- package/dist/index.js.map +1 -0
- package/package.json +1 -1
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,793 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
PersonaProvider: () => PersonaProvider,
|
|
24
|
+
VERSION: () => VERSION,
|
|
25
|
+
useAgents: () => useAgents,
|
|
26
|
+
useChat: () => useChat,
|
|
27
|
+
useConnection: () => useConnection,
|
|
28
|
+
useFiles: () => useFiles,
|
|
29
|
+
useMemory: () => useMemory,
|
|
30
|
+
usePersonaContext: () => usePersonaContext,
|
|
31
|
+
useThreads: () => useThreads
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(index_exports);
|
|
34
|
+
|
|
35
|
+
// src/context/PersonaContext.tsx
|
|
36
|
+
var import_react = require("react");
|
|
37
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
38
|
+
var PersonaContext = (0, import_react.createContext)(null);
|
|
39
|
+
function PersonaProvider({
|
|
40
|
+
baseUrl,
|
|
41
|
+
getAuthToken,
|
|
42
|
+
defaultAgentId,
|
|
43
|
+
children
|
|
44
|
+
}) {
|
|
45
|
+
const normalizedBaseUrl = (0, import_react.useMemo)(() => baseUrl.replace(/\/+$/, ""), [baseUrl]);
|
|
46
|
+
const value = (0, import_react.useMemo)(() => {
|
|
47
|
+
async function fetchWithAuth(path, init = {}) {
|
|
48
|
+
const token = getAuthToken ? await getAuthToken() : null;
|
|
49
|
+
const headers = new Headers(init.headers || {});
|
|
50
|
+
if (token) {
|
|
51
|
+
headers.set("Authorization", `Bearer ${token}`);
|
|
52
|
+
}
|
|
53
|
+
const cleanPath = path.startsWith("/") ? path : `/${path}`;
|
|
54
|
+
const url = `${normalizedBaseUrl}${cleanPath}`;
|
|
55
|
+
return fetch(url, {
|
|
56
|
+
...init,
|
|
57
|
+
headers
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
baseUrl: normalizedBaseUrl,
|
|
62
|
+
getAuthToken,
|
|
63
|
+
defaultAgentId,
|
|
64
|
+
fetchWithAuth
|
|
65
|
+
};
|
|
66
|
+
}, [normalizedBaseUrl, getAuthToken, defaultAgentId]);
|
|
67
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PersonaContext.Provider, { value, children });
|
|
68
|
+
}
|
|
69
|
+
function usePersonaContext() {
|
|
70
|
+
const context = (0, import_react.useContext)(PersonaContext);
|
|
71
|
+
if (!context) {
|
|
72
|
+
throw new Error("usePersonaContext must be used within a <PersonaProvider>");
|
|
73
|
+
}
|
|
74
|
+
return context;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// src/hooks/useChat.ts
|
|
78
|
+
var import_react2 = require("react");
|
|
79
|
+
function isErrorToolContent(content) {
|
|
80
|
+
if (typeof content !== "string" || !content.trim().startsWith("{")) return false;
|
|
81
|
+
try {
|
|
82
|
+
return JSON.parse(content)?.status === "error";
|
|
83
|
+
} catch {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function normalizePendingInterrupt(pending) {
|
|
88
|
+
if (!pending || typeof pending !== "object") return null;
|
|
89
|
+
const p = pending;
|
|
90
|
+
if (p.kind === "hitl") {
|
|
91
|
+
return {
|
|
92
|
+
kind: "hitl",
|
|
93
|
+
actionRequests: p.value?.actionRequests ?? [],
|
|
94
|
+
reviewConfigs: p.value?.reviewConfigs ?? []
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
if (p.kind === "clarification") {
|
|
98
|
+
return {
|
|
99
|
+
kind: "clarification",
|
|
100
|
+
questions: p.value?.questions ?? []
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
function useChat(options = {}) {
|
|
106
|
+
const { defaultAgentId, fetchWithAuth } = usePersonaContext();
|
|
107
|
+
const agentId = options.agentId || defaultAgentId;
|
|
108
|
+
const threadId = options.threadId;
|
|
109
|
+
const [messages, setMessages] = (0, import_react2.useState)(options.initialMessages || []);
|
|
110
|
+
const [input, setInput] = (0, import_react2.useState)("");
|
|
111
|
+
const [isStreaming, setIsStreaming] = (0, import_react2.useState)(false);
|
|
112
|
+
const [isLoadingHistory, setIsLoadingHistory] = (0, import_react2.useState)(false);
|
|
113
|
+
const [error, setError] = (0, import_react2.useState)(null);
|
|
114
|
+
const [interrupt, setInterrupt] = (0, import_react2.useState)(null);
|
|
115
|
+
const abortControllerRef = (0, import_react2.useRef)(null);
|
|
116
|
+
const loadedThreadIdRef = (0, import_react2.useRef)(void 0);
|
|
117
|
+
const stop = (0, import_react2.useCallback)(() => {
|
|
118
|
+
if (abortControllerRef.current) {
|
|
119
|
+
abortControllerRef.current.abort();
|
|
120
|
+
abortControllerRef.current = null;
|
|
121
|
+
setIsStreaming(false);
|
|
122
|
+
}
|
|
123
|
+
}, []);
|
|
124
|
+
const clear = (0, import_react2.useCallback)(() => {
|
|
125
|
+
stop();
|
|
126
|
+
setMessages([]);
|
|
127
|
+
setError(null);
|
|
128
|
+
}, [stop]);
|
|
129
|
+
const loadThreadMessages = (0, import_react2.useCallback)(
|
|
130
|
+
async (id) => {
|
|
131
|
+
setIsLoadingHistory(true);
|
|
132
|
+
setError(null);
|
|
133
|
+
try {
|
|
134
|
+
const res = await fetchWithAuth(`/threads/${id}/messages`);
|
|
135
|
+
if (!res.ok) throw new Error(`Failed to load thread history: ${res.statusText}`);
|
|
136
|
+
const body = await res.json();
|
|
137
|
+
const data = body?.data ?? body;
|
|
138
|
+
const raw = data?.messages ?? [];
|
|
139
|
+
const loaded = raw.map((m, i) => ({
|
|
140
|
+
id: m.id || `history-${id}-${i}`,
|
|
141
|
+
role: m.role,
|
|
142
|
+
content: m.content,
|
|
143
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
144
|
+
toolCalls: m.toolCalls
|
|
145
|
+
}));
|
|
146
|
+
setMessages(loaded);
|
|
147
|
+
setInterrupt(normalizePendingInterrupt(data?.pendingInterrupt));
|
|
148
|
+
return loaded;
|
|
149
|
+
} catch (err) {
|
|
150
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
151
|
+
setError(errorObj);
|
|
152
|
+
return [];
|
|
153
|
+
} finally {
|
|
154
|
+
setIsLoadingHistory(false);
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
[fetchWithAuth]
|
|
158
|
+
);
|
|
159
|
+
(0, import_react2.useEffect)(() => {
|
|
160
|
+
if (!threadId || isStreaming) return;
|
|
161
|
+
if (loadedThreadIdRef.current === threadId) return;
|
|
162
|
+
if (messages.length > 0) return;
|
|
163
|
+
loadedThreadIdRef.current = threadId;
|
|
164
|
+
void loadThreadMessages(threadId);
|
|
165
|
+
}, [threadId, isStreaming, messages.length, loadThreadMessages]);
|
|
166
|
+
const sendMessage = (0, import_react2.useCallback)(
|
|
167
|
+
async (contentToSend, overrideOptions) => {
|
|
168
|
+
const prompt = (contentToSend ?? input).trim();
|
|
169
|
+
if (!prompt || isStreaming) return;
|
|
170
|
+
const targetAgentId = overrideOptions?.agentId || agentId;
|
|
171
|
+
if (!targetAgentId) {
|
|
172
|
+
const err = new Error("No Agent ID specified for useChat.");
|
|
173
|
+
setError(err);
|
|
174
|
+
options.onError?.(err);
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
const userMessage = {
|
|
178
|
+
id: `user-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
|
|
179
|
+
role: "user",
|
|
180
|
+
content: prompt,
|
|
181
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
182
|
+
};
|
|
183
|
+
const assistantMessageId = `assistant-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
|
|
184
|
+
const placeholderAssistant = {
|
|
185
|
+
id: assistantMessageId,
|
|
186
|
+
role: "assistant",
|
|
187
|
+
content: "",
|
|
188
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
189
|
+
isStreaming: true,
|
|
190
|
+
toolCalls: []
|
|
191
|
+
};
|
|
192
|
+
const nextMessages = [...messages, userMessage];
|
|
193
|
+
setMessages([...nextMessages, placeholderAssistant]);
|
|
194
|
+
setInput("");
|
|
195
|
+
setIsStreaming(true);
|
|
196
|
+
setError(null);
|
|
197
|
+
setInterrupt(null);
|
|
198
|
+
const controller = new AbortController();
|
|
199
|
+
abortControllerRef.current = controller;
|
|
200
|
+
try {
|
|
201
|
+
const payloadMessages = nextMessages.map((m) => ({
|
|
202
|
+
role: m.role === "assistant" ? "assistant" : "user",
|
|
203
|
+
content: m.content
|
|
204
|
+
}));
|
|
205
|
+
const response = await fetchWithAuth("/chat", {
|
|
206
|
+
method: "POST",
|
|
207
|
+
headers: {
|
|
208
|
+
"Content-Type": "application/json"
|
|
209
|
+
},
|
|
210
|
+
body: JSON.stringify({
|
|
211
|
+
agentId: targetAgentId,
|
|
212
|
+
messages: payloadMessages,
|
|
213
|
+
threadId: overrideOptions?.threadId || options.threadId,
|
|
214
|
+
resume: overrideOptions?.resume
|
|
215
|
+
}),
|
|
216
|
+
signal: controller.signal
|
|
217
|
+
});
|
|
218
|
+
if (!response.ok) {
|
|
219
|
+
const errText = await response.text().catch(() => "Stream failed");
|
|
220
|
+
throw new Error(`Chat error (${response.status}): ${errText}`);
|
|
221
|
+
}
|
|
222
|
+
if (!response.body) {
|
|
223
|
+
throw new Error("No response body received for streaming.");
|
|
224
|
+
}
|
|
225
|
+
const reader = response.body.getReader();
|
|
226
|
+
const decoder = new TextDecoder("utf-8");
|
|
227
|
+
let buffer = "";
|
|
228
|
+
let accumulatedText = "";
|
|
229
|
+
let accumulatedReasoning = "";
|
|
230
|
+
const toolCallsMap = /* @__PURE__ */ new Map();
|
|
231
|
+
const patchAssistant = (patch) => {
|
|
232
|
+
setMessages(
|
|
233
|
+
(prev) => prev.map(
|
|
234
|
+
(msg) => msg.id === assistantMessageId ? { ...msg, toolCalls: Array.from(toolCallsMap.values()), ...patch } : msg
|
|
235
|
+
)
|
|
236
|
+
);
|
|
237
|
+
};
|
|
238
|
+
while (true) {
|
|
239
|
+
const { done, value } = await reader.read();
|
|
240
|
+
if (done) break;
|
|
241
|
+
buffer += decoder.decode(value, { stream: true });
|
|
242
|
+
const lines = buffer.split("\n");
|
|
243
|
+
buffer = lines.pop() ?? "";
|
|
244
|
+
for (const line of lines) {
|
|
245
|
+
const trimmed = line.trim();
|
|
246
|
+
if (!trimmed || !trimmed.startsWith("data:")) continue;
|
|
247
|
+
const raw = trimmed.replace(/^data:\s*/, "");
|
|
248
|
+
if (raw === "[DONE]") break;
|
|
249
|
+
try {
|
|
250
|
+
const event = JSON.parse(raw);
|
|
251
|
+
options.onEvent?.(event);
|
|
252
|
+
if (event.type === "TEXT_MESSAGE_CHUNK" && event.delta) {
|
|
253
|
+
accumulatedText += event.delta;
|
|
254
|
+
patchAssistant({ content: accumulatedText, isStreaming: true });
|
|
255
|
+
} else if (event.type === "TOOL_CALL_CHUNK" && event.toolCallId) {
|
|
256
|
+
const existing = toolCallsMap.get(event.toolCallId);
|
|
257
|
+
if (existing) {
|
|
258
|
+
existing.args = (existing.args || "") + (event.delta || "");
|
|
259
|
+
} else {
|
|
260
|
+
toolCallsMap.set(event.toolCallId, {
|
|
261
|
+
toolCallId: event.toolCallId,
|
|
262
|
+
toolName: event.toolCallName || "",
|
|
263
|
+
args: event.delta || ""
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
patchAssistant({});
|
|
267
|
+
} else if (event.type === "TOOL_CALL_RESULT") {
|
|
268
|
+
const existing = toolCallsMap.get(event.toolCallId);
|
|
269
|
+
if (existing) {
|
|
270
|
+
existing.result = event.content;
|
|
271
|
+
existing.isError = isErrorToolContent(event.content);
|
|
272
|
+
patchAssistant({});
|
|
273
|
+
}
|
|
274
|
+
} else if (event.type === "REASONING_MESSAGE_CONTENT") {
|
|
275
|
+
accumulatedReasoning += event.delta;
|
|
276
|
+
patchAssistant({ reasoning: accumulatedReasoning, isReasoning: true });
|
|
277
|
+
} else if (event.type === "REASONING_END") {
|
|
278
|
+
patchAssistant({ isReasoning: false });
|
|
279
|
+
} else if (event.type === "CUSTOM") {
|
|
280
|
+
if (event.name === "hitl_request") {
|
|
281
|
+
const value2 = event.value;
|
|
282
|
+
setInterrupt({
|
|
283
|
+
kind: "hitl",
|
|
284
|
+
actionRequests: value2.actionRequests,
|
|
285
|
+
reviewConfigs: value2.reviewConfigs
|
|
286
|
+
});
|
|
287
|
+
} else if (event.name === "clarification_request") {
|
|
288
|
+
const value2 = event.value;
|
|
289
|
+
setInterrupt({ kind: "clarification", questions: value2.questions });
|
|
290
|
+
} else if (event.name === "subagent_activity") {
|
|
291
|
+
const { toolCallId, ...entry } = event.value;
|
|
292
|
+
const existing = toolCallsMap.get(toolCallId);
|
|
293
|
+
if (existing) {
|
|
294
|
+
existing.subagentActivity = [...existing.subagentActivity || [], entry];
|
|
295
|
+
patchAssistant({});
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
} else if (event.type === "RUN_ERROR") {
|
|
299
|
+
throw new Error(event.message || "Stream error from agent");
|
|
300
|
+
}
|
|
301
|
+
} catch (e) {
|
|
302
|
+
if (e instanceof Error && e.message.startsWith("Stream error")) {
|
|
303
|
+
throw e;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
const finalMessage = {
|
|
309
|
+
id: assistantMessageId,
|
|
310
|
+
role: "assistant",
|
|
311
|
+
content: accumulatedText,
|
|
312
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
313
|
+
isStreaming: false,
|
|
314
|
+
toolCalls: Array.from(toolCallsMap.values()),
|
|
315
|
+
...accumulatedReasoning ? { reasoning: accumulatedReasoning, isReasoning: false } : {}
|
|
316
|
+
};
|
|
317
|
+
setMessages(
|
|
318
|
+
(prev) => prev.map((msg) => msg.id === assistantMessageId ? finalMessage : msg)
|
|
319
|
+
);
|
|
320
|
+
options.onFinish?.(finalMessage);
|
|
321
|
+
} catch (err) {
|
|
322
|
+
if (controller.signal.aborted) {
|
|
323
|
+
setMessages(
|
|
324
|
+
(prev) => prev.map(
|
|
325
|
+
(msg) => msg.id === assistantMessageId ? { ...msg, isStreaming: false } : msg
|
|
326
|
+
)
|
|
327
|
+
);
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
331
|
+
setError(errorObj);
|
|
332
|
+
options.onError?.(errorObj);
|
|
333
|
+
setMessages(
|
|
334
|
+
(prev) => prev.map(
|
|
335
|
+
(msg) => msg.id === assistantMessageId ? {
|
|
336
|
+
...msg,
|
|
337
|
+
content: msg.content || `\u26A0\uFE0F Error: ${errorObj.message || "Failed to get response."}`,
|
|
338
|
+
isStreaming: false
|
|
339
|
+
} : msg
|
|
340
|
+
)
|
|
341
|
+
);
|
|
342
|
+
} finally {
|
|
343
|
+
setIsStreaming(false);
|
|
344
|
+
abortControllerRef.current = null;
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
[agentId, fetchWithAuth, input, isStreaming, messages, options]
|
|
348
|
+
);
|
|
349
|
+
const handleInputChange = (0, import_react2.useCallback)((e) => {
|
|
350
|
+
setInput(e.target.value);
|
|
351
|
+
}, []);
|
|
352
|
+
const handleSubmit = (0, import_react2.useCallback)(
|
|
353
|
+
(e) => {
|
|
354
|
+
if (e) e.preventDefault();
|
|
355
|
+
void sendMessage();
|
|
356
|
+
},
|
|
357
|
+
[sendMessage]
|
|
358
|
+
);
|
|
359
|
+
const reload = (0, import_react2.useCallback)(() => {
|
|
360
|
+
if (messages.length === 0 || isStreaming) return;
|
|
361
|
+
let lastUserIndex = -1;
|
|
362
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
363
|
+
if (messages[i].role === "user") {
|
|
364
|
+
lastUserIndex = i;
|
|
365
|
+
break;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
if (lastUserIndex === -1) return;
|
|
369
|
+
const lastUserMessage = messages[lastUserIndex];
|
|
370
|
+
setMessages(messages.slice(0, lastUserIndex));
|
|
371
|
+
void sendMessage(lastUserMessage.content);
|
|
372
|
+
}, [isStreaming, messages, sendMessage]);
|
|
373
|
+
const resumeInterrupt = (0, import_react2.useCallback)(
|
|
374
|
+
(resume, displayContent) => sendMessage(displayContent, { resume }),
|
|
375
|
+
[sendMessage]
|
|
376
|
+
);
|
|
377
|
+
return {
|
|
378
|
+
messages,
|
|
379
|
+
input,
|
|
380
|
+
setInput,
|
|
381
|
+
handleInputChange,
|
|
382
|
+
handleSubmit,
|
|
383
|
+
sendMessage,
|
|
384
|
+
isStreaming,
|
|
385
|
+
isLoading: isStreaming,
|
|
386
|
+
isLoadingHistory,
|
|
387
|
+
error,
|
|
388
|
+
interrupt,
|
|
389
|
+
resumeInterrupt,
|
|
390
|
+
stop,
|
|
391
|
+
reload,
|
|
392
|
+
clear,
|
|
393
|
+
setMessages,
|
|
394
|
+
loadThreadMessages
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// src/hooks/useMemory.ts
|
|
399
|
+
var import_react3 = require("react");
|
|
400
|
+
function useMemory(autoFetch = true) {
|
|
401
|
+
const { fetchWithAuth } = usePersonaContext();
|
|
402
|
+
const [memory, setMemory] = (0, import_react3.useState)({ userFiles: [], agentMemories: [] });
|
|
403
|
+
const [isLoading, setIsLoading] = (0, import_react3.useState)(false);
|
|
404
|
+
const [error, setError] = (0, import_react3.useState)(null);
|
|
405
|
+
const fetchMemory = (0, import_react3.useCallback)(async () => {
|
|
406
|
+
setIsLoading(true);
|
|
407
|
+
setError(null);
|
|
408
|
+
try {
|
|
409
|
+
const res = await fetchWithAuth("/memory");
|
|
410
|
+
if (!res.ok) {
|
|
411
|
+
throw new Error(`Failed to fetch memory: ${res.statusText}`);
|
|
412
|
+
}
|
|
413
|
+
const data = await res.json();
|
|
414
|
+
setMemory(data);
|
|
415
|
+
return data;
|
|
416
|
+
} catch (err) {
|
|
417
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
418
|
+
setError(errorObj);
|
|
419
|
+
return { userFiles: [], agentMemories: [] };
|
|
420
|
+
} finally {
|
|
421
|
+
setIsLoading(false);
|
|
422
|
+
}
|
|
423
|
+
}, [fetchWithAuth]);
|
|
424
|
+
const getFile = (0, import_react3.useCallback)(
|
|
425
|
+
async (params) => {
|
|
426
|
+
const query = new URLSearchParams({ path: params.path });
|
|
427
|
+
if (params.scope) query.set("scope", params.scope);
|
|
428
|
+
if (params.agentId) query.set("agentId", params.agentId);
|
|
429
|
+
const res = await fetchWithAuth(`/memory/file?${query.toString()}`);
|
|
430
|
+
if (!res.ok) throw new Error(`Failed to get memory file: ${res.statusText}`);
|
|
431
|
+
return await res.json();
|
|
432
|
+
},
|
|
433
|
+
[fetchWithAuth]
|
|
434
|
+
);
|
|
435
|
+
const writeFile = (0, import_react3.useCallback)(
|
|
436
|
+
async (params) => {
|
|
437
|
+
const res = await fetchWithAuth("/memory/file", {
|
|
438
|
+
method: "PUT",
|
|
439
|
+
headers: { "Content-Type": "application/json" },
|
|
440
|
+
body: JSON.stringify(params)
|
|
441
|
+
});
|
|
442
|
+
if (!res.ok) throw new Error(`Failed to write memory file: ${res.statusText}`);
|
|
443
|
+
const updated = await res.json();
|
|
444
|
+
void fetchMemory();
|
|
445
|
+
return updated;
|
|
446
|
+
},
|
|
447
|
+
[fetchWithAuth, fetchMemory]
|
|
448
|
+
);
|
|
449
|
+
const deleteFile = (0, import_react3.useCallback)(
|
|
450
|
+
async (params) => {
|
|
451
|
+
const query = new URLSearchParams({ path: params.path });
|
|
452
|
+
if (params.scope) query.set("scope", params.scope);
|
|
453
|
+
if (params.agentId) query.set("agentId", params.agentId);
|
|
454
|
+
const res = await fetchWithAuth(`/memory/file?${query.toString()}`, {
|
|
455
|
+
method: "DELETE"
|
|
456
|
+
});
|
|
457
|
+
if (!res.ok) throw new Error(`Failed to delete memory file: ${res.statusText}`);
|
|
458
|
+
void fetchMemory();
|
|
459
|
+
},
|
|
460
|
+
[fetchWithAuth, fetchMemory]
|
|
461
|
+
);
|
|
462
|
+
(0, import_react3.useEffect)(() => {
|
|
463
|
+
if (autoFetch) {
|
|
464
|
+
void fetchMemory();
|
|
465
|
+
}
|
|
466
|
+
}, [autoFetch, fetchMemory]);
|
|
467
|
+
return {
|
|
468
|
+
memory,
|
|
469
|
+
isLoading,
|
|
470
|
+
error,
|
|
471
|
+
refetch: fetchMemory,
|
|
472
|
+
getFile,
|
|
473
|
+
writeFile,
|
|
474
|
+
deleteFile
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// src/hooks/useThreads.ts
|
|
479
|
+
var import_react4 = require("react");
|
|
480
|
+
function useThreads(autoFetch = true) {
|
|
481
|
+
const { fetchWithAuth, defaultAgentId } = usePersonaContext();
|
|
482
|
+
const [threads, setThreads] = (0, import_react4.useState)([]);
|
|
483
|
+
const [isLoading, setIsLoading] = (0, import_react4.useState)(false);
|
|
484
|
+
const [error, setError] = (0, import_react4.useState)(null);
|
|
485
|
+
const fetchThreads = (0, import_react4.useCallback)(async () => {
|
|
486
|
+
setIsLoading(true);
|
|
487
|
+
setError(null);
|
|
488
|
+
try {
|
|
489
|
+
const res = await fetchWithAuth("/threads");
|
|
490
|
+
if (!res.ok) throw new Error(`Failed to list threads: ${res.statusText}`);
|
|
491
|
+
const data = await res.json();
|
|
492
|
+
const items = Array.isArray(data) ? data : data?.items || data?.threads || (Array.isArray(data?.data) ? data.data : void 0) || [];
|
|
493
|
+
setThreads(items);
|
|
494
|
+
return items;
|
|
495
|
+
} catch (err) {
|
|
496
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
497
|
+
setError(errorObj);
|
|
498
|
+
return [];
|
|
499
|
+
} finally {
|
|
500
|
+
setIsLoading(false);
|
|
501
|
+
}
|
|
502
|
+
}, [fetchWithAuth]);
|
|
503
|
+
const createThread = (0, import_react4.useCallback)(
|
|
504
|
+
async (agentId) => {
|
|
505
|
+
const targetAgentId = agentId || defaultAgentId;
|
|
506
|
+
const res = await fetchWithAuth("/threads", {
|
|
507
|
+
method: "POST",
|
|
508
|
+
headers: { "Content-Type": "application/json" },
|
|
509
|
+
body: JSON.stringify({ agentId: targetAgentId })
|
|
510
|
+
});
|
|
511
|
+
if (!res.ok) throw new Error(`Failed to create thread: ${res.statusText}`);
|
|
512
|
+
const data = await res.json();
|
|
513
|
+
const created = data?.data ?? data;
|
|
514
|
+
void fetchThreads();
|
|
515
|
+
return created;
|
|
516
|
+
},
|
|
517
|
+
[fetchWithAuth, defaultAgentId, fetchThreads]
|
|
518
|
+
);
|
|
519
|
+
const deleteThread = (0, import_react4.useCallback)(
|
|
520
|
+
async (threadId) => {
|
|
521
|
+
const res = await fetchWithAuth(`/threads/${threadId}`, { method: "DELETE" });
|
|
522
|
+
if (!res.ok) throw new Error(`Failed to delete thread: ${res.statusText}`);
|
|
523
|
+
setThreads((prev) => prev.filter((t) => t._id !== threadId));
|
|
524
|
+
},
|
|
525
|
+
[fetchWithAuth]
|
|
526
|
+
);
|
|
527
|
+
const bulkDeleteThreads = (0, import_react4.useCallback)(
|
|
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 = (0, import_react4.useCallback)(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 = (0, import_react4.useCallback)(
|
|
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 = (0, import_react4.useCallback)(
|
|
565
|
+
(threadId, title) => updateThread(threadId, { title }),
|
|
566
|
+
[updateThread]
|
|
567
|
+
);
|
|
568
|
+
const getThread = (0, import_react4.useCallback)(
|
|
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
|
+
(0, import_react4.useEffect)(() => {
|
|
578
|
+
if (autoFetch) {
|
|
579
|
+
void fetchThreads();
|
|
580
|
+
}
|
|
581
|
+
}, [autoFetch, fetchThreads]);
|
|
582
|
+
return {
|
|
583
|
+
threads,
|
|
584
|
+
isLoading,
|
|
585
|
+
error,
|
|
586
|
+
refetch: fetchThreads,
|
|
587
|
+
createThread,
|
|
588
|
+
deleteThread,
|
|
589
|
+
bulkDeleteThreads,
|
|
590
|
+
deleteAllThreads,
|
|
591
|
+
updateThread,
|
|
592
|
+
renameThread,
|
|
593
|
+
getThread
|
|
594
|
+
};
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// src/hooks/useFiles.ts
|
|
598
|
+
var import_react5 = require("react");
|
|
599
|
+
function useFiles(autoFetch = true) {
|
|
600
|
+
const { fetchWithAuth } = usePersonaContext();
|
|
601
|
+
const [files, setFiles] = (0, import_react5.useState)([]);
|
|
602
|
+
const [isLoading, setIsLoading] = (0, import_react5.useState)(false);
|
|
603
|
+
const [isUploading, setIsUploading] = (0, import_react5.useState)(false);
|
|
604
|
+
const [error, setError] = (0, import_react5.useState)(null);
|
|
605
|
+
const fetchFiles = (0, import_react5.useCallback)(async () => {
|
|
606
|
+
setIsLoading(true);
|
|
607
|
+
setError(null);
|
|
608
|
+
try {
|
|
609
|
+
const res = await fetchWithAuth("/files");
|
|
610
|
+
if (!res.ok) throw new Error(`Failed to list files: ${res.statusText}`);
|
|
611
|
+
const data = await res.json();
|
|
612
|
+
const items = Array.isArray(data) ? data : data?.items || data?.files || [];
|
|
613
|
+
setFiles(items);
|
|
614
|
+
return items;
|
|
615
|
+
} catch (err) {
|
|
616
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
617
|
+
setError(errorObj);
|
|
618
|
+
return [];
|
|
619
|
+
} finally {
|
|
620
|
+
setIsLoading(false);
|
|
621
|
+
}
|
|
622
|
+
}, [fetchWithAuth]);
|
|
623
|
+
const uploadFile = (0, import_react5.useCallback)(
|
|
624
|
+
async (fileOrFormData) => {
|
|
625
|
+
setIsUploading(true);
|
|
626
|
+
setError(null);
|
|
627
|
+
try {
|
|
628
|
+
let body;
|
|
629
|
+
if (fileOrFormData instanceof FormData) {
|
|
630
|
+
body = fileOrFormData;
|
|
631
|
+
} else {
|
|
632
|
+
body = new FormData();
|
|
633
|
+
body.append("file", fileOrFormData);
|
|
634
|
+
}
|
|
635
|
+
const res = await fetchWithAuth("/files", {
|
|
636
|
+
method: "POST",
|
|
637
|
+
body
|
|
638
|
+
});
|
|
639
|
+
if (!res.ok) {
|
|
640
|
+
const errText = await res.text().catch(() => "Upload failed");
|
|
641
|
+
throw new Error(`Upload error (${res.status}): ${errText}`);
|
|
642
|
+
}
|
|
643
|
+
const uploaded = await res.json();
|
|
644
|
+
void fetchFiles();
|
|
645
|
+
return uploaded;
|
|
646
|
+
} catch (err) {
|
|
647
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
648
|
+
setError(errorObj);
|
|
649
|
+
throw errorObj;
|
|
650
|
+
} finally {
|
|
651
|
+
setIsUploading(false);
|
|
652
|
+
}
|
|
653
|
+
},
|
|
654
|
+
[fetchWithAuth, fetchFiles]
|
|
655
|
+
);
|
|
656
|
+
const deleteFile = (0, import_react5.useCallback)(
|
|
657
|
+
async (fileId) => {
|
|
658
|
+
const res = await fetchWithAuth(`/files/${fileId}`, { method: "DELETE" });
|
|
659
|
+
if (!res.ok) throw new Error(`Failed to delete file: ${res.statusText}`);
|
|
660
|
+
setFiles((prev) => prev.filter((f) => f.id !== fileId));
|
|
661
|
+
},
|
|
662
|
+
[fetchWithAuth]
|
|
663
|
+
);
|
|
664
|
+
const bulkDeleteFiles = (0, import_react5.useCallback)(
|
|
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();
|
|
675
|
+
},
|
|
676
|
+
[fetchWithAuth]
|
|
677
|
+
);
|
|
678
|
+
const getDownloadUrl = (0, import_react5.useCallback)(
|
|
679
|
+
(fileId) => {
|
|
680
|
+
return `/files/${fileId}`;
|
|
681
|
+
},
|
|
682
|
+
[]
|
|
683
|
+
);
|
|
684
|
+
(0, import_react5.useEffect)(() => {
|
|
685
|
+
if (autoFetch) {
|
|
686
|
+
void fetchFiles();
|
|
687
|
+
}
|
|
688
|
+
}, [autoFetch, fetchFiles]);
|
|
689
|
+
return {
|
|
690
|
+
files,
|
|
691
|
+
isLoading,
|
|
692
|
+
isUploading,
|
|
693
|
+
error,
|
|
694
|
+
refetch: fetchFiles,
|
|
695
|
+
uploadFile,
|
|
696
|
+
deleteFile,
|
|
697
|
+
bulkDeleteFiles,
|
|
698
|
+
getDownloadUrl
|
|
699
|
+
};
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// src/hooks/useAgents.ts
|
|
703
|
+
var import_react6 = require("react");
|
|
704
|
+
function useAgents(autoFetch = true) {
|
|
705
|
+
const { fetchWithAuth } = usePersonaContext();
|
|
706
|
+
const [agents, setAgents] = (0, import_react6.useState)([]);
|
|
707
|
+
const [isLoading, setIsLoading] = (0, import_react6.useState)(false);
|
|
708
|
+
const [error, setError] = (0, import_react6.useState)(null);
|
|
709
|
+
const fetchAgents = (0, import_react6.useCallback)(async () => {
|
|
710
|
+
setIsLoading(true);
|
|
711
|
+
setError(null);
|
|
712
|
+
try {
|
|
713
|
+
const res = await fetchWithAuth("/agents");
|
|
714
|
+
if (!res.ok) throw new Error(`Failed to list agents: ${res.statusText}`);
|
|
715
|
+
const data = await res.json();
|
|
716
|
+
const items = Array.isArray(data) ? data : data?.items || data?.agents || [];
|
|
717
|
+
setAgents(items);
|
|
718
|
+
return items;
|
|
719
|
+
} catch (err) {
|
|
720
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
721
|
+
setError(errorObj);
|
|
722
|
+
return [];
|
|
723
|
+
} finally {
|
|
724
|
+
setIsLoading(false);
|
|
725
|
+
}
|
|
726
|
+
}, [fetchWithAuth]);
|
|
727
|
+
(0, import_react6.useEffect)(() => {
|
|
728
|
+
if (autoFetch) {
|
|
729
|
+
void fetchAgents();
|
|
730
|
+
}
|
|
731
|
+
}, [autoFetch, fetchAgents]);
|
|
732
|
+
return {
|
|
733
|
+
agents,
|
|
734
|
+
isLoading,
|
|
735
|
+
error,
|
|
736
|
+
refetch: fetchAgents
|
|
737
|
+
};
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
// src/hooks/useConnection.ts
|
|
741
|
+
var import_react7 = require("react");
|
|
742
|
+
function useConnection(autoCheck = true) {
|
|
743
|
+
const { fetchWithAuth } = usePersonaContext();
|
|
744
|
+
const [health, setHealth] = (0, import_react7.useState)(null);
|
|
745
|
+
const [isConnected, setIsConnected] = (0, import_react7.useState)(false);
|
|
746
|
+
const [isLoading, setIsLoading] = (0, import_react7.useState)(false);
|
|
747
|
+
const checkHealth = (0, import_react7.useCallback)(async () => {
|
|
748
|
+
setIsLoading(true);
|
|
749
|
+
try {
|
|
750
|
+
const res = await fetchWithAuth("/health");
|
|
751
|
+
if (res.ok) {
|
|
752
|
+
const data = await res.json();
|
|
753
|
+
setHealth(data);
|
|
754
|
+
setIsConnected(true);
|
|
755
|
+
return data;
|
|
756
|
+
}
|
|
757
|
+
setIsConnected(false);
|
|
758
|
+
return null;
|
|
759
|
+
} catch {
|
|
760
|
+
setIsConnected(false);
|
|
761
|
+
return null;
|
|
762
|
+
} finally {
|
|
763
|
+
setIsLoading(false);
|
|
764
|
+
}
|
|
765
|
+
}, [fetchWithAuth]);
|
|
766
|
+
(0, import_react7.useEffect)(() => {
|
|
767
|
+
if (autoCheck) {
|
|
768
|
+
void checkHealth();
|
|
769
|
+
}
|
|
770
|
+
}, [autoCheck, checkHealth]);
|
|
771
|
+
return {
|
|
772
|
+
isConnected,
|
|
773
|
+
health,
|
|
774
|
+
isLoading,
|
|
775
|
+
checkHealth
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
// src/index.ts
|
|
780
|
+
var VERSION = "0.2.0";
|
|
781
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
782
|
+
0 && (module.exports = {
|
|
783
|
+
PersonaProvider,
|
|
784
|
+
VERSION,
|
|
785
|
+
useAgents,
|
|
786
|
+
useChat,
|
|
787
|
+
useConnection,
|
|
788
|
+
useFiles,
|
|
789
|
+
useMemory,
|
|
790
|
+
usePersonaContext,
|
|
791
|
+
useThreads
|
|
792
|
+
});
|
|
793
|
+
//# sourceMappingURL=index.cjs.map
|