@personaai/react 0.9.0 → 0.11.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/README.md +210 -187
- package/dist/docs/.nojekyll +1 -0
- package/dist/index.cjs +1324 -253
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +456 -13
- package/dist/index.d.ts +456 -13
- package/dist/index.js +1321 -254
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
ARCHITECT_AGENT_ID: () => ARCHITECT_AGENT_ID,
|
|
23
24
|
PersonaProvider: () => PersonaProvider,
|
|
24
25
|
VERSION: () => VERSION,
|
|
25
26
|
createLogger: () => import_logger2.createLogger,
|
|
@@ -30,6 +31,7 @@ __export(index_exports, {
|
|
|
30
31
|
setLogLevel: () => import_logger2.setLogLevel,
|
|
31
32
|
supportsStreamingFetch: () => supportsStreamingFetch,
|
|
32
33
|
useAgents: () => useAgents,
|
|
34
|
+
useArchitectChat: () => useArchitectChat,
|
|
33
35
|
useChat: () => useChat,
|
|
34
36
|
useConnection: () => useConnection,
|
|
35
37
|
useFiles: () => useFiles,
|
|
@@ -37,6 +39,8 @@ __export(index_exports, {
|
|
|
37
39
|
useMcpConnections: () => useMcpConnections,
|
|
38
40
|
useMemory: () => useMemory,
|
|
39
41
|
usePersonaContext: () => usePersonaContext,
|
|
42
|
+
useRcpSources: () => useRcpSources,
|
|
43
|
+
useSkills: () => useSkills,
|
|
40
44
|
useThreads: () => useThreads,
|
|
41
45
|
useVoice: () => useVoice,
|
|
42
46
|
useWorkflow: () => useWorkflow,
|
|
@@ -334,7 +338,7 @@ async function openSSEStream(opts) {
|
|
|
334
338
|
};
|
|
335
339
|
}
|
|
336
340
|
|
|
337
|
-
// src/hooks/
|
|
341
|
+
// src/hooks/streamEventHelpers.ts
|
|
338
342
|
function isErrorToolContent(content) {
|
|
339
343
|
if (typeof content !== "string" || !content.trim().startsWith("{"))
|
|
340
344
|
return false;
|
|
@@ -380,6 +384,38 @@ function parsePresentedFile(content) {
|
|
|
380
384
|
return null;
|
|
381
385
|
}
|
|
382
386
|
}
|
|
387
|
+
function normalizeWorkspaceFiles(raw) {
|
|
388
|
+
const normalized = {};
|
|
389
|
+
for (const [path, file] of Object.entries(raw || {})) {
|
|
390
|
+
normalized[path] = {
|
|
391
|
+
content: file.content,
|
|
392
|
+
size: file.size,
|
|
393
|
+
createdAt: file.created_at,
|
|
394
|
+
modifiedAt: file.modified_at
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
return normalized;
|
|
398
|
+
}
|
|
399
|
+
function normalizePendingInterrupt(pending) {
|
|
400
|
+
if (!pending || typeof pending !== "object") return null;
|
|
401
|
+
const p = pending;
|
|
402
|
+
if (p.kind === "hitl") {
|
|
403
|
+
return {
|
|
404
|
+
kind: "hitl",
|
|
405
|
+
actionRequests: p.value?.actionRequests ?? [],
|
|
406
|
+
reviewConfigs: p.value?.reviewConfigs ?? []
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
if (p.kind === "clarification") {
|
|
410
|
+
return {
|
|
411
|
+
kind: "clarification",
|
|
412
|
+
questions: p.value?.questions ?? []
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
return null;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// src/hooks/useChat.ts
|
|
383
419
|
function parseSandboxCommand(tc) {
|
|
384
420
|
let command = tc.args ?? "";
|
|
385
421
|
try {
|
|
@@ -411,36 +447,6 @@ function parseSandboxCommand(tc) {
|
|
|
411
447
|
seq: tc.seq
|
|
412
448
|
};
|
|
413
449
|
}
|
|
414
|
-
function normalizeWorkspaceFiles(raw) {
|
|
415
|
-
const normalized = {};
|
|
416
|
-
for (const [path, file] of Object.entries(raw || {})) {
|
|
417
|
-
normalized[path] = {
|
|
418
|
-
content: file.content,
|
|
419
|
-
size: file.size,
|
|
420
|
-
createdAt: file.created_at,
|
|
421
|
-
modifiedAt: file.modified_at
|
|
422
|
-
};
|
|
423
|
-
}
|
|
424
|
-
return normalized;
|
|
425
|
-
}
|
|
426
|
-
function normalizePendingInterrupt(pending) {
|
|
427
|
-
if (!pending || typeof pending !== "object") return null;
|
|
428
|
-
const p = pending;
|
|
429
|
-
if (p.kind === "hitl") {
|
|
430
|
-
return {
|
|
431
|
-
kind: "hitl",
|
|
432
|
-
actionRequests: p.value?.actionRequests ?? [],
|
|
433
|
-
reviewConfigs: p.value?.reviewConfigs ?? []
|
|
434
|
-
};
|
|
435
|
-
}
|
|
436
|
-
if (p.kind === "clarification") {
|
|
437
|
-
return {
|
|
438
|
-
kind: "clarification",
|
|
439
|
-
questions: p.value?.questions ?? []
|
|
440
|
-
};
|
|
441
|
-
}
|
|
442
|
-
return null;
|
|
443
|
-
}
|
|
444
450
|
function useChat(options = {}) {
|
|
445
451
|
const { defaultAgentId, fetchWithAuth, baseUrl, getAuthToken, logger } = usePersonaContext();
|
|
446
452
|
const chatLogger = (0, import_react2.useMemo)(() => logger.child("chat"), [logger]);
|
|
@@ -1154,104 +1160,656 @@ function useChat(options = {}) {
|
|
|
1154
1160
|
};
|
|
1155
1161
|
}
|
|
1156
1162
|
|
|
1157
|
-
// src/hooks/
|
|
1163
|
+
// src/hooks/useArchitectChat.ts
|
|
1158
1164
|
var import_react3 = require("react");
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
const
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
const
|
|
1165
|
+
var ARCHITECT_AGENT_ID = "000000000000000000000002";
|
|
1166
|
+
function useArchitectChat(options = {}) {
|
|
1167
|
+
const { fetchWithAuth, baseUrl, getAuthToken, logger } = usePersonaContext();
|
|
1168
|
+
const chatLogger = (0, import_react3.useMemo)(() => logger.child("architect"), [logger]);
|
|
1169
|
+
const threadId = options.threadId;
|
|
1170
|
+
const [internalThreadId, setInternalThreadId] = (0, import_react3.useState)(void 0);
|
|
1171
|
+
const effectiveThreadId = threadId ?? internalThreadId;
|
|
1172
|
+
(0, import_react3.useEffect)(() => {
|
|
1173
|
+
if (threadId !== void 0) setInternalThreadId(threadId);
|
|
1174
|
+
}, [threadId]);
|
|
1175
|
+
const didLogInitRef = (0, import_react3.useRef)(false);
|
|
1176
|
+
if (!didLogInitRef.current) {
|
|
1177
|
+
didLogInitRef.current = true;
|
|
1178
|
+
chatLogger.debug("useArchitectChat init", {
|
|
1179
|
+
threadId,
|
|
1180
|
+
hasInitialMessages: !!options.initialMessages?.length
|
|
1181
|
+
});
|
|
1182
|
+
chatLogger.trace("useArchitectChat options", {
|
|
1183
|
+
threadId,
|
|
1184
|
+
initialMessageCount: options.initialMessages?.length ?? 0
|
|
1185
|
+
});
|
|
1186
|
+
}
|
|
1187
|
+
const [messages, setMessages] = (0, import_react3.useState)(
|
|
1188
|
+
options.initialMessages || []
|
|
1189
|
+
);
|
|
1190
|
+
const [input, setInput] = (0, import_react3.useState)("");
|
|
1191
|
+
const [isStreaming, setIsStreaming] = (0, import_react3.useState)(false);
|
|
1192
|
+
const [isLoadingHistory, setIsLoadingHistory] = (0, import_react3.useState)(false);
|
|
1166
1193
|
const [error, setError] = (0, import_react3.useState)(null);
|
|
1167
|
-
const
|
|
1168
|
-
|
|
1194
|
+
const [interrupt, setInterrupt] = (0, import_react3.useState)(null);
|
|
1195
|
+
const [files, setFiles] = (0, import_react3.useState)({});
|
|
1196
|
+
const [todos, setTodos] = (0, import_react3.useState)([]);
|
|
1197
|
+
const [presentedFile, setPresentedFile] = (0, import_react3.useState)(null);
|
|
1198
|
+
const abortControllerRef = (0, import_react3.useRef)(null);
|
|
1199
|
+
const loadedThreadIdRef = (0, import_react3.useRef)(void 0);
|
|
1200
|
+
const stop = (0, import_react3.useCallback)(() => {
|
|
1201
|
+
if (abortControllerRef.current) {
|
|
1202
|
+
chatLogger.info("stop streaming", {});
|
|
1203
|
+
chatLogger.debug("abort controller", {
|
|
1204
|
+
hasController: !!abortControllerRef.current
|
|
1205
|
+
});
|
|
1206
|
+
abortControllerRef.current.abort();
|
|
1207
|
+
abortControllerRef.current = null;
|
|
1208
|
+
setIsStreaming(false);
|
|
1209
|
+
chatLogger.debug("streaming stopped");
|
|
1210
|
+
} else {
|
|
1211
|
+
chatLogger.trace("stop called \u2014 no active stream");
|
|
1212
|
+
}
|
|
1213
|
+
}, [chatLogger]);
|
|
1214
|
+
const clear = (0, import_react3.useCallback)(() => {
|
|
1215
|
+
chatLogger.info("clear chat", { messageCount: messages.length });
|
|
1216
|
+
chatLogger.debug("clear", { messageCount: messages.length });
|
|
1217
|
+
stop();
|
|
1218
|
+
setMessages([]);
|
|
1169
1219
|
setError(null);
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1220
|
+
setInterrupt(null);
|
|
1221
|
+
setFiles({});
|
|
1222
|
+
setTodos([]);
|
|
1223
|
+
setPresentedFile(null);
|
|
1224
|
+
loadedThreadIdRef.current = void 0;
|
|
1225
|
+
}, [stop, chatLogger, messages.length]);
|
|
1226
|
+
const startNewChat = (0, import_react3.useCallback)(() => {
|
|
1227
|
+
chatLogger.info("startNewChat \u2014 entering ephemeral mode");
|
|
1228
|
+
stop();
|
|
1229
|
+
setMessages([]);
|
|
1230
|
+
setError(null);
|
|
1231
|
+
setInterrupt(null);
|
|
1232
|
+
setFiles({});
|
|
1233
|
+
setTodos([]);
|
|
1234
|
+
setPresentedFile(null);
|
|
1235
|
+
setInput("");
|
|
1236
|
+
loadedThreadIdRef.current = void 0;
|
|
1237
|
+
setInternalThreadId(void 0);
|
|
1238
|
+
}, [stop, chatLogger]);
|
|
1239
|
+
const loadThreadMessages = (0, import_react3.useCallback)(
|
|
1240
|
+
async (id) => {
|
|
1241
|
+
chatLogger.debug("loadThreadMessages start", { threadId: id });
|
|
1242
|
+
chatLogger.trace("loadThreadMessages", { threadId: id });
|
|
1243
|
+
setIsLoadingHistory(true);
|
|
1244
|
+
setError(null);
|
|
1245
|
+
try {
|
|
1246
|
+
const res = await fetchWithAuth(`/threads/${id}/messages`);
|
|
1247
|
+
if (!res.ok)
|
|
1248
|
+
throw new Error(`Failed to load thread history: ${res.statusText}`);
|
|
1249
|
+
const body = await res.json();
|
|
1250
|
+
const data = body?.data ?? body;
|
|
1251
|
+
const raw = data?.messages ?? [];
|
|
1252
|
+
const subagentTraces = data?.subagentTraces ?? {};
|
|
1253
|
+
const loaded = raw.map((m, i) => ({
|
|
1254
|
+
id: m.id || `history-${id}-${i}`,
|
|
1255
|
+
role: m.role,
|
|
1256
|
+
content: m.content,
|
|
1257
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
1258
|
+
toolCalls: m.toolCalls?.map((tc) => {
|
|
1259
|
+
const trace = subagentTraces[tc.toolCallId];
|
|
1260
|
+
return Array.isArray(trace) && trace.length > 0 ? {
|
|
1261
|
+
...tc,
|
|
1262
|
+
subagentActivity: persistedTraceToActivityEntries(trace)
|
|
1263
|
+
} : tc;
|
|
1264
|
+
})
|
|
1265
|
+
}));
|
|
1266
|
+
setMessages(loaded);
|
|
1267
|
+
setInterrupt(normalizePendingInterrupt(data?.pendingInterrupt));
|
|
1268
|
+
setFiles(normalizeWorkspaceFiles(data?.state?.files ?? {}));
|
|
1269
|
+
setTodos(data?.state?.todos ?? []);
|
|
1270
|
+
loadedThreadIdRef.current = id;
|
|
1271
|
+
chatLogger.info("loadThreadMessages succeeded", {
|
|
1272
|
+
threadId: id,
|
|
1273
|
+
messageCount: loaded.length
|
|
1274
|
+
});
|
|
1275
|
+
chatLogger.debug("loadThreadMessages completed", {
|
|
1276
|
+
threadId: id,
|
|
1277
|
+
messageCount: loaded.length
|
|
1278
|
+
});
|
|
1279
|
+
return loaded;
|
|
1280
|
+
} catch (err) {
|
|
1281
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
1282
|
+
chatLogger.warn("loadThreadMessages failed", {
|
|
1283
|
+
threadId: id,
|
|
1284
|
+
error: errorObj.message
|
|
1285
|
+
});
|
|
1286
|
+
chatLogger.error("loadThreadMessages error", {
|
|
1287
|
+
threadId: id,
|
|
1288
|
+
error: errorObj.message
|
|
1289
|
+
});
|
|
1290
|
+
setError(errorObj);
|
|
1291
|
+
if (loadedThreadIdRef.current === id) loadedThreadIdRef.current = void 0;
|
|
1292
|
+
return [];
|
|
1293
|
+
} finally {
|
|
1294
|
+
setIsLoadingHistory(false);
|
|
1295
|
+
chatLogger.trace("loadThreadMessages end", { threadId: id });
|
|
1174
1296
|
}
|
|
1175
|
-
const data = await res.json();
|
|
1176
|
-
setMemory(data);
|
|
1177
|
-
return data;
|
|
1178
|
-
} catch (err) {
|
|
1179
|
-
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
1180
|
-
setError(errorObj);
|
|
1181
|
-
return { userFiles: [], agentMemories: [] };
|
|
1182
|
-
} finally {
|
|
1183
|
-
setIsLoading(false);
|
|
1184
|
-
}
|
|
1185
|
-
}, [fetchWithAuth]);
|
|
1186
|
-
const getFile = (0, import_react3.useCallback)(
|
|
1187
|
-
async (params) => {
|
|
1188
|
-
const query = new URLSearchParams({ path: params.path });
|
|
1189
|
-
if (params.scope) query.set("scope", params.scope);
|
|
1190
|
-
if (params.agentId) query.set("agentId", params.agentId);
|
|
1191
|
-
const res = await fetchWithAuth(`/memory/file?${query.toString()}`);
|
|
1192
|
-
if (!res.ok)
|
|
1193
|
-
throw new Error(`Failed to get memory file: ${res.statusText}`);
|
|
1194
|
-
return await res.json();
|
|
1195
|
-
},
|
|
1196
|
-
[fetchWithAuth]
|
|
1197
|
-
);
|
|
1198
|
-
const writeFile = (0, import_react3.useCallback)(
|
|
1199
|
-
async (params) => {
|
|
1200
|
-
const res = await fetchWithAuth("/memory/file", {
|
|
1201
|
-
method: "PUT",
|
|
1202
|
-
headers: { "Content-Type": "application/json" },
|
|
1203
|
-
body: JSON.stringify(params)
|
|
1204
|
-
});
|
|
1205
|
-
if (!res.ok)
|
|
1206
|
-
throw new Error(`Failed to write memory file: ${res.statusText}`);
|
|
1207
|
-
const updated = await res.json();
|
|
1208
|
-
void fetchMemory();
|
|
1209
|
-
return updated;
|
|
1210
|
-
},
|
|
1211
|
-
[fetchWithAuth, fetchMemory]
|
|
1212
|
-
);
|
|
1213
|
-
const deleteFile = (0, import_react3.useCallback)(
|
|
1214
|
-
async (params) => {
|
|
1215
|
-
const query = new URLSearchParams({ path: params.path });
|
|
1216
|
-
if (params.scope) query.set("scope", params.scope);
|
|
1217
|
-
if (params.agentId) query.set("agentId", params.agentId);
|
|
1218
|
-
const res = await fetchWithAuth(`/memory/file?${query.toString()}`, {
|
|
1219
|
-
method: "DELETE"
|
|
1220
|
-
});
|
|
1221
|
-
if (!res.ok)
|
|
1222
|
-
throw new Error(`Failed to delete memory file: ${res.statusText}`);
|
|
1223
|
-
void fetchMemory();
|
|
1224
1297
|
},
|
|
1225
|
-
[fetchWithAuth,
|
|
1298
|
+
[fetchWithAuth, chatLogger]
|
|
1226
1299
|
);
|
|
1227
1300
|
(0, import_react3.useEffect)(() => {
|
|
1228
|
-
if (
|
|
1229
|
-
|
|
1301
|
+
if (!effectiveThreadId || isStreaming) {
|
|
1302
|
+
chatLogger.trace("auto-load skipped", { threadId: effectiveThreadId, isStreaming });
|
|
1303
|
+
return;
|
|
1230
1304
|
}
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
}
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
const
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1305
|
+
if (loadedThreadIdRef.current === effectiveThreadId) {
|
|
1306
|
+
chatLogger.trace("auto-load already loaded", { threadId: effectiveThreadId });
|
|
1307
|
+
return;
|
|
1308
|
+
}
|
|
1309
|
+
if (messages.length > 0) {
|
|
1310
|
+
chatLogger.trace("auto-load has messages", {
|
|
1311
|
+
threadId: effectiveThreadId,
|
|
1312
|
+
count: messages.length
|
|
1313
|
+
});
|
|
1314
|
+
return;
|
|
1315
|
+
}
|
|
1316
|
+
chatLogger.info("auto-load thread history", { threadId: effectiveThreadId });
|
|
1317
|
+
chatLogger.debug("loadThreadMessages trigger", { threadId: effectiveThreadId });
|
|
1318
|
+
void loadThreadMessages(effectiveThreadId);
|
|
1319
|
+
}, [effectiveThreadId, isStreaming, messages.length, loadThreadMessages, chatLogger]);
|
|
1320
|
+
const doSend = (0, import_react3.useCallback)(
|
|
1321
|
+
async (prompt, baseMessages, overrideOptions) => {
|
|
1322
|
+
chatLogger.debug("sendMessage start", {
|
|
1323
|
+
promptPreview: prompt.slice(0, 100),
|
|
1324
|
+
threadId: effectiveThreadId ?? overrideOptions?.threadId,
|
|
1325
|
+
hasResume: !!overrideOptions?.resume,
|
|
1326
|
+
messageCount: baseMessages.length
|
|
1327
|
+
});
|
|
1328
|
+
chatLogger.trace("sendMessage details", {
|
|
1329
|
+
promptPreview: prompt.slice(0, 200),
|
|
1330
|
+
hasResume: !!overrideOptions?.resume
|
|
1331
|
+
});
|
|
1332
|
+
const userMessage = {
|
|
1333
|
+
id: `user-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
|
|
1334
|
+
role: "user",
|
|
1335
|
+
content: prompt,
|
|
1336
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
1337
|
+
};
|
|
1338
|
+
const assistantMessageId = `assistant-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
|
|
1339
|
+
const placeholderAssistant = {
|
|
1340
|
+
id: assistantMessageId,
|
|
1341
|
+
role: "assistant",
|
|
1342
|
+
content: "",
|
|
1343
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
1344
|
+
isStreaming: true,
|
|
1345
|
+
toolCalls: []
|
|
1346
|
+
};
|
|
1347
|
+
const nextMessages = [...baseMessages, userMessage];
|
|
1348
|
+
setMessages([...nextMessages, placeholderAssistant]);
|
|
1349
|
+
setInput("");
|
|
1350
|
+
setIsStreaming(true);
|
|
1351
|
+
setError(null);
|
|
1352
|
+
setInterrupt(null);
|
|
1353
|
+
const controller = new AbortController();
|
|
1354
|
+
abortControllerRef.current = controller;
|
|
1355
|
+
const finalizeReasoning = () => {
|
|
1356
|
+
setMessages(
|
|
1357
|
+
(prev) => prev.map((m) => m.role === "reasoning" && m.isStreaming ? { ...m, isStreaming: false } : m)
|
|
1358
|
+
);
|
|
1359
|
+
};
|
|
1360
|
+
try {
|
|
1361
|
+
const payloadMessages = nextMessages.filter((m) => m.role !== "reasoning").map((m) => ({
|
|
1362
|
+
role: m.role === "assistant" ? "assistant" : "user",
|
|
1363
|
+
content: m.content
|
|
1364
|
+
}));
|
|
1365
|
+
let resolvedThreadId = await overrideOptions?.threadId ?? effectiveThreadId;
|
|
1366
|
+
if (!resolvedThreadId) {
|
|
1367
|
+
chatLogger.info("minting real thread for ephemeral architect chat", {});
|
|
1368
|
+
const createRes = await fetchWithAuth("/threads", {
|
|
1369
|
+
method: "POST",
|
|
1370
|
+
headers: { "Content-Type": "application/json" },
|
|
1371
|
+
body: JSON.stringify({ agentId: ARCHITECT_AGENT_ID })
|
|
1372
|
+
});
|
|
1373
|
+
if (!createRes.ok) throw new Error(`Failed to create thread: ${createRes.statusText}`);
|
|
1374
|
+
const createBody = await createRes.json();
|
|
1375
|
+
const created = createBody?.data ?? createBody;
|
|
1376
|
+
resolvedThreadId = created._id ?? created.id;
|
|
1377
|
+
if (!resolvedThreadId) throw new Error("Thread creation returned no id");
|
|
1378
|
+
setInternalThreadId(resolvedThreadId);
|
|
1379
|
+
loadedThreadIdRef.current = resolvedThreadId;
|
|
1380
|
+
options.onThreadCreated?.(resolvedThreadId);
|
|
1381
|
+
chatLogger.info("ephemeral architect chat minted", { threadId: resolvedThreadId });
|
|
1382
|
+
}
|
|
1383
|
+
chatLogger.trace("resolved threadId", { threadId: resolvedThreadId });
|
|
1384
|
+
const token = getAuthToken ? await getAuthToken() : null;
|
|
1385
|
+
chatLogger.debug("opening SSE stream", {
|
|
1386
|
+
hasToken: !!token,
|
|
1387
|
+
hasThreadId: !!resolvedThreadId
|
|
1388
|
+
});
|
|
1389
|
+
const stream = await openSSEStream({
|
|
1390
|
+
url: `${baseUrl}/architect`,
|
|
1391
|
+
headers: {
|
|
1392
|
+
"Content-Type": "application/json",
|
|
1393
|
+
...token ? { Authorization: `Bearer ${token}` } : {}
|
|
1394
|
+
},
|
|
1395
|
+
body: JSON.stringify({
|
|
1396
|
+
messages: payloadMessages,
|
|
1397
|
+
threadId: resolvedThreadId,
|
|
1398
|
+
resume: overrideOptions?.resume
|
|
1399
|
+
}),
|
|
1400
|
+
signal: controller.signal
|
|
1401
|
+
});
|
|
1402
|
+
if (!stream.ok) {
|
|
1403
|
+
chatLogger.warn("SSE stream not ok", { status: stream.status, errorText: stream.errorText });
|
|
1404
|
+
chatLogger.error("architect stream failed", { status: stream.status, error: stream.errorText });
|
|
1405
|
+
throw new Error(`Architect error (${stream.status}): ${stream.errorText ?? "Stream failed"}`);
|
|
1406
|
+
}
|
|
1407
|
+
chatLogger.debug("SSE stream opened", { status: stream.status });
|
|
1408
|
+
chatLogger.info("architect stream started", { threadId: resolvedThreadId });
|
|
1409
|
+
const reader = stream.reader;
|
|
1410
|
+
let buffer = "";
|
|
1411
|
+
let accumulatedText = "";
|
|
1412
|
+
const toolCallsMap = /* @__PURE__ */ new Map();
|
|
1413
|
+
let streamSeq = 0;
|
|
1414
|
+
let activeReasoningId = null;
|
|
1415
|
+
const reasoningById = /* @__PURE__ */ new Map();
|
|
1416
|
+
const patchAssistant = (patch) => {
|
|
1417
|
+
setMessages(
|
|
1418
|
+
(prev) => prev.map(
|
|
1419
|
+
(msg) => msg.id === assistantMessageId ? { ...msg, toolCalls: Array.from(toolCallsMap.values()), ...patch } : msg
|
|
1420
|
+
)
|
|
1421
|
+
);
|
|
1422
|
+
};
|
|
1423
|
+
const insertReasoningMessage = (id, seq) => {
|
|
1424
|
+
const msg = { id, role: "reasoning", content: "", createdAt: /* @__PURE__ */ new Date(), isStreaming: true, seq };
|
|
1425
|
+
setMessages((prev) => {
|
|
1426
|
+
const idx = prev.findIndex((m) => m.id === assistantMessageId);
|
|
1427
|
+
if (idx === -1) return [...prev, msg];
|
|
1428
|
+
const next = [...prev];
|
|
1429
|
+
next.splice(idx, 0, msg);
|
|
1430
|
+
return next;
|
|
1431
|
+
});
|
|
1432
|
+
};
|
|
1433
|
+
while (true) {
|
|
1434
|
+
const { done, value } = await reader.read();
|
|
1435
|
+
if (done) break;
|
|
1436
|
+
buffer += value ?? "";
|
|
1437
|
+
const lines = buffer.split("\n");
|
|
1438
|
+
buffer = lines.pop() ?? "";
|
|
1439
|
+
for (const line of lines) {
|
|
1440
|
+
const trimmed = line.trim();
|
|
1441
|
+
if (!trimmed || !trimmed.startsWith("data:")) continue;
|
|
1442
|
+
const raw = trimmed.replace(/^data:\s*/, "");
|
|
1443
|
+
if (raw === "[DONE]") break;
|
|
1444
|
+
try {
|
|
1445
|
+
const event = JSON.parse(raw);
|
|
1446
|
+
chatLogger.trace("stream event", { type: event.type, event });
|
|
1447
|
+
options.onEvent?.(event);
|
|
1448
|
+
if (event.type === "TEXT_MESSAGE_CHUNK" && event.delta) {
|
|
1449
|
+
chatLogger.debug("text chunk", { deltaLength: event.delta.length });
|
|
1450
|
+
accumulatedText += event.delta;
|
|
1451
|
+
patchAssistant({ content: accumulatedText, isStreaming: true });
|
|
1452
|
+
} else if (event.type === "TOOL_CALL_CHUNK" && event.toolCallId) {
|
|
1453
|
+
chatLogger.debug("tool call chunk", { toolCallId: event.toolCallId, toolCallName: event.toolCallName });
|
|
1454
|
+
const existing = toolCallsMap.get(event.toolCallId);
|
|
1455
|
+
if (existing) {
|
|
1456
|
+
existing.args = (existing.args || "") + (event.delta || "");
|
|
1457
|
+
} else {
|
|
1458
|
+
toolCallsMap.set(event.toolCallId, {
|
|
1459
|
+
toolCallId: event.toolCallId,
|
|
1460
|
+
toolName: event.toolCallName || "",
|
|
1461
|
+
args: event.delta || "",
|
|
1462
|
+
seq: streamSeq++
|
|
1463
|
+
});
|
|
1464
|
+
}
|
|
1465
|
+
patchAssistant({});
|
|
1466
|
+
} else if (event.type === "TOOL_CALL_RESULT") {
|
|
1467
|
+
chatLogger.debug("tool call result", { toolCallId: event.toolCallId });
|
|
1468
|
+
const existing = toolCallsMap.get(event.toolCallId);
|
|
1469
|
+
if (existing) {
|
|
1470
|
+
existing.result = event.content;
|
|
1471
|
+
existing.isError = isErrorToolContent(event.content);
|
|
1472
|
+
if (existing.isError) chatLogger.warn("tool call error", { toolCallId: event.toolCallId });
|
|
1473
|
+
if (existing.toolName === "present_file" && !existing.isError) {
|
|
1474
|
+
const presented = parsePresentedFile(event.content);
|
|
1475
|
+
if (presented) {
|
|
1476
|
+
chatLogger.info("present_file", { path: presented.path });
|
|
1477
|
+
setPresentedFile(presented);
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
patchAssistant({});
|
|
1481
|
+
}
|
|
1482
|
+
} else if (event.type === "STATE_SNAPSHOT") {
|
|
1483
|
+
chatLogger.debug("state snapshot", {
|
|
1484
|
+
fileCount: Object.keys(event.snapshot.files ?? {}).length,
|
|
1485
|
+
todoCount: event.snapshot.todos?.length ?? 0
|
|
1486
|
+
});
|
|
1487
|
+
setFiles(normalizeWorkspaceFiles(event.snapshot.files ?? {}));
|
|
1488
|
+
setTodos(event.snapshot.todos ?? []);
|
|
1489
|
+
} else if (event.type === "REASONING_MESSAGE_START" && event.messageId) {
|
|
1490
|
+
chatLogger.debug("reasoning start", { messageId: event.messageId });
|
|
1491
|
+
activeReasoningId = event.messageId;
|
|
1492
|
+
reasoningById.set(event.messageId, { content: "" });
|
|
1493
|
+
insertReasoningMessage(event.messageId, streamSeq++);
|
|
1494
|
+
} else if (event.type === "REASONING_MESSAGE_CONTENT") {
|
|
1495
|
+
let rid = event.messageId || activeReasoningId || "";
|
|
1496
|
+
if (!rid || !reasoningById.has(rid)) {
|
|
1497
|
+
rid = rid || `reasoning-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
|
|
1498
|
+
activeReasoningId = rid;
|
|
1499
|
+
reasoningById.set(rid, { content: "" });
|
|
1500
|
+
insertReasoningMessage(rid, streamSeq++);
|
|
1501
|
+
chatLogger.debug("reasoning lazy start", { messageId: rid });
|
|
1502
|
+
}
|
|
1503
|
+
const entry = reasoningById.get(rid);
|
|
1504
|
+
entry.content += event.delta;
|
|
1505
|
+
chatLogger.trace("reasoning content", { messageId: rid, deltaLength: event.delta?.length ?? 0 });
|
|
1506
|
+
setMessages((prev) => prev.map((m) => m.id === rid ? { ...m, content: entry.content, isStreaming: true } : m));
|
|
1507
|
+
} else if (event.type === "REASONING_END") {
|
|
1508
|
+
chatLogger.debug("reasoning end", { messageId: activeReasoningId });
|
|
1509
|
+
const rid = activeReasoningId;
|
|
1510
|
+
activeReasoningId = null;
|
|
1511
|
+
if (rid) {
|
|
1512
|
+
setMessages((prev) => prev.map((m) => m.id === rid ? { ...m, isStreaming: false } : m));
|
|
1513
|
+
}
|
|
1514
|
+
} else if (event.type === "CUSTOM") {
|
|
1515
|
+
chatLogger.debug("custom event", { name: event.name });
|
|
1516
|
+
if (event.name === "hitl_request") {
|
|
1517
|
+
const value2 = event.value;
|
|
1518
|
+
chatLogger.info("hitl interrupt", { actionCount: value2.actionRequests?.length ?? 0 });
|
|
1519
|
+
setInterrupt({ kind: "hitl", actionRequests: value2.actionRequests, reviewConfigs: value2.reviewConfigs });
|
|
1520
|
+
} else if (event.name === "clarification_request") {
|
|
1521
|
+
const value2 = event.value;
|
|
1522
|
+
chatLogger.info("clarification interrupt", { questionCount: value2.questions?.length ?? 0 });
|
|
1523
|
+
setInterrupt({ kind: "clarification", questions: value2.questions });
|
|
1524
|
+
} else if (event.name === "subagent_activity") {
|
|
1525
|
+
const { toolCallId, ...entry } = event.value;
|
|
1526
|
+
chatLogger.trace("subagent activity", { toolCallId, kind: entry.kind });
|
|
1527
|
+
const existing = toolCallsMap.get(toolCallId);
|
|
1528
|
+
if (existing) {
|
|
1529
|
+
existing.subagentActivity = [...existing.subagentActivity || [], entry];
|
|
1530
|
+
patchAssistant({});
|
|
1531
|
+
}
|
|
1532
|
+
} else if (event.name === "mcp_app") {
|
|
1533
|
+
const val = event.value;
|
|
1534
|
+
if (val?.toolCallId && val?.resourceUri && val?.mcpId) {
|
|
1535
|
+
const existing = toolCallsMap.get(val.toolCallId);
|
|
1536
|
+
if (existing) {
|
|
1537
|
+
existing.mcpApp = { resourceUri: val.resourceUri, mcpId: val.mcpId };
|
|
1538
|
+
patchAssistant({});
|
|
1539
|
+
}
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
} else if (event.type === "title") {
|
|
1543
|
+
const title = event.title;
|
|
1544
|
+
if (typeof title === "string" && title.trim()) {
|
|
1545
|
+
chatLogger.info("auto title", { title });
|
|
1546
|
+
options.onTitle?.(title);
|
|
1547
|
+
}
|
|
1548
|
+
} else if (event.type === "RUN_ERROR") {
|
|
1549
|
+
chatLogger.warn("run error", { message: event.message, code: event.code });
|
|
1550
|
+
chatLogger.error("stream run error", { code: event.code, message: event.message });
|
|
1551
|
+
throw new Error(event.message || "Stream error from agent");
|
|
1552
|
+
} else {
|
|
1553
|
+
chatLogger.trace("unhandled event", { type: event.type });
|
|
1554
|
+
}
|
|
1555
|
+
} catch (e) {
|
|
1556
|
+
if (e instanceof Error && e.message.startsWith("Stream error")) throw e;
|
|
1557
|
+
chatLogger.warn("event parse error", { raw: raw.slice(0, 200), error: e instanceof Error ? e.message : String(e) });
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
const finalMessage = {
|
|
1562
|
+
id: assistantMessageId,
|
|
1563
|
+
role: "assistant",
|
|
1564
|
+
content: accumulatedText,
|
|
1565
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
1566
|
+
isStreaming: false,
|
|
1567
|
+
toolCalls: Array.from(toolCallsMap.values())
|
|
1568
|
+
};
|
|
1569
|
+
setMessages((prev) => prev.map((msg) => msg.id === assistantMessageId ? finalMessage : msg));
|
|
1570
|
+
chatLogger.info("sendMessage succeeded", { textLength: accumulatedText.length, toolCallCount: toolCallsMap.size });
|
|
1571
|
+
chatLogger.debug("sendMessage completed", { textLength: accumulatedText.length, eventCount: toolCallsMap.size + 1 });
|
|
1572
|
+
options.onFinish?.(finalMessage);
|
|
1573
|
+
return true;
|
|
1574
|
+
} catch (err) {
|
|
1575
|
+
if (controller.signal.aborted) {
|
|
1576
|
+
chatLogger.info("sendMessage aborted", {});
|
|
1577
|
+
chatLogger.debug("stream aborted", {});
|
|
1578
|
+
setMessages((prev) => prev.map((msg) => msg.id === assistantMessageId ? { ...msg, isStreaming: false } : msg));
|
|
1579
|
+
return false;
|
|
1580
|
+
}
|
|
1581
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
1582
|
+
chatLogger.warn("sendMessage failed", { error: errorObj.message });
|
|
1583
|
+
chatLogger.error("sendMessage error", { error: errorObj.message });
|
|
1584
|
+
setError(errorObj);
|
|
1585
|
+
options.onError?.(errorObj);
|
|
1586
|
+
setMessages(
|
|
1587
|
+
(prev) => prev.map(
|
|
1588
|
+
(msg) => msg.id === assistantMessageId ? { ...msg, content: msg.content || `\u26A0\uFE0F Error: ${errorObj.message || "Failed to get response."}`, isStreaming: false } : msg
|
|
1589
|
+
)
|
|
1590
|
+
);
|
|
1591
|
+
return false;
|
|
1592
|
+
} finally {
|
|
1593
|
+
setIsStreaming(false);
|
|
1594
|
+
abortControllerRef.current = null;
|
|
1595
|
+
finalizeReasoning();
|
|
1596
|
+
chatLogger.debug("sendMessage finally", { isStreaming: false });
|
|
1597
|
+
chatLogger.trace("sendMessage end", {});
|
|
1598
|
+
}
|
|
1599
|
+
},
|
|
1600
|
+
[baseUrl, getAuthToken, fetchWithAuth, options, chatLogger, effectiveThreadId]
|
|
1601
|
+
);
|
|
1602
|
+
const sendMessage = (0, import_react3.useCallback)(
|
|
1603
|
+
async (contentToSend, overrideOptions) => {
|
|
1604
|
+
const prompt = (contentToSend ?? input).trim();
|
|
1605
|
+
if (!prompt || isStreaming) {
|
|
1606
|
+
chatLogger.trace("sendMessage skipped", {
|
|
1607
|
+
hasPrompt: !!prompt,
|
|
1608
|
+
isStreaming
|
|
1609
|
+
});
|
|
1610
|
+
if (isStreaming) {
|
|
1611
|
+
chatLogger.warn("sendMessage dropped while streaming \u2014 caller should queue or disable send", {});
|
|
1612
|
+
}
|
|
1613
|
+
return false;
|
|
1614
|
+
}
|
|
1615
|
+
return doSend(prompt, messages, overrideOptions);
|
|
1616
|
+
},
|
|
1617
|
+
[input, isStreaming, messages, doSend, chatLogger]
|
|
1618
|
+
);
|
|
1619
|
+
const handleInputChange = (0, import_react3.useCallback)(
|
|
1620
|
+
(e) => {
|
|
1621
|
+
chatLogger.trace("handleInputChange", { length: e.target.value.length });
|
|
1622
|
+
setInput(e.target.value);
|
|
1623
|
+
},
|
|
1624
|
+
[chatLogger]
|
|
1625
|
+
);
|
|
1626
|
+
const handleSubmit = (0, import_react3.useCallback)(
|
|
1627
|
+
(e) => {
|
|
1628
|
+
if (e) e.preventDefault();
|
|
1629
|
+
chatLogger.debug("handleSubmit", {});
|
|
1630
|
+
void sendMessage();
|
|
1631
|
+
},
|
|
1632
|
+
[sendMessage, chatLogger]
|
|
1633
|
+
);
|
|
1634
|
+
const reload = (0, import_react3.useCallback)(async () => {
|
|
1635
|
+
if (messages.length === 0 || isStreaming) {
|
|
1636
|
+
chatLogger.trace("reload skipped", {
|
|
1637
|
+
messageCount: messages.length,
|
|
1638
|
+
isStreaming
|
|
1639
|
+
});
|
|
1640
|
+
return false;
|
|
1641
|
+
}
|
|
1642
|
+
let lastUserIndex = -1;
|
|
1643
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
1644
|
+
if (messages[i].role === "user") {
|
|
1645
|
+
lastUserIndex = i;
|
|
1646
|
+
break;
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
if (lastUserIndex === -1) {
|
|
1650
|
+
chatLogger.warn("reload no user message", {});
|
|
1651
|
+
return false;
|
|
1652
|
+
}
|
|
1653
|
+
const lastUserMessage = messages[lastUserIndex];
|
|
1654
|
+
const truncated = messages.slice(0, lastUserIndex);
|
|
1655
|
+
chatLogger.info("reload", { messageId: lastUserMessage.id });
|
|
1656
|
+
chatLogger.debug("reload last user", {
|
|
1657
|
+
preview: lastUserMessage.content.slice(0, 100)
|
|
1658
|
+
});
|
|
1659
|
+
return doSend(lastUserMessage.content, truncated);
|
|
1660
|
+
}, [isStreaming, messages, doSend, chatLogger]);
|
|
1661
|
+
const resumeInterrupt = (0, import_react3.useCallback)(
|
|
1662
|
+
(resume, displayContent) => {
|
|
1663
|
+
chatLogger.info("resumeInterrupt", {
|
|
1664
|
+
kind: resume.decisions ? "hitl" : "clarification",
|
|
1665
|
+
preview: displayContent.slice(0, 50)
|
|
1666
|
+
});
|
|
1667
|
+
return sendMessage(displayContent, { resume });
|
|
1668
|
+
},
|
|
1669
|
+
[sendMessage, chatLogger]
|
|
1670
|
+
);
|
|
1671
|
+
const dismissPresentedFile = (0, import_react3.useCallback)(() => {
|
|
1672
|
+
chatLogger.debug("dismissPresentedFile", {});
|
|
1673
|
+
setPresentedFile(null);
|
|
1674
|
+
}, [chatLogger]);
|
|
1675
|
+
const openWorkspaceFile = (0, import_react3.useCallback)(
|
|
1676
|
+
(path) => {
|
|
1677
|
+
chatLogger.debug("openWorkspaceFile", { path });
|
|
1678
|
+
setPresentedFile({
|
|
1679
|
+
path,
|
|
1680
|
+
title: path.split("/").pop() || path,
|
|
1681
|
+
description: ""
|
|
1682
|
+
});
|
|
1683
|
+
},
|
|
1684
|
+
[chatLogger]
|
|
1685
|
+
);
|
|
1686
|
+
return {
|
|
1687
|
+
messages,
|
|
1688
|
+
input,
|
|
1689
|
+
setInput,
|
|
1690
|
+
handleInputChange,
|
|
1691
|
+
handleSubmit,
|
|
1692
|
+
sendMessage,
|
|
1693
|
+
isStreaming,
|
|
1694
|
+
isLoading: isStreaming,
|
|
1695
|
+
isLoadingHistory,
|
|
1696
|
+
error,
|
|
1697
|
+
interrupt,
|
|
1698
|
+
resumeInterrupt,
|
|
1699
|
+
files,
|
|
1700
|
+
todos,
|
|
1701
|
+
presentedFile,
|
|
1702
|
+
dismissPresentedFile,
|
|
1703
|
+
openWorkspaceFile,
|
|
1704
|
+
stop,
|
|
1705
|
+
reload,
|
|
1706
|
+
clear,
|
|
1707
|
+
startNewChat,
|
|
1708
|
+
currentThreadId: effectiveThreadId,
|
|
1709
|
+
isEphemeral: !effectiveThreadId,
|
|
1710
|
+
setMessages,
|
|
1711
|
+
loadThreadMessages
|
|
1712
|
+
};
|
|
1713
|
+
}
|
|
1714
|
+
|
|
1715
|
+
// src/hooks/useMemory.ts
|
|
1716
|
+
var import_react4 = require("react");
|
|
1717
|
+
function useMemory(autoFetch = true) {
|
|
1718
|
+
const { fetchWithAuth } = usePersonaContext();
|
|
1719
|
+
const [memory, setMemory] = (0, import_react4.useState)({
|
|
1720
|
+
userFiles: [],
|
|
1721
|
+
agentMemories: []
|
|
1722
|
+
});
|
|
1723
|
+
const [isLoading, setIsLoading] = (0, import_react4.useState)(false);
|
|
1724
|
+
const [error, setError] = (0, import_react4.useState)(null);
|
|
1725
|
+
const fetchMemory = (0, import_react4.useCallback)(async () => {
|
|
1726
|
+
setIsLoading(true);
|
|
1727
|
+
setError(null);
|
|
1728
|
+
try {
|
|
1729
|
+
const res = await fetchWithAuth("/memory");
|
|
1730
|
+
if (!res.ok) {
|
|
1731
|
+
throw new Error(`Failed to fetch memory: ${res.statusText}`);
|
|
1732
|
+
}
|
|
1733
|
+
const data = await res.json();
|
|
1734
|
+
setMemory(data);
|
|
1735
|
+
return data;
|
|
1736
|
+
} catch (err) {
|
|
1737
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
1738
|
+
setError(errorObj);
|
|
1739
|
+
return { userFiles: [], agentMemories: [] };
|
|
1740
|
+
} finally {
|
|
1741
|
+
setIsLoading(false);
|
|
1742
|
+
}
|
|
1743
|
+
}, [fetchWithAuth]);
|
|
1744
|
+
const getFile = (0, import_react4.useCallback)(
|
|
1745
|
+
async (params) => {
|
|
1746
|
+
const query = new URLSearchParams({ path: params.path });
|
|
1747
|
+
if (params.scope) query.set("scope", params.scope);
|
|
1748
|
+
if (params.agentId) query.set("agentId", params.agentId);
|
|
1749
|
+
const res = await fetchWithAuth(`/memory/file?${query.toString()}`);
|
|
1750
|
+
if (!res.ok)
|
|
1751
|
+
throw new Error(`Failed to get memory file: ${res.statusText}`);
|
|
1752
|
+
return await res.json();
|
|
1753
|
+
},
|
|
1754
|
+
[fetchWithAuth]
|
|
1755
|
+
);
|
|
1756
|
+
const writeFile = (0, import_react4.useCallback)(
|
|
1757
|
+
async (params) => {
|
|
1758
|
+
const res = await fetchWithAuth("/memory/file", {
|
|
1759
|
+
method: "PUT",
|
|
1760
|
+
headers: { "Content-Type": "application/json" },
|
|
1761
|
+
body: JSON.stringify(params)
|
|
1762
|
+
});
|
|
1763
|
+
if (!res.ok)
|
|
1764
|
+
throw new Error(`Failed to write memory file: ${res.statusText}`);
|
|
1765
|
+
const updated = await res.json();
|
|
1766
|
+
void fetchMemory();
|
|
1767
|
+
return updated;
|
|
1768
|
+
},
|
|
1769
|
+
[fetchWithAuth, fetchMemory]
|
|
1770
|
+
);
|
|
1771
|
+
const deleteFile = (0, import_react4.useCallback)(
|
|
1772
|
+
async (params) => {
|
|
1773
|
+
const query = new URLSearchParams({ path: params.path });
|
|
1774
|
+
if (params.scope) query.set("scope", params.scope);
|
|
1775
|
+
if (params.agentId) query.set("agentId", params.agentId);
|
|
1776
|
+
const res = await fetchWithAuth(`/memory/file?${query.toString()}`, {
|
|
1777
|
+
method: "DELETE"
|
|
1778
|
+
});
|
|
1779
|
+
if (!res.ok)
|
|
1780
|
+
throw new Error(`Failed to delete memory file: ${res.statusText}`);
|
|
1781
|
+
void fetchMemory();
|
|
1782
|
+
},
|
|
1783
|
+
[fetchWithAuth, fetchMemory]
|
|
1784
|
+
);
|
|
1785
|
+
(0, import_react4.useEffect)(() => {
|
|
1786
|
+
if (autoFetch) {
|
|
1787
|
+
void fetchMemory();
|
|
1788
|
+
}
|
|
1789
|
+
}, [autoFetch, fetchMemory]);
|
|
1790
|
+
return {
|
|
1791
|
+
memory,
|
|
1792
|
+
isLoading,
|
|
1793
|
+
error,
|
|
1794
|
+
refetch: fetchMemory,
|
|
1795
|
+
getFile,
|
|
1796
|
+
writeFile,
|
|
1797
|
+
deleteFile
|
|
1798
|
+
};
|
|
1799
|
+
}
|
|
1800
|
+
|
|
1801
|
+
// src/hooks/useThreads.ts
|
|
1802
|
+
var import_react5 = require("react");
|
|
1803
|
+
function useThreads(autoFetch = true) {
|
|
1804
|
+
const { fetchWithAuth, defaultAgentId } = usePersonaContext();
|
|
1805
|
+
const [threads, setThreads] = (0, import_react5.useState)([]);
|
|
1806
|
+
const [isLoading, setIsLoading] = (0, import_react5.useState)(false);
|
|
1807
|
+
const [error, setError] = (0, import_react5.useState)(null);
|
|
1808
|
+
const fetchThreads = (0, import_react5.useCallback)(async () => {
|
|
1809
|
+
setIsLoading(true);
|
|
1810
|
+
setError(null);
|
|
1811
|
+
try {
|
|
1812
|
+
const res = await fetchWithAuth("/threads");
|
|
1255
1813
|
if (!res.ok) throw new Error(`Failed to list threads: ${res.statusText}`);
|
|
1256
1814
|
const data = await res.json();
|
|
1257
1815
|
const items = Array.isArray(data) ? data : data?.items || data?.threads || (Array.isArray(data?.data) ? data.data : void 0) || [];
|
|
@@ -1265,7 +1823,7 @@ function useThreads(autoFetch = true) {
|
|
|
1265
1823
|
setIsLoading(false);
|
|
1266
1824
|
}
|
|
1267
1825
|
}, [fetchWithAuth]);
|
|
1268
|
-
const createThread = (0,
|
|
1826
|
+
const createThread = (0, import_react5.useCallback)(
|
|
1269
1827
|
async (agentId) => {
|
|
1270
1828
|
const targetAgentId = agentId || defaultAgentId;
|
|
1271
1829
|
const res = await fetchWithAuth("/threads", {
|
|
@@ -1282,7 +1840,7 @@ function useThreads(autoFetch = true) {
|
|
|
1282
1840
|
},
|
|
1283
1841
|
[fetchWithAuth, defaultAgentId, fetchThreads]
|
|
1284
1842
|
);
|
|
1285
|
-
const deleteThread = (0,
|
|
1843
|
+
const deleteThread = (0, import_react5.useCallback)(
|
|
1286
1844
|
async (threadId) => {
|
|
1287
1845
|
const res = await fetchWithAuth(`/threads/${threadId}`, {
|
|
1288
1846
|
method: "DELETE"
|
|
@@ -1293,7 +1851,7 @@ function useThreads(autoFetch = true) {
|
|
|
1293
1851
|
},
|
|
1294
1852
|
[fetchWithAuth]
|
|
1295
1853
|
);
|
|
1296
|
-
const bulkDeleteThreads = (0,
|
|
1854
|
+
const bulkDeleteThreads = (0, import_react5.useCallback)(
|
|
1297
1855
|
async (threadIds) => {
|
|
1298
1856
|
const res = await fetchWithAuth("/threads/bulk-delete", {
|
|
1299
1857
|
method: "POST",
|
|
@@ -1310,13 +1868,13 @@ function useThreads(autoFetch = true) {
|
|
|
1310
1868
|
},
|
|
1311
1869
|
[fetchWithAuth]
|
|
1312
1870
|
);
|
|
1313
|
-
const deleteAllThreads = (0,
|
|
1871
|
+
const deleteAllThreads = (0, import_react5.useCallback)(async () => {
|
|
1314
1872
|
const ids = threads.map((t) => t._id);
|
|
1315
1873
|
for (let i = 0; i < ids.length; i += 100) {
|
|
1316
1874
|
await bulkDeleteThreads(ids.slice(i, i + 100));
|
|
1317
1875
|
}
|
|
1318
1876
|
}, [threads, bulkDeleteThreads]);
|
|
1319
|
-
const updateThread = (0,
|
|
1877
|
+
const updateThread = (0, import_react5.useCallback)(
|
|
1320
1878
|
async (threadId, input) => {
|
|
1321
1879
|
const res = await fetchWithAuth(`/threads/${threadId}`, {
|
|
1322
1880
|
method: "PATCH",
|
|
@@ -1334,11 +1892,11 @@ function useThreads(autoFetch = true) {
|
|
|
1334
1892
|
},
|
|
1335
1893
|
[fetchWithAuth]
|
|
1336
1894
|
);
|
|
1337
|
-
const renameThread = (0,
|
|
1895
|
+
const renameThread = (0, import_react5.useCallback)(
|
|
1338
1896
|
(threadId, title) => updateThread(threadId, { title }),
|
|
1339
1897
|
[updateThread]
|
|
1340
1898
|
);
|
|
1341
|
-
const resetThread = (0,
|
|
1899
|
+
const resetThread = (0, import_react5.useCallback)(
|
|
1342
1900
|
async (threadId) => {
|
|
1343
1901
|
const res = await fetchWithAuth(`/threads/${threadId}/reset`, {
|
|
1344
1902
|
method: "POST"
|
|
@@ -1353,7 +1911,7 @@ function useThreads(autoFetch = true) {
|
|
|
1353
1911
|
},
|
|
1354
1912
|
[fetchWithAuth]
|
|
1355
1913
|
);
|
|
1356
|
-
const getThread = (0,
|
|
1914
|
+
const getThread = (0, import_react5.useCallback)(
|
|
1357
1915
|
async (threadId) => {
|
|
1358
1916
|
const res = await fetchWithAuth(`/threads/${threadId}`);
|
|
1359
1917
|
if (!res.ok) throw new Error(`Failed to fetch thread: ${res.statusText}`);
|
|
@@ -1362,7 +1920,7 @@ function useThreads(autoFetch = true) {
|
|
|
1362
1920
|
},
|
|
1363
1921
|
[fetchWithAuth]
|
|
1364
1922
|
);
|
|
1365
|
-
(0,
|
|
1923
|
+
(0, import_react5.useEffect)(() => {
|
|
1366
1924
|
if (autoFetch) {
|
|
1367
1925
|
void fetchThreads();
|
|
1368
1926
|
}
|
|
@@ -1384,7 +1942,7 @@ function useThreads(autoFetch = true) {
|
|
|
1384
1942
|
}
|
|
1385
1943
|
|
|
1386
1944
|
// src/hooks/useVoice.ts
|
|
1387
|
-
var
|
|
1945
|
+
var import_react6 = require("react");
|
|
1388
1946
|
|
|
1389
1947
|
// src/hooks/voiceWorklets.ts
|
|
1390
1948
|
var RECORDER_WORKLET_SOURCE = `
|
|
@@ -1487,42 +2045,42 @@ function mergeTranscriptText(prev, next) {
|
|
|
1487
2045
|
}
|
|
1488
2046
|
function useVoice(options = {}) {
|
|
1489
2047
|
const { defaultAgentId, fetchWithAuth, logger } = usePersonaContext();
|
|
1490
|
-
const voiceLogger = (0,
|
|
2048
|
+
const voiceLogger = (0, import_react6.useMemo)(() => logger.child("voice"), [logger]);
|
|
1491
2049
|
const agentId = options.agentId || defaultAgentId;
|
|
1492
2050
|
const threadId = options.threadId;
|
|
1493
2051
|
const contextOverride = options.contextOverride;
|
|
1494
2052
|
const context = options.context;
|
|
1495
|
-
const [state, setState] = (0,
|
|
1496
|
-
const [isMuted, setIsMuted] = (0,
|
|
1497
|
-
const [transcript, setTranscript] = (0,
|
|
2053
|
+
const [state, setState] = (0, import_react6.useState)("idle");
|
|
2054
|
+
const [isMuted, setIsMuted] = (0, import_react6.useState)(false);
|
|
2055
|
+
const [transcript, setTranscript] = (0, import_react6.useState)(
|
|
1498
2056
|
[]
|
|
1499
2057
|
);
|
|
1500
|
-
const [partial, setPartial] = (0,
|
|
2058
|
+
const [partial, setPartial] = (0, import_react6.useState)(
|
|
1501
2059
|
null
|
|
1502
2060
|
);
|
|
1503
|
-
const [toolCalls, setToolCalls] = (0,
|
|
1504
|
-
const [error, setError] = (0,
|
|
1505
|
-
const [endReason, setEndReason] = (0,
|
|
2061
|
+
const [toolCalls, setToolCalls] = (0, import_react6.useState)([]);
|
|
2062
|
+
const [error, setError] = (0, import_react6.useState)(null);
|
|
2063
|
+
const [endReason, setEndReason] = (0, import_react6.useState)(
|
|
1506
2064
|
null
|
|
1507
2065
|
);
|
|
1508
|
-
const wsRef = (0,
|
|
1509
|
-
const streamRef = (0,
|
|
1510
|
-
const inputCtxRef = (0,
|
|
1511
|
-
const outputCtxRef = (0,
|
|
1512
|
-
const recorderNodeRef = (0,
|
|
1513
|
-
const playerNodeRef = (0,
|
|
1514
|
-
const acceptedTurnSeqRef = (0,
|
|
1515
|
-
const mountedRef = (0,
|
|
1516
|
-
const lastFinalTurnRef = (0,
|
|
2066
|
+
const wsRef = (0, import_react6.useRef)(null);
|
|
2067
|
+
const streamRef = (0, import_react6.useRef)(null);
|
|
2068
|
+
const inputCtxRef = (0, import_react6.useRef)(null);
|
|
2069
|
+
const outputCtxRef = (0, import_react6.useRef)(null);
|
|
2070
|
+
const recorderNodeRef = (0, import_react6.useRef)(null);
|
|
2071
|
+
const playerNodeRef = (0, import_react6.useRef)(null);
|
|
2072
|
+
const acceptedTurnSeqRef = (0, import_react6.useRef)(0);
|
|
2073
|
+
const mountedRef = (0, import_react6.useRef)(true);
|
|
2074
|
+
const lastFinalTurnRef = (0, import_react6.useRef)(
|
|
1517
2075
|
null
|
|
1518
2076
|
);
|
|
1519
|
-
(0,
|
|
2077
|
+
(0, import_react6.useEffect)(() => {
|
|
1520
2078
|
mountedRef.current = true;
|
|
1521
2079
|
return () => {
|
|
1522
2080
|
mountedRef.current = false;
|
|
1523
2081
|
};
|
|
1524
2082
|
}, []);
|
|
1525
|
-
const teardownAudio = (0,
|
|
2083
|
+
const teardownAudio = (0, import_react6.useCallback)(() => {
|
|
1526
2084
|
try {
|
|
1527
2085
|
streamRef.current?.getTracks().forEach((track) => track.stop());
|
|
1528
2086
|
} catch {
|
|
@@ -1549,7 +2107,7 @@ function useVoice(options = {}) {
|
|
|
1549
2107
|
}
|
|
1550
2108
|
outputCtxRef.current = null;
|
|
1551
2109
|
}, []);
|
|
1552
|
-
const stop = (0,
|
|
2110
|
+
const stop = (0, import_react6.useCallback)(() => {
|
|
1553
2111
|
voiceLogger.debug("stop() called");
|
|
1554
2112
|
try {
|
|
1555
2113
|
wsRef.current?.close(1e3, "client_stop");
|
|
@@ -1559,8 +2117,8 @@ function useVoice(options = {}) {
|
|
|
1559
2117
|
teardownAudio();
|
|
1560
2118
|
if (mountedRef.current) setState("idle");
|
|
1561
2119
|
}, [teardownAudio, voiceLogger]);
|
|
1562
|
-
(0,
|
|
1563
|
-
const startCapture = (0,
|
|
2120
|
+
(0, import_react6.useEffect)(() => stop, [stop]);
|
|
2121
|
+
const startCapture = (0, import_react6.useCallback)(async (inputSampleRate) => {
|
|
1564
2122
|
const stream = await navigator.mediaDevices.getUserMedia({
|
|
1565
2123
|
audio: {
|
|
1566
2124
|
echoCancellation: true,
|
|
@@ -1586,7 +2144,7 @@ function useVoice(options = {}) {
|
|
|
1586
2144
|
recorderNodeRef.current = recorderNode;
|
|
1587
2145
|
source.connect(recorderNode);
|
|
1588
2146
|
}, []);
|
|
1589
|
-
const setupPlayback = (0,
|
|
2147
|
+
const setupPlayback = (0, import_react6.useCallback)(async (outputSampleRate) => {
|
|
1590
2148
|
const outputCtx = new AudioContext({ sampleRate: outputSampleRate });
|
|
1591
2149
|
outputCtxRef.current = outputCtx;
|
|
1592
2150
|
await outputCtx.audioWorklet.addModule(playerWorkletUrl());
|
|
@@ -1594,7 +2152,7 @@ function useVoice(options = {}) {
|
|
|
1594
2152
|
playerNode.connect(outputCtx.destination);
|
|
1595
2153
|
playerNodeRef.current = playerNode;
|
|
1596
2154
|
}, []);
|
|
1597
|
-
const upsertToolCall = (0,
|
|
2155
|
+
const upsertToolCall = (0, import_react6.useCallback)(
|
|
1598
2156
|
(id, patch) => {
|
|
1599
2157
|
setToolCalls((prev) => {
|
|
1600
2158
|
const idx = prev.findIndex((t) => t.id === id);
|
|
@@ -1606,7 +2164,7 @@ function useVoice(options = {}) {
|
|
|
1606
2164
|
},
|
|
1607
2165
|
[]
|
|
1608
2166
|
);
|
|
1609
|
-
const handleTranscript = (0,
|
|
2167
|
+
const handleTranscript = (0, import_react6.useCallback)((value) => {
|
|
1610
2168
|
const { speaker, text, isFinal, turnSeq } = value;
|
|
1611
2169
|
if (!isFinal) {
|
|
1612
2170
|
setPartial({ id: "partial", speaker, text });
|
|
@@ -1629,7 +2187,7 @@ function useVoice(options = {}) {
|
|
|
1629
2187
|
});
|
|
1630
2188
|
lastFinalTurnRef.current = { speaker, turnSeq };
|
|
1631
2189
|
}, []);
|
|
1632
|
-
const handleCustomEvent = (0,
|
|
2190
|
+
const handleCustomEvent = (0, import_react6.useCallback)(
|
|
1633
2191
|
(name, value) => {
|
|
1634
2192
|
switch (name) {
|
|
1635
2193
|
case "voice_session_ready":
|
|
@@ -1687,7 +2245,7 @@ function useVoice(options = {}) {
|
|
|
1687
2245
|
},
|
|
1688
2246
|
[handleTranscript, setupPlayback, startCapture, teardownAudio, voiceLogger]
|
|
1689
2247
|
);
|
|
1690
|
-
const handleMessage = (0,
|
|
2248
|
+
const handleMessage = (0, import_react6.useCallback)(
|
|
1691
2249
|
(event) => {
|
|
1692
2250
|
if (typeof event.data !== "string") {
|
|
1693
2251
|
const buf = event.data;
|
|
@@ -1745,7 +2303,7 @@ function useVoice(options = {}) {
|
|
|
1745
2303
|
},
|
|
1746
2304
|
[handleCustomEvent, upsertToolCall, voiceLogger]
|
|
1747
2305
|
);
|
|
1748
|
-
const start = (0,
|
|
2306
|
+
const start = (0, import_react6.useCallback)(async () => {
|
|
1749
2307
|
if (!agentId) {
|
|
1750
2308
|
const err = new Error(
|
|
1751
2309
|
"useVoice: no agentId provided and no defaultAgentId set on PersonaProvider"
|
|
@@ -1812,17 +2370,17 @@ function useVoice(options = {}) {
|
|
|
1812
2370
|
teardownAudio();
|
|
1813
2371
|
}
|
|
1814
2372
|
}, [agentId, threadId, contextOverride, context, fetchWithAuth, handleMessage, teardownAudio, voiceLogger]);
|
|
1815
|
-
const mute = (0,
|
|
2373
|
+
const mute = (0, import_react6.useCallback)((muted) => {
|
|
1816
2374
|
setIsMuted(muted);
|
|
1817
2375
|
streamRef.current?.getAudioTracks().forEach((track) => {
|
|
1818
2376
|
track.enabled = !muted;
|
|
1819
2377
|
});
|
|
1820
2378
|
}, []);
|
|
1821
|
-
const sendText = (0,
|
|
2379
|
+
const sendText = (0, import_react6.useCallback)((text) => {
|
|
1822
2380
|
if (!text?.trim() || wsRef.current?.readyState !== WebSocket.OPEN) return;
|
|
1823
2381
|
wsRef.current.send(JSON.stringify({ type: "voice.text", text }));
|
|
1824
2382
|
}, []);
|
|
1825
|
-
const updateContext = (0,
|
|
2383
|
+
const updateContext = (0, import_react6.useCallback)((newContext) => {
|
|
1826
2384
|
if (wsRef.current?.readyState !== WebSocket.OPEN) return;
|
|
1827
2385
|
wsRef.current.send(JSON.stringify({ type: "voice.context", context: newContext }));
|
|
1828
2386
|
}, []);
|
|
@@ -1843,14 +2401,14 @@ function useVoice(options = {}) {
|
|
|
1843
2401
|
}
|
|
1844
2402
|
|
|
1845
2403
|
// src/hooks/useFiles.ts
|
|
1846
|
-
var
|
|
2404
|
+
var import_react7 = require("react");
|
|
1847
2405
|
function useFiles(autoFetch = true) {
|
|
1848
2406
|
const { fetchWithAuth } = usePersonaContext();
|
|
1849
|
-
const [files, setFiles] = (0,
|
|
1850
|
-
const [isLoading, setIsLoading] = (0,
|
|
1851
|
-
const [isUploading, setIsUploading] = (0,
|
|
1852
|
-
const [error, setError] = (0,
|
|
1853
|
-
const fetchFiles = (0,
|
|
2407
|
+
const [files, setFiles] = (0, import_react7.useState)([]);
|
|
2408
|
+
const [isLoading, setIsLoading] = (0, import_react7.useState)(false);
|
|
2409
|
+
const [isUploading, setIsUploading] = (0, import_react7.useState)(false);
|
|
2410
|
+
const [error, setError] = (0, import_react7.useState)(null);
|
|
2411
|
+
const fetchFiles = (0, import_react7.useCallback)(async () => {
|
|
1854
2412
|
setIsLoading(true);
|
|
1855
2413
|
setError(null);
|
|
1856
2414
|
try {
|
|
@@ -1868,7 +2426,7 @@ function useFiles(autoFetch = true) {
|
|
|
1868
2426
|
setIsLoading(false);
|
|
1869
2427
|
}
|
|
1870
2428
|
}, [fetchWithAuth]);
|
|
1871
|
-
const uploadFile = (0,
|
|
2429
|
+
const uploadFile = (0, import_react7.useCallback)(
|
|
1872
2430
|
async (fileOrFormData) => {
|
|
1873
2431
|
setIsUploading(true);
|
|
1874
2432
|
setError(null);
|
|
@@ -1901,7 +2459,7 @@ function useFiles(autoFetch = true) {
|
|
|
1901
2459
|
},
|
|
1902
2460
|
[fetchWithAuth, fetchFiles]
|
|
1903
2461
|
);
|
|
1904
|
-
const deleteFile = (0,
|
|
2462
|
+
const deleteFile = (0, import_react7.useCallback)(
|
|
1905
2463
|
async (fileId) => {
|
|
1906
2464
|
const res = await fetchWithAuth(`/files/${fileId}`, { method: "DELETE" });
|
|
1907
2465
|
if (!res.ok) throw new Error(`Failed to delete file: ${res.statusText}`);
|
|
@@ -1909,7 +2467,7 @@ function useFiles(autoFetch = true) {
|
|
|
1909
2467
|
},
|
|
1910
2468
|
[fetchWithAuth]
|
|
1911
2469
|
);
|
|
1912
|
-
const bulkDeleteFiles = (0,
|
|
2470
|
+
const bulkDeleteFiles = (0, import_react7.useCallback)(
|
|
1913
2471
|
async (fileIds) => {
|
|
1914
2472
|
const res = await fetchWithAuth("/files/bulk-delete", {
|
|
1915
2473
|
method: "POST",
|
|
@@ -1924,10 +2482,10 @@ function useFiles(autoFetch = true) {
|
|
|
1924
2482
|
},
|
|
1925
2483
|
[fetchWithAuth]
|
|
1926
2484
|
);
|
|
1927
|
-
const getDownloadUrl = (0,
|
|
2485
|
+
const getDownloadUrl = (0, import_react7.useCallback)((fileId) => {
|
|
1928
2486
|
return `/files/${fileId}`;
|
|
1929
2487
|
}, []);
|
|
1930
|
-
(0,
|
|
2488
|
+
(0, import_react7.useEffect)(() => {
|
|
1931
2489
|
if (autoFetch) {
|
|
1932
2490
|
void fetchFiles();
|
|
1933
2491
|
}
|
|
@@ -1946,21 +2504,39 @@ function useFiles(autoFetch = true) {
|
|
|
1946
2504
|
}
|
|
1947
2505
|
|
|
1948
2506
|
// src/hooks/useAgents.ts
|
|
1949
|
-
var
|
|
1950
|
-
function useAgents(
|
|
2507
|
+
var import_react8 = require("react");
|
|
2508
|
+
function useAgents(options = true) {
|
|
2509
|
+
const opts = typeof options === "boolean" ? { autoFetch: options } : options;
|
|
2510
|
+
const { autoFetch = true, page, limit, search, category, scope } = opts;
|
|
1951
2511
|
const { fetchWithAuth } = usePersonaContext();
|
|
1952
|
-
const [agents, setAgents] = (0,
|
|
1953
|
-
const [
|
|
1954
|
-
|
|
1955
|
-
|
|
2512
|
+
const [agents, setAgents] = (0, import_react8.useState)([]);
|
|
2513
|
+
const [pagination, setPagination] = (0, import_react8.useState)({
|
|
2514
|
+
total: 0,
|
|
2515
|
+
page: page ?? 1,
|
|
2516
|
+
limit: limit ?? 20,
|
|
2517
|
+
pages: 0
|
|
2518
|
+
});
|
|
2519
|
+
const [isLoading, setIsLoading] = (0, import_react8.useState)(false);
|
|
2520
|
+
const [error, setError] = (0, import_react8.useState)(null);
|
|
2521
|
+
const fetchAgents = (0, import_react8.useCallback)(async () => {
|
|
1956
2522
|
setIsLoading(true);
|
|
1957
2523
|
setError(null);
|
|
1958
2524
|
try {
|
|
1959
|
-
const
|
|
2525
|
+
const query = new URLSearchParams();
|
|
2526
|
+
if (page) query.set("page", String(page));
|
|
2527
|
+
if (limit) query.set("limit", String(limit));
|
|
2528
|
+
if (search) query.set("search", search);
|
|
2529
|
+
if (category) query.set("category", category);
|
|
2530
|
+
if (scope) query.set("scope", scope);
|
|
2531
|
+
const queryStr = query.toString() ? `?${query.toString()}` : "";
|
|
2532
|
+
const res = await fetchWithAuth(`/agents${queryStr}`);
|
|
1960
2533
|
if (!res.ok) throw new Error(`Failed to list agents: ${res.statusText}`);
|
|
1961
2534
|
const data = await res.json();
|
|
1962
|
-
const items = Array.isArray(data) ? data : data?.items
|
|
2535
|
+
const items = Array.isArray(data) ? data : data?.items ?? [];
|
|
1963
2536
|
setAgents(items);
|
|
2537
|
+
setPagination(
|
|
2538
|
+
data?.pagination ?? { total: items.length, page: 1, limit: items.length, pages: 1 }
|
|
2539
|
+
);
|
|
1964
2540
|
return items;
|
|
1965
2541
|
} catch (err) {
|
|
1966
2542
|
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
@@ -1969,28 +2545,131 @@ function useAgents(autoFetch = true) {
|
|
|
1969
2545
|
} finally {
|
|
1970
2546
|
setIsLoading(false);
|
|
1971
2547
|
}
|
|
1972
|
-
}, [fetchWithAuth]);
|
|
1973
|
-
(0,
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
2548
|
+
}, [fetchWithAuth, page, limit, search, category, scope]);
|
|
2549
|
+
const getAgent = (0, import_react8.useCallback)(
|
|
2550
|
+
async (agentId) => {
|
|
2551
|
+
const res = await fetchWithAuth(`/agents/${agentId}`);
|
|
2552
|
+
if (!res.ok) throw new Error(`Failed to fetch agent: ${res.statusText}`);
|
|
2553
|
+
return res.json();
|
|
2554
|
+
},
|
|
2555
|
+
[fetchWithAuth]
|
|
2556
|
+
);
|
|
2557
|
+
const createAgent = (0, import_react8.useCallback)(
|
|
2558
|
+
async (input) => {
|
|
2559
|
+
setError(null);
|
|
2560
|
+
try {
|
|
2561
|
+
const res = await fetchWithAuth("/agents", {
|
|
2562
|
+
method: "POST",
|
|
2563
|
+
headers: { "Content-Type": "application/json" },
|
|
2564
|
+
body: JSON.stringify(input)
|
|
2565
|
+
});
|
|
2566
|
+
if (!res.ok) {
|
|
2567
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
2568
|
+
throw new Error(`Failed to create agent (${res.status}): ${errText}`);
|
|
2569
|
+
}
|
|
2570
|
+
const created = await res.json();
|
|
2571
|
+
setAgents((prev) => [created, ...prev]);
|
|
2572
|
+
return created;
|
|
2573
|
+
} catch (err) {
|
|
2574
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
2575
|
+
setError(errorObj);
|
|
2576
|
+
throw errorObj;
|
|
2577
|
+
}
|
|
2578
|
+
},
|
|
2579
|
+
[fetchWithAuth]
|
|
2580
|
+
);
|
|
2581
|
+
const updateAgent = (0, import_react8.useCallback)(
|
|
2582
|
+
async (agentId, input) => {
|
|
2583
|
+
setError(null);
|
|
2584
|
+
try {
|
|
2585
|
+
const res = await fetchWithAuth(`/agents/${agentId}`, {
|
|
2586
|
+
method: "PATCH",
|
|
2587
|
+
headers: { "Content-Type": "application/json" },
|
|
2588
|
+
body: JSON.stringify(input)
|
|
2589
|
+
});
|
|
2590
|
+
if (!res.ok) {
|
|
2591
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
2592
|
+
throw new Error(`Failed to update agent (${res.status}): ${errText}`);
|
|
2593
|
+
}
|
|
2594
|
+
const updated = await res.json();
|
|
2595
|
+
setAgents((prev) => prev.map((a) => a._id === agentId ? updated : a));
|
|
2596
|
+
return updated;
|
|
2597
|
+
} catch (err) {
|
|
2598
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
2599
|
+
setError(errorObj);
|
|
2600
|
+
throw errorObj;
|
|
2601
|
+
}
|
|
2602
|
+
},
|
|
2603
|
+
[fetchWithAuth]
|
|
2604
|
+
);
|
|
2605
|
+
const deleteAgent = (0, import_react8.useCallback)(
|
|
2606
|
+
async (agentId) => {
|
|
2607
|
+
setError(null);
|
|
2608
|
+
try {
|
|
2609
|
+
const res = await fetchWithAuth(`/agents/${agentId}`, { method: "DELETE" });
|
|
2610
|
+
if (!res.ok) {
|
|
2611
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
2612
|
+
throw new Error(`Failed to delete agent (${res.status}): ${errText}`);
|
|
2613
|
+
}
|
|
2614
|
+
setAgents((prev) => prev.filter((a) => a._id !== agentId));
|
|
2615
|
+
} catch (err) {
|
|
2616
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
2617
|
+
setError(errorObj);
|
|
2618
|
+
throw errorObj;
|
|
2619
|
+
}
|
|
2620
|
+
},
|
|
2621
|
+
[fetchWithAuth]
|
|
2622
|
+
);
|
|
2623
|
+
const bulkDeleteAgents = (0, import_react8.useCallback)(
|
|
2624
|
+
async (ids) => {
|
|
2625
|
+
setError(null);
|
|
2626
|
+
try {
|
|
2627
|
+
const res = await fetchWithAuth("/agents/bulk-delete", {
|
|
2628
|
+
method: "POST",
|
|
2629
|
+
headers: { "Content-Type": "application/json" },
|
|
2630
|
+
body: JSON.stringify({ ids })
|
|
2631
|
+
});
|
|
2632
|
+
if (!res.ok) {
|
|
2633
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
2634
|
+
throw new Error(`Failed to bulk-delete agents (${res.status}): ${errText}`);
|
|
2635
|
+
}
|
|
2636
|
+
const result = await res.json();
|
|
2637
|
+
const deletedSet = new Set(result.deleted);
|
|
2638
|
+
setAgents((prev) => prev.filter((a) => !deletedSet.has(a._id)));
|
|
2639
|
+
return result;
|
|
2640
|
+
} catch (err) {
|
|
2641
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
2642
|
+
setError(errorObj);
|
|
2643
|
+
throw errorObj;
|
|
2644
|
+
}
|
|
2645
|
+
},
|
|
2646
|
+
[fetchWithAuth]
|
|
2647
|
+
);
|
|
2648
|
+
(0, import_react8.useEffect)(() => {
|
|
2649
|
+
if (autoFetch) void fetchAgents();
|
|
1977
2650
|
}, [autoFetch, fetchAgents]);
|
|
1978
2651
|
return {
|
|
1979
2652
|
agents,
|
|
2653
|
+
pagination,
|
|
1980
2654
|
isLoading,
|
|
1981
2655
|
error,
|
|
1982
|
-
refetch: fetchAgents
|
|
2656
|
+
refetch: fetchAgents,
|
|
2657
|
+
getAgent,
|
|
2658
|
+
createAgent,
|
|
2659
|
+
updateAgent,
|
|
2660
|
+
deleteAgent,
|
|
2661
|
+
bulkDeleteAgents
|
|
1983
2662
|
};
|
|
1984
2663
|
}
|
|
1985
2664
|
|
|
1986
2665
|
// src/hooks/useConnection.ts
|
|
1987
|
-
var
|
|
2666
|
+
var import_react9 = require("react");
|
|
1988
2667
|
function useConnection(autoCheck = true) {
|
|
1989
2668
|
const { fetchWithAuth } = usePersonaContext();
|
|
1990
|
-
const [health, setHealth] = (0,
|
|
1991
|
-
const [isConnected, setIsConnected] = (0,
|
|
1992
|
-
const [isLoading, setIsLoading] = (0,
|
|
1993
|
-
const checkHealth = (0,
|
|
2669
|
+
const [health, setHealth] = (0, import_react9.useState)(null);
|
|
2670
|
+
const [isConnected, setIsConnected] = (0, import_react9.useState)(false);
|
|
2671
|
+
const [isLoading, setIsLoading] = (0, import_react9.useState)(false);
|
|
2672
|
+
const checkHealth = (0, import_react9.useCallback)(async () => {
|
|
1994
2673
|
setIsLoading(true);
|
|
1995
2674
|
try {
|
|
1996
2675
|
const res = await fetchWithAuth("/health");
|
|
@@ -2009,7 +2688,7 @@ function useConnection(autoCheck = true) {
|
|
|
2009
2688
|
setIsLoading(false);
|
|
2010
2689
|
}
|
|
2011
2690
|
}, [fetchWithAuth]);
|
|
2012
|
-
(0,
|
|
2691
|
+
(0, import_react9.useEffect)(() => {
|
|
2013
2692
|
if (autoCheck) {
|
|
2014
2693
|
void checkHealth();
|
|
2015
2694
|
}
|
|
@@ -2023,15 +2702,15 @@ function useConnection(autoCheck = true) {
|
|
|
2023
2702
|
}
|
|
2024
2703
|
|
|
2025
2704
|
// src/hooks/useMcpConnections.ts
|
|
2026
|
-
var
|
|
2705
|
+
var import_react10 = require("react");
|
|
2027
2706
|
function useMcpConnections(options = {}) {
|
|
2028
2707
|
const { defaultAgentId, fetchWithAuth } = usePersonaContext();
|
|
2029
2708
|
const agentId = options.agentId ?? defaultAgentId;
|
|
2030
2709
|
const autoFetch = options.autoFetch ?? true;
|
|
2031
|
-
const [connections, setConnections] = (0,
|
|
2032
|
-
const [isLoading, setIsLoading] = (0,
|
|
2033
|
-
const [error, setError] = (0,
|
|
2034
|
-
const fetchConnections = (0,
|
|
2710
|
+
const [connections, setConnections] = (0, import_react10.useState)([]);
|
|
2711
|
+
const [isLoading, setIsLoading] = (0, import_react10.useState)(false);
|
|
2712
|
+
const [error, setError] = (0, import_react10.useState)(null);
|
|
2713
|
+
const fetchConnections = (0, import_react10.useCallback)(async () => {
|
|
2035
2714
|
if (!agentId) return [];
|
|
2036
2715
|
setIsLoading(true);
|
|
2037
2716
|
setError(null);
|
|
@@ -2055,7 +2734,34 @@ function useMcpConnections(options = {}) {
|
|
|
2055
2734
|
setIsLoading(false);
|
|
2056
2735
|
}
|
|
2057
2736
|
}, [agentId, fetchWithAuth, options.returnTo]);
|
|
2058
|
-
(0,
|
|
2737
|
+
const [isDisconnecting, setIsDisconnecting] = (0, import_react10.useState)(false);
|
|
2738
|
+
const disconnect = (0, import_react10.useCallback)(
|
|
2739
|
+
async (mcpId) => {
|
|
2740
|
+
setIsDisconnecting(true);
|
|
2741
|
+
setError(null);
|
|
2742
|
+
try {
|
|
2743
|
+
const res = await fetchWithAuth(`/mcps/${mcpId}/oauth/user/connection`, {
|
|
2744
|
+
method: "DELETE"
|
|
2745
|
+
});
|
|
2746
|
+
if (!res.ok)
|
|
2747
|
+
throw new Error(`Failed to disconnect MCP: ${res.statusText}`);
|
|
2748
|
+
setConnections(
|
|
2749
|
+
(prev) => prev.map(
|
|
2750
|
+
(c) => c.mcpId === mcpId ? { ...c, connected: false, authorizeUrl: null } : c
|
|
2751
|
+
)
|
|
2752
|
+
);
|
|
2753
|
+
void fetchConnections();
|
|
2754
|
+
} catch (err) {
|
|
2755
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
2756
|
+
setError(errorObj);
|
|
2757
|
+
throw errorObj;
|
|
2758
|
+
} finally {
|
|
2759
|
+
setIsDisconnecting(false);
|
|
2760
|
+
}
|
|
2761
|
+
},
|
|
2762
|
+
[fetchWithAuth, fetchConnections]
|
|
2763
|
+
);
|
|
2764
|
+
(0, import_react10.useEffect)(() => {
|
|
2059
2765
|
if (autoFetch) void fetchConnections();
|
|
2060
2766
|
}, [autoFetch, fetchConnections]);
|
|
2061
2767
|
return {
|
|
@@ -2064,16 +2770,18 @@ function useMcpConnections(options = {}) {
|
|
|
2064
2770
|
unconnected: connections.filter((c) => !c.connected),
|
|
2065
2771
|
isLoading,
|
|
2066
2772
|
error,
|
|
2067
|
-
refetch: fetchConnections
|
|
2773
|
+
refetch: fetchConnections,
|
|
2774
|
+
disconnect,
|
|
2775
|
+
isDisconnecting
|
|
2068
2776
|
};
|
|
2069
2777
|
}
|
|
2070
2778
|
|
|
2071
2779
|
// src/hooks/useMcp.ts
|
|
2072
|
-
var
|
|
2780
|
+
var import_react11 = require("react");
|
|
2073
2781
|
function useMcp(options = {}) {
|
|
2074
2782
|
const { fetchWithAuth } = usePersonaContext();
|
|
2075
2783
|
const defaultMcpId = options.mcpId;
|
|
2076
|
-
const readResource = (0,
|
|
2784
|
+
const readResource = (0, import_react11.useCallback)(
|
|
2077
2785
|
async (uri, mcpId) => {
|
|
2078
2786
|
const id = mcpId ?? defaultMcpId;
|
|
2079
2787
|
if (!id) throw new Error("MCP server ID is required to read resource");
|
|
@@ -2087,7 +2795,7 @@ function useMcp(options = {}) {
|
|
|
2087
2795
|
},
|
|
2088
2796
|
[fetchWithAuth, defaultMcpId]
|
|
2089
2797
|
);
|
|
2090
|
-
const callTool = (0,
|
|
2798
|
+
const callTool = (0, import_react11.useCallback)(
|
|
2091
2799
|
async (name, args, mcpId) => {
|
|
2092
2800
|
const id = mcpId ?? defaultMcpId;
|
|
2093
2801
|
if (!id) throw new Error("MCP server ID is required to call tool");
|
|
@@ -2109,22 +2817,378 @@ function useMcp(options = {}) {
|
|
|
2109
2817
|
};
|
|
2110
2818
|
}
|
|
2111
2819
|
|
|
2820
|
+
// src/hooks/useSkills.ts
|
|
2821
|
+
var import_react12 = require("react");
|
|
2822
|
+
function useSkills(options = {}) {
|
|
2823
|
+
const { autoFetch = true, page, limit, search, scope } = options;
|
|
2824
|
+
const { fetchWithAuth } = usePersonaContext();
|
|
2825
|
+
const [skills, setSkills] = (0, import_react12.useState)([]);
|
|
2826
|
+
const [pagination, setPagination] = (0, import_react12.useState)({
|
|
2827
|
+
total: 0,
|
|
2828
|
+
page: page ?? 1,
|
|
2829
|
+
limit: limit ?? 20,
|
|
2830
|
+
pages: 0
|
|
2831
|
+
});
|
|
2832
|
+
const [isLoading, setIsLoading] = (0, import_react12.useState)(false);
|
|
2833
|
+
const [error, setError] = (0, import_react12.useState)(null);
|
|
2834
|
+
const fetchSkills = (0, import_react12.useCallback)(async () => {
|
|
2835
|
+
setIsLoading(true);
|
|
2836
|
+
setError(null);
|
|
2837
|
+
try {
|
|
2838
|
+
const query = new URLSearchParams();
|
|
2839
|
+
if (page) query.set("page", String(page));
|
|
2840
|
+
if (limit) query.set("limit", String(limit));
|
|
2841
|
+
if (search) query.set("search", search);
|
|
2842
|
+
if (scope) query.set("scope", scope);
|
|
2843
|
+
const queryStr = query.toString() ? `?${query.toString()}` : "";
|
|
2844
|
+
const res = await fetchWithAuth(`/skills${queryStr}`);
|
|
2845
|
+
if (!res.ok) throw new Error(`Failed to list skills: ${res.statusText}`);
|
|
2846
|
+
const data = await res.json();
|
|
2847
|
+
const items = Array.isArray(data) ? data : data?.items ?? [];
|
|
2848
|
+
setSkills(items);
|
|
2849
|
+
setPagination(
|
|
2850
|
+
data?.pagination ?? { total: items.length, page: 1, limit: items.length, pages: 1 }
|
|
2851
|
+
);
|
|
2852
|
+
return items;
|
|
2853
|
+
} catch (err) {
|
|
2854
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
2855
|
+
setError(errorObj);
|
|
2856
|
+
return [];
|
|
2857
|
+
} finally {
|
|
2858
|
+
setIsLoading(false);
|
|
2859
|
+
}
|
|
2860
|
+
}, [fetchWithAuth, page, limit, search, scope]);
|
|
2861
|
+
const getSkill = (0, import_react12.useCallback)(
|
|
2862
|
+
async (skillId) => {
|
|
2863
|
+
const res = await fetchWithAuth(`/skills/${skillId}`);
|
|
2864
|
+
if (!res.ok) throw new Error(`Failed to fetch skill: ${res.statusText}`);
|
|
2865
|
+
return res.json();
|
|
2866
|
+
},
|
|
2867
|
+
[fetchWithAuth]
|
|
2868
|
+
);
|
|
2869
|
+
const createSkill = (0, import_react12.useCallback)(
|
|
2870
|
+
async (input) => {
|
|
2871
|
+
setError(null);
|
|
2872
|
+
try {
|
|
2873
|
+
const res = await fetchWithAuth("/skills", {
|
|
2874
|
+
method: "POST",
|
|
2875
|
+
headers: { "Content-Type": "application/json" },
|
|
2876
|
+
body: JSON.stringify(input)
|
|
2877
|
+
});
|
|
2878
|
+
if (!res.ok) {
|
|
2879
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
2880
|
+
throw new Error(`Failed to create skill (${res.status}): ${errText}`);
|
|
2881
|
+
}
|
|
2882
|
+
const created = await res.json();
|
|
2883
|
+
setSkills((prev) => [created, ...prev]);
|
|
2884
|
+
return created;
|
|
2885
|
+
} catch (err) {
|
|
2886
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
2887
|
+
setError(errorObj);
|
|
2888
|
+
throw errorObj;
|
|
2889
|
+
}
|
|
2890
|
+
},
|
|
2891
|
+
[fetchWithAuth]
|
|
2892
|
+
);
|
|
2893
|
+
const updateSkill = (0, import_react12.useCallback)(
|
|
2894
|
+
async (skillId, input) => {
|
|
2895
|
+
setError(null);
|
|
2896
|
+
try {
|
|
2897
|
+
const res = await fetchWithAuth(`/skills/${skillId}`, {
|
|
2898
|
+
method: "PATCH",
|
|
2899
|
+
headers: { "Content-Type": "application/json" },
|
|
2900
|
+
body: JSON.stringify(input)
|
|
2901
|
+
});
|
|
2902
|
+
if (!res.ok) {
|
|
2903
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
2904
|
+
throw new Error(`Failed to update skill (${res.status}): ${errText}`);
|
|
2905
|
+
}
|
|
2906
|
+
const updated = await res.json();
|
|
2907
|
+
setSkills((prev) => prev.map((s) => s._id === skillId ? updated : s));
|
|
2908
|
+
return updated;
|
|
2909
|
+
} catch (err) {
|
|
2910
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
2911
|
+
setError(errorObj);
|
|
2912
|
+
throw errorObj;
|
|
2913
|
+
}
|
|
2914
|
+
},
|
|
2915
|
+
[fetchWithAuth]
|
|
2916
|
+
);
|
|
2917
|
+
const deleteSkill = (0, import_react12.useCallback)(
|
|
2918
|
+
async (skillId) => {
|
|
2919
|
+
setError(null);
|
|
2920
|
+
try {
|
|
2921
|
+
const res = await fetchWithAuth(`/skills/${skillId}`, { method: "DELETE" });
|
|
2922
|
+
if (!res.ok) {
|
|
2923
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
2924
|
+
throw new Error(`Failed to delete skill (${res.status}): ${errText}`);
|
|
2925
|
+
}
|
|
2926
|
+
setSkills((prev) => prev.filter((s) => s._id !== skillId));
|
|
2927
|
+
} catch (err) {
|
|
2928
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
2929
|
+
setError(errorObj);
|
|
2930
|
+
throw errorObj;
|
|
2931
|
+
}
|
|
2932
|
+
},
|
|
2933
|
+
[fetchWithAuth]
|
|
2934
|
+
);
|
|
2935
|
+
const bulkDeleteSkills = (0, import_react12.useCallback)(
|
|
2936
|
+
async (ids) => {
|
|
2937
|
+
setError(null);
|
|
2938
|
+
try {
|
|
2939
|
+
const res = await fetchWithAuth("/skills/bulk-delete", {
|
|
2940
|
+
method: "POST",
|
|
2941
|
+
headers: { "Content-Type": "application/json" },
|
|
2942
|
+
body: JSON.stringify({ ids })
|
|
2943
|
+
});
|
|
2944
|
+
if (!res.ok) {
|
|
2945
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
2946
|
+
throw new Error(`Failed to bulk-delete skills (${res.status}): ${errText}`);
|
|
2947
|
+
}
|
|
2948
|
+
const result = await res.json();
|
|
2949
|
+
const deletedSet = new Set(result.deleted);
|
|
2950
|
+
setSkills((prev) => prev.filter((s) => !deletedSet.has(s._id)));
|
|
2951
|
+
return result;
|
|
2952
|
+
} catch (err) {
|
|
2953
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
2954
|
+
setError(errorObj);
|
|
2955
|
+
throw errorObj;
|
|
2956
|
+
}
|
|
2957
|
+
},
|
|
2958
|
+
[fetchWithAuth]
|
|
2959
|
+
);
|
|
2960
|
+
const getSkillUsage = (0, import_react12.useCallback)(
|
|
2961
|
+
async (skillId) => {
|
|
2962
|
+
const res = await fetchWithAuth(`/skills/${skillId}/usage`);
|
|
2963
|
+
if (!res.ok) throw new Error(`Failed to fetch skill usage: ${res.statusText}`);
|
|
2964
|
+
return res.json();
|
|
2965
|
+
},
|
|
2966
|
+
[fetchWithAuth]
|
|
2967
|
+
);
|
|
2968
|
+
(0, import_react12.useEffect)(() => {
|
|
2969
|
+
if (autoFetch) void fetchSkills();
|
|
2970
|
+
}, [autoFetch, fetchSkills]);
|
|
2971
|
+
return {
|
|
2972
|
+
skills,
|
|
2973
|
+
pagination,
|
|
2974
|
+
isLoading,
|
|
2975
|
+
error,
|
|
2976
|
+
refetch: fetchSkills,
|
|
2977
|
+
getSkill,
|
|
2978
|
+
createSkill,
|
|
2979
|
+
updateSkill,
|
|
2980
|
+
deleteSkill,
|
|
2981
|
+
bulkDeleteSkills,
|
|
2982
|
+
getSkillUsage
|
|
2983
|
+
};
|
|
2984
|
+
}
|
|
2985
|
+
|
|
2986
|
+
// src/hooks/useRcpSources.ts
|
|
2987
|
+
var import_react13 = require("react");
|
|
2988
|
+
function useRcpSources(options = {}) {
|
|
2989
|
+
const { autoFetch = true, page, limit, search } = options;
|
|
2990
|
+
const { fetchWithAuth } = usePersonaContext();
|
|
2991
|
+
const [rcpSources, setRcpSources] = (0, import_react13.useState)([]);
|
|
2992
|
+
const [pagination, setPagination] = (0, import_react13.useState)({
|
|
2993
|
+
total: 0,
|
|
2994
|
+
page: page ?? 1,
|
|
2995
|
+
limit: limit ?? 20,
|
|
2996
|
+
pages: 0
|
|
2997
|
+
});
|
|
2998
|
+
const [isLoading, setIsLoading] = (0, import_react13.useState)(false);
|
|
2999
|
+
const [error, setError] = (0, import_react13.useState)(null);
|
|
3000
|
+
const fetchRcpSources = (0, import_react13.useCallback)(async () => {
|
|
3001
|
+
setIsLoading(true);
|
|
3002
|
+
setError(null);
|
|
3003
|
+
try {
|
|
3004
|
+
const query = new URLSearchParams();
|
|
3005
|
+
if (page) query.set("page", String(page));
|
|
3006
|
+
if (limit) query.set("limit", String(limit));
|
|
3007
|
+
if (search) query.set("search", search);
|
|
3008
|
+
const queryStr = query.toString() ? `?${query.toString()}` : "";
|
|
3009
|
+
const res = await fetchWithAuth(`/rcp-sources${queryStr}`);
|
|
3010
|
+
if (!res.ok) throw new Error(`Failed to list RCP sources: ${res.statusText}`);
|
|
3011
|
+
const data = await res.json();
|
|
3012
|
+
const items = Array.isArray(data) ? data : data?.items ?? [];
|
|
3013
|
+
setRcpSources(items);
|
|
3014
|
+
setPagination(
|
|
3015
|
+
data?.pagination ?? { total: items.length, page: 1, limit: items.length, pages: 1 }
|
|
3016
|
+
);
|
|
3017
|
+
return items;
|
|
3018
|
+
} catch (err) {
|
|
3019
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3020
|
+
setError(errorObj);
|
|
3021
|
+
return [];
|
|
3022
|
+
} finally {
|
|
3023
|
+
setIsLoading(false);
|
|
3024
|
+
}
|
|
3025
|
+
}, [fetchWithAuth, page, limit, search]);
|
|
3026
|
+
const getRcpSource = (0, import_react13.useCallback)(
|
|
3027
|
+
async (sourceId) => {
|
|
3028
|
+
const res = await fetchWithAuth(`/rcp-sources/${sourceId}`);
|
|
3029
|
+
if (!res.ok) throw new Error(`Failed to fetch RCP source: ${res.statusText}`);
|
|
3030
|
+
return res.json();
|
|
3031
|
+
},
|
|
3032
|
+
[fetchWithAuth]
|
|
3033
|
+
);
|
|
3034
|
+
const createRcpSource = (0, import_react13.useCallback)(
|
|
3035
|
+
async (input) => {
|
|
3036
|
+
setError(null);
|
|
3037
|
+
try {
|
|
3038
|
+
const res = await fetchWithAuth("/rcp-sources", {
|
|
3039
|
+
method: "POST",
|
|
3040
|
+
headers: { "Content-Type": "application/json" },
|
|
3041
|
+
body: JSON.stringify(input)
|
|
3042
|
+
});
|
|
3043
|
+
if (!res.ok) {
|
|
3044
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3045
|
+
throw new Error(`Failed to create RCP source (${res.status}): ${errText}`);
|
|
3046
|
+
}
|
|
3047
|
+
const created = await res.json();
|
|
3048
|
+
setRcpSources((prev) => [created, ...prev]);
|
|
3049
|
+
return created;
|
|
3050
|
+
} catch (err) {
|
|
3051
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3052
|
+
setError(errorObj);
|
|
3053
|
+
throw errorObj;
|
|
3054
|
+
}
|
|
3055
|
+
},
|
|
3056
|
+
[fetchWithAuth]
|
|
3057
|
+
);
|
|
3058
|
+
const updateRcpSource = (0, import_react13.useCallback)(
|
|
3059
|
+
async (sourceId, input) => {
|
|
3060
|
+
setError(null);
|
|
3061
|
+
try {
|
|
3062
|
+
const res = await fetchWithAuth(`/rcp-sources/${sourceId}`, {
|
|
3063
|
+
method: "PATCH",
|
|
3064
|
+
headers: { "Content-Type": "application/json" },
|
|
3065
|
+
body: JSON.stringify(input)
|
|
3066
|
+
});
|
|
3067
|
+
if (!res.ok) {
|
|
3068
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3069
|
+
throw new Error(`Failed to update RCP source (${res.status}): ${errText}`);
|
|
3070
|
+
}
|
|
3071
|
+
const updated = await res.json();
|
|
3072
|
+
setRcpSources((prev) => prev.map((s) => s._id === sourceId ? updated : s));
|
|
3073
|
+
return updated;
|
|
3074
|
+
} catch (err) {
|
|
3075
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3076
|
+
setError(errorObj);
|
|
3077
|
+
throw errorObj;
|
|
3078
|
+
}
|
|
3079
|
+
},
|
|
3080
|
+
[fetchWithAuth]
|
|
3081
|
+
);
|
|
3082
|
+
const deleteRcpSource = (0, import_react13.useCallback)(
|
|
3083
|
+
async (sourceId) => {
|
|
3084
|
+
setError(null);
|
|
3085
|
+
try {
|
|
3086
|
+
const res = await fetchWithAuth(`/rcp-sources/${sourceId}`, { method: "DELETE" });
|
|
3087
|
+
if (!res.ok) {
|
|
3088
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3089
|
+
throw new Error(`Failed to delete RCP source (${res.status}): ${errText}`);
|
|
3090
|
+
}
|
|
3091
|
+
setRcpSources((prev) => prev.filter((s) => s._id !== sourceId));
|
|
3092
|
+
} catch (err) {
|
|
3093
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3094
|
+
setError(errorObj);
|
|
3095
|
+
throw errorObj;
|
|
3096
|
+
}
|
|
3097
|
+
},
|
|
3098
|
+
[fetchWithAuth]
|
|
3099
|
+
);
|
|
3100
|
+
const bulkDeleteRcpSources = (0, import_react13.useCallback)(
|
|
3101
|
+
async (ids) => {
|
|
3102
|
+
setError(null);
|
|
3103
|
+
try {
|
|
3104
|
+
const res = await fetchWithAuth("/rcp-sources/bulk-delete", {
|
|
3105
|
+
method: "POST",
|
|
3106
|
+
headers: { "Content-Type": "application/json" },
|
|
3107
|
+
body: JSON.stringify({ ids })
|
|
3108
|
+
});
|
|
3109
|
+
if (!res.ok) {
|
|
3110
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3111
|
+
throw new Error(`Failed to bulk-delete RCP sources (${res.status}): ${errText}`);
|
|
3112
|
+
}
|
|
3113
|
+
const result = await res.json();
|
|
3114
|
+
const deletedSet = new Set(result.deleted);
|
|
3115
|
+
setRcpSources((prev) => prev.filter((s) => !deletedSet.has(s._id)));
|
|
3116
|
+
return result;
|
|
3117
|
+
} catch (err) {
|
|
3118
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3119
|
+
setError(errorObj);
|
|
3120
|
+
throw errorObj;
|
|
3121
|
+
}
|
|
3122
|
+
},
|
|
3123
|
+
[fetchWithAuth]
|
|
3124
|
+
);
|
|
3125
|
+
const getRcpSourceUsage = (0, import_react13.useCallback)(
|
|
3126
|
+
async (sourceId) => {
|
|
3127
|
+
const res = await fetchWithAuth(`/rcp-sources/${sourceId}/usage`);
|
|
3128
|
+
if (!res.ok) throw new Error(`Failed to fetch RCP source usage: ${res.statusText}`);
|
|
3129
|
+
return res.json();
|
|
3130
|
+
},
|
|
3131
|
+
[fetchWithAuth]
|
|
3132
|
+
);
|
|
3133
|
+
const testRcpSourceConnection = (0, import_react13.useCallback)(
|
|
3134
|
+
async (sourceId) => {
|
|
3135
|
+
setError(null);
|
|
3136
|
+
try {
|
|
3137
|
+
const res = await fetchWithAuth(`/rcp-sources/${sourceId}/test`, { method: "POST" });
|
|
3138
|
+
if (!res.ok) {
|
|
3139
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3140
|
+
throw new Error(`Failed to test RCP source connection (${res.status}): ${errText}`);
|
|
3141
|
+
}
|
|
3142
|
+
const result = await res.json();
|
|
3143
|
+
setRcpSources(
|
|
3144
|
+
(prev) => prev.map(
|
|
3145
|
+
(s) => s._id === sourceId ? { ...s, tools: result.tools, lastTestedAt: (/* @__PURE__ */ new Date()).toISOString() } : s
|
|
3146
|
+
)
|
|
3147
|
+
);
|
|
3148
|
+
return result;
|
|
3149
|
+
} catch (err) {
|
|
3150
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3151
|
+
setError(errorObj);
|
|
3152
|
+
throw errorObj;
|
|
3153
|
+
}
|
|
3154
|
+
},
|
|
3155
|
+
[fetchWithAuth]
|
|
3156
|
+
);
|
|
3157
|
+
(0, import_react13.useEffect)(() => {
|
|
3158
|
+
if (autoFetch) void fetchRcpSources();
|
|
3159
|
+
}, [autoFetch, fetchRcpSources]);
|
|
3160
|
+
return {
|
|
3161
|
+
rcpSources,
|
|
3162
|
+
pagination,
|
|
3163
|
+
isLoading,
|
|
3164
|
+
error,
|
|
3165
|
+
refetch: fetchRcpSources,
|
|
3166
|
+
getRcpSource,
|
|
3167
|
+
createRcpSource,
|
|
3168
|
+
updateRcpSource,
|
|
3169
|
+
deleteRcpSource,
|
|
3170
|
+
bulkDeleteRcpSources,
|
|
3171
|
+
getRcpSourceUsage,
|
|
3172
|
+
testRcpSourceConnection
|
|
3173
|
+
};
|
|
3174
|
+
}
|
|
3175
|
+
|
|
2112
3176
|
// src/hooks/useWorkflows.ts
|
|
2113
|
-
var
|
|
3177
|
+
var import_react14 = require("react");
|
|
2114
3178
|
function useWorkflows(options) {
|
|
2115
3179
|
const opts = typeof options === "boolean" ? { autoFetch: options } : options ?? {};
|
|
2116
3180
|
const { autoFetch = true, search, status, page, limit } = opts;
|
|
2117
3181
|
const { fetchWithAuth } = usePersonaContext();
|
|
2118
|
-
const [workflows, setWorkflows] = (0,
|
|
2119
|
-
const [pagination, setPagination] = (0,
|
|
3182
|
+
const [workflows, setWorkflows] = (0, import_react14.useState)([]);
|
|
3183
|
+
const [pagination, setPagination] = (0, import_react14.useState)({
|
|
2120
3184
|
page: page ?? 1,
|
|
2121
3185
|
limit: limit ?? 20,
|
|
2122
3186
|
total: 0,
|
|
2123
3187
|
totalPages: 0
|
|
2124
3188
|
});
|
|
2125
|
-
const [isLoading, setIsLoading] = (0,
|
|
2126
|
-
const [error, setError] = (0,
|
|
2127
|
-
const fetchWorkflows = (0,
|
|
3189
|
+
const [isLoading, setIsLoading] = (0, import_react14.useState)(false);
|
|
3190
|
+
const [error, setError] = (0, import_react14.useState)(null);
|
|
3191
|
+
const fetchWorkflows = (0, import_react14.useCallback)(async () => {
|
|
2128
3192
|
setIsLoading(true);
|
|
2129
3193
|
setError(null);
|
|
2130
3194
|
try {
|
|
@@ -2146,7 +3210,10 @@ function useWorkflows(options) {
|
|
|
2146
3210
|
page: data.pagination.page ?? 1,
|
|
2147
3211
|
limit: data.pagination.limit ?? items.length,
|
|
2148
3212
|
total: data.pagination.total ?? items.length,
|
|
2149
|
-
|
|
3213
|
+
// Backend's paginationEnvelope() names this field `pages`, not
|
|
3214
|
+
// `totalPages` — this used to always fall through to the `?? 1`
|
|
3215
|
+
// default.
|
|
3216
|
+
totalPages: data.pagination.pages ?? 1
|
|
2150
3217
|
});
|
|
2151
3218
|
} else {
|
|
2152
3219
|
setPagination({
|
|
@@ -2165,7 +3232,7 @@ function useWorkflows(options) {
|
|
|
2165
3232
|
setIsLoading(false);
|
|
2166
3233
|
}
|
|
2167
3234
|
}, [fetchWithAuth, search, status, page, limit]);
|
|
2168
|
-
const createWorkflow = (0,
|
|
3235
|
+
const createWorkflow = (0, import_react14.useCallback)(
|
|
2169
3236
|
async (input) => {
|
|
2170
3237
|
setError(null);
|
|
2171
3238
|
try {
|
|
@@ -2189,7 +3256,7 @@ function useWorkflows(options) {
|
|
|
2189
3256
|
},
|
|
2190
3257
|
[fetchWithAuth]
|
|
2191
3258
|
);
|
|
2192
|
-
(0,
|
|
3259
|
+
(0, import_react14.useEffect)(() => {
|
|
2193
3260
|
if (autoFetch) {
|
|
2194
3261
|
void fetchWorkflows();
|
|
2195
3262
|
}
|
|
@@ -2205,17 +3272,17 @@ function useWorkflows(options) {
|
|
|
2205
3272
|
}
|
|
2206
3273
|
|
|
2207
3274
|
// src/hooks/useWorkflow.ts
|
|
2208
|
-
var
|
|
3275
|
+
var import_react15 = require("react");
|
|
2209
3276
|
function useWorkflow(workflowId, options) {
|
|
2210
3277
|
const opts = typeof options === "boolean" ? { autoFetch: options } : options ?? {};
|
|
2211
3278
|
const { autoFetch = true } = opts;
|
|
2212
3279
|
const { fetchWithAuth } = usePersonaContext();
|
|
2213
|
-
const [workflow, setWorkflow] = (0,
|
|
2214
|
-
const [versions, setVersions] = (0,
|
|
2215
|
-
const [mermaid, setMermaid] = (0,
|
|
2216
|
-
const [isLoading, setIsLoading] = (0,
|
|
2217
|
-
const [error, setError] = (0,
|
|
2218
|
-
const fetchWorkflow = (0,
|
|
3280
|
+
const [workflow, setWorkflow] = (0, import_react15.useState)(null);
|
|
3281
|
+
const [versions, setVersions] = (0, import_react15.useState)([]);
|
|
3282
|
+
const [mermaid, setMermaid] = (0, import_react15.useState)(null);
|
|
3283
|
+
const [isLoading, setIsLoading] = (0, import_react15.useState)(false);
|
|
3284
|
+
const [error, setError] = (0, import_react15.useState)(null);
|
|
3285
|
+
const fetchWorkflow = (0, import_react15.useCallback)(async () => {
|
|
2219
3286
|
if (!workflowId) return null;
|
|
2220
3287
|
setIsLoading(true);
|
|
2221
3288
|
setError(null);
|
|
@@ -2235,7 +3302,7 @@ function useWorkflow(workflowId, options) {
|
|
|
2235
3302
|
setIsLoading(false);
|
|
2236
3303
|
}
|
|
2237
3304
|
}, [fetchWithAuth, workflowId]);
|
|
2238
|
-
const fetchVersions = (0,
|
|
3305
|
+
const fetchVersions = (0, import_react15.useCallback)(async () => {
|
|
2239
3306
|
if (!workflowId) return [];
|
|
2240
3307
|
try {
|
|
2241
3308
|
const res = await fetchWithAuth(`/workflows/${workflowId}/versions`);
|
|
@@ -2248,7 +3315,7 @@ function useWorkflow(workflowId, options) {
|
|
|
2248
3315
|
return [];
|
|
2249
3316
|
}
|
|
2250
3317
|
}, [fetchWithAuth, workflowId]);
|
|
2251
|
-
const fetchMermaid = (0,
|
|
3318
|
+
const fetchMermaid = (0, import_react15.useCallback)(async () => {
|
|
2252
3319
|
if (!workflowId) return "";
|
|
2253
3320
|
try {
|
|
2254
3321
|
const res = await fetchWithAuth(`/workflows/${workflowId}/mermaid`);
|
|
@@ -2261,7 +3328,7 @@ function useWorkflow(workflowId, options) {
|
|
|
2261
3328
|
return "";
|
|
2262
3329
|
}
|
|
2263
3330
|
}, [fetchWithAuth, workflowId]);
|
|
2264
|
-
const saveDraft = (0,
|
|
3331
|
+
const saveDraft = (0, import_react15.useCallback)(
|
|
2265
3332
|
async (draft) => {
|
|
2266
3333
|
if (!workflowId) throw new Error("Workflow ID is required");
|
|
2267
3334
|
setError(null);
|
|
@@ -2280,7 +3347,7 @@ function useWorkflow(workflowId, options) {
|
|
|
2280
3347
|
},
|
|
2281
3348
|
[fetchWithAuth, workflowId]
|
|
2282
3349
|
);
|
|
2283
|
-
const publish = (0,
|
|
3350
|
+
const publish = (0, import_react15.useCallback)(
|
|
2284
3351
|
async (summary) => {
|
|
2285
3352
|
if (!workflowId) throw new Error("Workflow ID is required");
|
|
2286
3353
|
setError(null);
|
|
@@ -2300,7 +3367,7 @@ function useWorkflow(workflowId, options) {
|
|
|
2300
3367
|
},
|
|
2301
3368
|
[fetchWithAuth, workflowId, fetchWorkflow, fetchVersions]
|
|
2302
3369
|
);
|
|
2303
|
-
const deleteWorkflow = (0,
|
|
3370
|
+
const deleteWorkflow = (0, import_react15.useCallback)(async () => {
|
|
2304
3371
|
if (!workflowId) throw new Error("Workflow ID is required");
|
|
2305
3372
|
setError(null);
|
|
2306
3373
|
const res = await fetchWithAuth(`/workflows/${workflowId}`, {
|
|
@@ -2311,7 +3378,7 @@ function useWorkflow(workflowId, options) {
|
|
|
2311
3378
|
}
|
|
2312
3379
|
setWorkflow(null);
|
|
2313
3380
|
}, [fetchWithAuth, workflowId]);
|
|
2314
|
-
(0,
|
|
3381
|
+
(0, import_react15.useEffect)(() => {
|
|
2315
3382
|
if (autoFetch && workflowId) {
|
|
2316
3383
|
void fetchWorkflow();
|
|
2317
3384
|
}
|
|
@@ -2332,25 +3399,25 @@ function useWorkflow(workflowId, options) {
|
|
|
2332
3399
|
}
|
|
2333
3400
|
|
|
2334
3401
|
// src/hooks/useWorkflowStream.ts
|
|
2335
|
-
var
|
|
3402
|
+
var import_react16 = require("react");
|
|
2336
3403
|
function useWorkflowStream(workflowId, options) {
|
|
2337
3404
|
const { baseUrl, getAuthToken, fetchWithAuth, logger } = usePersonaContext();
|
|
2338
|
-
const [status, setStatus] = (0,
|
|
2339
|
-
const [runId, setRunId] = (0,
|
|
2340
|
-
const [activeNodeId, setActiveNodeId] = (0,
|
|
2341
|
-
const [nodeRuns, setNodeRuns] = (0,
|
|
3405
|
+
const [status, setStatus] = (0, import_react16.useState)("idle");
|
|
3406
|
+
const [runId, setRunId] = (0, import_react16.useState)(null);
|
|
3407
|
+
const [activeNodeId, setActiveNodeId] = (0, import_react16.useState)(null);
|
|
3408
|
+
const [nodeRuns, setNodeRuns] = (0, import_react16.useState)(
|
|
2342
3409
|
{}
|
|
2343
3410
|
);
|
|
2344
|
-
const [text, setText] = (0,
|
|
2345
|
-
const [output, setOutput] = (0,
|
|
2346
|
-
const [error, setError] = (0,
|
|
2347
|
-
const [events, setEvents] = (0,
|
|
2348
|
-
const abortControllerRef = (0,
|
|
2349
|
-
const currentRunIdRef = (0,
|
|
3411
|
+
const [text, setText] = (0, import_react16.useState)("");
|
|
3412
|
+
const [output, setOutput] = (0, import_react16.useState)(null);
|
|
3413
|
+
const [error, setError] = (0, import_react16.useState)(null);
|
|
3414
|
+
const [events, setEvents] = (0, import_react16.useState)([]);
|
|
3415
|
+
const abortControllerRef = (0, import_react16.useRef)(null);
|
|
3416
|
+
const currentRunIdRef = (0, import_react16.useRef)(null);
|
|
2350
3417
|
currentRunIdRef.current = runId;
|
|
2351
|
-
const optionsRef = (0,
|
|
3418
|
+
const optionsRef = (0, import_react16.useRef)(options);
|
|
2352
3419
|
optionsRef.current = options;
|
|
2353
|
-
const cancel = (0,
|
|
3420
|
+
const cancel = (0, import_react16.useCallback)(async () => {
|
|
2354
3421
|
if (abortControllerRef.current) {
|
|
2355
3422
|
abortControllerRef.current.abort();
|
|
2356
3423
|
abortControllerRef.current = null;
|
|
@@ -2371,7 +3438,7 @@ function useWorkflowStream(workflowId, options) {
|
|
|
2371
3438
|
setStatus("cancelled");
|
|
2372
3439
|
setActiveNodeId(null);
|
|
2373
3440
|
}, [fetchWithAuth, logger]);
|
|
2374
|
-
const reset = (0,
|
|
3441
|
+
const reset = (0, import_react16.useCallback)(() => {
|
|
2375
3442
|
if (abortControllerRef.current) {
|
|
2376
3443
|
abortControllerRef.current.abort();
|
|
2377
3444
|
abortControllerRef.current = null;
|
|
@@ -2385,7 +3452,7 @@ function useWorkflowStream(workflowId, options) {
|
|
|
2385
3452
|
setError(null);
|
|
2386
3453
|
setEvents([]);
|
|
2387
3454
|
}, []);
|
|
2388
|
-
const processStream = (0,
|
|
3455
|
+
const processStream = (0, import_react16.useCallback)(
|
|
2389
3456
|
async (url, method, body, targetRunId) => {
|
|
2390
3457
|
if (abortControllerRef.current) {
|
|
2391
3458
|
abortControllerRef.current.abort();
|
|
@@ -2550,7 +3617,7 @@ function useWorkflowStream(workflowId, options) {
|
|
|
2550
3617
|
},
|
|
2551
3618
|
[getAuthToken]
|
|
2552
3619
|
);
|
|
2553
|
-
const start = (0,
|
|
3620
|
+
const start = (0, import_react16.useCallback)(
|
|
2554
3621
|
async (input, opts) => {
|
|
2555
3622
|
const targetWfId = opts?.workflowId || workflowId;
|
|
2556
3623
|
if (!targetWfId) {
|
|
@@ -2571,7 +3638,7 @@ function useWorkflowStream(workflowId, options) {
|
|
|
2571
3638
|
},
|
|
2572
3639
|
[workflowId, baseUrl, processStream]
|
|
2573
3640
|
);
|
|
2574
|
-
const resume = (0,
|
|
3641
|
+
const resume = (0, import_react16.useCallback)(
|
|
2575
3642
|
async (targetRunId, sinceSeq) => {
|
|
2576
3643
|
if (!targetRunId) {
|
|
2577
3644
|
throw new Error("Run ID is required to resume stream");
|
|
@@ -2584,7 +3651,7 @@ function useWorkflowStream(workflowId, options) {
|
|
|
2584
3651
|
},
|
|
2585
3652
|
[baseUrl, processStream]
|
|
2586
3653
|
);
|
|
2587
|
-
(0,
|
|
3654
|
+
(0, import_react16.useEffect)(() => {
|
|
2588
3655
|
return () => {
|
|
2589
3656
|
if (abortControllerRef.current) {
|
|
2590
3657
|
abortControllerRef.current.abort();
|
|
@@ -2609,21 +3676,21 @@ function useWorkflowStream(workflowId, options) {
|
|
|
2609
3676
|
}
|
|
2610
3677
|
|
|
2611
3678
|
// src/hooks/useWorkflowRuns.ts
|
|
2612
|
-
var
|
|
3679
|
+
var import_react17 = require("react");
|
|
2613
3680
|
function useWorkflowRuns(workflowId, options) {
|
|
2614
3681
|
const opts = typeof options === "boolean" ? { autoFetch: options } : options ?? {};
|
|
2615
3682
|
const { autoFetch = true, page = 1, limit = 20 } = opts;
|
|
2616
3683
|
const { fetchWithAuth } = usePersonaContext();
|
|
2617
|
-
const [runs, setRuns] = (0,
|
|
2618
|
-
const [pagination, setPagination] = (0,
|
|
3684
|
+
const [runs, setRuns] = (0, import_react17.useState)([]);
|
|
3685
|
+
const [pagination, setPagination] = (0, import_react17.useState)({
|
|
2619
3686
|
page,
|
|
2620
3687
|
limit,
|
|
2621
3688
|
total: 0,
|
|
2622
3689
|
totalPages: 0
|
|
2623
3690
|
});
|
|
2624
|
-
const [isLoading, setIsLoading] = (0,
|
|
2625
|
-
const [error, setError] = (0,
|
|
2626
|
-
const fetchRuns = (0,
|
|
3691
|
+
const [isLoading, setIsLoading] = (0, import_react17.useState)(false);
|
|
3692
|
+
const [error, setError] = (0, import_react17.useState)(null);
|
|
3693
|
+
const fetchRuns = (0, import_react17.useCallback)(async () => {
|
|
2627
3694
|
if (!workflowId) return [];
|
|
2628
3695
|
setIsLoading(true);
|
|
2629
3696
|
setError(null);
|
|
@@ -2653,7 +3720,7 @@ function useWorkflowRuns(workflowId, options) {
|
|
|
2653
3720
|
setIsLoading(false);
|
|
2654
3721
|
}
|
|
2655
3722
|
}, [fetchWithAuth, workflowId, page, limit]);
|
|
2656
|
-
const getRun = (0,
|
|
3723
|
+
const getRun = (0, import_react17.useCallback)(
|
|
2657
3724
|
async (runId) => {
|
|
2658
3725
|
if (!runId) throw new Error("Run ID is required");
|
|
2659
3726
|
const res = await fetchWithAuth(`/workflows/runs/${runId}`);
|
|
@@ -2664,7 +3731,7 @@ function useWorkflowRuns(workflowId, options) {
|
|
|
2664
3731
|
},
|
|
2665
3732
|
[fetchWithAuth]
|
|
2666
3733
|
);
|
|
2667
|
-
const cancelRun = (0,
|
|
3734
|
+
const cancelRun = (0, import_react17.useCallback)(
|
|
2668
3735
|
async (runId) => {
|
|
2669
3736
|
if (!runId) throw new Error("Run ID is required");
|
|
2670
3737
|
const res = await fetchWithAuth(`/workflows/runs/${runId}/cancel`, {
|
|
@@ -2679,7 +3746,7 @@ function useWorkflowRuns(workflowId, options) {
|
|
|
2679
3746
|
},
|
|
2680
3747
|
[fetchWithAuth]
|
|
2681
3748
|
);
|
|
2682
|
-
(0,
|
|
3749
|
+
(0, import_react17.useEffect)(() => {
|
|
2683
3750
|
if (autoFetch && workflowId) {
|
|
2684
3751
|
void fetchRuns();
|
|
2685
3752
|
}
|
|
@@ -2697,9 +3764,10 @@ function useWorkflowRuns(workflowId, options) {
|
|
|
2697
3764
|
|
|
2698
3765
|
// src/index.ts
|
|
2699
3766
|
var import_logger2 = require("@personaai/logger");
|
|
2700
|
-
var VERSION = "0.
|
|
3767
|
+
var VERSION = "0.10.0";
|
|
2701
3768
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2702
3769
|
0 && (module.exports = {
|
|
3770
|
+
ARCHITECT_AGENT_ID,
|
|
2703
3771
|
PersonaProvider,
|
|
2704
3772
|
VERSION,
|
|
2705
3773
|
createLogger,
|
|
@@ -2710,6 +3778,7 @@ var VERSION = "0.9.0";
|
|
|
2710
3778
|
setLogLevel,
|
|
2711
3779
|
supportsStreamingFetch,
|
|
2712
3780
|
useAgents,
|
|
3781
|
+
useArchitectChat,
|
|
2713
3782
|
useChat,
|
|
2714
3783
|
useConnection,
|
|
2715
3784
|
useFiles,
|
|
@@ -2717,6 +3786,8 @@ var VERSION = "0.9.0";
|
|
|
2717
3786
|
useMcpConnections,
|
|
2718
3787
|
useMemory,
|
|
2719
3788
|
usePersonaContext,
|
|
3789
|
+
useRcpSources,
|
|
3790
|
+
useSkills,
|
|
2720
3791
|
useThreads,
|
|
2721
3792
|
useVoice,
|
|
2722
3793
|
useWorkflow,
|