@personaai/react 0.11.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +755 -171
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +446 -46
- package/dist/index.d.ts +446 -46
- package/dist/index.js +738 -157
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1889,8 +1889,110 @@ function useThreads(autoFetch = true) {
|
|
|
1889
1889
|
};
|
|
1890
1890
|
}
|
|
1891
1891
|
|
|
1892
|
+
// src/hooks/useWorkspaceFiles.ts
|
|
1893
|
+
import { useCallback as useCallback5, useEffect as useEffect5, useState as useState5 } from "react";
|
|
1894
|
+
function useWorkspaceFiles(threadId, autoFetch = true) {
|
|
1895
|
+
const { fetchWithAuth } = usePersonaContext();
|
|
1896
|
+
const [files, setFiles] = useState5({});
|
|
1897
|
+
const [isLoading, setIsLoading] = useState5(false);
|
|
1898
|
+
const [isSaving, setIsSaving] = useState5(false);
|
|
1899
|
+
const [error, setError] = useState5(null);
|
|
1900
|
+
const fetchFiles = useCallback5(async () => {
|
|
1901
|
+
if (!threadId) return {};
|
|
1902
|
+
setIsLoading(true);
|
|
1903
|
+
setError(null);
|
|
1904
|
+
try {
|
|
1905
|
+
const res = await fetchWithAuth(`/threads/${threadId}/files`);
|
|
1906
|
+
if (!res.ok) throw new Error(`Failed to list workspace files: ${res.statusText}`);
|
|
1907
|
+
const data = await res.json();
|
|
1908
|
+
const normalized = normalizeWorkspaceFiles(data?.data ?? data ?? {});
|
|
1909
|
+
setFiles(normalized);
|
|
1910
|
+
return normalized;
|
|
1911
|
+
} catch (err) {
|
|
1912
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
1913
|
+
setError(errorObj);
|
|
1914
|
+
return {};
|
|
1915
|
+
} finally {
|
|
1916
|
+
setIsLoading(false);
|
|
1917
|
+
}
|
|
1918
|
+
}, [fetchWithAuth, threadId]);
|
|
1919
|
+
const getFile = useCallback5(
|
|
1920
|
+
async (path) => {
|
|
1921
|
+
if (!threadId) throw new Error("useWorkspaceFiles: no threadId set");
|
|
1922
|
+
const res = await fetchWithAuth(
|
|
1923
|
+
`/threads/${threadId}/file?path=${encodeURIComponent(path)}`
|
|
1924
|
+
);
|
|
1925
|
+
if (!res.ok) throw new Error(`Failed to read workspace file: ${res.statusText}`);
|
|
1926
|
+
const data = await res.json();
|
|
1927
|
+
const raw = data?.data ?? data;
|
|
1928
|
+
return normalizeWorkspaceFiles({ [path]: raw })[path];
|
|
1929
|
+
},
|
|
1930
|
+
[fetchWithAuth, threadId]
|
|
1931
|
+
);
|
|
1932
|
+
const writeFile = useCallback5(
|
|
1933
|
+
async (path, content) => {
|
|
1934
|
+
if (!threadId) throw new Error("useWorkspaceFiles: no threadId set");
|
|
1935
|
+
setIsSaving(true);
|
|
1936
|
+
setError(null);
|
|
1937
|
+
try {
|
|
1938
|
+
const res = await fetchWithAuth(`/threads/${threadId}/file`, {
|
|
1939
|
+
method: "PUT",
|
|
1940
|
+
headers: { "Content-Type": "application/json" },
|
|
1941
|
+
body: JSON.stringify({ path, content })
|
|
1942
|
+
});
|
|
1943
|
+
if (!res.ok) throw new Error(`Failed to write workspace file: ${res.statusText}`);
|
|
1944
|
+
const data = await res.json();
|
|
1945
|
+
const raw = data?.data ?? data;
|
|
1946
|
+
const file = normalizeWorkspaceFiles({ [path]: raw })[path];
|
|
1947
|
+
setFiles((prev) => ({ ...prev, [path]: file }));
|
|
1948
|
+
return file;
|
|
1949
|
+
} catch (err) {
|
|
1950
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
1951
|
+
setError(errorObj);
|
|
1952
|
+
throw errorObj;
|
|
1953
|
+
} finally {
|
|
1954
|
+
setIsSaving(false);
|
|
1955
|
+
}
|
|
1956
|
+
},
|
|
1957
|
+
[fetchWithAuth, threadId]
|
|
1958
|
+
);
|
|
1959
|
+
const deleteFile = useCallback5(
|
|
1960
|
+
async (path) => {
|
|
1961
|
+
if (!threadId) throw new Error("useWorkspaceFiles: no threadId set");
|
|
1962
|
+
const res = await fetchWithAuth(
|
|
1963
|
+
`/threads/${threadId}/file?path=${encodeURIComponent(path)}`,
|
|
1964
|
+
{ method: "DELETE" }
|
|
1965
|
+
);
|
|
1966
|
+
if (!res.ok) throw new Error(`Failed to delete workspace file: ${res.statusText}`);
|
|
1967
|
+
setFiles((prev) => {
|
|
1968
|
+
const next = { ...prev };
|
|
1969
|
+
delete next[path];
|
|
1970
|
+
return next;
|
|
1971
|
+
});
|
|
1972
|
+
},
|
|
1973
|
+
[fetchWithAuth, threadId]
|
|
1974
|
+
);
|
|
1975
|
+
useEffect5(() => {
|
|
1976
|
+
if (autoFetch && threadId) {
|
|
1977
|
+
void fetchFiles();
|
|
1978
|
+
} else if (!threadId) {
|
|
1979
|
+
setFiles({});
|
|
1980
|
+
}
|
|
1981
|
+
}, [autoFetch, threadId, fetchFiles]);
|
|
1982
|
+
return {
|
|
1983
|
+
files,
|
|
1984
|
+
isLoading,
|
|
1985
|
+
isSaving,
|
|
1986
|
+
error,
|
|
1987
|
+
refetch: fetchFiles,
|
|
1988
|
+
getFile,
|
|
1989
|
+
writeFile,
|
|
1990
|
+
deleteFile
|
|
1991
|
+
};
|
|
1992
|
+
}
|
|
1993
|
+
|
|
1892
1994
|
// src/hooks/useVoice.ts
|
|
1893
|
-
import { useCallback as
|
|
1995
|
+
import { useCallback as useCallback6, useEffect as useEffect6, useMemo as useMemo4, useRef as useRef3, useState as useState6 } from "react";
|
|
1894
1996
|
|
|
1895
1997
|
// src/hooks/voiceWorklets.ts
|
|
1896
1998
|
var RECORDER_WORKLET_SOURCE = `
|
|
@@ -1998,17 +2100,17 @@ function useVoice(options = {}) {
|
|
|
1998
2100
|
const threadId = options.threadId;
|
|
1999
2101
|
const contextOverride = options.contextOverride;
|
|
2000
2102
|
const context = options.context;
|
|
2001
|
-
const [state, setState] =
|
|
2002
|
-
const [isMuted, setIsMuted] =
|
|
2003
|
-
const [transcript, setTranscript] =
|
|
2103
|
+
const [state, setState] = useState6("idle");
|
|
2104
|
+
const [isMuted, setIsMuted] = useState6(false);
|
|
2105
|
+
const [transcript, setTranscript] = useState6(
|
|
2004
2106
|
[]
|
|
2005
2107
|
);
|
|
2006
|
-
const [partial, setPartial] =
|
|
2108
|
+
const [partial, setPartial] = useState6(
|
|
2007
2109
|
null
|
|
2008
2110
|
);
|
|
2009
|
-
const [toolCalls, setToolCalls] =
|
|
2010
|
-
const [error, setError] =
|
|
2011
|
-
const [endReason, setEndReason] =
|
|
2111
|
+
const [toolCalls, setToolCalls] = useState6([]);
|
|
2112
|
+
const [error, setError] = useState6(null);
|
|
2113
|
+
const [endReason, setEndReason] = useState6(
|
|
2012
2114
|
null
|
|
2013
2115
|
);
|
|
2014
2116
|
const wsRef = useRef3(null);
|
|
@@ -2022,13 +2124,13 @@ function useVoice(options = {}) {
|
|
|
2022
2124
|
const lastFinalTurnRef = useRef3(
|
|
2023
2125
|
null
|
|
2024
2126
|
);
|
|
2025
|
-
|
|
2127
|
+
useEffect6(() => {
|
|
2026
2128
|
mountedRef.current = true;
|
|
2027
2129
|
return () => {
|
|
2028
2130
|
mountedRef.current = false;
|
|
2029
2131
|
};
|
|
2030
2132
|
}, []);
|
|
2031
|
-
const teardownAudio =
|
|
2133
|
+
const teardownAudio = useCallback6(() => {
|
|
2032
2134
|
try {
|
|
2033
2135
|
streamRef.current?.getTracks().forEach((track) => track.stop());
|
|
2034
2136
|
} catch {
|
|
@@ -2055,7 +2157,7 @@ function useVoice(options = {}) {
|
|
|
2055
2157
|
}
|
|
2056
2158
|
outputCtxRef.current = null;
|
|
2057
2159
|
}, []);
|
|
2058
|
-
const stop =
|
|
2160
|
+
const stop = useCallback6(() => {
|
|
2059
2161
|
voiceLogger.debug("stop() called");
|
|
2060
2162
|
try {
|
|
2061
2163
|
wsRef.current?.close(1e3, "client_stop");
|
|
@@ -2065,8 +2167,8 @@ function useVoice(options = {}) {
|
|
|
2065
2167
|
teardownAudio();
|
|
2066
2168
|
if (mountedRef.current) setState("idle");
|
|
2067
2169
|
}, [teardownAudio, voiceLogger]);
|
|
2068
|
-
|
|
2069
|
-
const startCapture =
|
|
2170
|
+
useEffect6(() => stop, [stop]);
|
|
2171
|
+
const startCapture = useCallback6(async (inputSampleRate) => {
|
|
2070
2172
|
const stream = await navigator.mediaDevices.getUserMedia({
|
|
2071
2173
|
audio: {
|
|
2072
2174
|
echoCancellation: true,
|
|
@@ -2092,7 +2194,7 @@ function useVoice(options = {}) {
|
|
|
2092
2194
|
recorderNodeRef.current = recorderNode;
|
|
2093
2195
|
source.connect(recorderNode);
|
|
2094
2196
|
}, []);
|
|
2095
|
-
const setupPlayback =
|
|
2197
|
+
const setupPlayback = useCallback6(async (outputSampleRate) => {
|
|
2096
2198
|
const outputCtx = new AudioContext({ sampleRate: outputSampleRate });
|
|
2097
2199
|
outputCtxRef.current = outputCtx;
|
|
2098
2200
|
await outputCtx.audioWorklet.addModule(playerWorkletUrl());
|
|
@@ -2100,7 +2202,7 @@ function useVoice(options = {}) {
|
|
|
2100
2202
|
playerNode.connect(outputCtx.destination);
|
|
2101
2203
|
playerNodeRef.current = playerNode;
|
|
2102
2204
|
}, []);
|
|
2103
|
-
const upsertToolCall =
|
|
2205
|
+
const upsertToolCall = useCallback6(
|
|
2104
2206
|
(id, patch) => {
|
|
2105
2207
|
setToolCalls((prev) => {
|
|
2106
2208
|
const idx = prev.findIndex((t) => t.id === id);
|
|
@@ -2112,7 +2214,7 @@ function useVoice(options = {}) {
|
|
|
2112
2214
|
},
|
|
2113
2215
|
[]
|
|
2114
2216
|
);
|
|
2115
|
-
const handleTranscript =
|
|
2217
|
+
const handleTranscript = useCallback6((value) => {
|
|
2116
2218
|
const { speaker, text, isFinal, turnSeq } = value;
|
|
2117
2219
|
if (!isFinal) {
|
|
2118
2220
|
setPartial({ id: "partial", speaker, text });
|
|
@@ -2135,7 +2237,7 @@ function useVoice(options = {}) {
|
|
|
2135
2237
|
});
|
|
2136
2238
|
lastFinalTurnRef.current = { speaker, turnSeq };
|
|
2137
2239
|
}, []);
|
|
2138
|
-
const handleCustomEvent =
|
|
2240
|
+
const handleCustomEvent = useCallback6(
|
|
2139
2241
|
(name, value) => {
|
|
2140
2242
|
switch (name) {
|
|
2141
2243
|
case "voice_session_ready":
|
|
@@ -2193,7 +2295,7 @@ function useVoice(options = {}) {
|
|
|
2193
2295
|
},
|
|
2194
2296
|
[handleTranscript, setupPlayback, startCapture, teardownAudio, voiceLogger]
|
|
2195
2297
|
);
|
|
2196
|
-
const handleMessage =
|
|
2298
|
+
const handleMessage = useCallback6(
|
|
2197
2299
|
(event) => {
|
|
2198
2300
|
if (typeof event.data !== "string") {
|
|
2199
2301
|
const buf = event.data;
|
|
@@ -2251,7 +2353,7 @@ function useVoice(options = {}) {
|
|
|
2251
2353
|
},
|
|
2252
2354
|
[handleCustomEvent, upsertToolCall, voiceLogger]
|
|
2253
2355
|
);
|
|
2254
|
-
const start =
|
|
2356
|
+
const start = useCallback6(async () => {
|
|
2255
2357
|
if (!agentId) {
|
|
2256
2358
|
const err = new Error(
|
|
2257
2359
|
"useVoice: no agentId provided and no defaultAgentId set on PersonaProvider"
|
|
@@ -2318,17 +2420,17 @@ function useVoice(options = {}) {
|
|
|
2318
2420
|
teardownAudio();
|
|
2319
2421
|
}
|
|
2320
2422
|
}, [agentId, threadId, contextOverride, context, fetchWithAuth, handleMessage, teardownAudio, voiceLogger]);
|
|
2321
|
-
const mute =
|
|
2423
|
+
const mute = useCallback6((muted) => {
|
|
2322
2424
|
setIsMuted(muted);
|
|
2323
2425
|
streamRef.current?.getAudioTracks().forEach((track) => {
|
|
2324
2426
|
track.enabled = !muted;
|
|
2325
2427
|
});
|
|
2326
2428
|
}, []);
|
|
2327
|
-
const sendText =
|
|
2429
|
+
const sendText = useCallback6((text) => {
|
|
2328
2430
|
if (!text?.trim() || wsRef.current?.readyState !== WebSocket.OPEN) return;
|
|
2329
2431
|
wsRef.current.send(JSON.stringify({ type: "voice.text", text }));
|
|
2330
2432
|
}, []);
|
|
2331
|
-
const updateContext =
|
|
2433
|
+
const updateContext = useCallback6((newContext) => {
|
|
2332
2434
|
if (wsRef.current?.readyState !== WebSocket.OPEN) return;
|
|
2333
2435
|
wsRef.current.send(JSON.stringify({ type: "voice.context", context: newContext }));
|
|
2334
2436
|
}, []);
|
|
@@ -2349,14 +2451,14 @@ function useVoice(options = {}) {
|
|
|
2349
2451
|
}
|
|
2350
2452
|
|
|
2351
2453
|
// src/hooks/useFiles.ts
|
|
2352
|
-
import { useCallback as
|
|
2454
|
+
import { useCallback as useCallback7, useEffect as useEffect7, useState as useState7 } from "react";
|
|
2353
2455
|
function useFiles(autoFetch = true) {
|
|
2354
2456
|
const { fetchWithAuth } = usePersonaContext();
|
|
2355
|
-
const [files, setFiles] =
|
|
2356
|
-
const [isLoading, setIsLoading] =
|
|
2357
|
-
const [isUploading, setIsUploading] =
|
|
2358
|
-
const [error, setError] =
|
|
2359
|
-
const fetchFiles =
|
|
2457
|
+
const [files, setFiles] = useState7([]);
|
|
2458
|
+
const [isLoading, setIsLoading] = useState7(false);
|
|
2459
|
+
const [isUploading, setIsUploading] = useState7(false);
|
|
2460
|
+
const [error, setError] = useState7(null);
|
|
2461
|
+
const fetchFiles = useCallback7(async () => {
|
|
2360
2462
|
setIsLoading(true);
|
|
2361
2463
|
setError(null);
|
|
2362
2464
|
try {
|
|
@@ -2374,7 +2476,7 @@ function useFiles(autoFetch = true) {
|
|
|
2374
2476
|
setIsLoading(false);
|
|
2375
2477
|
}
|
|
2376
2478
|
}, [fetchWithAuth]);
|
|
2377
|
-
const uploadFile =
|
|
2479
|
+
const uploadFile = useCallback7(
|
|
2378
2480
|
async (fileOrFormData) => {
|
|
2379
2481
|
setIsUploading(true);
|
|
2380
2482
|
setError(null);
|
|
@@ -2407,7 +2509,7 @@ function useFiles(autoFetch = true) {
|
|
|
2407
2509
|
},
|
|
2408
2510
|
[fetchWithAuth, fetchFiles]
|
|
2409
2511
|
);
|
|
2410
|
-
const deleteFile =
|
|
2512
|
+
const deleteFile = useCallback7(
|
|
2411
2513
|
async (fileId) => {
|
|
2412
2514
|
const res = await fetchWithAuth(`/files/${fileId}`, { method: "DELETE" });
|
|
2413
2515
|
if (!res.ok) throw new Error(`Failed to delete file: ${res.statusText}`);
|
|
@@ -2415,7 +2517,7 @@ function useFiles(autoFetch = true) {
|
|
|
2415
2517
|
},
|
|
2416
2518
|
[fetchWithAuth]
|
|
2417
2519
|
);
|
|
2418
|
-
const bulkDeleteFiles =
|
|
2520
|
+
const bulkDeleteFiles = useCallback7(
|
|
2419
2521
|
async (fileIds) => {
|
|
2420
2522
|
const res = await fetchWithAuth("/files/bulk-delete", {
|
|
2421
2523
|
method: "POST",
|
|
@@ -2430,10 +2532,10 @@ function useFiles(autoFetch = true) {
|
|
|
2430
2532
|
},
|
|
2431
2533
|
[fetchWithAuth]
|
|
2432
2534
|
);
|
|
2433
|
-
const getDownloadUrl =
|
|
2535
|
+
const getDownloadUrl = useCallback7((fileId) => {
|
|
2434
2536
|
return `/files/${fileId}`;
|
|
2435
2537
|
}, []);
|
|
2436
|
-
|
|
2538
|
+
useEffect7(() => {
|
|
2437
2539
|
if (autoFetch) {
|
|
2438
2540
|
void fetchFiles();
|
|
2439
2541
|
}
|
|
@@ -2452,21 +2554,21 @@ function useFiles(autoFetch = true) {
|
|
|
2452
2554
|
}
|
|
2453
2555
|
|
|
2454
2556
|
// src/hooks/useAgents.ts
|
|
2455
|
-
import { useCallback as
|
|
2557
|
+
import { useCallback as useCallback8, useEffect as useEffect8, useState as useState8 } from "react";
|
|
2456
2558
|
function useAgents(options = true) {
|
|
2457
2559
|
const opts = typeof options === "boolean" ? { autoFetch: options } : options;
|
|
2458
2560
|
const { autoFetch = true, page, limit, search, category, scope } = opts;
|
|
2459
2561
|
const { fetchWithAuth } = usePersonaContext();
|
|
2460
|
-
const [agents, setAgents] =
|
|
2461
|
-
const [pagination, setPagination] =
|
|
2562
|
+
const [agents, setAgents] = useState8([]);
|
|
2563
|
+
const [pagination, setPagination] = useState8({
|
|
2462
2564
|
total: 0,
|
|
2463
2565
|
page: page ?? 1,
|
|
2464
2566
|
limit: limit ?? 20,
|
|
2465
2567
|
pages: 0
|
|
2466
2568
|
});
|
|
2467
|
-
const [isLoading, setIsLoading] =
|
|
2468
|
-
const [error, setError] =
|
|
2469
|
-
const fetchAgents =
|
|
2569
|
+
const [isLoading, setIsLoading] = useState8(false);
|
|
2570
|
+
const [error, setError] = useState8(null);
|
|
2571
|
+
const fetchAgents = useCallback8(async () => {
|
|
2470
2572
|
setIsLoading(true);
|
|
2471
2573
|
setError(null);
|
|
2472
2574
|
try {
|
|
@@ -2494,7 +2596,7 @@ function useAgents(options = true) {
|
|
|
2494
2596
|
setIsLoading(false);
|
|
2495
2597
|
}
|
|
2496
2598
|
}, [fetchWithAuth, page, limit, search, category, scope]);
|
|
2497
|
-
const getAgent =
|
|
2599
|
+
const getAgent = useCallback8(
|
|
2498
2600
|
async (agentId) => {
|
|
2499
2601
|
const res = await fetchWithAuth(`/agents/${agentId}`);
|
|
2500
2602
|
if (!res.ok) throw new Error(`Failed to fetch agent: ${res.statusText}`);
|
|
@@ -2502,7 +2604,7 @@ function useAgents(options = true) {
|
|
|
2502
2604
|
},
|
|
2503
2605
|
[fetchWithAuth]
|
|
2504
2606
|
);
|
|
2505
|
-
const createAgent =
|
|
2607
|
+
const createAgent = useCallback8(
|
|
2506
2608
|
async (input) => {
|
|
2507
2609
|
setError(null);
|
|
2508
2610
|
try {
|
|
@@ -2526,7 +2628,7 @@ function useAgents(options = true) {
|
|
|
2526
2628
|
},
|
|
2527
2629
|
[fetchWithAuth]
|
|
2528
2630
|
);
|
|
2529
|
-
const updateAgent =
|
|
2631
|
+
const updateAgent = useCallback8(
|
|
2530
2632
|
async (agentId, input) => {
|
|
2531
2633
|
setError(null);
|
|
2532
2634
|
try {
|
|
@@ -2550,7 +2652,7 @@ function useAgents(options = true) {
|
|
|
2550
2652
|
},
|
|
2551
2653
|
[fetchWithAuth]
|
|
2552
2654
|
);
|
|
2553
|
-
const deleteAgent =
|
|
2655
|
+
const deleteAgent = useCallback8(
|
|
2554
2656
|
async (agentId) => {
|
|
2555
2657
|
setError(null);
|
|
2556
2658
|
try {
|
|
@@ -2568,7 +2670,7 @@ function useAgents(options = true) {
|
|
|
2568
2670
|
},
|
|
2569
2671
|
[fetchWithAuth]
|
|
2570
2672
|
);
|
|
2571
|
-
const bulkDeleteAgents =
|
|
2673
|
+
const bulkDeleteAgents = useCallback8(
|
|
2572
2674
|
async (ids) => {
|
|
2573
2675
|
setError(null);
|
|
2574
2676
|
try {
|
|
@@ -2593,7 +2695,7 @@ function useAgents(options = true) {
|
|
|
2593
2695
|
},
|
|
2594
2696
|
[fetchWithAuth]
|
|
2595
2697
|
);
|
|
2596
|
-
|
|
2698
|
+
useEffect8(() => {
|
|
2597
2699
|
if (autoFetch) void fetchAgents();
|
|
2598
2700
|
}, [autoFetch, fetchAgents]);
|
|
2599
2701
|
return {
|
|
@@ -2611,13 +2713,13 @@ function useAgents(options = true) {
|
|
|
2611
2713
|
}
|
|
2612
2714
|
|
|
2613
2715
|
// src/hooks/useConnection.ts
|
|
2614
|
-
import { useCallback as
|
|
2716
|
+
import { useCallback as useCallback9, useEffect as useEffect9, useState as useState9 } from "react";
|
|
2615
2717
|
function useConnection(autoCheck = true) {
|
|
2616
2718
|
const { fetchWithAuth } = usePersonaContext();
|
|
2617
|
-
const [health, setHealth] =
|
|
2618
|
-
const [isConnected, setIsConnected] =
|
|
2619
|
-
const [isLoading, setIsLoading] =
|
|
2620
|
-
const checkHealth =
|
|
2719
|
+
const [health, setHealth] = useState9(null);
|
|
2720
|
+
const [isConnected, setIsConnected] = useState9(false);
|
|
2721
|
+
const [isLoading, setIsLoading] = useState9(false);
|
|
2722
|
+
const checkHealth = useCallback9(async () => {
|
|
2621
2723
|
setIsLoading(true);
|
|
2622
2724
|
try {
|
|
2623
2725
|
const res = await fetchWithAuth("/health");
|
|
@@ -2636,7 +2738,7 @@ function useConnection(autoCheck = true) {
|
|
|
2636
2738
|
setIsLoading(false);
|
|
2637
2739
|
}
|
|
2638
2740
|
}, [fetchWithAuth]);
|
|
2639
|
-
|
|
2741
|
+
useEffect9(() => {
|
|
2640
2742
|
if (autoCheck) {
|
|
2641
2743
|
void checkHealth();
|
|
2642
2744
|
}
|
|
@@ -2650,15 +2752,15 @@ function useConnection(autoCheck = true) {
|
|
|
2650
2752
|
}
|
|
2651
2753
|
|
|
2652
2754
|
// src/hooks/useMcpConnections.ts
|
|
2653
|
-
import { useCallback as
|
|
2755
|
+
import { useCallback as useCallback10, useEffect as useEffect10, useState as useState10 } from "react";
|
|
2654
2756
|
function useMcpConnections(options = {}) {
|
|
2655
2757
|
const { defaultAgentId, fetchWithAuth } = usePersonaContext();
|
|
2656
2758
|
const agentId = options.agentId ?? defaultAgentId;
|
|
2657
2759
|
const autoFetch = options.autoFetch ?? true;
|
|
2658
|
-
const [connections, setConnections] =
|
|
2659
|
-
const [isLoading, setIsLoading] =
|
|
2660
|
-
const [error, setError] =
|
|
2661
|
-
const fetchConnections =
|
|
2760
|
+
const [connections, setConnections] = useState10([]);
|
|
2761
|
+
const [isLoading, setIsLoading] = useState10(false);
|
|
2762
|
+
const [error, setError] = useState10(null);
|
|
2763
|
+
const fetchConnections = useCallback10(async () => {
|
|
2662
2764
|
if (!agentId) return [];
|
|
2663
2765
|
setIsLoading(true);
|
|
2664
2766
|
setError(null);
|
|
@@ -2682,8 +2784,8 @@ function useMcpConnections(options = {}) {
|
|
|
2682
2784
|
setIsLoading(false);
|
|
2683
2785
|
}
|
|
2684
2786
|
}, [agentId, fetchWithAuth, options.returnTo]);
|
|
2685
|
-
const [isDisconnecting, setIsDisconnecting] =
|
|
2686
|
-
const disconnect =
|
|
2787
|
+
const [isDisconnecting, setIsDisconnecting] = useState10(false);
|
|
2788
|
+
const disconnect = useCallback10(
|
|
2687
2789
|
async (mcpId) => {
|
|
2688
2790
|
setIsDisconnecting(true);
|
|
2689
2791
|
setError(null);
|
|
@@ -2709,7 +2811,7 @@ function useMcpConnections(options = {}) {
|
|
|
2709
2811
|
},
|
|
2710
2812
|
[fetchWithAuth, fetchConnections]
|
|
2711
2813
|
);
|
|
2712
|
-
|
|
2814
|
+
useEffect10(() => {
|
|
2713
2815
|
if (autoFetch) void fetchConnections();
|
|
2714
2816
|
}, [autoFetch, fetchConnections]);
|
|
2715
2817
|
return {
|
|
@@ -2725,11 +2827,11 @@ function useMcpConnections(options = {}) {
|
|
|
2725
2827
|
}
|
|
2726
2828
|
|
|
2727
2829
|
// src/hooks/useMcp.ts
|
|
2728
|
-
import { useCallback as
|
|
2830
|
+
import { useCallback as useCallback11 } from "react";
|
|
2729
2831
|
function useMcp(options = {}) {
|
|
2730
2832
|
const { fetchWithAuth } = usePersonaContext();
|
|
2731
2833
|
const defaultMcpId = options.mcpId;
|
|
2732
|
-
const readResource =
|
|
2834
|
+
const readResource = useCallback11(
|
|
2733
2835
|
async (uri, mcpId) => {
|
|
2734
2836
|
const id = mcpId ?? defaultMcpId;
|
|
2735
2837
|
if (!id) throw new Error("MCP server ID is required to read resource");
|
|
@@ -2743,7 +2845,7 @@ function useMcp(options = {}) {
|
|
|
2743
2845
|
},
|
|
2744
2846
|
[fetchWithAuth, defaultMcpId]
|
|
2745
2847
|
);
|
|
2746
|
-
const callTool =
|
|
2848
|
+
const callTool = useCallback11(
|
|
2747
2849
|
async (name, args, mcpId) => {
|
|
2748
2850
|
const id = mcpId ?? defaultMcpId;
|
|
2749
2851
|
if (!id) throw new Error("MCP server ID is required to call tool");
|
|
@@ -2766,20 +2868,20 @@ function useMcp(options = {}) {
|
|
|
2766
2868
|
}
|
|
2767
2869
|
|
|
2768
2870
|
// src/hooks/useSkills.ts
|
|
2769
|
-
import { useCallback as
|
|
2871
|
+
import { useCallback as useCallback12, useEffect as useEffect11, useState as useState11 } from "react";
|
|
2770
2872
|
function useSkills(options = {}) {
|
|
2771
2873
|
const { autoFetch = true, page, limit, search, scope } = options;
|
|
2772
2874
|
const { fetchWithAuth } = usePersonaContext();
|
|
2773
|
-
const [skills, setSkills] =
|
|
2774
|
-
const [pagination, setPagination] =
|
|
2875
|
+
const [skills, setSkills] = useState11([]);
|
|
2876
|
+
const [pagination, setPagination] = useState11({
|
|
2775
2877
|
total: 0,
|
|
2776
2878
|
page: page ?? 1,
|
|
2777
2879
|
limit: limit ?? 20,
|
|
2778
2880
|
pages: 0
|
|
2779
2881
|
});
|
|
2780
|
-
const [isLoading, setIsLoading] =
|
|
2781
|
-
const [error, setError] =
|
|
2782
|
-
const fetchSkills =
|
|
2882
|
+
const [isLoading, setIsLoading] = useState11(false);
|
|
2883
|
+
const [error, setError] = useState11(null);
|
|
2884
|
+
const fetchSkills = useCallback12(async () => {
|
|
2783
2885
|
setIsLoading(true);
|
|
2784
2886
|
setError(null);
|
|
2785
2887
|
try {
|
|
@@ -2806,7 +2908,7 @@ function useSkills(options = {}) {
|
|
|
2806
2908
|
setIsLoading(false);
|
|
2807
2909
|
}
|
|
2808
2910
|
}, [fetchWithAuth, page, limit, search, scope]);
|
|
2809
|
-
const getSkill =
|
|
2911
|
+
const getSkill = useCallback12(
|
|
2810
2912
|
async (skillId) => {
|
|
2811
2913
|
const res = await fetchWithAuth(`/skills/${skillId}`);
|
|
2812
2914
|
if (!res.ok) throw new Error(`Failed to fetch skill: ${res.statusText}`);
|
|
@@ -2814,7 +2916,7 @@ function useSkills(options = {}) {
|
|
|
2814
2916
|
},
|
|
2815
2917
|
[fetchWithAuth]
|
|
2816
2918
|
);
|
|
2817
|
-
const createSkill =
|
|
2919
|
+
const createSkill = useCallback12(
|
|
2818
2920
|
async (input) => {
|
|
2819
2921
|
setError(null);
|
|
2820
2922
|
try {
|
|
@@ -2838,7 +2940,7 @@ function useSkills(options = {}) {
|
|
|
2838
2940
|
},
|
|
2839
2941
|
[fetchWithAuth]
|
|
2840
2942
|
);
|
|
2841
|
-
const updateSkill =
|
|
2943
|
+
const updateSkill = useCallback12(
|
|
2842
2944
|
async (skillId, input) => {
|
|
2843
2945
|
setError(null);
|
|
2844
2946
|
try {
|
|
@@ -2862,7 +2964,7 @@ function useSkills(options = {}) {
|
|
|
2862
2964
|
},
|
|
2863
2965
|
[fetchWithAuth]
|
|
2864
2966
|
);
|
|
2865
|
-
const deleteSkill =
|
|
2967
|
+
const deleteSkill = useCallback12(
|
|
2866
2968
|
async (skillId) => {
|
|
2867
2969
|
setError(null);
|
|
2868
2970
|
try {
|
|
@@ -2880,7 +2982,7 @@ function useSkills(options = {}) {
|
|
|
2880
2982
|
},
|
|
2881
2983
|
[fetchWithAuth]
|
|
2882
2984
|
);
|
|
2883
|
-
const bulkDeleteSkills =
|
|
2985
|
+
const bulkDeleteSkills = useCallback12(
|
|
2884
2986
|
async (ids) => {
|
|
2885
2987
|
setError(null);
|
|
2886
2988
|
try {
|
|
@@ -2905,7 +3007,7 @@ function useSkills(options = {}) {
|
|
|
2905
3007
|
},
|
|
2906
3008
|
[fetchWithAuth]
|
|
2907
3009
|
);
|
|
2908
|
-
const getSkillUsage =
|
|
3010
|
+
const getSkillUsage = useCallback12(
|
|
2909
3011
|
async (skillId) => {
|
|
2910
3012
|
const res = await fetchWithAuth(`/skills/${skillId}/usage`);
|
|
2911
3013
|
if (!res.ok) throw new Error(`Failed to fetch skill usage: ${res.statusText}`);
|
|
@@ -2913,7 +3015,7 @@ function useSkills(options = {}) {
|
|
|
2913
3015
|
},
|
|
2914
3016
|
[fetchWithAuth]
|
|
2915
3017
|
);
|
|
2916
|
-
|
|
3018
|
+
useEffect11(() => {
|
|
2917
3019
|
if (autoFetch) void fetchSkills();
|
|
2918
3020
|
}, [autoFetch, fetchSkills]);
|
|
2919
3021
|
return {
|
|
@@ -2932,20 +3034,20 @@ function useSkills(options = {}) {
|
|
|
2932
3034
|
}
|
|
2933
3035
|
|
|
2934
3036
|
// src/hooks/useRcpSources.ts
|
|
2935
|
-
import { useCallback as
|
|
3037
|
+
import { useCallback as useCallback13, useEffect as useEffect12, useState as useState12 } from "react";
|
|
2936
3038
|
function useRcpSources(options = {}) {
|
|
2937
3039
|
const { autoFetch = true, page, limit, search } = options;
|
|
2938
3040
|
const { fetchWithAuth } = usePersonaContext();
|
|
2939
|
-
const [rcpSources, setRcpSources] =
|
|
2940
|
-
const [pagination, setPagination] =
|
|
3041
|
+
const [rcpSources, setRcpSources] = useState12([]);
|
|
3042
|
+
const [pagination, setPagination] = useState12({
|
|
2941
3043
|
total: 0,
|
|
2942
3044
|
page: page ?? 1,
|
|
2943
3045
|
limit: limit ?? 20,
|
|
2944
3046
|
pages: 0
|
|
2945
3047
|
});
|
|
2946
|
-
const [isLoading, setIsLoading] =
|
|
2947
|
-
const [error, setError] =
|
|
2948
|
-
const fetchRcpSources =
|
|
3048
|
+
const [isLoading, setIsLoading] = useState12(false);
|
|
3049
|
+
const [error, setError] = useState12(null);
|
|
3050
|
+
const fetchRcpSources = useCallback13(async () => {
|
|
2949
3051
|
setIsLoading(true);
|
|
2950
3052
|
setError(null);
|
|
2951
3053
|
try {
|
|
@@ -2971,7 +3073,7 @@ function useRcpSources(options = {}) {
|
|
|
2971
3073
|
setIsLoading(false);
|
|
2972
3074
|
}
|
|
2973
3075
|
}, [fetchWithAuth, page, limit, search]);
|
|
2974
|
-
const getRcpSource =
|
|
3076
|
+
const getRcpSource = useCallback13(
|
|
2975
3077
|
async (sourceId) => {
|
|
2976
3078
|
const res = await fetchWithAuth(`/rcp-sources/${sourceId}`);
|
|
2977
3079
|
if (!res.ok) throw new Error(`Failed to fetch RCP source: ${res.statusText}`);
|
|
@@ -2979,7 +3081,7 @@ function useRcpSources(options = {}) {
|
|
|
2979
3081
|
},
|
|
2980
3082
|
[fetchWithAuth]
|
|
2981
3083
|
);
|
|
2982
|
-
const createRcpSource =
|
|
3084
|
+
const createRcpSource = useCallback13(
|
|
2983
3085
|
async (input) => {
|
|
2984
3086
|
setError(null);
|
|
2985
3087
|
try {
|
|
@@ -3003,7 +3105,7 @@ function useRcpSources(options = {}) {
|
|
|
3003
3105
|
},
|
|
3004
3106
|
[fetchWithAuth]
|
|
3005
3107
|
);
|
|
3006
|
-
const updateRcpSource =
|
|
3108
|
+
const updateRcpSource = useCallback13(
|
|
3007
3109
|
async (sourceId, input) => {
|
|
3008
3110
|
setError(null);
|
|
3009
3111
|
try {
|
|
@@ -3027,7 +3129,7 @@ function useRcpSources(options = {}) {
|
|
|
3027
3129
|
},
|
|
3028
3130
|
[fetchWithAuth]
|
|
3029
3131
|
);
|
|
3030
|
-
const deleteRcpSource =
|
|
3132
|
+
const deleteRcpSource = useCallback13(
|
|
3031
3133
|
async (sourceId) => {
|
|
3032
3134
|
setError(null);
|
|
3033
3135
|
try {
|
|
@@ -3045,7 +3147,7 @@ function useRcpSources(options = {}) {
|
|
|
3045
3147
|
},
|
|
3046
3148
|
[fetchWithAuth]
|
|
3047
3149
|
);
|
|
3048
|
-
const bulkDeleteRcpSources =
|
|
3150
|
+
const bulkDeleteRcpSources = useCallback13(
|
|
3049
3151
|
async (ids) => {
|
|
3050
3152
|
setError(null);
|
|
3051
3153
|
try {
|
|
@@ -3070,7 +3172,7 @@ function useRcpSources(options = {}) {
|
|
|
3070
3172
|
},
|
|
3071
3173
|
[fetchWithAuth]
|
|
3072
3174
|
);
|
|
3073
|
-
const getRcpSourceUsage =
|
|
3175
|
+
const getRcpSourceUsage = useCallback13(
|
|
3074
3176
|
async (sourceId) => {
|
|
3075
3177
|
const res = await fetchWithAuth(`/rcp-sources/${sourceId}/usage`);
|
|
3076
3178
|
if (!res.ok) throw new Error(`Failed to fetch RCP source usage: ${res.statusText}`);
|
|
@@ -3078,7 +3180,7 @@ function useRcpSources(options = {}) {
|
|
|
3078
3180
|
},
|
|
3079
3181
|
[fetchWithAuth]
|
|
3080
3182
|
);
|
|
3081
|
-
const testRcpSourceConnection =
|
|
3183
|
+
const testRcpSourceConnection = useCallback13(
|
|
3082
3184
|
async (sourceId) => {
|
|
3083
3185
|
setError(null);
|
|
3084
3186
|
try {
|
|
@@ -3102,7 +3204,7 @@ function useRcpSources(options = {}) {
|
|
|
3102
3204
|
},
|
|
3103
3205
|
[fetchWithAuth]
|
|
3104
3206
|
);
|
|
3105
|
-
|
|
3207
|
+
useEffect12(() => {
|
|
3106
3208
|
if (autoFetch) void fetchRcpSources();
|
|
3107
3209
|
}, [autoFetch, fetchRcpSources]);
|
|
3108
3210
|
return {
|
|
@@ -3121,28 +3223,475 @@ function useRcpSources(options = {}) {
|
|
|
3121
3223
|
};
|
|
3122
3224
|
}
|
|
3123
3225
|
|
|
3226
|
+
// src/hooks/useKnowledgeBases.ts
|
|
3227
|
+
import { useCallback as useCallback14, useEffect as useEffect13, useState as useState13 } from "react";
|
|
3228
|
+
function useKnowledgeBases(options = {}) {
|
|
3229
|
+
const { autoFetch = true, page, limit, search, scope } = options;
|
|
3230
|
+
const { fetchWithAuth } = usePersonaContext();
|
|
3231
|
+
const [knowledgeBases, setKnowledgeBases] = useState13([]);
|
|
3232
|
+
const [pagination, setPagination] = useState13({
|
|
3233
|
+
total: 0,
|
|
3234
|
+
page: page ?? 1,
|
|
3235
|
+
limit: limit ?? 20,
|
|
3236
|
+
pages: 0
|
|
3237
|
+
});
|
|
3238
|
+
const [isLoading, setIsLoading] = useState13(false);
|
|
3239
|
+
const [isUploading, setIsUploading] = useState13(false);
|
|
3240
|
+
const [error, setError] = useState13(null);
|
|
3241
|
+
const fetchKnowledgeBases = useCallback14(async () => {
|
|
3242
|
+
setIsLoading(true);
|
|
3243
|
+
setError(null);
|
|
3244
|
+
try {
|
|
3245
|
+
const query = new URLSearchParams();
|
|
3246
|
+
if (page) query.set("page", String(page));
|
|
3247
|
+
if (limit) query.set("limit", String(limit));
|
|
3248
|
+
if (search) query.set("search", search);
|
|
3249
|
+
if (scope) query.set("scope", scope);
|
|
3250
|
+
const queryStr = query.toString() ? `?${query.toString()}` : "";
|
|
3251
|
+
const res = await fetchWithAuth(`/knowledge${queryStr}`);
|
|
3252
|
+
if (!res.ok) throw new Error(`Failed to list knowledge bases: ${res.statusText}`);
|
|
3253
|
+
const data = await res.json();
|
|
3254
|
+
const items = Array.isArray(data) ? data : data?.items ?? [];
|
|
3255
|
+
setKnowledgeBases(items);
|
|
3256
|
+
setPagination(
|
|
3257
|
+
data?.pagination ?? { total: items.length, page: 1, limit: items.length, pages: 1 }
|
|
3258
|
+
);
|
|
3259
|
+
return items;
|
|
3260
|
+
} catch (err) {
|
|
3261
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3262
|
+
setError(errorObj);
|
|
3263
|
+
return [];
|
|
3264
|
+
} finally {
|
|
3265
|
+
setIsLoading(false);
|
|
3266
|
+
}
|
|
3267
|
+
}, [fetchWithAuth, page, limit, search, scope]);
|
|
3268
|
+
const getKnowledgeBase = useCallback14(
|
|
3269
|
+
async (kbId) => {
|
|
3270
|
+
const res = await fetchWithAuth(`/knowledge/${kbId}`);
|
|
3271
|
+
if (!res.ok) throw new Error(`Failed to fetch knowledge base: ${res.statusText}`);
|
|
3272
|
+
return res.json();
|
|
3273
|
+
},
|
|
3274
|
+
[fetchWithAuth]
|
|
3275
|
+
);
|
|
3276
|
+
const createKnowledgeBase = useCallback14(
|
|
3277
|
+
async (input) => {
|
|
3278
|
+
setError(null);
|
|
3279
|
+
try {
|
|
3280
|
+
const res = await fetchWithAuth("/knowledge", {
|
|
3281
|
+
method: "POST",
|
|
3282
|
+
headers: { "Content-Type": "application/json" },
|
|
3283
|
+
body: JSON.stringify(input)
|
|
3284
|
+
});
|
|
3285
|
+
if (!res.ok) {
|
|
3286
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3287
|
+
throw new Error(`Failed to create knowledge base (${res.status}): ${errText}`);
|
|
3288
|
+
}
|
|
3289
|
+
const created = await res.json();
|
|
3290
|
+
setKnowledgeBases((prev) => [created, ...prev]);
|
|
3291
|
+
return created;
|
|
3292
|
+
} catch (err) {
|
|
3293
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3294
|
+
setError(errorObj);
|
|
3295
|
+
throw errorObj;
|
|
3296
|
+
}
|
|
3297
|
+
},
|
|
3298
|
+
[fetchWithAuth]
|
|
3299
|
+
);
|
|
3300
|
+
const updateKnowledgeBase = useCallback14(
|
|
3301
|
+
async (kbId, input) => {
|
|
3302
|
+
setError(null);
|
|
3303
|
+
try {
|
|
3304
|
+
const res = await fetchWithAuth(`/knowledge/${kbId}`, {
|
|
3305
|
+
method: "PATCH",
|
|
3306
|
+
headers: { "Content-Type": "application/json" },
|
|
3307
|
+
body: JSON.stringify(input)
|
|
3308
|
+
});
|
|
3309
|
+
if (!res.ok) {
|
|
3310
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3311
|
+
throw new Error(`Failed to update knowledge base (${res.status}): ${errText}`);
|
|
3312
|
+
}
|
|
3313
|
+
const updated = await res.json();
|
|
3314
|
+
setKnowledgeBases((prev) => prev.map((kb) => kb._id === kbId ? updated : kb));
|
|
3315
|
+
return updated;
|
|
3316
|
+
} catch (err) {
|
|
3317
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3318
|
+
setError(errorObj);
|
|
3319
|
+
throw errorObj;
|
|
3320
|
+
}
|
|
3321
|
+
},
|
|
3322
|
+
[fetchWithAuth]
|
|
3323
|
+
);
|
|
3324
|
+
const deleteKnowledgeBase = useCallback14(
|
|
3325
|
+
async (kbId) => {
|
|
3326
|
+
setError(null);
|
|
3327
|
+
try {
|
|
3328
|
+
const res = await fetchWithAuth(`/knowledge/${kbId}`, { method: "DELETE" });
|
|
3329
|
+
if (!res.ok) {
|
|
3330
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3331
|
+
throw new Error(`Failed to delete knowledge base (${res.status}): ${errText}`);
|
|
3332
|
+
}
|
|
3333
|
+
setKnowledgeBases((prev) => prev.filter((kb) => kb._id !== kbId));
|
|
3334
|
+
} catch (err) {
|
|
3335
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3336
|
+
setError(errorObj);
|
|
3337
|
+
throw errorObj;
|
|
3338
|
+
}
|
|
3339
|
+
},
|
|
3340
|
+
[fetchWithAuth]
|
|
3341
|
+
);
|
|
3342
|
+
const bulkDeleteKnowledgeBases = useCallback14(
|
|
3343
|
+
async (ids) => {
|
|
3344
|
+
setError(null);
|
|
3345
|
+
try {
|
|
3346
|
+
const res = await fetchWithAuth("/knowledge/bulk-delete", {
|
|
3347
|
+
method: "POST",
|
|
3348
|
+
headers: { "Content-Type": "application/json" },
|
|
3349
|
+
body: JSON.stringify({ ids })
|
|
3350
|
+
});
|
|
3351
|
+
if (!res.ok) {
|
|
3352
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3353
|
+
throw new Error(`Failed to bulk-delete knowledge bases (${res.status}): ${errText}`);
|
|
3354
|
+
}
|
|
3355
|
+
const result = await res.json();
|
|
3356
|
+
const deletedSet = new Set(result.deleted);
|
|
3357
|
+
setKnowledgeBases((prev) => prev.filter((kb) => !deletedSet.has(kb._id)));
|
|
3358
|
+
return result;
|
|
3359
|
+
} catch (err) {
|
|
3360
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3361
|
+
setError(errorObj);
|
|
3362
|
+
throw errorObj;
|
|
3363
|
+
}
|
|
3364
|
+
},
|
|
3365
|
+
[fetchWithAuth]
|
|
3366
|
+
);
|
|
3367
|
+
const getKnowledgeBaseUsage = useCallback14(
|
|
3368
|
+
async (kbId) => {
|
|
3369
|
+
const res = await fetchWithAuth(`/knowledge/${kbId}/usage`);
|
|
3370
|
+
if (!res.ok) throw new Error(`Failed to fetch knowledge base usage: ${res.statusText}`);
|
|
3371
|
+
return res.json();
|
|
3372
|
+
},
|
|
3373
|
+
[fetchWithAuth]
|
|
3374
|
+
);
|
|
3375
|
+
const uploadDocuments = useCallback14(
|
|
3376
|
+
async (kbId, files) => {
|
|
3377
|
+
setIsUploading(true);
|
|
3378
|
+
setError(null);
|
|
3379
|
+
try {
|
|
3380
|
+
const body = new FormData();
|
|
3381
|
+
for (const file of files) {
|
|
3382
|
+
if (file.content instanceof Blob) {
|
|
3383
|
+
body.append("files", file.content, file.filename);
|
|
3384
|
+
} else {
|
|
3385
|
+
body.append("files", {
|
|
3386
|
+
uri: file.content.uri,
|
|
3387
|
+
name: file.content.name ?? file.filename,
|
|
3388
|
+
type: file.content.type ?? file.contentType
|
|
3389
|
+
});
|
|
3390
|
+
}
|
|
3391
|
+
}
|
|
3392
|
+
const res = await fetchWithAuth(`/knowledge/${kbId}/documents`, {
|
|
3393
|
+
method: "POST",
|
|
3394
|
+
body
|
|
3395
|
+
});
|
|
3396
|
+
if (!res.ok) {
|
|
3397
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3398
|
+
throw new Error(`Failed to upload documents (${res.status}): ${errText}`);
|
|
3399
|
+
}
|
|
3400
|
+
const result = await res.json();
|
|
3401
|
+
setKnowledgeBases(
|
|
3402
|
+
(prev) => prev.map(
|
|
3403
|
+
(kb) => kb._id === kbId ? { ...kb, documentCount: result.documentCount, chunkCount: result.chunkCount } : kb
|
|
3404
|
+
)
|
|
3405
|
+
);
|
|
3406
|
+
return result;
|
|
3407
|
+
} catch (err) {
|
|
3408
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3409
|
+
setError(errorObj);
|
|
3410
|
+
throw errorObj;
|
|
3411
|
+
} finally {
|
|
3412
|
+
setIsUploading(false);
|
|
3413
|
+
}
|
|
3414
|
+
},
|
|
3415
|
+
[fetchWithAuth]
|
|
3416
|
+
);
|
|
3417
|
+
const listDocuments = useCallback14(
|
|
3418
|
+
async (kbId) => {
|
|
3419
|
+
const res = await fetchWithAuth(`/knowledge/${kbId}/documents`);
|
|
3420
|
+
if (!res.ok) throw new Error(`Failed to list documents: ${res.statusText}`);
|
|
3421
|
+
return res.json();
|
|
3422
|
+
},
|
|
3423
|
+
[fetchWithAuth]
|
|
3424
|
+
);
|
|
3425
|
+
const deleteDocument = useCallback14(
|
|
3426
|
+
async (kbId, sourceName) => {
|
|
3427
|
+
setError(null);
|
|
3428
|
+
try {
|
|
3429
|
+
const res = await fetchWithAuth(
|
|
3430
|
+
`/knowledge/${kbId}/documents/${encodeURIComponent(sourceName)}`,
|
|
3431
|
+
{ method: "DELETE" }
|
|
3432
|
+
);
|
|
3433
|
+
if (!res.ok) {
|
|
3434
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3435
|
+
throw new Error(`Failed to delete document (${res.status}): ${errText}`);
|
|
3436
|
+
}
|
|
3437
|
+
const result = await res.json();
|
|
3438
|
+
setKnowledgeBases(
|
|
3439
|
+
(prev) => prev.map(
|
|
3440
|
+
(kb) => kb._id === kbId ? { ...kb, documentCount: result.remainingDocuments, chunkCount: result.remainingChunks } : kb
|
|
3441
|
+
)
|
|
3442
|
+
);
|
|
3443
|
+
return result;
|
|
3444
|
+
} catch (err) {
|
|
3445
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3446
|
+
setError(errorObj);
|
|
3447
|
+
throw errorObj;
|
|
3448
|
+
}
|
|
3449
|
+
},
|
|
3450
|
+
[fetchWithAuth]
|
|
3451
|
+
);
|
|
3452
|
+
const searchKnowledgeBase = useCallback14(
|
|
3453
|
+
async (kbId, query, opts) => {
|
|
3454
|
+
const res = await fetchWithAuth(`/knowledge/${kbId}/search`, {
|
|
3455
|
+
method: "POST",
|
|
3456
|
+
headers: { "Content-Type": "application/json" },
|
|
3457
|
+
body: JSON.stringify({ query, topK: opts?.topK })
|
|
3458
|
+
});
|
|
3459
|
+
if (!res.ok) {
|
|
3460
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3461
|
+
throw new Error(`Failed to search knowledge base (${res.status}): ${errText}`);
|
|
3462
|
+
}
|
|
3463
|
+
return res.json();
|
|
3464
|
+
},
|
|
3465
|
+
[fetchWithAuth]
|
|
3466
|
+
);
|
|
3467
|
+
useEffect13(() => {
|
|
3468
|
+
if (autoFetch) void fetchKnowledgeBases();
|
|
3469
|
+
}, [autoFetch, fetchKnowledgeBases]);
|
|
3470
|
+
return {
|
|
3471
|
+
knowledgeBases,
|
|
3472
|
+
pagination,
|
|
3473
|
+
isLoading,
|
|
3474
|
+
isUploading,
|
|
3475
|
+
error,
|
|
3476
|
+
refetch: fetchKnowledgeBases,
|
|
3477
|
+
getKnowledgeBase,
|
|
3478
|
+
createKnowledgeBase,
|
|
3479
|
+
updateKnowledgeBase,
|
|
3480
|
+
deleteKnowledgeBase,
|
|
3481
|
+
bulkDeleteKnowledgeBases,
|
|
3482
|
+
getKnowledgeBaseUsage,
|
|
3483
|
+
uploadDocuments,
|
|
3484
|
+
listDocuments,
|
|
3485
|
+
deleteDocument,
|
|
3486
|
+
search: searchKnowledgeBase
|
|
3487
|
+
};
|
|
3488
|
+
}
|
|
3489
|
+
|
|
3490
|
+
// src/hooks/useMcpAdmin.ts
|
|
3491
|
+
import { useCallback as useCallback15, useEffect as useEffect14, useState as useState14 } from "react";
|
|
3492
|
+
function useMcpAdmin(options = {}) {
|
|
3493
|
+
const { autoFetch = true, page, limit, search } = options;
|
|
3494
|
+
const { fetchWithAuth } = usePersonaContext();
|
|
3495
|
+
const [mcps, setMcps] = useState14([]);
|
|
3496
|
+
const [pagination, setPagination] = useState14({
|
|
3497
|
+
total: 0,
|
|
3498
|
+
page: page ?? 1,
|
|
3499
|
+
limit: limit ?? 20,
|
|
3500
|
+
pages: 0
|
|
3501
|
+
});
|
|
3502
|
+
const [isLoading, setIsLoading] = useState14(false);
|
|
3503
|
+
const [error, setError] = useState14(null);
|
|
3504
|
+
const fetchMcps = useCallback15(async () => {
|
|
3505
|
+
setIsLoading(true);
|
|
3506
|
+
setError(null);
|
|
3507
|
+
try {
|
|
3508
|
+
const query = new URLSearchParams();
|
|
3509
|
+
if (page) query.set("page", String(page));
|
|
3510
|
+
if (limit) query.set("limit", String(limit));
|
|
3511
|
+
if (search) query.set("search", search);
|
|
3512
|
+
query.set("scope", "mine");
|
|
3513
|
+
const res = await fetchWithAuth(`/mcps?${query.toString()}`);
|
|
3514
|
+
if (!res.ok) throw new Error(`Failed to list MCPs: ${res.statusText}`);
|
|
3515
|
+
const data = await res.json();
|
|
3516
|
+
const items = Array.isArray(data) ? data : data?.items ?? [];
|
|
3517
|
+
setMcps(items);
|
|
3518
|
+
setPagination(
|
|
3519
|
+
data?.pagination ?? { total: items.length, page: 1, limit: items.length, pages: 1 }
|
|
3520
|
+
);
|
|
3521
|
+
return items;
|
|
3522
|
+
} catch (err) {
|
|
3523
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3524
|
+
setError(errorObj);
|
|
3525
|
+
return [];
|
|
3526
|
+
} finally {
|
|
3527
|
+
setIsLoading(false);
|
|
3528
|
+
}
|
|
3529
|
+
}, [fetchWithAuth, page, limit, search]);
|
|
3530
|
+
const getMcp = useCallback15(
|
|
3531
|
+
async (mcpId) => {
|
|
3532
|
+
const res = await fetchWithAuth(`/mcps/${mcpId}`);
|
|
3533
|
+
if (!res.ok) throw new Error(`Failed to fetch MCP: ${res.statusText}`);
|
|
3534
|
+
return res.json();
|
|
3535
|
+
},
|
|
3536
|
+
[fetchWithAuth]
|
|
3537
|
+
);
|
|
3538
|
+
const createMcp = useCallback15(
|
|
3539
|
+
async (input) => {
|
|
3540
|
+
setError(null);
|
|
3541
|
+
try {
|
|
3542
|
+
const res = await fetchWithAuth("/mcps", {
|
|
3543
|
+
method: "POST",
|
|
3544
|
+
headers: { "Content-Type": "application/json" },
|
|
3545
|
+
body: JSON.stringify(input)
|
|
3546
|
+
});
|
|
3547
|
+
if (!res.ok) {
|
|
3548
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3549
|
+
throw new Error(`Failed to create MCP (${res.status}): ${errText}`);
|
|
3550
|
+
}
|
|
3551
|
+
const created = await res.json();
|
|
3552
|
+
setMcps((prev) => [created, ...prev]);
|
|
3553
|
+
return created;
|
|
3554
|
+
} catch (err) {
|
|
3555
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3556
|
+
setError(errorObj);
|
|
3557
|
+
throw errorObj;
|
|
3558
|
+
}
|
|
3559
|
+
},
|
|
3560
|
+
[fetchWithAuth]
|
|
3561
|
+
);
|
|
3562
|
+
const updateMcp = useCallback15(
|
|
3563
|
+
async (mcpId, input) => {
|
|
3564
|
+
setError(null);
|
|
3565
|
+
try {
|
|
3566
|
+
const res = await fetchWithAuth(`/mcps/${mcpId}`, {
|
|
3567
|
+
method: "PATCH",
|
|
3568
|
+
headers: { "Content-Type": "application/json" },
|
|
3569
|
+
body: JSON.stringify(input)
|
|
3570
|
+
});
|
|
3571
|
+
if (!res.ok) {
|
|
3572
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3573
|
+
throw new Error(`Failed to update MCP (${res.status}): ${errText}`);
|
|
3574
|
+
}
|
|
3575
|
+
const updated = await res.json();
|
|
3576
|
+
setMcps((prev) => prev.map((m) => m._id === mcpId ? updated : m));
|
|
3577
|
+
return updated;
|
|
3578
|
+
} catch (err) {
|
|
3579
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3580
|
+
setError(errorObj);
|
|
3581
|
+
throw errorObj;
|
|
3582
|
+
}
|
|
3583
|
+
},
|
|
3584
|
+
[fetchWithAuth]
|
|
3585
|
+
);
|
|
3586
|
+
const deleteMcp = useCallback15(
|
|
3587
|
+
async (mcpId) => {
|
|
3588
|
+
setError(null);
|
|
3589
|
+
try {
|
|
3590
|
+
const res = await fetchWithAuth(`/mcps/${mcpId}`, { method: "DELETE" });
|
|
3591
|
+
if (!res.ok) {
|
|
3592
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3593
|
+
throw new Error(`Failed to delete MCP (${res.status}): ${errText}`);
|
|
3594
|
+
}
|
|
3595
|
+
setMcps((prev) => prev.filter((m) => m._id !== mcpId));
|
|
3596
|
+
} catch (err) {
|
|
3597
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3598
|
+
setError(errorObj);
|
|
3599
|
+
throw errorObj;
|
|
3600
|
+
}
|
|
3601
|
+
},
|
|
3602
|
+
[fetchWithAuth]
|
|
3603
|
+
);
|
|
3604
|
+
const bulkDeleteMcps = useCallback15(
|
|
3605
|
+
async (ids) => {
|
|
3606
|
+
setError(null);
|
|
3607
|
+
try {
|
|
3608
|
+
const res = await fetchWithAuth("/mcps/bulk-delete", {
|
|
3609
|
+
method: "POST",
|
|
3610
|
+
headers: { "Content-Type": "application/json" },
|
|
3611
|
+
body: JSON.stringify({ ids })
|
|
3612
|
+
});
|
|
3613
|
+
if (!res.ok) {
|
|
3614
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3615
|
+
throw new Error(`Failed to bulk-delete MCPs (${res.status}): ${errText}`);
|
|
3616
|
+
}
|
|
3617
|
+
const result = await res.json();
|
|
3618
|
+
const deletedSet = new Set(result.deleted);
|
|
3619
|
+
setMcps((prev) => prev.filter((m) => !deletedSet.has(m._id)));
|
|
3620
|
+
return result;
|
|
3621
|
+
} catch (err) {
|
|
3622
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3623
|
+
setError(errorObj);
|
|
3624
|
+
throw errorObj;
|
|
3625
|
+
}
|
|
3626
|
+
},
|
|
3627
|
+
[fetchWithAuth]
|
|
3628
|
+
);
|
|
3629
|
+
const testConnection = useCallback15(
|
|
3630
|
+
async (mcpId) => {
|
|
3631
|
+
setError(null);
|
|
3632
|
+
try {
|
|
3633
|
+
const res = await fetchWithAuth(`/mcps/${mcpId}/test`, { method: "POST" });
|
|
3634
|
+
if (!res.ok) {
|
|
3635
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3636
|
+
throw new Error(`Failed to test MCP connection (${res.status}): ${errText}`);
|
|
3637
|
+
}
|
|
3638
|
+
const result = await res.json();
|
|
3639
|
+
setMcps(
|
|
3640
|
+
(prev) => prev.map(
|
|
3641
|
+
(m) => m._id === mcpId ? { ...m, tools: result.tools, resources: result.resources, resourceTemplates: result.resourceTemplates } : m
|
|
3642
|
+
)
|
|
3643
|
+
);
|
|
3644
|
+
return result;
|
|
3645
|
+
} catch (err) {
|
|
3646
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3647
|
+
setError(errorObj);
|
|
3648
|
+
throw errorObj;
|
|
3649
|
+
}
|
|
3650
|
+
},
|
|
3651
|
+
[fetchWithAuth]
|
|
3652
|
+
);
|
|
3653
|
+
useEffect14(() => {
|
|
3654
|
+
if (autoFetch) void fetchMcps();
|
|
3655
|
+
}, [autoFetch, fetchMcps]);
|
|
3656
|
+
return {
|
|
3657
|
+
mcps,
|
|
3658
|
+
pagination,
|
|
3659
|
+
isLoading,
|
|
3660
|
+
error,
|
|
3661
|
+
refetch: fetchMcps,
|
|
3662
|
+
getMcp,
|
|
3663
|
+
createMcp,
|
|
3664
|
+
updateMcp,
|
|
3665
|
+
deleteMcp,
|
|
3666
|
+
bulkDeleteMcps,
|
|
3667
|
+
testConnection
|
|
3668
|
+
};
|
|
3669
|
+
}
|
|
3670
|
+
|
|
3124
3671
|
// src/hooks/useWorkflows.ts
|
|
3125
|
-
import { useCallback as
|
|
3672
|
+
import { useCallback as useCallback16, useEffect as useEffect15, useState as useState15 } from "react";
|
|
3126
3673
|
function useWorkflows(options) {
|
|
3127
3674
|
const opts = typeof options === "boolean" ? { autoFetch: options } : options ?? {};
|
|
3128
|
-
const { autoFetch = true, search,
|
|
3675
|
+
const { autoFetch = true, search, scope, visibility, isEnabled, page, limit } = opts;
|
|
3129
3676
|
const { fetchWithAuth } = usePersonaContext();
|
|
3130
|
-
const [workflows, setWorkflows] =
|
|
3131
|
-
const [pagination, setPagination] =
|
|
3677
|
+
const [workflows, setWorkflows] = useState15([]);
|
|
3678
|
+
const [pagination, setPagination] = useState15({
|
|
3132
3679
|
page: page ?? 1,
|
|
3133
3680
|
limit: limit ?? 20,
|
|
3134
3681
|
total: 0,
|
|
3135
3682
|
totalPages: 0
|
|
3136
3683
|
});
|
|
3137
|
-
const [isLoading, setIsLoading] =
|
|
3138
|
-
const [error, setError] =
|
|
3139
|
-
const fetchWorkflows =
|
|
3684
|
+
const [isLoading, setIsLoading] = useState15(false);
|
|
3685
|
+
const [error, setError] = useState15(null);
|
|
3686
|
+
const fetchWorkflows = useCallback16(async () => {
|
|
3140
3687
|
setIsLoading(true);
|
|
3141
3688
|
setError(null);
|
|
3142
3689
|
try {
|
|
3143
3690
|
const params = new URLSearchParams();
|
|
3144
3691
|
if (search) params.set("search", search);
|
|
3145
|
-
if (
|
|
3692
|
+
if (scope) params.set("scope", scope);
|
|
3693
|
+
if (visibility) params.set("visibility", visibility);
|
|
3694
|
+
if (isEnabled !== void 0) params.set("isEnabled", String(isEnabled));
|
|
3146
3695
|
if (page) params.set("page", String(page));
|
|
3147
3696
|
if (limit) params.set("limit", String(limit));
|
|
3148
3697
|
const queryStr = params.toString() ? `?${params.toString()}` : "";
|
|
@@ -3151,7 +3700,7 @@ function useWorkflows(options) {
|
|
|
3151
3700
|
throw new Error(`Failed to list workflows: ${res.statusText}`);
|
|
3152
3701
|
}
|
|
3153
3702
|
const data = await res.json();
|
|
3154
|
-
const items = Array.isArray(data) ? data : data?.items
|
|
3703
|
+
const items = Array.isArray(data) ? data : data?.items ?? [];
|
|
3155
3704
|
setWorkflows(items);
|
|
3156
3705
|
if (data?.pagination) {
|
|
3157
3706
|
setPagination({
|
|
@@ -3179,8 +3728,8 @@ function useWorkflows(options) {
|
|
|
3179
3728
|
} finally {
|
|
3180
3729
|
setIsLoading(false);
|
|
3181
3730
|
}
|
|
3182
|
-
}, [fetchWithAuth, search,
|
|
3183
|
-
const createWorkflow =
|
|
3731
|
+
}, [fetchWithAuth, search, scope, visibility, isEnabled, page, limit]);
|
|
3732
|
+
const createWorkflow = useCallback16(
|
|
3184
3733
|
async (input) => {
|
|
3185
3734
|
setError(null);
|
|
3186
3735
|
try {
|
|
@@ -3204,7 +3753,7 @@ function useWorkflows(options) {
|
|
|
3204
3753
|
},
|
|
3205
3754
|
[fetchWithAuth]
|
|
3206
3755
|
);
|
|
3207
|
-
|
|
3756
|
+
useEffect15(() => {
|
|
3208
3757
|
if (autoFetch) {
|
|
3209
3758
|
void fetchWorkflows();
|
|
3210
3759
|
}
|
|
@@ -3220,17 +3769,17 @@ function useWorkflows(options) {
|
|
|
3220
3769
|
}
|
|
3221
3770
|
|
|
3222
3771
|
// src/hooks/useWorkflow.ts
|
|
3223
|
-
import { useCallback as
|
|
3772
|
+
import { useCallback as useCallback17, useEffect as useEffect16, useState as useState16 } from "react";
|
|
3224
3773
|
function useWorkflow(workflowId, options) {
|
|
3225
3774
|
const opts = typeof options === "boolean" ? { autoFetch: options } : options ?? {};
|
|
3226
3775
|
const { autoFetch = true } = opts;
|
|
3227
3776
|
const { fetchWithAuth } = usePersonaContext();
|
|
3228
|
-
const [workflow, setWorkflow] =
|
|
3229
|
-
const [versions, setVersions] =
|
|
3230
|
-
const [mermaid, setMermaid] =
|
|
3231
|
-
const [isLoading, setIsLoading] =
|
|
3232
|
-
const [error, setError] =
|
|
3233
|
-
const fetchWorkflow =
|
|
3777
|
+
const [workflow, setWorkflow] = useState16(null);
|
|
3778
|
+
const [versions, setVersions] = useState16([]);
|
|
3779
|
+
const [mermaid, setMermaid] = useState16(null);
|
|
3780
|
+
const [isLoading, setIsLoading] = useState16(false);
|
|
3781
|
+
const [error, setError] = useState16(null);
|
|
3782
|
+
const fetchWorkflow = useCallback17(async () => {
|
|
3234
3783
|
if (!workflowId) return null;
|
|
3235
3784
|
setIsLoading(true);
|
|
3236
3785
|
setError(null);
|
|
@@ -3250,20 +3799,31 @@ function useWorkflow(workflowId, options) {
|
|
|
3250
3799
|
setIsLoading(false);
|
|
3251
3800
|
}
|
|
3252
3801
|
}, [fetchWithAuth, workflowId]);
|
|
3253
|
-
const fetchVersions =
|
|
3802
|
+
const fetchVersions = useCallback17(async () => {
|
|
3254
3803
|
if (!workflowId) return [];
|
|
3255
3804
|
try {
|
|
3256
3805
|
const res = await fetchWithAuth(`/workflows/${workflowId}/versions`);
|
|
3257
3806
|
if (!res.ok) return [];
|
|
3258
3807
|
const data = await res.json();
|
|
3259
|
-
const items = Array.isArray(data) ? data : data?.items
|
|
3808
|
+
const items = Array.isArray(data) ? data : data?.items ?? [];
|
|
3260
3809
|
setVersions(items);
|
|
3261
3810
|
return items;
|
|
3262
3811
|
} catch {
|
|
3263
3812
|
return [];
|
|
3264
3813
|
}
|
|
3265
3814
|
}, [fetchWithAuth, workflowId]);
|
|
3266
|
-
const
|
|
3815
|
+
const getVersion = useCallback17(
|
|
3816
|
+
async (version) => {
|
|
3817
|
+
if (!workflowId) throw new Error("Workflow ID is required");
|
|
3818
|
+
const res = await fetchWithAuth(`/workflows/${workflowId}/versions/${version}`);
|
|
3819
|
+
if (!res.ok) {
|
|
3820
|
+
throw new Error(`Failed to fetch workflow version (${res.status}): ${res.statusText}`);
|
|
3821
|
+
}
|
|
3822
|
+
return await res.json();
|
|
3823
|
+
},
|
|
3824
|
+
[fetchWithAuth, workflowId]
|
|
3825
|
+
);
|
|
3826
|
+
const fetchMermaid = useCallback17(async () => {
|
|
3267
3827
|
if (!workflowId) return "";
|
|
3268
3828
|
try {
|
|
3269
3829
|
const res = await fetchWithAuth(`/workflows/${workflowId}/mermaid`);
|
|
@@ -3276,18 +3836,18 @@ function useWorkflow(workflowId, options) {
|
|
|
3276
3836
|
return "";
|
|
3277
3837
|
}
|
|
3278
3838
|
}, [fetchWithAuth, workflowId]);
|
|
3279
|
-
const
|
|
3280
|
-
async (
|
|
3839
|
+
const updateWorkflow = useCallback17(
|
|
3840
|
+
async (input) => {
|
|
3281
3841
|
if (!workflowId) throw new Error("Workflow ID is required");
|
|
3282
3842
|
setError(null);
|
|
3283
|
-
const res = await fetchWithAuth(`/workflows/${workflowId}
|
|
3284
|
-
method: "
|
|
3843
|
+
const res = await fetchWithAuth(`/workflows/${workflowId}`, {
|
|
3844
|
+
method: "PATCH",
|
|
3285
3845
|
headers: { "Content-Type": "application/json" },
|
|
3286
|
-
body: JSON.stringify(
|
|
3846
|
+
body: JSON.stringify(input)
|
|
3287
3847
|
});
|
|
3288
3848
|
if (!res.ok) {
|
|
3289
3849
|
const errText = await res.text().catch(() => res.statusText);
|
|
3290
|
-
throw new Error(`Failed to
|
|
3850
|
+
throw new Error(`Failed to update workflow (${res.status}): ${errText}`);
|
|
3291
3851
|
}
|
|
3292
3852
|
const updated = await res.json();
|
|
3293
3853
|
setWorkflow(updated);
|
|
@@ -3295,27 +3855,41 @@ function useWorkflow(workflowId, options) {
|
|
|
3295
3855
|
},
|
|
3296
3856
|
[fetchWithAuth, workflowId]
|
|
3297
3857
|
);
|
|
3298
|
-
const
|
|
3299
|
-
async (
|
|
3858
|
+
const saveDraft = useCallback17(
|
|
3859
|
+
async (draft) => {
|
|
3300
3860
|
if (!workflowId) throw new Error("Workflow ID is required");
|
|
3301
3861
|
setError(null);
|
|
3302
|
-
const res = await fetchWithAuth(`/workflows/${workflowId}/
|
|
3303
|
-
method: "
|
|
3862
|
+
const res = await fetchWithAuth(`/workflows/${workflowId}/draft`, {
|
|
3863
|
+
method: "PUT",
|
|
3304
3864
|
headers: { "Content-Type": "application/json" },
|
|
3305
|
-
body: JSON.stringify(
|
|
3865
|
+
body: JSON.stringify(draft)
|
|
3306
3866
|
});
|
|
3307
3867
|
if (!res.ok) {
|
|
3308
3868
|
const errText = await res.text().catch(() => res.statusText);
|
|
3309
|
-
throw new Error(`Failed to
|
|
3869
|
+
throw new Error(`Failed to save draft (${res.status}): ${errText}`);
|
|
3310
3870
|
}
|
|
3311
|
-
const
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
return versionResult;
|
|
3871
|
+
const updated = await res.json();
|
|
3872
|
+
setWorkflow(updated);
|
|
3873
|
+
return updated;
|
|
3315
3874
|
},
|
|
3316
|
-
[fetchWithAuth, workflowId
|
|
3875
|
+
[fetchWithAuth, workflowId]
|
|
3317
3876
|
);
|
|
3318
|
-
const
|
|
3877
|
+
const publish = useCallback17(async () => {
|
|
3878
|
+
if (!workflowId) throw new Error("Workflow ID is required");
|
|
3879
|
+
setError(null);
|
|
3880
|
+
const res = await fetchWithAuth(`/workflows/${workflowId}/publish`, {
|
|
3881
|
+
method: "POST"
|
|
3882
|
+
});
|
|
3883
|
+
if (!res.ok) {
|
|
3884
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3885
|
+
throw new Error(`Failed to publish workflow (${res.status}): ${errText}`);
|
|
3886
|
+
}
|
|
3887
|
+
const versionResult = await res.json();
|
|
3888
|
+
void fetchWorkflow();
|
|
3889
|
+
void fetchVersions();
|
|
3890
|
+
return versionResult;
|
|
3891
|
+
}, [fetchWithAuth, workflowId, fetchWorkflow, fetchVersions]);
|
|
3892
|
+
const deleteWorkflow = useCallback17(async () => {
|
|
3319
3893
|
if (!workflowId) throw new Error("Workflow ID is required");
|
|
3320
3894
|
setError(null);
|
|
3321
3895
|
const res = await fetchWithAuth(`/workflows/${workflowId}`, {
|
|
@@ -3326,7 +3900,7 @@ function useWorkflow(workflowId, options) {
|
|
|
3326
3900
|
}
|
|
3327
3901
|
setWorkflow(null);
|
|
3328
3902
|
}, [fetchWithAuth, workflowId]);
|
|
3329
|
-
|
|
3903
|
+
useEffect16(() => {
|
|
3330
3904
|
if (autoFetch && workflowId) {
|
|
3331
3905
|
void fetchWorkflow();
|
|
3332
3906
|
}
|
|
@@ -3339,7 +3913,9 @@ function useWorkflow(workflowId, options) {
|
|
|
3339
3913
|
error,
|
|
3340
3914
|
refetch: fetchWorkflow,
|
|
3341
3915
|
fetchVersions,
|
|
3916
|
+
getVersion,
|
|
3342
3917
|
fetchMermaid,
|
|
3918
|
+
updateWorkflow,
|
|
3343
3919
|
saveDraft,
|
|
3344
3920
|
publish,
|
|
3345
3921
|
deleteWorkflow
|
|
@@ -3347,25 +3923,25 @@ function useWorkflow(workflowId, options) {
|
|
|
3347
3923
|
}
|
|
3348
3924
|
|
|
3349
3925
|
// src/hooks/useWorkflowStream.ts
|
|
3350
|
-
import { useCallback as
|
|
3926
|
+
import { useCallback as useCallback18, useEffect as useEffect17, useRef as useRef4, useState as useState17 } from "react";
|
|
3351
3927
|
function useWorkflowStream(workflowId, options) {
|
|
3352
3928
|
const { baseUrl, getAuthToken, fetchWithAuth, logger } = usePersonaContext();
|
|
3353
|
-
const [status, setStatus] =
|
|
3354
|
-
const [runId, setRunId] =
|
|
3355
|
-
const [activeNodeId, setActiveNodeId] =
|
|
3356
|
-
const [nodeRuns, setNodeRuns] =
|
|
3929
|
+
const [status, setStatus] = useState17("idle");
|
|
3930
|
+
const [runId, setRunId] = useState17(null);
|
|
3931
|
+
const [activeNodeId, setActiveNodeId] = useState17(null);
|
|
3932
|
+
const [nodeRuns, setNodeRuns] = useState17(
|
|
3357
3933
|
{}
|
|
3358
3934
|
);
|
|
3359
|
-
const [text, setText] =
|
|
3360
|
-
const [output, setOutput] =
|
|
3361
|
-
const [error, setError] =
|
|
3362
|
-
const [events, setEvents] =
|
|
3935
|
+
const [text, setText] = useState17("");
|
|
3936
|
+
const [output, setOutput] = useState17(null);
|
|
3937
|
+
const [error, setError] = useState17(null);
|
|
3938
|
+
const [events, setEvents] = useState17([]);
|
|
3363
3939
|
const abortControllerRef = useRef4(null);
|
|
3364
3940
|
const currentRunIdRef = useRef4(null);
|
|
3365
3941
|
currentRunIdRef.current = runId;
|
|
3366
3942
|
const optionsRef = useRef4(options);
|
|
3367
3943
|
optionsRef.current = options;
|
|
3368
|
-
const cancel =
|
|
3944
|
+
const cancel = useCallback18(async () => {
|
|
3369
3945
|
if (abortControllerRef.current) {
|
|
3370
3946
|
abortControllerRef.current.abort();
|
|
3371
3947
|
abortControllerRef.current = null;
|
|
@@ -3386,7 +3962,7 @@ function useWorkflowStream(workflowId, options) {
|
|
|
3386
3962
|
setStatus("cancelled");
|
|
3387
3963
|
setActiveNodeId(null);
|
|
3388
3964
|
}, [fetchWithAuth, logger]);
|
|
3389
|
-
const reset =
|
|
3965
|
+
const reset = useCallback18(() => {
|
|
3390
3966
|
if (abortControllerRef.current) {
|
|
3391
3967
|
abortControllerRef.current.abort();
|
|
3392
3968
|
abortControllerRef.current = null;
|
|
@@ -3400,7 +3976,7 @@ function useWorkflowStream(workflowId, options) {
|
|
|
3400
3976
|
setError(null);
|
|
3401
3977
|
setEvents([]);
|
|
3402
3978
|
}, []);
|
|
3403
|
-
const processStream =
|
|
3979
|
+
const processStream = useCallback18(
|
|
3404
3980
|
async (url, method, body, targetRunId) => {
|
|
3405
3981
|
if (abortControllerRef.current) {
|
|
3406
3982
|
abortControllerRef.current.abort();
|
|
@@ -3565,7 +4141,7 @@ function useWorkflowStream(workflowId, options) {
|
|
|
3565
4141
|
},
|
|
3566
4142
|
[getAuthToken]
|
|
3567
4143
|
);
|
|
3568
|
-
const start =
|
|
4144
|
+
const start = useCallback18(
|
|
3569
4145
|
async (input, opts) => {
|
|
3570
4146
|
const targetWfId = opts?.workflowId || workflowId;
|
|
3571
4147
|
if (!targetWfId) {
|
|
@@ -3586,7 +4162,7 @@ function useWorkflowStream(workflowId, options) {
|
|
|
3586
4162
|
},
|
|
3587
4163
|
[workflowId, baseUrl, processStream]
|
|
3588
4164
|
);
|
|
3589
|
-
const resume =
|
|
4165
|
+
const resume = useCallback18(
|
|
3590
4166
|
async (targetRunId, sinceSeq) => {
|
|
3591
4167
|
if (!targetRunId) {
|
|
3592
4168
|
throw new Error("Run ID is required to resume stream");
|
|
@@ -3599,7 +4175,7 @@ function useWorkflowStream(workflowId, options) {
|
|
|
3599
4175
|
},
|
|
3600
4176
|
[baseUrl, processStream]
|
|
3601
4177
|
);
|
|
3602
|
-
|
|
4178
|
+
useEffect17(() => {
|
|
3603
4179
|
return () => {
|
|
3604
4180
|
if (abortControllerRef.current) {
|
|
3605
4181
|
abortControllerRef.current.abort();
|
|
@@ -3624,21 +4200,21 @@ function useWorkflowStream(workflowId, options) {
|
|
|
3624
4200
|
}
|
|
3625
4201
|
|
|
3626
4202
|
// src/hooks/useWorkflowRuns.ts
|
|
3627
|
-
import { useCallback as
|
|
4203
|
+
import { useCallback as useCallback19, useEffect as useEffect18, useState as useState18 } from "react";
|
|
3628
4204
|
function useWorkflowRuns(workflowId, options) {
|
|
3629
4205
|
const opts = typeof options === "boolean" ? { autoFetch: options } : options ?? {};
|
|
3630
4206
|
const { autoFetch = true, page = 1, limit = 20 } = opts;
|
|
3631
4207
|
const { fetchWithAuth } = usePersonaContext();
|
|
3632
|
-
const [runs, setRuns] =
|
|
3633
|
-
const [pagination, setPagination] =
|
|
4208
|
+
const [runs, setRuns] = useState18([]);
|
|
4209
|
+
const [pagination, setPagination] = useState18({
|
|
3634
4210
|
page,
|
|
3635
4211
|
limit,
|
|
3636
4212
|
total: 0,
|
|
3637
4213
|
totalPages: 0
|
|
3638
4214
|
});
|
|
3639
|
-
const [isLoading, setIsLoading] =
|
|
3640
|
-
const [error, setError] =
|
|
3641
|
-
const fetchRuns =
|
|
4215
|
+
const [isLoading, setIsLoading] = useState18(false);
|
|
4216
|
+
const [error, setError] = useState18(null);
|
|
4217
|
+
const fetchRuns = useCallback19(async () => {
|
|
3642
4218
|
if (!workflowId) return [];
|
|
3643
4219
|
setIsLoading(true);
|
|
3644
4220
|
setError(null);
|
|
@@ -3649,14 +4225,16 @@ function useWorkflowRuns(workflowId, options) {
|
|
|
3649
4225
|
throw new Error(`Failed to list workflow runs: ${res.statusText}`);
|
|
3650
4226
|
}
|
|
3651
4227
|
const data = await res.json();
|
|
3652
|
-
const items = Array.isArray(data) ? data : data?.items
|
|
4228
|
+
const items = Array.isArray(data) ? data : data?.items ?? [];
|
|
3653
4229
|
setRuns(items);
|
|
3654
4230
|
if (data?.pagination) {
|
|
3655
4231
|
setPagination({
|
|
3656
4232
|
page: data.pagination.page ?? page,
|
|
3657
4233
|
limit: data.pagination.limit ?? limit,
|
|
3658
4234
|
total: data.pagination.total ?? items.length,
|
|
3659
|
-
|
|
4235
|
+
// Backend's paginationEnvelope() names this field `pages`, not
|
|
4236
|
+
// `totalPages`.
|
|
4237
|
+
totalPages: data.pagination.pages ?? 1
|
|
3660
4238
|
});
|
|
3661
4239
|
}
|
|
3662
4240
|
return items;
|
|
@@ -3668,7 +4246,7 @@ function useWorkflowRuns(workflowId, options) {
|
|
|
3668
4246
|
setIsLoading(false);
|
|
3669
4247
|
}
|
|
3670
4248
|
}, [fetchWithAuth, workflowId, page, limit]);
|
|
3671
|
-
const getRun =
|
|
4249
|
+
const getRun = useCallback19(
|
|
3672
4250
|
async (runId) => {
|
|
3673
4251
|
if (!runId) throw new Error("Run ID is required");
|
|
3674
4252
|
const res = await fetchWithAuth(`/workflows/runs/${runId}`);
|
|
@@ -3679,7 +4257,7 @@ function useWorkflowRuns(workflowId, options) {
|
|
|
3679
4257
|
},
|
|
3680
4258
|
[fetchWithAuth]
|
|
3681
4259
|
);
|
|
3682
|
-
const cancelRun =
|
|
4260
|
+
const cancelRun = useCallback19(
|
|
3683
4261
|
async (runId) => {
|
|
3684
4262
|
if (!runId) throw new Error("Run ID is required");
|
|
3685
4263
|
const res = await fetchWithAuth(`/workflows/runs/${runId}/cancel`, {
|
|
@@ -3694,7 +4272,7 @@ function useWorkflowRuns(workflowId, options) {
|
|
|
3694
4272
|
},
|
|
3695
4273
|
[fetchWithAuth]
|
|
3696
4274
|
);
|
|
3697
|
-
|
|
4275
|
+
useEffect18(() => {
|
|
3698
4276
|
if (autoFetch && workflowId) {
|
|
3699
4277
|
void fetchRuns();
|
|
3700
4278
|
}
|
|
@@ -3735,7 +4313,9 @@ export {
|
|
|
3735
4313
|
useChat,
|
|
3736
4314
|
useConnection,
|
|
3737
4315
|
useFiles,
|
|
4316
|
+
useKnowledgeBases,
|
|
3738
4317
|
useMcp,
|
|
4318
|
+
useMcpAdmin,
|
|
3739
4319
|
useMcpConnections,
|
|
3740
4320
|
useMemory,
|
|
3741
4321
|
usePersonaContext,
|
|
@@ -3746,6 +4326,7 @@ export {
|
|
|
3746
4326
|
useWorkflow,
|
|
3747
4327
|
useWorkflowRuns,
|
|
3748
4328
|
useWorkflowStream,
|
|
3749
|
-
useWorkflows
|
|
4329
|
+
useWorkflows,
|
|
4330
|
+
useWorkspaceFiles
|
|
3750
4331
|
};
|
|
3751
4332
|
//# sourceMappingURL=index.js.map
|