@personaai/react 0.11.0 → 0.14.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 +550 -70
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +424 -46
- package/dist/index.d.ts +424 -46
- package/dist/index.js +545 -67
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3121,28 +3121,475 @@ function useRcpSources(options = {}) {
|
|
|
3121
3121
|
};
|
|
3122
3122
|
}
|
|
3123
3123
|
|
|
3124
|
-
// src/hooks/
|
|
3124
|
+
// src/hooks/useKnowledgeBases.ts
|
|
3125
3125
|
import { useCallback as useCallback13, useEffect as useEffect12, useState as useState12 } from "react";
|
|
3126
|
+
function useKnowledgeBases(options = {}) {
|
|
3127
|
+
const { autoFetch = true, page, limit, search, scope } = options;
|
|
3128
|
+
const { fetchWithAuth } = usePersonaContext();
|
|
3129
|
+
const [knowledgeBases, setKnowledgeBases] = useState12([]);
|
|
3130
|
+
const [pagination, setPagination] = useState12({
|
|
3131
|
+
total: 0,
|
|
3132
|
+
page: page ?? 1,
|
|
3133
|
+
limit: limit ?? 20,
|
|
3134
|
+
pages: 0
|
|
3135
|
+
});
|
|
3136
|
+
const [isLoading, setIsLoading] = useState12(false);
|
|
3137
|
+
const [isUploading, setIsUploading] = useState12(false);
|
|
3138
|
+
const [error, setError] = useState12(null);
|
|
3139
|
+
const fetchKnowledgeBases = useCallback13(async () => {
|
|
3140
|
+
setIsLoading(true);
|
|
3141
|
+
setError(null);
|
|
3142
|
+
try {
|
|
3143
|
+
const query = new URLSearchParams();
|
|
3144
|
+
if (page) query.set("page", String(page));
|
|
3145
|
+
if (limit) query.set("limit", String(limit));
|
|
3146
|
+
if (search) query.set("search", search);
|
|
3147
|
+
if (scope) query.set("scope", scope);
|
|
3148
|
+
const queryStr = query.toString() ? `?${query.toString()}` : "";
|
|
3149
|
+
const res = await fetchWithAuth(`/knowledge${queryStr}`);
|
|
3150
|
+
if (!res.ok) throw new Error(`Failed to list knowledge bases: ${res.statusText}`);
|
|
3151
|
+
const data = await res.json();
|
|
3152
|
+
const items = Array.isArray(data) ? data : data?.items ?? [];
|
|
3153
|
+
setKnowledgeBases(items);
|
|
3154
|
+
setPagination(
|
|
3155
|
+
data?.pagination ?? { total: items.length, page: 1, limit: items.length, pages: 1 }
|
|
3156
|
+
);
|
|
3157
|
+
return items;
|
|
3158
|
+
} catch (err) {
|
|
3159
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3160
|
+
setError(errorObj);
|
|
3161
|
+
return [];
|
|
3162
|
+
} finally {
|
|
3163
|
+
setIsLoading(false);
|
|
3164
|
+
}
|
|
3165
|
+
}, [fetchWithAuth, page, limit, search, scope]);
|
|
3166
|
+
const getKnowledgeBase = useCallback13(
|
|
3167
|
+
async (kbId) => {
|
|
3168
|
+
const res = await fetchWithAuth(`/knowledge/${kbId}`);
|
|
3169
|
+
if (!res.ok) throw new Error(`Failed to fetch knowledge base: ${res.statusText}`);
|
|
3170
|
+
return res.json();
|
|
3171
|
+
},
|
|
3172
|
+
[fetchWithAuth]
|
|
3173
|
+
);
|
|
3174
|
+
const createKnowledgeBase = useCallback13(
|
|
3175
|
+
async (input) => {
|
|
3176
|
+
setError(null);
|
|
3177
|
+
try {
|
|
3178
|
+
const res = await fetchWithAuth("/knowledge", {
|
|
3179
|
+
method: "POST",
|
|
3180
|
+
headers: { "Content-Type": "application/json" },
|
|
3181
|
+
body: JSON.stringify(input)
|
|
3182
|
+
});
|
|
3183
|
+
if (!res.ok) {
|
|
3184
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3185
|
+
throw new Error(`Failed to create knowledge base (${res.status}): ${errText}`);
|
|
3186
|
+
}
|
|
3187
|
+
const created = await res.json();
|
|
3188
|
+
setKnowledgeBases((prev) => [created, ...prev]);
|
|
3189
|
+
return created;
|
|
3190
|
+
} catch (err) {
|
|
3191
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3192
|
+
setError(errorObj);
|
|
3193
|
+
throw errorObj;
|
|
3194
|
+
}
|
|
3195
|
+
},
|
|
3196
|
+
[fetchWithAuth]
|
|
3197
|
+
);
|
|
3198
|
+
const updateKnowledgeBase = useCallback13(
|
|
3199
|
+
async (kbId, input) => {
|
|
3200
|
+
setError(null);
|
|
3201
|
+
try {
|
|
3202
|
+
const res = await fetchWithAuth(`/knowledge/${kbId}`, {
|
|
3203
|
+
method: "PATCH",
|
|
3204
|
+
headers: { "Content-Type": "application/json" },
|
|
3205
|
+
body: JSON.stringify(input)
|
|
3206
|
+
});
|
|
3207
|
+
if (!res.ok) {
|
|
3208
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3209
|
+
throw new Error(`Failed to update knowledge base (${res.status}): ${errText}`);
|
|
3210
|
+
}
|
|
3211
|
+
const updated = await res.json();
|
|
3212
|
+
setKnowledgeBases((prev) => prev.map((kb) => kb._id === kbId ? updated : kb));
|
|
3213
|
+
return updated;
|
|
3214
|
+
} catch (err) {
|
|
3215
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3216
|
+
setError(errorObj);
|
|
3217
|
+
throw errorObj;
|
|
3218
|
+
}
|
|
3219
|
+
},
|
|
3220
|
+
[fetchWithAuth]
|
|
3221
|
+
);
|
|
3222
|
+
const deleteKnowledgeBase = useCallback13(
|
|
3223
|
+
async (kbId) => {
|
|
3224
|
+
setError(null);
|
|
3225
|
+
try {
|
|
3226
|
+
const res = await fetchWithAuth(`/knowledge/${kbId}`, { method: "DELETE" });
|
|
3227
|
+
if (!res.ok) {
|
|
3228
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3229
|
+
throw new Error(`Failed to delete knowledge base (${res.status}): ${errText}`);
|
|
3230
|
+
}
|
|
3231
|
+
setKnowledgeBases((prev) => prev.filter((kb) => kb._id !== kbId));
|
|
3232
|
+
} catch (err) {
|
|
3233
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3234
|
+
setError(errorObj);
|
|
3235
|
+
throw errorObj;
|
|
3236
|
+
}
|
|
3237
|
+
},
|
|
3238
|
+
[fetchWithAuth]
|
|
3239
|
+
);
|
|
3240
|
+
const bulkDeleteKnowledgeBases = useCallback13(
|
|
3241
|
+
async (ids) => {
|
|
3242
|
+
setError(null);
|
|
3243
|
+
try {
|
|
3244
|
+
const res = await fetchWithAuth("/knowledge/bulk-delete", {
|
|
3245
|
+
method: "POST",
|
|
3246
|
+
headers: { "Content-Type": "application/json" },
|
|
3247
|
+
body: JSON.stringify({ ids })
|
|
3248
|
+
});
|
|
3249
|
+
if (!res.ok) {
|
|
3250
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3251
|
+
throw new Error(`Failed to bulk-delete knowledge bases (${res.status}): ${errText}`);
|
|
3252
|
+
}
|
|
3253
|
+
const result = await res.json();
|
|
3254
|
+
const deletedSet = new Set(result.deleted);
|
|
3255
|
+
setKnowledgeBases((prev) => prev.filter((kb) => !deletedSet.has(kb._id)));
|
|
3256
|
+
return result;
|
|
3257
|
+
} catch (err) {
|
|
3258
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3259
|
+
setError(errorObj);
|
|
3260
|
+
throw errorObj;
|
|
3261
|
+
}
|
|
3262
|
+
},
|
|
3263
|
+
[fetchWithAuth]
|
|
3264
|
+
);
|
|
3265
|
+
const getKnowledgeBaseUsage = useCallback13(
|
|
3266
|
+
async (kbId) => {
|
|
3267
|
+
const res = await fetchWithAuth(`/knowledge/${kbId}/usage`);
|
|
3268
|
+
if (!res.ok) throw new Error(`Failed to fetch knowledge base usage: ${res.statusText}`);
|
|
3269
|
+
return res.json();
|
|
3270
|
+
},
|
|
3271
|
+
[fetchWithAuth]
|
|
3272
|
+
);
|
|
3273
|
+
const uploadDocuments = useCallback13(
|
|
3274
|
+
async (kbId, files) => {
|
|
3275
|
+
setIsUploading(true);
|
|
3276
|
+
setError(null);
|
|
3277
|
+
try {
|
|
3278
|
+
const body = new FormData();
|
|
3279
|
+
for (const file of files) {
|
|
3280
|
+
if (file.content instanceof Blob) {
|
|
3281
|
+
body.append("files", file.content, file.filename);
|
|
3282
|
+
} else {
|
|
3283
|
+
body.append("files", {
|
|
3284
|
+
uri: file.content.uri,
|
|
3285
|
+
name: file.content.name ?? file.filename,
|
|
3286
|
+
type: file.content.type ?? file.contentType
|
|
3287
|
+
});
|
|
3288
|
+
}
|
|
3289
|
+
}
|
|
3290
|
+
const res = await fetchWithAuth(`/knowledge/${kbId}/documents`, {
|
|
3291
|
+
method: "POST",
|
|
3292
|
+
body
|
|
3293
|
+
});
|
|
3294
|
+
if (!res.ok) {
|
|
3295
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3296
|
+
throw new Error(`Failed to upload documents (${res.status}): ${errText}`);
|
|
3297
|
+
}
|
|
3298
|
+
const result = await res.json();
|
|
3299
|
+
setKnowledgeBases(
|
|
3300
|
+
(prev) => prev.map(
|
|
3301
|
+
(kb) => kb._id === kbId ? { ...kb, documentCount: result.documentCount, chunkCount: result.chunkCount } : kb
|
|
3302
|
+
)
|
|
3303
|
+
);
|
|
3304
|
+
return result;
|
|
3305
|
+
} catch (err) {
|
|
3306
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3307
|
+
setError(errorObj);
|
|
3308
|
+
throw errorObj;
|
|
3309
|
+
} finally {
|
|
3310
|
+
setIsUploading(false);
|
|
3311
|
+
}
|
|
3312
|
+
},
|
|
3313
|
+
[fetchWithAuth]
|
|
3314
|
+
);
|
|
3315
|
+
const listDocuments = useCallback13(
|
|
3316
|
+
async (kbId) => {
|
|
3317
|
+
const res = await fetchWithAuth(`/knowledge/${kbId}/documents`);
|
|
3318
|
+
if (!res.ok) throw new Error(`Failed to list documents: ${res.statusText}`);
|
|
3319
|
+
return res.json();
|
|
3320
|
+
},
|
|
3321
|
+
[fetchWithAuth]
|
|
3322
|
+
);
|
|
3323
|
+
const deleteDocument = useCallback13(
|
|
3324
|
+
async (kbId, sourceName) => {
|
|
3325
|
+
setError(null);
|
|
3326
|
+
try {
|
|
3327
|
+
const res = await fetchWithAuth(
|
|
3328
|
+
`/knowledge/${kbId}/documents/${encodeURIComponent(sourceName)}`,
|
|
3329
|
+
{ method: "DELETE" }
|
|
3330
|
+
);
|
|
3331
|
+
if (!res.ok) {
|
|
3332
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3333
|
+
throw new Error(`Failed to delete document (${res.status}): ${errText}`);
|
|
3334
|
+
}
|
|
3335
|
+
const result = await res.json();
|
|
3336
|
+
setKnowledgeBases(
|
|
3337
|
+
(prev) => prev.map(
|
|
3338
|
+
(kb) => kb._id === kbId ? { ...kb, documentCount: result.remainingDocuments, chunkCount: result.remainingChunks } : kb
|
|
3339
|
+
)
|
|
3340
|
+
);
|
|
3341
|
+
return result;
|
|
3342
|
+
} catch (err) {
|
|
3343
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3344
|
+
setError(errorObj);
|
|
3345
|
+
throw errorObj;
|
|
3346
|
+
}
|
|
3347
|
+
},
|
|
3348
|
+
[fetchWithAuth]
|
|
3349
|
+
);
|
|
3350
|
+
const searchKnowledgeBase = useCallback13(
|
|
3351
|
+
async (kbId, query, opts) => {
|
|
3352
|
+
const res = await fetchWithAuth(`/knowledge/${kbId}/search`, {
|
|
3353
|
+
method: "POST",
|
|
3354
|
+
headers: { "Content-Type": "application/json" },
|
|
3355
|
+
body: JSON.stringify({ query, topK: opts?.topK })
|
|
3356
|
+
});
|
|
3357
|
+
if (!res.ok) {
|
|
3358
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3359
|
+
throw new Error(`Failed to search knowledge base (${res.status}): ${errText}`);
|
|
3360
|
+
}
|
|
3361
|
+
return res.json();
|
|
3362
|
+
},
|
|
3363
|
+
[fetchWithAuth]
|
|
3364
|
+
);
|
|
3365
|
+
useEffect12(() => {
|
|
3366
|
+
if (autoFetch) void fetchKnowledgeBases();
|
|
3367
|
+
}, [autoFetch, fetchKnowledgeBases]);
|
|
3368
|
+
return {
|
|
3369
|
+
knowledgeBases,
|
|
3370
|
+
pagination,
|
|
3371
|
+
isLoading,
|
|
3372
|
+
isUploading,
|
|
3373
|
+
error,
|
|
3374
|
+
refetch: fetchKnowledgeBases,
|
|
3375
|
+
getKnowledgeBase,
|
|
3376
|
+
createKnowledgeBase,
|
|
3377
|
+
updateKnowledgeBase,
|
|
3378
|
+
deleteKnowledgeBase,
|
|
3379
|
+
bulkDeleteKnowledgeBases,
|
|
3380
|
+
getKnowledgeBaseUsage,
|
|
3381
|
+
uploadDocuments,
|
|
3382
|
+
listDocuments,
|
|
3383
|
+
deleteDocument,
|
|
3384
|
+
search: searchKnowledgeBase
|
|
3385
|
+
};
|
|
3386
|
+
}
|
|
3387
|
+
|
|
3388
|
+
// src/hooks/useMcpAdmin.ts
|
|
3389
|
+
import { useCallback as useCallback14, useEffect as useEffect13, useState as useState13 } from "react";
|
|
3390
|
+
function useMcpAdmin(options = {}) {
|
|
3391
|
+
const { autoFetch = true, page, limit, search } = options;
|
|
3392
|
+
const { fetchWithAuth } = usePersonaContext();
|
|
3393
|
+
const [mcps, setMcps] = useState13([]);
|
|
3394
|
+
const [pagination, setPagination] = useState13({
|
|
3395
|
+
total: 0,
|
|
3396
|
+
page: page ?? 1,
|
|
3397
|
+
limit: limit ?? 20,
|
|
3398
|
+
pages: 0
|
|
3399
|
+
});
|
|
3400
|
+
const [isLoading, setIsLoading] = useState13(false);
|
|
3401
|
+
const [error, setError] = useState13(null);
|
|
3402
|
+
const fetchMcps = useCallback14(async () => {
|
|
3403
|
+
setIsLoading(true);
|
|
3404
|
+
setError(null);
|
|
3405
|
+
try {
|
|
3406
|
+
const query = new URLSearchParams();
|
|
3407
|
+
if (page) query.set("page", String(page));
|
|
3408
|
+
if (limit) query.set("limit", String(limit));
|
|
3409
|
+
if (search) query.set("search", search);
|
|
3410
|
+
query.set("scope", "mine");
|
|
3411
|
+
const res = await fetchWithAuth(`/mcps?${query.toString()}`);
|
|
3412
|
+
if (!res.ok) throw new Error(`Failed to list MCPs: ${res.statusText}`);
|
|
3413
|
+
const data = await res.json();
|
|
3414
|
+
const items = Array.isArray(data) ? data : data?.items ?? [];
|
|
3415
|
+
setMcps(items);
|
|
3416
|
+
setPagination(
|
|
3417
|
+
data?.pagination ?? { total: items.length, page: 1, limit: items.length, pages: 1 }
|
|
3418
|
+
);
|
|
3419
|
+
return items;
|
|
3420
|
+
} catch (err) {
|
|
3421
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3422
|
+
setError(errorObj);
|
|
3423
|
+
return [];
|
|
3424
|
+
} finally {
|
|
3425
|
+
setIsLoading(false);
|
|
3426
|
+
}
|
|
3427
|
+
}, [fetchWithAuth, page, limit, search]);
|
|
3428
|
+
const getMcp = useCallback14(
|
|
3429
|
+
async (mcpId) => {
|
|
3430
|
+
const res = await fetchWithAuth(`/mcps/${mcpId}`);
|
|
3431
|
+
if (!res.ok) throw new Error(`Failed to fetch MCP: ${res.statusText}`);
|
|
3432
|
+
return res.json();
|
|
3433
|
+
},
|
|
3434
|
+
[fetchWithAuth]
|
|
3435
|
+
);
|
|
3436
|
+
const createMcp = useCallback14(
|
|
3437
|
+
async (input) => {
|
|
3438
|
+
setError(null);
|
|
3439
|
+
try {
|
|
3440
|
+
const res = await fetchWithAuth("/mcps", {
|
|
3441
|
+
method: "POST",
|
|
3442
|
+
headers: { "Content-Type": "application/json" },
|
|
3443
|
+
body: JSON.stringify(input)
|
|
3444
|
+
});
|
|
3445
|
+
if (!res.ok) {
|
|
3446
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3447
|
+
throw new Error(`Failed to create MCP (${res.status}): ${errText}`);
|
|
3448
|
+
}
|
|
3449
|
+
const created = await res.json();
|
|
3450
|
+
setMcps((prev) => [created, ...prev]);
|
|
3451
|
+
return created;
|
|
3452
|
+
} catch (err) {
|
|
3453
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3454
|
+
setError(errorObj);
|
|
3455
|
+
throw errorObj;
|
|
3456
|
+
}
|
|
3457
|
+
},
|
|
3458
|
+
[fetchWithAuth]
|
|
3459
|
+
);
|
|
3460
|
+
const updateMcp = useCallback14(
|
|
3461
|
+
async (mcpId, input) => {
|
|
3462
|
+
setError(null);
|
|
3463
|
+
try {
|
|
3464
|
+
const res = await fetchWithAuth(`/mcps/${mcpId}`, {
|
|
3465
|
+
method: "PATCH",
|
|
3466
|
+
headers: { "Content-Type": "application/json" },
|
|
3467
|
+
body: JSON.stringify(input)
|
|
3468
|
+
});
|
|
3469
|
+
if (!res.ok) {
|
|
3470
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3471
|
+
throw new Error(`Failed to update MCP (${res.status}): ${errText}`);
|
|
3472
|
+
}
|
|
3473
|
+
const updated = await res.json();
|
|
3474
|
+
setMcps((prev) => prev.map((m) => m._id === mcpId ? updated : m));
|
|
3475
|
+
return updated;
|
|
3476
|
+
} catch (err) {
|
|
3477
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3478
|
+
setError(errorObj);
|
|
3479
|
+
throw errorObj;
|
|
3480
|
+
}
|
|
3481
|
+
},
|
|
3482
|
+
[fetchWithAuth]
|
|
3483
|
+
);
|
|
3484
|
+
const deleteMcp = useCallback14(
|
|
3485
|
+
async (mcpId) => {
|
|
3486
|
+
setError(null);
|
|
3487
|
+
try {
|
|
3488
|
+
const res = await fetchWithAuth(`/mcps/${mcpId}`, { method: "DELETE" });
|
|
3489
|
+
if (!res.ok) {
|
|
3490
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3491
|
+
throw new Error(`Failed to delete MCP (${res.status}): ${errText}`);
|
|
3492
|
+
}
|
|
3493
|
+
setMcps((prev) => prev.filter((m) => m._id !== mcpId));
|
|
3494
|
+
} catch (err) {
|
|
3495
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3496
|
+
setError(errorObj);
|
|
3497
|
+
throw errorObj;
|
|
3498
|
+
}
|
|
3499
|
+
},
|
|
3500
|
+
[fetchWithAuth]
|
|
3501
|
+
);
|
|
3502
|
+
const bulkDeleteMcps = useCallback14(
|
|
3503
|
+
async (ids) => {
|
|
3504
|
+
setError(null);
|
|
3505
|
+
try {
|
|
3506
|
+
const res = await fetchWithAuth("/mcps/bulk-delete", {
|
|
3507
|
+
method: "POST",
|
|
3508
|
+
headers: { "Content-Type": "application/json" },
|
|
3509
|
+
body: JSON.stringify({ ids })
|
|
3510
|
+
});
|
|
3511
|
+
if (!res.ok) {
|
|
3512
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3513
|
+
throw new Error(`Failed to bulk-delete MCPs (${res.status}): ${errText}`);
|
|
3514
|
+
}
|
|
3515
|
+
const result = await res.json();
|
|
3516
|
+
const deletedSet = new Set(result.deleted);
|
|
3517
|
+
setMcps((prev) => prev.filter((m) => !deletedSet.has(m._id)));
|
|
3518
|
+
return result;
|
|
3519
|
+
} catch (err) {
|
|
3520
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3521
|
+
setError(errorObj);
|
|
3522
|
+
throw errorObj;
|
|
3523
|
+
}
|
|
3524
|
+
},
|
|
3525
|
+
[fetchWithAuth]
|
|
3526
|
+
);
|
|
3527
|
+
const testConnection = useCallback14(
|
|
3528
|
+
async (mcpId) => {
|
|
3529
|
+
setError(null);
|
|
3530
|
+
try {
|
|
3531
|
+
const res = await fetchWithAuth(`/mcps/${mcpId}/test`, { method: "POST" });
|
|
3532
|
+
if (!res.ok) {
|
|
3533
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3534
|
+
throw new Error(`Failed to test MCP connection (${res.status}): ${errText}`);
|
|
3535
|
+
}
|
|
3536
|
+
const result = await res.json();
|
|
3537
|
+
setMcps(
|
|
3538
|
+
(prev) => prev.map(
|
|
3539
|
+
(m) => m._id === mcpId ? { ...m, tools: result.tools, resources: result.resources, resourceTemplates: result.resourceTemplates } : m
|
|
3540
|
+
)
|
|
3541
|
+
);
|
|
3542
|
+
return result;
|
|
3543
|
+
} catch (err) {
|
|
3544
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3545
|
+
setError(errorObj);
|
|
3546
|
+
throw errorObj;
|
|
3547
|
+
}
|
|
3548
|
+
},
|
|
3549
|
+
[fetchWithAuth]
|
|
3550
|
+
);
|
|
3551
|
+
useEffect13(() => {
|
|
3552
|
+
if (autoFetch) void fetchMcps();
|
|
3553
|
+
}, [autoFetch, fetchMcps]);
|
|
3554
|
+
return {
|
|
3555
|
+
mcps,
|
|
3556
|
+
pagination,
|
|
3557
|
+
isLoading,
|
|
3558
|
+
error,
|
|
3559
|
+
refetch: fetchMcps,
|
|
3560
|
+
getMcp,
|
|
3561
|
+
createMcp,
|
|
3562
|
+
updateMcp,
|
|
3563
|
+
deleteMcp,
|
|
3564
|
+
bulkDeleteMcps,
|
|
3565
|
+
testConnection
|
|
3566
|
+
};
|
|
3567
|
+
}
|
|
3568
|
+
|
|
3569
|
+
// src/hooks/useWorkflows.ts
|
|
3570
|
+
import { useCallback as useCallback15, useEffect as useEffect14, useState as useState14 } from "react";
|
|
3126
3571
|
function useWorkflows(options) {
|
|
3127
3572
|
const opts = typeof options === "boolean" ? { autoFetch: options } : options ?? {};
|
|
3128
|
-
const { autoFetch = true, search,
|
|
3573
|
+
const { autoFetch = true, search, scope, visibility, isEnabled, page, limit } = opts;
|
|
3129
3574
|
const { fetchWithAuth } = usePersonaContext();
|
|
3130
|
-
const [workflows, setWorkflows] =
|
|
3131
|
-
const [pagination, setPagination] =
|
|
3575
|
+
const [workflows, setWorkflows] = useState14([]);
|
|
3576
|
+
const [pagination, setPagination] = useState14({
|
|
3132
3577
|
page: page ?? 1,
|
|
3133
3578
|
limit: limit ?? 20,
|
|
3134
3579
|
total: 0,
|
|
3135
3580
|
totalPages: 0
|
|
3136
3581
|
});
|
|
3137
|
-
const [isLoading, setIsLoading] =
|
|
3138
|
-
const [error, setError] =
|
|
3139
|
-
const fetchWorkflows =
|
|
3582
|
+
const [isLoading, setIsLoading] = useState14(false);
|
|
3583
|
+
const [error, setError] = useState14(null);
|
|
3584
|
+
const fetchWorkflows = useCallback15(async () => {
|
|
3140
3585
|
setIsLoading(true);
|
|
3141
3586
|
setError(null);
|
|
3142
3587
|
try {
|
|
3143
3588
|
const params = new URLSearchParams();
|
|
3144
3589
|
if (search) params.set("search", search);
|
|
3145
|
-
if (
|
|
3590
|
+
if (scope) params.set("scope", scope);
|
|
3591
|
+
if (visibility) params.set("visibility", visibility);
|
|
3592
|
+
if (isEnabled !== void 0) params.set("isEnabled", String(isEnabled));
|
|
3146
3593
|
if (page) params.set("page", String(page));
|
|
3147
3594
|
if (limit) params.set("limit", String(limit));
|
|
3148
3595
|
const queryStr = params.toString() ? `?${params.toString()}` : "";
|
|
@@ -3151,7 +3598,7 @@ function useWorkflows(options) {
|
|
|
3151
3598
|
throw new Error(`Failed to list workflows: ${res.statusText}`);
|
|
3152
3599
|
}
|
|
3153
3600
|
const data = await res.json();
|
|
3154
|
-
const items = Array.isArray(data) ? data : data?.items
|
|
3601
|
+
const items = Array.isArray(data) ? data : data?.items ?? [];
|
|
3155
3602
|
setWorkflows(items);
|
|
3156
3603
|
if (data?.pagination) {
|
|
3157
3604
|
setPagination({
|
|
@@ -3179,8 +3626,8 @@ function useWorkflows(options) {
|
|
|
3179
3626
|
} finally {
|
|
3180
3627
|
setIsLoading(false);
|
|
3181
3628
|
}
|
|
3182
|
-
}, [fetchWithAuth, search,
|
|
3183
|
-
const createWorkflow =
|
|
3629
|
+
}, [fetchWithAuth, search, scope, visibility, isEnabled, page, limit]);
|
|
3630
|
+
const createWorkflow = useCallback15(
|
|
3184
3631
|
async (input) => {
|
|
3185
3632
|
setError(null);
|
|
3186
3633
|
try {
|
|
@@ -3204,7 +3651,7 @@ function useWorkflows(options) {
|
|
|
3204
3651
|
},
|
|
3205
3652
|
[fetchWithAuth]
|
|
3206
3653
|
);
|
|
3207
|
-
|
|
3654
|
+
useEffect14(() => {
|
|
3208
3655
|
if (autoFetch) {
|
|
3209
3656
|
void fetchWorkflows();
|
|
3210
3657
|
}
|
|
@@ -3220,17 +3667,17 @@ function useWorkflows(options) {
|
|
|
3220
3667
|
}
|
|
3221
3668
|
|
|
3222
3669
|
// src/hooks/useWorkflow.ts
|
|
3223
|
-
import { useCallback as
|
|
3670
|
+
import { useCallback as useCallback16, useEffect as useEffect15, useState as useState15 } from "react";
|
|
3224
3671
|
function useWorkflow(workflowId, options) {
|
|
3225
3672
|
const opts = typeof options === "boolean" ? { autoFetch: options } : options ?? {};
|
|
3226
3673
|
const { autoFetch = true } = opts;
|
|
3227
3674
|
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 =
|
|
3675
|
+
const [workflow, setWorkflow] = useState15(null);
|
|
3676
|
+
const [versions, setVersions] = useState15([]);
|
|
3677
|
+
const [mermaid, setMermaid] = useState15(null);
|
|
3678
|
+
const [isLoading, setIsLoading] = useState15(false);
|
|
3679
|
+
const [error, setError] = useState15(null);
|
|
3680
|
+
const fetchWorkflow = useCallback16(async () => {
|
|
3234
3681
|
if (!workflowId) return null;
|
|
3235
3682
|
setIsLoading(true);
|
|
3236
3683
|
setError(null);
|
|
@@ -3250,20 +3697,31 @@ function useWorkflow(workflowId, options) {
|
|
|
3250
3697
|
setIsLoading(false);
|
|
3251
3698
|
}
|
|
3252
3699
|
}, [fetchWithAuth, workflowId]);
|
|
3253
|
-
const fetchVersions =
|
|
3700
|
+
const fetchVersions = useCallback16(async () => {
|
|
3254
3701
|
if (!workflowId) return [];
|
|
3255
3702
|
try {
|
|
3256
3703
|
const res = await fetchWithAuth(`/workflows/${workflowId}/versions`);
|
|
3257
3704
|
if (!res.ok) return [];
|
|
3258
3705
|
const data = await res.json();
|
|
3259
|
-
const items = Array.isArray(data) ? data : data?.items
|
|
3706
|
+
const items = Array.isArray(data) ? data : data?.items ?? [];
|
|
3260
3707
|
setVersions(items);
|
|
3261
3708
|
return items;
|
|
3262
3709
|
} catch {
|
|
3263
3710
|
return [];
|
|
3264
3711
|
}
|
|
3265
3712
|
}, [fetchWithAuth, workflowId]);
|
|
3266
|
-
const
|
|
3713
|
+
const getVersion = useCallback16(
|
|
3714
|
+
async (version) => {
|
|
3715
|
+
if (!workflowId) throw new Error("Workflow ID is required");
|
|
3716
|
+
const res = await fetchWithAuth(`/workflows/${workflowId}/versions/${version}`);
|
|
3717
|
+
if (!res.ok) {
|
|
3718
|
+
throw new Error(`Failed to fetch workflow version (${res.status}): ${res.statusText}`);
|
|
3719
|
+
}
|
|
3720
|
+
return await res.json();
|
|
3721
|
+
},
|
|
3722
|
+
[fetchWithAuth, workflowId]
|
|
3723
|
+
);
|
|
3724
|
+
const fetchMermaid = useCallback16(async () => {
|
|
3267
3725
|
if (!workflowId) return "";
|
|
3268
3726
|
try {
|
|
3269
3727
|
const res = await fetchWithAuth(`/workflows/${workflowId}/mermaid`);
|
|
@@ -3276,18 +3734,18 @@ function useWorkflow(workflowId, options) {
|
|
|
3276
3734
|
return "";
|
|
3277
3735
|
}
|
|
3278
3736
|
}, [fetchWithAuth, workflowId]);
|
|
3279
|
-
const
|
|
3280
|
-
async (
|
|
3737
|
+
const updateWorkflow = useCallback16(
|
|
3738
|
+
async (input) => {
|
|
3281
3739
|
if (!workflowId) throw new Error("Workflow ID is required");
|
|
3282
3740
|
setError(null);
|
|
3283
|
-
const res = await fetchWithAuth(`/workflows/${workflowId}
|
|
3284
|
-
method: "
|
|
3741
|
+
const res = await fetchWithAuth(`/workflows/${workflowId}`, {
|
|
3742
|
+
method: "PATCH",
|
|
3285
3743
|
headers: { "Content-Type": "application/json" },
|
|
3286
|
-
body: JSON.stringify(
|
|
3744
|
+
body: JSON.stringify(input)
|
|
3287
3745
|
});
|
|
3288
3746
|
if (!res.ok) {
|
|
3289
3747
|
const errText = await res.text().catch(() => res.statusText);
|
|
3290
|
-
throw new Error(`Failed to
|
|
3748
|
+
throw new Error(`Failed to update workflow (${res.status}): ${errText}`);
|
|
3291
3749
|
}
|
|
3292
3750
|
const updated = await res.json();
|
|
3293
3751
|
setWorkflow(updated);
|
|
@@ -3295,27 +3753,41 @@ function useWorkflow(workflowId, options) {
|
|
|
3295
3753
|
},
|
|
3296
3754
|
[fetchWithAuth, workflowId]
|
|
3297
3755
|
);
|
|
3298
|
-
const
|
|
3299
|
-
async (
|
|
3756
|
+
const saveDraft = useCallback16(
|
|
3757
|
+
async (draft) => {
|
|
3300
3758
|
if (!workflowId) throw new Error("Workflow ID is required");
|
|
3301
3759
|
setError(null);
|
|
3302
|
-
const res = await fetchWithAuth(`/workflows/${workflowId}/
|
|
3303
|
-
method: "
|
|
3760
|
+
const res = await fetchWithAuth(`/workflows/${workflowId}/draft`, {
|
|
3761
|
+
method: "PUT",
|
|
3304
3762
|
headers: { "Content-Type": "application/json" },
|
|
3305
|
-
body: JSON.stringify(
|
|
3763
|
+
body: JSON.stringify(draft)
|
|
3306
3764
|
});
|
|
3307
3765
|
if (!res.ok) {
|
|
3308
3766
|
const errText = await res.text().catch(() => res.statusText);
|
|
3309
|
-
throw new Error(`Failed to
|
|
3767
|
+
throw new Error(`Failed to save draft (${res.status}): ${errText}`);
|
|
3310
3768
|
}
|
|
3311
|
-
const
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
return versionResult;
|
|
3769
|
+
const updated = await res.json();
|
|
3770
|
+
setWorkflow(updated);
|
|
3771
|
+
return updated;
|
|
3315
3772
|
},
|
|
3316
|
-
[fetchWithAuth, workflowId
|
|
3773
|
+
[fetchWithAuth, workflowId]
|
|
3317
3774
|
);
|
|
3318
|
-
const
|
|
3775
|
+
const publish = useCallback16(async () => {
|
|
3776
|
+
if (!workflowId) throw new Error("Workflow ID is required");
|
|
3777
|
+
setError(null);
|
|
3778
|
+
const res = await fetchWithAuth(`/workflows/${workflowId}/publish`, {
|
|
3779
|
+
method: "POST"
|
|
3780
|
+
});
|
|
3781
|
+
if (!res.ok) {
|
|
3782
|
+
const errText = await res.text().catch(() => res.statusText);
|
|
3783
|
+
throw new Error(`Failed to publish workflow (${res.status}): ${errText}`);
|
|
3784
|
+
}
|
|
3785
|
+
const versionResult = await res.json();
|
|
3786
|
+
void fetchWorkflow();
|
|
3787
|
+
void fetchVersions();
|
|
3788
|
+
return versionResult;
|
|
3789
|
+
}, [fetchWithAuth, workflowId, fetchWorkflow, fetchVersions]);
|
|
3790
|
+
const deleteWorkflow = useCallback16(async () => {
|
|
3319
3791
|
if (!workflowId) throw new Error("Workflow ID is required");
|
|
3320
3792
|
setError(null);
|
|
3321
3793
|
const res = await fetchWithAuth(`/workflows/${workflowId}`, {
|
|
@@ -3326,7 +3798,7 @@ function useWorkflow(workflowId, options) {
|
|
|
3326
3798
|
}
|
|
3327
3799
|
setWorkflow(null);
|
|
3328
3800
|
}, [fetchWithAuth, workflowId]);
|
|
3329
|
-
|
|
3801
|
+
useEffect15(() => {
|
|
3330
3802
|
if (autoFetch && workflowId) {
|
|
3331
3803
|
void fetchWorkflow();
|
|
3332
3804
|
}
|
|
@@ -3339,7 +3811,9 @@ function useWorkflow(workflowId, options) {
|
|
|
3339
3811
|
error,
|
|
3340
3812
|
refetch: fetchWorkflow,
|
|
3341
3813
|
fetchVersions,
|
|
3814
|
+
getVersion,
|
|
3342
3815
|
fetchMermaid,
|
|
3816
|
+
updateWorkflow,
|
|
3343
3817
|
saveDraft,
|
|
3344
3818
|
publish,
|
|
3345
3819
|
deleteWorkflow
|
|
@@ -3347,25 +3821,25 @@ function useWorkflow(workflowId, options) {
|
|
|
3347
3821
|
}
|
|
3348
3822
|
|
|
3349
3823
|
// src/hooks/useWorkflowStream.ts
|
|
3350
|
-
import { useCallback as
|
|
3824
|
+
import { useCallback as useCallback17, useEffect as useEffect16, useRef as useRef4, useState as useState16 } from "react";
|
|
3351
3825
|
function useWorkflowStream(workflowId, options) {
|
|
3352
3826
|
const { baseUrl, getAuthToken, fetchWithAuth, logger } = usePersonaContext();
|
|
3353
|
-
const [status, setStatus] =
|
|
3354
|
-
const [runId, setRunId] =
|
|
3355
|
-
const [activeNodeId, setActiveNodeId] =
|
|
3356
|
-
const [nodeRuns, setNodeRuns] =
|
|
3827
|
+
const [status, setStatus] = useState16("idle");
|
|
3828
|
+
const [runId, setRunId] = useState16(null);
|
|
3829
|
+
const [activeNodeId, setActiveNodeId] = useState16(null);
|
|
3830
|
+
const [nodeRuns, setNodeRuns] = useState16(
|
|
3357
3831
|
{}
|
|
3358
3832
|
);
|
|
3359
|
-
const [text, setText] =
|
|
3360
|
-
const [output, setOutput] =
|
|
3361
|
-
const [error, setError] =
|
|
3362
|
-
const [events, setEvents] =
|
|
3833
|
+
const [text, setText] = useState16("");
|
|
3834
|
+
const [output, setOutput] = useState16(null);
|
|
3835
|
+
const [error, setError] = useState16(null);
|
|
3836
|
+
const [events, setEvents] = useState16([]);
|
|
3363
3837
|
const abortControllerRef = useRef4(null);
|
|
3364
3838
|
const currentRunIdRef = useRef4(null);
|
|
3365
3839
|
currentRunIdRef.current = runId;
|
|
3366
3840
|
const optionsRef = useRef4(options);
|
|
3367
3841
|
optionsRef.current = options;
|
|
3368
|
-
const cancel =
|
|
3842
|
+
const cancel = useCallback17(async () => {
|
|
3369
3843
|
if (abortControllerRef.current) {
|
|
3370
3844
|
abortControllerRef.current.abort();
|
|
3371
3845
|
abortControllerRef.current = null;
|
|
@@ -3386,7 +3860,7 @@ function useWorkflowStream(workflowId, options) {
|
|
|
3386
3860
|
setStatus("cancelled");
|
|
3387
3861
|
setActiveNodeId(null);
|
|
3388
3862
|
}, [fetchWithAuth, logger]);
|
|
3389
|
-
const reset =
|
|
3863
|
+
const reset = useCallback17(() => {
|
|
3390
3864
|
if (abortControllerRef.current) {
|
|
3391
3865
|
abortControllerRef.current.abort();
|
|
3392
3866
|
abortControllerRef.current = null;
|
|
@@ -3400,7 +3874,7 @@ function useWorkflowStream(workflowId, options) {
|
|
|
3400
3874
|
setError(null);
|
|
3401
3875
|
setEvents([]);
|
|
3402
3876
|
}, []);
|
|
3403
|
-
const processStream =
|
|
3877
|
+
const processStream = useCallback17(
|
|
3404
3878
|
async (url, method, body, targetRunId) => {
|
|
3405
3879
|
if (abortControllerRef.current) {
|
|
3406
3880
|
abortControllerRef.current.abort();
|
|
@@ -3565,7 +4039,7 @@ function useWorkflowStream(workflowId, options) {
|
|
|
3565
4039
|
},
|
|
3566
4040
|
[getAuthToken]
|
|
3567
4041
|
);
|
|
3568
|
-
const start =
|
|
4042
|
+
const start = useCallback17(
|
|
3569
4043
|
async (input, opts) => {
|
|
3570
4044
|
const targetWfId = opts?.workflowId || workflowId;
|
|
3571
4045
|
if (!targetWfId) {
|
|
@@ -3586,7 +4060,7 @@ function useWorkflowStream(workflowId, options) {
|
|
|
3586
4060
|
},
|
|
3587
4061
|
[workflowId, baseUrl, processStream]
|
|
3588
4062
|
);
|
|
3589
|
-
const resume =
|
|
4063
|
+
const resume = useCallback17(
|
|
3590
4064
|
async (targetRunId, sinceSeq) => {
|
|
3591
4065
|
if (!targetRunId) {
|
|
3592
4066
|
throw new Error("Run ID is required to resume stream");
|
|
@@ -3599,7 +4073,7 @@ function useWorkflowStream(workflowId, options) {
|
|
|
3599
4073
|
},
|
|
3600
4074
|
[baseUrl, processStream]
|
|
3601
4075
|
);
|
|
3602
|
-
|
|
4076
|
+
useEffect16(() => {
|
|
3603
4077
|
return () => {
|
|
3604
4078
|
if (abortControllerRef.current) {
|
|
3605
4079
|
abortControllerRef.current.abort();
|
|
@@ -3624,21 +4098,21 @@ function useWorkflowStream(workflowId, options) {
|
|
|
3624
4098
|
}
|
|
3625
4099
|
|
|
3626
4100
|
// src/hooks/useWorkflowRuns.ts
|
|
3627
|
-
import { useCallback as
|
|
4101
|
+
import { useCallback as useCallback18, useEffect as useEffect17, useState as useState17 } from "react";
|
|
3628
4102
|
function useWorkflowRuns(workflowId, options) {
|
|
3629
4103
|
const opts = typeof options === "boolean" ? { autoFetch: options } : options ?? {};
|
|
3630
4104
|
const { autoFetch = true, page = 1, limit = 20 } = opts;
|
|
3631
4105
|
const { fetchWithAuth } = usePersonaContext();
|
|
3632
|
-
const [runs, setRuns] =
|
|
3633
|
-
const [pagination, setPagination] =
|
|
4106
|
+
const [runs, setRuns] = useState17([]);
|
|
4107
|
+
const [pagination, setPagination] = useState17({
|
|
3634
4108
|
page,
|
|
3635
4109
|
limit,
|
|
3636
4110
|
total: 0,
|
|
3637
4111
|
totalPages: 0
|
|
3638
4112
|
});
|
|
3639
|
-
const [isLoading, setIsLoading] =
|
|
3640
|
-
const [error, setError] =
|
|
3641
|
-
const fetchRuns =
|
|
4113
|
+
const [isLoading, setIsLoading] = useState17(false);
|
|
4114
|
+
const [error, setError] = useState17(null);
|
|
4115
|
+
const fetchRuns = useCallback18(async () => {
|
|
3642
4116
|
if (!workflowId) return [];
|
|
3643
4117
|
setIsLoading(true);
|
|
3644
4118
|
setError(null);
|
|
@@ -3649,14 +4123,16 @@ function useWorkflowRuns(workflowId, options) {
|
|
|
3649
4123
|
throw new Error(`Failed to list workflow runs: ${res.statusText}`);
|
|
3650
4124
|
}
|
|
3651
4125
|
const data = await res.json();
|
|
3652
|
-
const items = Array.isArray(data) ? data : data?.items
|
|
4126
|
+
const items = Array.isArray(data) ? data : data?.items ?? [];
|
|
3653
4127
|
setRuns(items);
|
|
3654
4128
|
if (data?.pagination) {
|
|
3655
4129
|
setPagination({
|
|
3656
4130
|
page: data.pagination.page ?? page,
|
|
3657
4131
|
limit: data.pagination.limit ?? limit,
|
|
3658
4132
|
total: data.pagination.total ?? items.length,
|
|
3659
|
-
|
|
4133
|
+
// Backend's paginationEnvelope() names this field `pages`, not
|
|
4134
|
+
// `totalPages`.
|
|
4135
|
+
totalPages: data.pagination.pages ?? 1
|
|
3660
4136
|
});
|
|
3661
4137
|
}
|
|
3662
4138
|
return items;
|
|
@@ -3668,7 +4144,7 @@ function useWorkflowRuns(workflowId, options) {
|
|
|
3668
4144
|
setIsLoading(false);
|
|
3669
4145
|
}
|
|
3670
4146
|
}, [fetchWithAuth, workflowId, page, limit]);
|
|
3671
|
-
const getRun =
|
|
4147
|
+
const getRun = useCallback18(
|
|
3672
4148
|
async (runId) => {
|
|
3673
4149
|
if (!runId) throw new Error("Run ID is required");
|
|
3674
4150
|
const res = await fetchWithAuth(`/workflows/runs/${runId}`);
|
|
@@ -3679,7 +4155,7 @@ function useWorkflowRuns(workflowId, options) {
|
|
|
3679
4155
|
},
|
|
3680
4156
|
[fetchWithAuth]
|
|
3681
4157
|
);
|
|
3682
|
-
const cancelRun =
|
|
4158
|
+
const cancelRun = useCallback18(
|
|
3683
4159
|
async (runId) => {
|
|
3684
4160
|
if (!runId) throw new Error("Run ID is required");
|
|
3685
4161
|
const res = await fetchWithAuth(`/workflows/runs/${runId}/cancel`, {
|
|
@@ -3694,7 +4170,7 @@ function useWorkflowRuns(workflowId, options) {
|
|
|
3694
4170
|
},
|
|
3695
4171
|
[fetchWithAuth]
|
|
3696
4172
|
);
|
|
3697
|
-
|
|
4173
|
+
useEffect17(() => {
|
|
3698
4174
|
if (autoFetch && workflowId) {
|
|
3699
4175
|
void fetchRuns();
|
|
3700
4176
|
}
|
|
@@ -3735,7 +4211,9 @@ export {
|
|
|
3735
4211
|
useChat,
|
|
3736
4212
|
useConnection,
|
|
3737
4213
|
useFiles,
|
|
4214
|
+
useKnowledgeBases,
|
|
3738
4215
|
useMcp,
|
|
4216
|
+
useMcpAdmin,
|
|
3739
4217
|
useMcpConnections,
|
|
3740
4218
|
useMemory,
|
|
3741
4219
|
usePersonaContext,
|