openxgen 2.4.0 → 2.5.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.js +602 -743
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1222,15 +1222,21 @@ var raw_tui_exports = {};
|
|
|
1222
1222
|
__export(raw_tui_exports, {
|
|
1223
1223
|
startRawTui: () => startRawTui
|
|
1224
1224
|
});
|
|
1225
|
-
function
|
|
1226
|
-
return
|
|
1227
|
-
|
|
1225
|
+
function visualLen(s) {
|
|
1226
|
+
return s.replace(/\x1b\[[0-9;]*m/g, "").length;
|
|
1227
|
+
}
|
|
1228
|
+
function padV(s, w) {
|
|
1229
|
+
return s + " ".repeat(Math.max(0, w - visualLen(s)));
|
|
1230
|
+
}
|
|
1231
|
+
function withTimeout(p, ms = 3e3, label = "") {
|
|
1232
|
+
return new Promise((res, rej) => {
|
|
1233
|
+
const t = setTimeout(() => rej(new Error(`${label} \uD0C0\uC784\uC544\uC6C3`)), ms);
|
|
1228
1234
|
p.then((v) => {
|
|
1229
1235
|
clearTimeout(t);
|
|
1230
|
-
|
|
1236
|
+
res(v);
|
|
1231
1237
|
}, (e) => {
|
|
1232
1238
|
clearTimeout(t);
|
|
1233
|
-
|
|
1239
|
+
rej(e);
|
|
1234
1240
|
});
|
|
1235
1241
|
});
|
|
1236
1242
|
}
|
|
@@ -1238,283 +1244,213 @@ async function startRawTui() {
|
|
|
1238
1244
|
const provider = getDefaultProvider();
|
|
1239
1245
|
const server = getServer();
|
|
1240
1246
|
const auth = getAuth();
|
|
1241
|
-
const
|
|
1247
|
+
const sv = auth && server ? `${auth.username}@${server.replace(/https?:\/\//, "")}` : "\uBBF8\uC5F0\uACB0";
|
|
1242
1248
|
let tab = "workflows";
|
|
1243
|
-
let
|
|
1244
|
-
let
|
|
1245
|
-
let
|
|
1246
|
-
let formCtx = null;
|
|
1249
|
+
let sel = 0;
|
|
1250
|
+
let inputBuf = "";
|
|
1251
|
+
let inputActive = false;
|
|
1247
1252
|
let workflows = [];
|
|
1248
1253
|
let collections = [];
|
|
1249
1254
|
let nodes = [];
|
|
1250
1255
|
let prompts = [];
|
|
1251
1256
|
let tools2 = [];
|
|
1252
1257
|
let mcpSessions = [];
|
|
1253
|
-
let
|
|
1258
|
+
let sandbox = ["\u2190 \uD56D\uBAA9 \uC120\uD0DD"];
|
|
1259
|
+
let chatLines = [dim("\uCC44\uD305: \uC9C8\uBB38\uC744 \uC785\uB825\uD558\uC138\uC694 (\uC120\uD0DD\uD55C \uC6CC\uD06C\uD50C\uB85C\uC6B0\uB85C \uC2E4\uD589)")];
|
|
1254
1260
|
let statusMsg = "\uB85C\uB529...";
|
|
1255
|
-
let errors = [];
|
|
1256
1261
|
async function loadData() {
|
|
1257
|
-
statusMsg = "\
|
|
1258
|
-
errors = [];
|
|
1262
|
+
statusMsg = "\uB85C\uB529 \uC911...";
|
|
1259
1263
|
render();
|
|
1260
1264
|
if (!server || !auth) {
|
|
1261
1265
|
statusMsg = "\uC11C\uBC84 \uBBF8\uC5F0\uACB0";
|
|
1262
|
-
|
|
1266
|
+
sandbox = [red("\uC11C\uBC84 \uBBF8\uC5F0\uACB0"), "", cyan(" xgen config set-server <URL>"), cyan(" xgen login")];
|
|
1263
1267
|
render();
|
|
1264
1268
|
return;
|
|
1265
1269
|
}
|
|
1270
|
+
const errors = [];
|
|
1266
1271
|
try {
|
|
1267
|
-
const [
|
|
1272
|
+
const [wf, doc, ex] = await Promise.all([
|
|
1268
1273
|
Promise.resolve().then(() => (init_workflow(), workflow_exports)),
|
|
1269
1274
|
Promise.resolve().then(() => (init_document(), document_exports)),
|
|
1270
1275
|
Promise.resolve().then(() => (init_xgen_extra(), xgen_extra_exports))
|
|
1271
1276
|
]);
|
|
1272
|
-
const
|
|
1273
|
-
withTimeout(
|
|
1274
|
-
withTimeout(
|
|
1275
|
-
withTimeout(
|
|
1276
|
-
withTimeout(
|
|
1277
|
-
withTimeout(
|
|
1278
|
-
withTimeout(
|
|
1277
|
+
const r = await Promise.allSettled([
|
|
1278
|
+
withTimeout(wf.getWorkflowListDetail(), 3e3, "\uC6CC\uD06C\uD50C\uB85C\uC6B0"),
|
|
1279
|
+
withTimeout(doc.listCollections(), 3e3, "\uCEEC\uB809\uC158"),
|
|
1280
|
+
withTimeout(ex.listNodes(), 3e3, "\uB178\uB4DC"),
|
|
1281
|
+
withTimeout(ex.listPrompts(), 3e3, "\uD504\uB86C\uD504\uD2B8"),
|
|
1282
|
+
withTimeout(ex.listToolStore(), 3e3, "\uB3C4\uAD6C"),
|
|
1283
|
+
withTimeout(ex.listMcpSessions(), 3e3, "MCP").catch(() => [])
|
|
1279
1284
|
]);
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
}));
|
|
1295
|
-
} else errors.push(`\uCEEC\uB809\uC158: ${colR.reason?.message ?? "\uC2E4\uD328"}`);
|
|
1296
|
-
if (nodeR.status === "fulfilled") {
|
|
1285
|
+
if (r[0].status === "fulfilled") workflows = r[0].value.map((w) => ({
|
|
1286
|
+
name: w.workflow_name ?? w.name ?? "?",
|
|
1287
|
+
id: w.workflow_id ?? w.id ?? "",
|
|
1288
|
+
deployed: w.deploy_status === "deployed" || w.deploy_status === "DEPLOYED" || !!w.is_deployed
|
|
1289
|
+
}));
|
|
1290
|
+
else errors.push(`\uC6CC\uD06C\uD50C\uB85C\uC6B0: ${r[0].reason?.message ?? "\uC2E4\uD328"}`);
|
|
1291
|
+
if (r[1].status === "fulfilled") collections = r[1].value.map((c) => ({
|
|
1292
|
+
name: c.collection_make_name ?? c.collection_name ?? "?",
|
|
1293
|
+
id: c.id ?? c.collection_id ?? "",
|
|
1294
|
+
docs: c.total_documents ?? 0,
|
|
1295
|
+
chunks: c.total_chunks ?? 0
|
|
1296
|
+
}));
|
|
1297
|
+
else errors.push(`\uCEEC\uB809\uC158: ${r[1].reason?.message ?? "\uC2E4\uD328"}`);
|
|
1298
|
+
if (r[2].status === "fulfilled") {
|
|
1297
1299
|
nodes = [];
|
|
1298
|
-
const
|
|
1299
|
-
|
|
1300
|
-
const
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
for (const fn of fns) {
|
|
1304
|
-
const fnNodes = fn.nodes ?? [];
|
|
1305
|
-
if (Array.isArray(fnNodes)) {
|
|
1306
|
-
for (const n of fnNodes) {
|
|
1307
|
-
nodes.push({
|
|
1308
|
-
name: n.nodeName ?? n.name ?? "?",
|
|
1309
|
-
desc: (n.description ?? "").slice(0, 50),
|
|
1310
|
-
id: n.id ?? n.nodeId,
|
|
1311
|
-
category: `${catName}/${fn.functionName ?? fn.functionId ?? ""}`
|
|
1312
|
-
});
|
|
1313
|
-
}
|
|
1314
|
-
} else {
|
|
1315
|
-
nodes.push({
|
|
1316
|
-
name: fn.nodeName ?? fn.name ?? "?",
|
|
1317
|
-
desc: (fn.description ?? "").slice(0, 50),
|
|
1318
|
-
id: fn.id ?? fn.nodeId,
|
|
1319
|
-
category: catName
|
|
1320
|
-
});
|
|
1321
|
-
}
|
|
1300
|
+
for (const cat of r[2].value) {
|
|
1301
|
+
const catName = cat.categoryName ?? "";
|
|
1302
|
+
for (const fn of cat.functions ?? []) {
|
|
1303
|
+
for (const n of fn.nodes ?? []) {
|
|
1304
|
+
nodes.push({ name: n.nodeName ?? n.name ?? "?", desc: (n.description ?? "").slice(0, 40), id: n.id, category: `${catName}/${fn.functionName ?? ""}` });
|
|
1322
1305
|
}
|
|
1323
1306
|
}
|
|
1324
1307
|
}
|
|
1325
|
-
} else errors.push(`\uB178\uB4DC: ${
|
|
1326
|
-
if (
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
command: s.server_command
|
|
1355
|
-
}));
|
|
1356
|
-
}
|
|
1357
|
-
} catch (err) {
|
|
1358
|
-
errors.push(`\uC804\uCCB4: ${err.message}`);
|
|
1308
|
+
} else errors.push(`\uB178\uB4DC: ${r[2].reason?.message ?? "\uC2E4\uD328"}`);
|
|
1309
|
+
if (r[3].status === "fulfilled") prompts = r[3].value.map((p) => ({
|
|
1310
|
+
name: p.prompt_title ?? p.name ?? "?",
|
|
1311
|
+
type: p.prompt_type ?? "",
|
|
1312
|
+
uid: p.prompt_uid,
|
|
1313
|
+
content: p.prompt_content,
|
|
1314
|
+
dbId: p.id
|
|
1315
|
+
}));
|
|
1316
|
+
else errors.push(`\uD504\uB86C\uD504\uD2B8: ${r[3].reason?.message ?? "\uC2E4\uD328"}`);
|
|
1317
|
+
if (r[4].status === "fulfilled") tools2 = r[4].value.map((t) => {
|
|
1318
|
+
const fd = t.function_data ?? {};
|
|
1319
|
+
return {
|
|
1320
|
+
name: fd.function_name ?? t.function_name ?? "?",
|
|
1321
|
+
desc: (fd.description ?? t.description ?? "").slice(0, 40),
|
|
1322
|
+
id: t.id,
|
|
1323
|
+
fid: fd.function_id ?? t.function_upload_id,
|
|
1324
|
+
url: fd.api_url,
|
|
1325
|
+
status: fd.status ?? t.status
|
|
1326
|
+
};
|
|
1327
|
+
});
|
|
1328
|
+
else errors.push(`\uB3C4\uAD6C: ${r[4].reason?.message ?? "\uC2E4\uD328"}`);
|
|
1329
|
+
if (r[5].status === "fulfilled" && Array.isArray(r[5].value)) mcpSessions = r[5].value.map((s) => ({
|
|
1330
|
+
id: s.session_id ?? "",
|
|
1331
|
+
name: s.session_name ?? "?",
|
|
1332
|
+
type: s.server_type ?? "?",
|
|
1333
|
+
status: s.status ?? "?"
|
|
1334
|
+
}));
|
|
1335
|
+
} catch (e) {
|
|
1336
|
+
errors.push(e.message);
|
|
1359
1337
|
}
|
|
1360
|
-
|
|
1361
|
-
|
|
1338
|
+
sel = 0;
|
|
1339
|
+
updateSandbox();
|
|
1362
1340
|
statusMsg = errors.length > 0 ? `\u26A0 ${errors.length}\uAC1C \uC624\uB958 \u2502 r \uC7AC\uC2DC\uB3C4` : getHint();
|
|
1363
|
-
if (errors.length > 0)
|
|
1341
|
+
if (errors.length > 0) sandbox = [red("\uC624\uB958:"), ...errors.map((e) => yellow(` \u2022 ${e}`))];
|
|
1364
1342
|
render();
|
|
1365
1343
|
}
|
|
1366
1344
|
function getHint() {
|
|
1367
|
-
const
|
|
1368
|
-
workflows: "\u2191\u2193 \u2502 Enter \
|
|
1369
|
-
collections: "\u2191\u2193 \u2502 Enter \uBB38\uC11C
|
|
1370
|
-
nodes: "\u2191\u2193 \u2502 Enter \uC0C1\uC138
|
|
1371
|
-
prompts: "\u2191\u2193 \u2502 Enter \uB0B4\uC6A9 \u2502 c\uC0DD\uC131 e\uC218\uC815 d\uC0AD\uC81C
|
|
1372
|
-
tools: "\u2191\u2193 \u2502 Enter
|
|
1373
|
-
mcp: "\u2191\u2193 \u2502 Enter \uB3C4\uAD6C
|
|
1345
|
+
const h = {
|
|
1346
|
+
workflows: "\u2191\u2193 \uC774\uB3D9 \u2502 Enter \uAD6C\uC870 \u2502 \uC9C8\uBB38 \uC785\uB825\u2192\uC2E4\uD589 \u2502 1-6 \uD0ED \u2502 r \u2502 q",
|
|
1347
|
+
collections: "\u2191\u2193 \u2502 Enter \uBB38\uC11C \u2502 1-6 \uD0ED \u2502 q",
|
|
1348
|
+
nodes: "\u2191\u2193 \u2502 Enter \uC0C1\uC138 \u2502 1-6 \uD0ED \u2502 q",
|
|
1349
|
+
prompts: "\u2191\u2193 \u2502 Enter \uB0B4\uC6A9 \u2502 c\uC0DD\uC131 e\uC218\uC815 d\uC0AD\uC81C \u2502 q",
|
|
1350
|
+
tools: "\u2191\u2193 \u2502 Enter \uD14C\uC2A4\uD2B8 \u2502 c\uC0DD\uC131 u\uC2A4\uD1A0\uC5B4 \u2502 q",
|
|
1351
|
+
mcp: "\u2191\u2193 \u2502 Enter \uB3C4\uAD6C \u2502 c\uC0DD\uC131 t\uD638\uCD9C d\uC0AD\uC81C \u2502 q"
|
|
1374
1352
|
};
|
|
1375
|
-
return
|
|
1353
|
+
return h[tab];
|
|
1376
1354
|
}
|
|
1377
1355
|
function getItems() {
|
|
1378
1356
|
switch (tab) {
|
|
1379
1357
|
case "workflows":
|
|
1380
|
-
return workflows.map((w) => ({ label: `${w.deployed ? green("\u25CF") : dim("\u25CB")} ${w.name}`, sub: w.id.slice(0,
|
|
1358
|
+
return workflows.map((w) => ({ label: `${w.deployed ? green("\u25CF") : dim("\u25CB")} ${w.name}`, sub: w.id.slice(0, 12) }));
|
|
1381
1359
|
case "collections":
|
|
1382
|
-
return collections.map((c) => ({ label: c.name, sub: `${c.docs}\uBB38\uC11C
|
|
1360
|
+
return collections.map((c) => ({ label: c.name, sub: `${c.docs}\uBB38\uC11C` }));
|
|
1383
1361
|
case "nodes":
|
|
1384
|
-
return nodes.map((n) => ({ label: n.name, sub: n.category
|
|
1362
|
+
return nodes.map((n) => ({ label: n.name, sub: n.category }));
|
|
1385
1363
|
case "prompts":
|
|
1386
1364
|
return prompts.map((p) => ({ label: p.name, sub: `[${p.type}]` }));
|
|
1387
1365
|
case "tools":
|
|
1388
|
-
return tools2.map((t) => {
|
|
1389
|
-
const st = t.status === "active" ? green("\u25CF") : t.status === "inactive" ? red("\u25CF") : dim("\u25CB");
|
|
1390
|
-
return { label: `${st} ${t.name}`, sub: t.desc };
|
|
1391
|
-
});
|
|
1366
|
+
return tools2.map((t) => ({ label: `${t.status === "active" ? green("\u25CF") : dim("\u25CB")} ${t.name}`, sub: t.desc }));
|
|
1392
1367
|
case "mcp":
|
|
1393
|
-
return mcpSessions.map((s) => {
|
|
1394
|
-
const st = s.status === "running" ? green("\u25CF") : s.status === "error" ? red("\u25CF") : dim("\u25CB");
|
|
1395
|
-
return { label: `${st} ${s.name}`, sub: `[${s.type}] ${s.status}` };
|
|
1396
|
-
});
|
|
1368
|
+
return mcpSessions.map((s) => ({ label: `${s.status === "running" ? green("\u25CF") : dim("\u25CB")} ${s.name}`, sub: s.type }));
|
|
1397
1369
|
}
|
|
1398
1370
|
}
|
|
1399
|
-
function
|
|
1371
|
+
function updateSandbox() {
|
|
1400
1372
|
const items = getItems();
|
|
1401
1373
|
if (items.length === 0) {
|
|
1402
|
-
|
|
1403
|
-
detail = [dim("\uB370\uC774\uD130 \uC5C6\uC74C"), "", dim(createHint)];
|
|
1374
|
+
sandbox = [dim("\uB370\uC774\uD130 \uC5C6\uC74C")];
|
|
1404
1375
|
return;
|
|
1405
1376
|
}
|
|
1406
|
-
if (
|
|
1407
|
-
if (
|
|
1408
|
-
if (tab === "workflows" && workflows[
|
|
1409
|
-
const w = workflows[
|
|
1410
|
-
|
|
1377
|
+
if (sel < 0) sel = 0;
|
|
1378
|
+
if (sel >= items.length) sel = items.length - 1;
|
|
1379
|
+
if (tab === "workflows" && workflows[sel]) {
|
|
1380
|
+
const w = workflows[sel];
|
|
1381
|
+
sandbox = [
|
|
1411
1382
|
bold(w.name),
|
|
1383
|
+
`ID: ${w.id}`,
|
|
1384
|
+
`\uBC30\uD3EC: ${w.deployed ? green("Yes") : red("No")}`,
|
|
1412
1385
|
"",
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
"",
|
|
1416
|
-
cyan("Enter") + " \uB178\uB4DC/\uC5E3\uC9C0 \uAD6C\uC870 \uBCF4\uAE30",
|
|
1417
|
-
cyan("i") + " \uC9C8\uBB38 \uC785\uB825 \uD6C4 \uC2E4\uD589"
|
|
1418
|
-
];
|
|
1419
|
-
} else if (tab === "collections" && collections[selected]) {
|
|
1420
|
-
const c = collections[selected];
|
|
1421
|
-
detail = [bold(c.name), "", `\uBB38\uC11C ${c.docs}\uAC1C`, `\uCCAD\uD06C ${c.chunks}\uAC1C`, "", cyan("Enter") + " \uBB38\uC11C \uBAA9\uB85D"];
|
|
1422
|
-
} else if (tab === "nodes" && nodes[selected]) {
|
|
1423
|
-
const n = nodes[selected];
|
|
1424
|
-
detail = [
|
|
1425
|
-
bold(n.name),
|
|
1426
|
-
"",
|
|
1427
|
-
`\uCE74\uD14C\uACE0\uB9AC: ${n.category || dim("\uC5C6\uC74C")}`,
|
|
1428
|
-
n.desc || dim("\uC124\uBA85 \uC5C6\uC74C"),
|
|
1429
|
-
"",
|
|
1430
|
-
cyan("Enter") + " \uD30C\uB77C\uBBF8\uD130/\uD3EC\uD2B8 \uC0C1\uC138"
|
|
1431
|
-
];
|
|
1432
|
-
} else if (tab === "prompts" && prompts[selected]) {
|
|
1433
|
-
const p = prompts[selected];
|
|
1434
|
-
const preview = p.content ? p.content.split("\n").slice(0, 8) : [dim("\uB0B4\uC6A9 \uC5C6\uC74C")];
|
|
1435
|
-
detail = [
|
|
1436
|
-
bold(p.name),
|
|
1437
|
-
`\uD0C0\uC785: ${p.type || "\uC5C6\uC74C"}`,
|
|
1438
|
-
`UID: ${p.uid || dim("\uC5C6\uC74C")}`,
|
|
1439
|
-
"",
|
|
1440
|
-
...preview,
|
|
1441
|
-
"",
|
|
1442
|
-
`${cyan("c")}\uC0DD\uC131 ${cyan("e")}\uC218\uC815 ${cyan("d")}\uC0AD\uC81C ${cyan("u")}\uC2A4\uD1A0\uC5B4 ${cyan("v")}\uBC84\uC804`
|
|
1443
|
-
];
|
|
1444
|
-
} else if (tab === "tools" && tools2[selected]) {
|
|
1445
|
-
const t = tools2[selected];
|
|
1446
|
-
detail = [
|
|
1447
|
-
bold(t.name),
|
|
1448
|
-
"",
|
|
1449
|
-
`ID ${t.functionId || dim("\uC5C6\uC74C")}`,
|
|
1450
|
-
`URL ${t.apiUrl || dim("\uC5C6\uC74C")}`,
|
|
1451
|
-
`\uC0C1\uD0DC ${t.status === "active" ? green("active") : t.status === "inactive" ? red("inactive") : dim(t.status || "\uC5C6\uC74C")}`,
|
|
1452
|
-
"",
|
|
1453
|
-
t.desc || dim("\uC124\uBA85 \uC5C6\uC74C"),
|
|
1454
|
-
"",
|
|
1455
|
-
`${cyan("t")}\uD14C\uC2A4\uD2B8 ${cyan("u")}\uC2A4\uD1A0\uC5B4\uB4F1\uB85D ${cyan("c")}\uC0DD\uC131`
|
|
1456
|
-
];
|
|
1457
|
-
} else if (tab === "mcp" && mcpSessions[selected]) {
|
|
1458
|
-
const s = mcpSessions[selected];
|
|
1459
|
-
detail = [
|
|
1460
|
-
bold(s.name),
|
|
1461
|
-
"",
|
|
1462
|
-
`\uC138\uC158ID ${s.id}`,
|
|
1463
|
-
`\uD0C0\uC785 ${s.type}`,
|
|
1464
|
-
`\uC0C1\uD0DC ${s.status === "running" ? green(s.status) : red(s.status)}`,
|
|
1465
|
-
`\uCEE4\uB9E8\uB4DC ${s.command || dim("\uC5C6\uC74C")}`,
|
|
1466
|
-
"",
|
|
1467
|
-
`${cyan("Enter")}\uB3C4\uAD6C\uBAA9\uB85D ${cyan("t")}\uB3C4\uAD6C\uD638\uCD9C ${cyan("d")}\uC0AD\uC81C`
|
|
1386
|
+
cyan("Enter") + " \uB178\uB4DC\uAD6C\uC870",
|
|
1387
|
+
dim("\uC9C8\uBB38 \uC785\uB825 \u2192 \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC2E4\uD589")
|
|
1468
1388
|
];
|
|
1389
|
+
} else if (tab === "collections" && collections[sel]) {
|
|
1390
|
+
const c = collections[sel];
|
|
1391
|
+
sandbox = [bold(c.name), `\uBB38\uC11C ${c.docs}\uAC1C \u2502 \uCCAD\uD06C ${c.chunks}\uAC1C`, "", cyan("Enter") + " \uBB38\uC11C \uBAA9\uB85D"];
|
|
1392
|
+
} else if (tab === "nodes" && nodes[sel]) {
|
|
1393
|
+
const n = nodes[sel];
|
|
1394
|
+
sandbox = [bold(n.name), `\uCE74\uD14C\uACE0\uB9AC: ${n.category ?? "?"}`, n.desc, "", cyan("Enter") + " \uD30C\uB77C\uBBF8\uD130 \uC0C1\uC138"];
|
|
1395
|
+
} else if (tab === "prompts" && prompts[sel]) {
|
|
1396
|
+
const p = prompts[sel];
|
|
1397
|
+
sandbox = [bold(p.name), `\uD0C0\uC785: ${p.type}`, "", ...p.content?.split("\n").slice(0, 8) ?? [dim("\uB0B4\uC6A9 \uC5C6\uC74C")]];
|
|
1398
|
+
} else if (tab === "tools" && tools2[sel]) {
|
|
1399
|
+
const t = tools2[sel];
|
|
1400
|
+
sandbox = [bold(t.name), `URL: ${t.url ?? dim("\uC5C6\uC74C")}`, `\uC0C1\uD0DC: ${t.status ?? "?"}`, "", cyan("Enter") + " API \uD14C\uC2A4\uD2B8"];
|
|
1401
|
+
} else if (tab === "mcp" && mcpSessions[sel]) {
|
|
1402
|
+
const s = mcpSessions[sel];
|
|
1403
|
+
sandbox = [bold(s.name), `\uC138\uC158: ${s.id}`, `\uD0C0\uC785: ${s.type}`, `\uC0C1\uD0DC: ${s.status}`, "", cyan("Enter") + " \uB3C4\uAD6C \uBAA9\uB85D"];
|
|
1469
1404
|
}
|
|
1470
1405
|
}
|
|
1471
|
-
function visualLen(s) {
|
|
1472
|
-
return s.replace(/\x1b\[[0-9;]*m/g, "").length;
|
|
1473
|
-
}
|
|
1474
|
-
function padVisual(s, w) {
|
|
1475
|
-
return s + " ".repeat(Math.max(0, w - visualLen(s)));
|
|
1476
|
-
}
|
|
1477
1406
|
function render() {
|
|
1478
1407
|
const cols = process.stdout.columns || 120;
|
|
1479
1408
|
const rows = process.stdout.rows || 30;
|
|
1480
|
-
const leftW = Math.floor(cols * 0.
|
|
1409
|
+
const leftW = Math.floor(cols * 0.35);
|
|
1481
1410
|
const rightW = cols - leftW - 1;
|
|
1482
|
-
const
|
|
1411
|
+
const topH = Math.floor((rows - 4) * 0.55);
|
|
1412
|
+
const botH = rows - 4 - topH;
|
|
1483
1413
|
clear();
|
|
1484
1414
|
moveTo(1, 1);
|
|
1485
1415
|
const tabStr = TABS.map((t) => tab === t.key ? inverse(` ${t.num}:${t.label} `) : dim(` ${t.num}:${t.label} `)).join("");
|
|
1486
|
-
process.stdout.write(` ${bold(cyan("OPEN XGEN"))} ${dim("
|
|
1416
|
+
process.stdout.write(` ${bold(cyan("OPEN XGEN"))} ${dim("v3")} ${dim(sv)} \u2502 ${tabStr}`);
|
|
1487
1417
|
moveTo(2, 1);
|
|
1488
1418
|
process.stdout.write(dim("\u2500".repeat(leftW) + "\u252C" + "\u2500".repeat(rightW)));
|
|
1489
1419
|
const items = getItems();
|
|
1490
|
-
const
|
|
1491
|
-
const scr = items.length <=
|
|
1492
|
-
for (let i = 0; i <
|
|
1420
|
+
const listH = topH;
|
|
1421
|
+
const scr = items.length <= listH ? 0 : Math.max(0, Math.min(sel - Math.floor(listH / 2), items.length - listH));
|
|
1422
|
+
for (let i = 0; i < listH; i++) {
|
|
1493
1423
|
moveTo(3 + i, 1);
|
|
1494
1424
|
const idx = scr + i;
|
|
1495
1425
|
let left;
|
|
1496
1426
|
if (idx < items.length) {
|
|
1497
1427
|
const item = items[idx];
|
|
1498
1428
|
const sub = item.sub ? dim(` ${item.sub}`) : "";
|
|
1499
|
-
left =
|
|
1500
|
-
if (idx ===
|
|
1429
|
+
left = padV(`${idx === sel ? "\u25B8" : " "} ${String(idx + 1).padStart(2)}. ${item.label}${sub}`, leftW);
|
|
1430
|
+
if (idx === sel) left = inverse(left);
|
|
1501
1431
|
} else {
|
|
1502
1432
|
left = " ".repeat(leftW);
|
|
1503
1433
|
}
|
|
1504
1434
|
process.stdout.write(left);
|
|
1505
1435
|
process.stdout.write(dim("\u2502"));
|
|
1506
|
-
if (i <
|
|
1507
|
-
}
|
|
1508
|
-
if (items.length === 0) {
|
|
1509
|
-
moveTo(4, 3);
|
|
1510
|
-
process.stdout.write(dim("(\uD56D\uBAA9 \uC5C6\uC74C)"));
|
|
1436
|
+
if (i < sandbox.length) process.stdout.write(` ${sandbox[i]}`);
|
|
1511
1437
|
}
|
|
1512
|
-
moveTo(
|
|
1438
|
+
moveTo(3 + topH, 1);
|
|
1513
1439
|
process.stdout.write(dim("\u2500".repeat(leftW) + "\u2534" + "\u2500".repeat(rightW)));
|
|
1440
|
+
const chatStart = 4 + topH;
|
|
1441
|
+
const chatDisplayH = botH - 2;
|
|
1442
|
+
const chatOffset = Math.max(0, chatLines.length - chatDisplayH);
|
|
1443
|
+
for (let i = 0; i < chatDisplayH; i++) {
|
|
1444
|
+
moveTo(chatStart + i, 1);
|
|
1445
|
+
const lineIdx = chatOffset + i;
|
|
1446
|
+
if (lineIdx < chatLines.length) {
|
|
1447
|
+
process.stdout.write(` ${chatLines[lineIdx]}`.slice(0, cols));
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1514
1450
|
moveTo(rows - 1, 1);
|
|
1515
|
-
if (
|
|
1516
|
-
const
|
|
1517
|
-
process.stdout.write(` ${cyan(
|
|
1451
|
+
if (inputActive) {
|
|
1452
|
+
const ctx = tab === "workflows" && workflows[sel] ? `${workflows[sel].name} ` : "";
|
|
1453
|
+
process.stdout.write(` ${cyan(ctx + "\u276F")} ${inputBuf}`);
|
|
1518
1454
|
showCursor();
|
|
1519
1455
|
} else {
|
|
1520
1456
|
process.stdout.write(dim(` ${getHint()}`));
|
|
@@ -1523,8 +1459,14 @@ async function startRawTui() {
|
|
|
1523
1459
|
moveTo(rows, 1);
|
|
1524
1460
|
process.stdout.write(dim(` ${statusMsg}`.slice(0, cols)));
|
|
1525
1461
|
}
|
|
1462
|
+
function addChat(line) {
|
|
1463
|
+
chatLines.push(line);
|
|
1464
|
+
if (chatLines.length > 200) chatLines = chatLines.slice(-100);
|
|
1465
|
+
}
|
|
1526
1466
|
async function runWorkflow(wf, input) {
|
|
1527
|
-
|
|
1467
|
+
addChat(`${cyan("\u276F")} ${input}`);
|
|
1468
|
+
addChat(yellow(` ${wf.name} \uC2E4\uD589 \uC911...`));
|
|
1469
|
+
sandbox = [bold(wf.name), "", yellow("\uC2E4\uD589 \uC911...")];
|
|
1528
1470
|
render();
|
|
1529
1471
|
try {
|
|
1530
1472
|
const { executeWorkflow: executeWorkflow2 } = await Promise.resolve().then(() => (init_workflow(), workflow_exports));
|
|
@@ -1536,497 +1478,139 @@ async function startRawTui() {
|
|
|
1536
1478
|
interaction_id: `tui_${randomUUID4().slice(0, 8)}`,
|
|
1537
1479
|
user_id: auth?.userId ? parseInt(auth.userId) : 1
|
|
1538
1480
|
}), 3e4, "\uC2E4\uD589");
|
|
1539
|
-
const content = r?.content ?? r?.message ?? r?.result ?? JSON.stringify(r).slice(0, 500);
|
|
1540
|
-
|
|
1481
|
+
const content = String(r?.content ?? r?.message ?? r?.result ?? JSON.stringify(r).slice(0, 500));
|
|
1482
|
+
const lines = content.split("\n");
|
|
1483
|
+
addChat(green(" \uACB0\uACFC:"));
|
|
1484
|
+
for (const l of lines.slice(0, 20)) addChat(` ${l}`);
|
|
1485
|
+
addChat("");
|
|
1486
|
+
sandbox = [bold(wf.name), "", green("\uC644\uB8CC"), "", ...lines.slice(0, 10)];
|
|
1541
1487
|
} catch (err) {
|
|
1542
|
-
|
|
1488
|
+
addChat(red(` \uC2E4\uD328: ${err.message}`));
|
|
1489
|
+
sandbox = [bold(wf.name), "", red(`\uC2E4\uD328: ${err.message}`)];
|
|
1543
1490
|
}
|
|
1544
1491
|
statusMsg = getHint();
|
|
1545
1492
|
render();
|
|
1546
1493
|
}
|
|
1547
1494
|
async function loadWorkflowStructure(wf) {
|
|
1548
|
-
|
|
1495
|
+
sandbox = [bold(wf.name), "", yellow("\uB178\uB4DC/\uC5E3\uC9C0 \uB85C\uB529...")];
|
|
1549
1496
|
render();
|
|
1550
1497
|
try {
|
|
1551
1498
|
const { getWorkflowDetail: getWorkflowDetail2 } = await Promise.resolve().then(() => (init_workflow(), workflow_exports));
|
|
1552
|
-
const data = await withTimeout(getWorkflowDetail2(wf.id),
|
|
1553
|
-
const
|
|
1554
|
-
const ns =
|
|
1555
|
-
const es =
|
|
1556
|
-
|
|
1499
|
+
const data = await withTimeout(getWorkflowDetail2(wf.id), 8e3, "\uB85C\uB4DC");
|
|
1500
|
+
const wd = data?.workflow_data ?? data;
|
|
1501
|
+
const ns = wd?.nodes ?? data?.nodes ?? [];
|
|
1502
|
+
const es = wd?.edges ?? data?.edges ?? [];
|
|
1503
|
+
sandbox = [
|
|
1557
1504
|
bold(wf.name),
|
|
1558
|
-
"",
|
|
1559
1505
|
`\uB178\uB4DC ${ns.length}\uAC1C \uC5E3\uC9C0 ${es.length}\uAC1C`,
|
|
1560
1506
|
"",
|
|
1561
|
-
|
|
1562
|
-
...ns.
|
|
1563
|
-
const label = n.data?.label ?? n.data?.nodeName ?? n.type ?? "?";
|
|
1564
|
-
const nodeType = n.data?.nodeId ?? n.type ?? "";
|
|
1565
|
-
return ` ${i + 1}. ${label} ${dim(nodeType)}`;
|
|
1566
|
-
}),
|
|
1567
|
-
...ns.length > 15 ? [dim(` ... +${ns.length - 15}\uAC1C`)] : [],
|
|
1507
|
+
...ns.slice(0, 12).map((n, i) => ` ${i + 1}. ${n.data?.label ?? n.data?.nodeName ?? n.type ?? "?"} ${dim(n.data?.nodeId ?? "")}`),
|
|
1508
|
+
...ns.length > 12 ? [dim(` +${ns.length - 12}\uAC1C`)] : [],
|
|
1568
1509
|
"",
|
|
1569
1510
|
bold("\uC5F0\uACB0:"),
|
|
1570
|
-
...es.slice(0,
|
|
1571
|
-
const
|
|
1572
|
-
const
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
return ` ${srcName} \u2192 ${tgtName}`;
|
|
1576
|
-
}),
|
|
1577
|
-
...es.length > 8 ? [dim(` ... +${es.length - 8}\uAC1C`)] : [],
|
|
1578
|
-
"",
|
|
1579
|
-
cyan("i") + " \uC9C8\uBB38 \uC785\uB825 \uD6C4 \uC2E4\uD589"
|
|
1511
|
+
...es.slice(0, 6).map((e) => {
|
|
1512
|
+
const s = ns.find((n) => n.id === e.source);
|
|
1513
|
+
const t = ns.find((n) => n.id === e.target);
|
|
1514
|
+
return ` ${s?.data?.label ?? "?"} \u2192 ${t?.data?.label ?? "?"}`;
|
|
1515
|
+
})
|
|
1580
1516
|
];
|
|
1581
1517
|
} catch (err) {
|
|
1582
|
-
|
|
1518
|
+
sandbox = [bold(wf.name), "", red(err.message)];
|
|
1583
1519
|
}
|
|
1584
1520
|
render();
|
|
1585
1521
|
}
|
|
1586
1522
|
async function loadNodeDetail(n) {
|
|
1587
1523
|
if (!n.id) {
|
|
1588
|
-
|
|
1524
|
+
sandbox = [red("\uB178\uB4DC ID \uC5C6\uC74C")];
|
|
1589
1525
|
render();
|
|
1590
1526
|
return;
|
|
1591
1527
|
}
|
|
1592
|
-
|
|
1528
|
+
sandbox = [bold(n.name), yellow("\uB85C\uB529...")];
|
|
1593
1529
|
render();
|
|
1594
1530
|
try {
|
|
1595
1531
|
const { getNodeDetail: getNodeDetail2 } = await Promise.resolve().then(() => (init_xgen_extra(), xgen_extra_exports));
|
|
1596
|
-
const d = await withTimeout(getNodeDetail2(n.id),
|
|
1597
|
-
const
|
|
1598
|
-
const
|
|
1599
|
-
const params = d?.parameters ?? d?.
|
|
1600
|
-
const
|
|
1601
|
-
|
|
1602
|
-
bold(d?.nodeName ??
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
`\uCE74\uD14C\uACE0\uB9AC ${d?.category ?? d?.nodeCategory ?? dim("\uC5C6\uC74C")}`,
|
|
1606
|
-
`\uC124\uBA85 ${d?.description ?? dim("\uC5C6\uC74C")}`,
|
|
1607
|
-
"",
|
|
1608
|
-
bold(`\uC785\uB825 \uD3EC\uD2B8 (${inputs.length}):`),
|
|
1609
|
-
...inputs.slice(0, 5).map((p) => ` \u2022 ${p.name ?? p.id ?? "?"} ${dim(p.type ?? "")}`),
|
|
1610
|
-
"",
|
|
1611
|
-
bold(`\uCD9C\uB825 \uD3EC\uD2B8 (${outputs.length}):`),
|
|
1612
|
-
...outputs.slice(0, 5).map((p) => ` \u2022 ${p.name ?? p.id ?? "?"} ${dim(p.type ?? "")}`),
|
|
1532
|
+
const d = await withTimeout(getNodeDetail2(n.id), 5e3, "\uB178\uB4DC");
|
|
1533
|
+
const ins = d?.inputs ?? d?.inputPorts ?? [];
|
|
1534
|
+
const outs = d?.outputs ?? d?.outputPorts ?? [];
|
|
1535
|
+
const params = d?.parameters ?? d?.defaultParams ?? {};
|
|
1536
|
+
const pkeys = typeof params === "object" ? Object.keys(params) : [];
|
|
1537
|
+
sandbox = [
|
|
1538
|
+
bold(d?.nodeName ?? n.name),
|
|
1539
|
+
`ID: ${d?.nodeId ?? n.id}`,
|
|
1540
|
+
`\uCE74\uD14C\uACE0\uB9AC: ${d?.category ?? "?"}`,
|
|
1613
1541
|
"",
|
|
1614
|
-
bold(`\
|
|
1615
|
-
...
|
|
1542
|
+
bold(`\uC785\uB825(${ins.length}):`),
|
|
1543
|
+
...ins.slice(0, 4).map((p) => ` ${p.name ?? "?"} ${dim(p.type ?? "")}`),
|
|
1544
|
+
bold(`\uCD9C\uB825(${outs.length}):`),
|
|
1545
|
+
...outs.slice(0, 4).map((p) => ` ${p.name ?? "?"} ${dim(p.type ?? "")}`),
|
|
1546
|
+
bold(`\uD30C\uB77C\uBBF8\uD130(${pkeys.length}):`),
|
|
1547
|
+
...pkeys.slice(0, 6).map((k) => ` ${k}: ${dim(String(params[k]).slice(0, 25))}`)
|
|
1616
1548
|
];
|
|
1617
1549
|
} catch (err) {
|
|
1618
|
-
|
|
1550
|
+
sandbox = [red(err.message)];
|
|
1619
1551
|
}
|
|
1620
1552
|
render();
|
|
1621
1553
|
}
|
|
1622
|
-
function
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
{ key: "prompt_content", label: "\uB0B4\uC6A9", required: true },
|
|
1626
|
-
{ key: "prompt_type", label: "\uD0C0\uC785 (user/system)", default: "user" },
|
|
1627
|
-
{ key: "language", label: "\uC5B8\uC5B4 (ko/en)", default: "ko" }
|
|
1628
|
-
], async (v) => {
|
|
1629
|
-
detail = [bold("\uD504\uB86C\uD504\uD2B8 \uC0DD\uC131"), "", yellow("\uC800\uC7A5 \uC911...")];
|
|
1630
|
-
render();
|
|
1631
|
-
try {
|
|
1632
|
-
const { createPrompt: createPrompt2 } = await Promise.resolve().then(() => (init_xgen_extra(), xgen_extra_exports));
|
|
1633
|
-
await withTimeout(createPrompt2({ prompt_title: v.prompt_title, prompt_content: v.prompt_content, prompt_type: v.prompt_type || "user", language: v.language || "ko" }), 1e4, "\uC800\uC7A5");
|
|
1634
|
-
detail = [bold("\uD504\uB86C\uD504\uD2B8 \uC0DD\uC131"), "", green("\u2713 \uC800\uC7A5 \uC644\uB8CC!"), "", "r \uC0C8\uB85C\uACE0\uCE68"];
|
|
1635
|
-
statusMsg = green("\uC800\uC7A5 \uC644\uB8CC");
|
|
1636
|
-
} catch (err) {
|
|
1637
|
-
detail = [red(`\u2717 \uC2E4\uD328: ${err.message}`)];
|
|
1638
|
-
statusMsg = red("\uC2E4\uD328");
|
|
1639
|
-
}
|
|
1640
|
-
render();
|
|
1641
|
-
});
|
|
1642
|
-
}
|
|
1643
|
-
function startEditPrompt() {
|
|
1644
|
-
if (!prompts[selected]) return;
|
|
1645
|
-
const p = prompts[selected];
|
|
1646
|
-
if (!p.uid) {
|
|
1647
|
-
detail = [red("UID \uC5C6\uC74C \u2014 \uC218\uC815 \uBD88\uAC00")];
|
|
1648
|
-
render();
|
|
1649
|
-
return;
|
|
1650
|
-
}
|
|
1651
|
-
startForm("edit-prompt", `\uD504\uB86C\uD504\uD2B8 \uC218\uC815: ${p.name}`, [
|
|
1652
|
-
{ key: "prompt_title", label: "\uC81C\uBAA9", default: p.name },
|
|
1653
|
-
{ key: "prompt_content", label: "\uB0B4\uC6A9", default: p.content || "" },
|
|
1654
|
-
{ key: "prompt_type", label: "\uD0C0\uC785", default: p.type || "user" }
|
|
1655
|
-
], async (v) => {
|
|
1656
|
-
detail = [yellow("\uC218\uC815 \uC911...")];
|
|
1657
|
-
render();
|
|
1658
|
-
try {
|
|
1659
|
-
const { updatePrompt: updatePrompt2 } = await Promise.resolve().then(() => (init_xgen_extra(), xgen_extra_exports));
|
|
1660
|
-
await withTimeout(updatePrompt2({ prompt_uid: p.uid, prompt_title: v.prompt_title, prompt_content: v.prompt_content, prompt_type: v.prompt_type }), 1e4, "\uC218\uC815");
|
|
1661
|
-
detail = [green("\u2713 \uC218\uC815 \uC644\uB8CC!"), "", "r \uC0C8\uB85C\uACE0\uCE68"];
|
|
1662
|
-
statusMsg = green("\uC218\uC815 \uC644\uB8CC");
|
|
1663
|
-
} catch (err) {
|
|
1664
|
-
detail = [red(`\u2717 \uC2E4\uD328: ${err.message}`)];
|
|
1665
|
-
statusMsg = red("\uC2E4\uD328");
|
|
1666
|
-
}
|
|
1667
|
-
render();
|
|
1668
|
-
});
|
|
1669
|
-
}
|
|
1670
|
-
async function deleteSelectedPrompt() {
|
|
1671
|
-
if (!prompts[selected]?.uid) {
|
|
1672
|
-
detail = [red("UID \uC5C6\uC74C")];
|
|
1673
|
-
render();
|
|
1674
|
-
return;
|
|
1675
|
-
}
|
|
1676
|
-
const p = prompts[selected];
|
|
1677
|
-
detail = [bold(p.name), "", yellow("\uC0AD\uC81C \uC911...")];
|
|
1678
|
-
render();
|
|
1679
|
-
try {
|
|
1680
|
-
const { deletePrompt: deletePrompt2 } = await Promise.resolve().then(() => (init_xgen_extra(), xgen_extra_exports));
|
|
1681
|
-
await withTimeout(deletePrompt2(p.uid), 1e4, "\uC0AD\uC81C");
|
|
1682
|
-
detail = [green("\u2713 \uC0AD\uC81C \uC644\uB8CC!"), "", "r \uC0C8\uB85C\uACE0\uCE68"];
|
|
1683
|
-
statusMsg = green("\uC0AD\uC81C \uC644\uB8CC");
|
|
1684
|
-
} catch (err) {
|
|
1685
|
-
detail = [red(`\uC0AD\uC81C \uC2E4\uD328: ${err.message}`)];
|
|
1686
|
-
statusMsg = red("\uC2E4\uD328");
|
|
1687
|
-
}
|
|
1688
|
-
render();
|
|
1689
|
-
}
|
|
1690
|
-
async function uploadSelectedPromptToStore() {
|
|
1691
|
-
if (!prompts[selected]?.dbId) {
|
|
1692
|
-
detail = [red("DB ID \uC5C6\uC74C")];
|
|
1693
|
-
render();
|
|
1694
|
-
return;
|
|
1695
|
-
}
|
|
1696
|
-
const p = prompts[selected];
|
|
1697
|
-
detail = [bold(p.name), "", yellow("\uC2A4\uD1A0\uC5B4 \uB4F1\uB85D \uC911...")];
|
|
1698
|
-
render();
|
|
1699
|
-
try {
|
|
1700
|
-
const { uploadPromptToStore: uploadPromptToStore2 } = await Promise.resolve().then(() => (init_xgen_extra(), xgen_extra_exports));
|
|
1701
|
-
await withTimeout(uploadPromptToStore2(p.dbId), 1e4, "\uC2A4\uD1A0\uC5B4");
|
|
1702
|
-
detail = [green("\u2713 \uC2A4\uD1A0\uC5B4 \uB4F1\uB85D \uC644\uB8CC!")];
|
|
1703
|
-
statusMsg = green("\uB4F1\uB85D \uC644\uB8CC");
|
|
1704
|
-
} catch (err) {
|
|
1705
|
-
detail = [red(`\uC2E4\uD328: ${err.message}`)];
|
|
1706
|
-
statusMsg = red("\uC2E4\uD328");
|
|
1707
|
-
}
|
|
1708
|
-
render();
|
|
1709
|
-
}
|
|
1710
|
-
async function showPromptVersions() {
|
|
1711
|
-
if (!prompts[selected]?.uid) {
|
|
1712
|
-
detail = [red("UID \uC5C6\uC74C")];
|
|
1554
|
+
async function testTool(t) {
|
|
1555
|
+
if (!t.url) {
|
|
1556
|
+
sandbox = [red("URL \uC5C6\uC74C")];
|
|
1713
1557
|
render();
|
|
1714
1558
|
return;
|
|
1715
1559
|
}
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
render();
|
|
1719
|
-
try {
|
|
1720
|
-
const { listPromptVersions: listPromptVersions2 } = await Promise.resolve().then(() => (init_xgen_extra(), xgen_extra_exports));
|
|
1721
|
-
const vers = await withTimeout(listPromptVersions2(p.uid), 8e3, "\uBC84\uC804");
|
|
1722
|
-
if (!vers.length) {
|
|
1723
|
-
detail = [bold(p.name), "", dim("\uBC84\uC804 \uC5C6\uC74C")];
|
|
1724
|
-
} else {
|
|
1725
|
-
detail = [
|
|
1726
|
-
bold(p.name),
|
|
1727
|
-
"",
|
|
1728
|
-
bold(`\uBC84\uC804 ${vers.length}\uAC1C:`),
|
|
1729
|
-
"",
|
|
1730
|
-
...vers.slice(0, 15).map((v, i) => ` ${i + 1}. v${v.version ?? v.id ?? "?"} ${dim(v.label_name ?? v.created_at ?? "")}`)
|
|
1731
|
-
];
|
|
1732
|
-
}
|
|
1733
|
-
} catch (err) {
|
|
1734
|
-
detail = [red(`\uC2E4\uD328: ${err.message}`)];
|
|
1735
|
-
}
|
|
1736
|
-
render();
|
|
1737
|
-
}
|
|
1738
|
-
function startCreateTool() {
|
|
1739
|
-
startForm("create-tool", "\uC0C8 \uB3C4\uAD6C \uC0DD\uC131", [
|
|
1740
|
-
{ key: "function_name", label: "\uB3C4\uAD6C \uC774\uB984", required: true },
|
|
1741
|
-
{ key: "function_id", label: "\uB3C4\uAD6C ID (\uC601\uBB38)", required: true },
|
|
1742
|
-
{ key: "description", label: "\uC124\uBA85" },
|
|
1743
|
-
{ key: "api_url", label: "API URL", required: true },
|
|
1744
|
-
{ key: "api_method", label: "HTTP \uBA54\uC11C\uB4DC", default: "GET" },
|
|
1745
|
-
{ key: "api_timeout", label: "\uD0C0\uC784\uC544\uC6C3(\uCD08)", default: "30" }
|
|
1746
|
-
], async (v) => {
|
|
1747
|
-
detail = [bold("\uB3C4\uAD6C \uC0DD\uC131"), "", yellow("\uC800\uC7A5 \uC911...")];
|
|
1748
|
-
render();
|
|
1749
|
-
try {
|
|
1750
|
-
const { saveTool: saveTool2 } = await Promise.resolve().then(() => (init_xgen_extra(), xgen_extra_exports));
|
|
1751
|
-
await withTimeout(saveTool2(v.function_name, {
|
|
1752
|
-
function_name: v.function_name,
|
|
1753
|
-
function_id: v.function_id,
|
|
1754
|
-
description: v.description || "",
|
|
1755
|
-
api_url: v.api_url,
|
|
1756
|
-
api_method: v.api_method || "GET",
|
|
1757
|
-
api_timeout: parseInt(v.api_timeout || "30")
|
|
1758
|
-
}), 1e4, "\uC800\uC7A5");
|
|
1759
|
-
detail = [green("\u2713 \uB3C4\uAD6C \uC800\uC7A5 \uC644\uB8CC!"), "", "r \uC0C8\uB85C\uACE0\uCE68"];
|
|
1760
|
-
statusMsg = green("\uC800\uC7A5 \uC644\uB8CC");
|
|
1761
|
-
} catch (err) {
|
|
1762
|
-
detail = [red(`\u2717 \uC2E4\uD328: ${err.message}`)];
|
|
1763
|
-
statusMsg = red("\uC2E4\uD328");
|
|
1764
|
-
}
|
|
1765
|
-
render();
|
|
1766
|
-
});
|
|
1767
|
-
}
|
|
1768
|
-
async function testSelectedTool() {
|
|
1769
|
-
if (!tools2[selected]) return;
|
|
1770
|
-
const t = tools2[selected];
|
|
1771
|
-
if (!t.apiUrl) {
|
|
1772
|
-
detail = [bold(t.name), "", red("API URL \uC5C6\uC74C")];
|
|
1773
|
-
render();
|
|
1774
|
-
return;
|
|
1775
|
-
}
|
|
1776
|
-
detail = [bold(t.name), "", yellow("API \uD14C\uC2A4\uD2B8 \uC911..."), `URL: ${t.apiUrl}`];
|
|
1560
|
+
sandbox = [bold(t.name), yellow(`\uD14C\uC2A4\uD2B8: ${t.url}`)];
|
|
1561
|
+
addChat(yellow(` \uB3C4\uAD6C \uD14C\uC2A4\uD2B8: ${t.name}`));
|
|
1777
1562
|
render();
|
|
1778
1563
|
try {
|
|
1779
1564
|
const { apiTest: apiTest2 } = await Promise.resolve().then(() => (init_xgen_extra(), xgen_extra_exports));
|
|
1780
|
-
const r = await withTimeout(apiTest2({ api_url: t.
|
|
1565
|
+
const r = await withTimeout(apiTest2({ api_url: t.url, api_method: "GET", api_timeout: 10 }), 15e3, "\uD14C\uC2A4\uD2B8");
|
|
1781
1566
|
const ok = r?.success ?? (r?.data?.status && r.data.status < 400);
|
|
1782
1567
|
const st = r?.data?.status ?? "?";
|
|
1783
1568
|
const resp = r?.data?.response;
|
|
1784
|
-
const lines = (typeof resp === "string" ? resp : JSON.stringify(resp ?? {}, null, 2)).split("\n").slice(0,
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
} catch (err) {
|
|
1788
|
-
detail = [bold(t.name), "", red(`\uC2E4\uD328: ${err.message}`)];
|
|
1789
|
-
statusMsg = red("\uC2E4\uD328");
|
|
1790
|
-
}
|
|
1791
|
-
render();
|
|
1792
|
-
}
|
|
1793
|
-
async function uploadSelectedTool() {
|
|
1794
|
-
if (!tools2[selected]?.functionId) {
|
|
1795
|
-
detail = [red("function_id \uC5C6\uC74C")];
|
|
1796
|
-
render();
|
|
1797
|
-
return;
|
|
1798
|
-
}
|
|
1799
|
-
const t = tools2[selected];
|
|
1800
|
-
detail = [bold(t.name), "", yellow("\uC2A4\uD1A0\uC5B4 \uB4F1\uB85D \uC911...")];
|
|
1801
|
-
render();
|
|
1802
|
-
try {
|
|
1803
|
-
const { uploadToolToStore: uploadToolToStore2 } = await Promise.resolve().then(() => (init_xgen_extra(), xgen_extra_exports));
|
|
1804
|
-
await withTimeout(uploadToolToStore2(t.functionId, t.desc), 1e4, "\uB4F1\uB85D");
|
|
1805
|
-
detail = [green("\u2713 \uC2A4\uD1A0\uC5B4 \uB4F1\uB85D \uC644\uB8CC!")];
|
|
1806
|
-
statusMsg = green("\uB4F1\uB85D \uC644\uB8CC");
|
|
1569
|
+
const lines = (typeof resp === "string" ? resp : JSON.stringify(resp ?? {}, null, 2)).split("\n").slice(0, 10);
|
|
1570
|
+
sandbox = [bold(t.name), ok ? green(`\u2713 ${st} OK`) : red(`\u2717 ${st} FAIL`), "", ...lines];
|
|
1571
|
+
addChat(ok ? green(` \u2713 ${t.name} ${st} OK`) : red(` \u2717 ${t.name} ${st} FAIL`));
|
|
1807
1572
|
} catch (err) {
|
|
1808
|
-
|
|
1809
|
-
|
|
1573
|
+
sandbox = [red(err.message)];
|
|
1574
|
+
addChat(red(` \uC2E4\uD328: ${err.message}`));
|
|
1810
1575
|
}
|
|
1811
1576
|
render();
|
|
1812
1577
|
}
|
|
1813
|
-
function startCreateMcpSession() {
|
|
1814
|
-
startForm("create-mcp", "MCP \uC138\uC158 \uC0DD\uC131", [
|
|
1815
|
-
{ key: "session_name", label: "\uC138\uC158 \uC774\uB984", required: true },
|
|
1816
|
-
{ key: "server_type", label: "\uD0C0\uC785 (python/node)", required: true, default: "python" },
|
|
1817
|
-
{ key: "server_command", label: "\uC11C\uBC84 \uCEE4\uB9E8\uB4DC", required: true },
|
|
1818
|
-
{ key: "server_args", label: "\uCD94\uAC00 \uC778\uC790 (\uC27C\uD45C \uAD6C\uBD84)" },
|
|
1819
|
-
{ key: "working_dir", label: "\uC791\uC5C5 \uB514\uB809\uD1A0\uB9AC" }
|
|
1820
|
-
], async (v) => {
|
|
1821
|
-
detail = [yellow("MCP \uC138\uC158 \uC0DD\uC131 \uC911...")];
|
|
1822
|
-
render();
|
|
1823
|
-
try {
|
|
1824
|
-
const { createMcpSession: createMcpSession2 } = await Promise.resolve().then(() => (init_xgen_extra(), xgen_extra_exports));
|
|
1825
|
-
const args = v.server_args ? v.server_args.split(",").map((a) => a.trim()) : void 0;
|
|
1826
|
-
const r = await withTimeout(createMcpSession2({
|
|
1827
|
-
server_type: v.server_type,
|
|
1828
|
-
server_command: v.server_command,
|
|
1829
|
-
session_name: v.session_name,
|
|
1830
|
-
server_args: args,
|
|
1831
|
-
working_dir: v.working_dir || void 0
|
|
1832
|
-
}), 15e3, "MCP \uC138\uC158");
|
|
1833
|
-
detail = [green("\u2713 \uC138\uC158 \uC0DD\uC131 \uC644\uB8CC!"), "", `\uC138\uC158ID: ${r?.session_id ?? "?"}`, "", "r \uC0C8\uB85C\uACE0\uCE68"];
|
|
1834
|
-
statusMsg = green("MCP \uC138\uC158 \uC0DD\uC131 \uC644\uB8CC");
|
|
1835
|
-
} catch (err) {
|
|
1836
|
-
detail = [red(`\u2717 \uC2E4\uD328: ${err.message}`)];
|
|
1837
|
-
statusMsg = red("\uC2E4\uD328");
|
|
1838
|
-
}
|
|
1839
|
-
render();
|
|
1840
|
-
});
|
|
1841
|
-
}
|
|
1842
|
-
async function loadMcpTools() {
|
|
1843
|
-
if (!mcpSessions[selected]) return;
|
|
1844
|
-
const s = mcpSessions[selected];
|
|
1845
|
-
detail = [bold(s.name), "", yellow("\uB3C4\uAD6C \uBAA9\uB85D \uB85C\uB529...")];
|
|
1846
|
-
render();
|
|
1847
|
-
try {
|
|
1848
|
-
const { getMcpSessionTools: getMcpSessionTools2 } = await Promise.resolve().then(() => (init_xgen_extra(), xgen_extra_exports));
|
|
1849
|
-
const tools3 = await withTimeout(getMcpSessionTools2(s.id), 1e4, "MCP \uB3C4\uAD6C");
|
|
1850
|
-
if (!tools3.length) {
|
|
1851
|
-
detail = [bold(s.name), "", dim("\uB3C4\uAD6C \uC5C6\uC74C")];
|
|
1852
|
-
} else {
|
|
1853
|
-
detail = [
|
|
1854
|
-
bold(s.name),
|
|
1855
|
-
"",
|
|
1856
|
-
bold(`\uB3C4\uAD6C ${tools3.length}\uAC1C:`),
|
|
1857
|
-
"",
|
|
1858
|
-
...tools3.slice(0, 15).map((t, i) => {
|
|
1859
|
-
const name = t.name ?? t.function?.name ?? "?";
|
|
1860
|
-
const desc = (t.description ?? t.function?.description ?? "").slice(0, 40);
|
|
1861
|
-
return ` ${i + 1}. ${name} ${dim(desc)}`;
|
|
1862
|
-
}),
|
|
1863
|
-
...tools3.length > 15 ? [dim(` ... +${tools3.length - 15}\uAC1C`)] : [],
|
|
1864
|
-
"",
|
|
1865
|
-
cyan("t") + " \uB3C4\uAD6C \uD638\uCD9C \uD14C\uC2A4\uD2B8"
|
|
1866
|
-
];
|
|
1867
|
-
}
|
|
1868
|
-
} catch (err) {
|
|
1869
|
-
detail = [bold(s.name), "", red(`\uC2E4\uD328: ${err.message}`)];
|
|
1870
|
-
}
|
|
1871
|
-
render();
|
|
1872
|
-
}
|
|
1873
|
-
function startMcpToolCall() {
|
|
1874
|
-
if (!mcpSessions[selected]) return;
|
|
1875
|
-
const s = mcpSessions[selected];
|
|
1876
|
-
startForm("mcp-call", `MCP \uB3C4\uAD6C \uD638\uCD9C: ${s.name}`, [
|
|
1877
|
-
{ key: "tool_name", label: "\uB3C4\uAD6C \uC774\uB984", required: true },
|
|
1878
|
-
{ key: "params_json", label: "\uD30C\uB77C\uBBF8\uD130 (JSON)", default: "{}" }
|
|
1879
|
-
], async (v) => {
|
|
1880
|
-
detail = [yellow("MCP \uB3C4\uAD6C \uD638\uCD9C \uC911...")];
|
|
1881
|
-
render();
|
|
1882
|
-
try {
|
|
1883
|
-
const { sendMcpRequest: sendMcpRequest2 } = await Promise.resolve().then(() => (init_xgen_extra(), xgen_extra_exports));
|
|
1884
|
-
let params = {};
|
|
1885
|
-
try {
|
|
1886
|
-
params = JSON.parse(v.params_json || "{}");
|
|
1887
|
-
} catch {
|
|
1888
|
-
}
|
|
1889
|
-
const r = await withTimeout(sendMcpRequest2(s.id, "tools/call", { name: v.tool_name, arguments: params }), 2e4, "MCP \uD638\uCD9C");
|
|
1890
|
-
const ok = r?.success;
|
|
1891
|
-
const data = r?.data;
|
|
1892
|
-
const lines = (typeof data === "string" ? data : JSON.stringify(data ?? {}, null, 2)).split("\n").slice(0, 15);
|
|
1893
|
-
detail = [bold(`${s.name} \u2192 ${v.tool_name}`), "", ok ? green("\u2713 \uC131\uACF5") : red("\u2717 \uC2E4\uD328"), "", bold("\uC751\uB2F5:"), ...lines];
|
|
1894
|
-
statusMsg = ok ? green("\uD638\uCD9C \uC131\uACF5") : red("\uD638\uCD9C \uC2E4\uD328");
|
|
1895
|
-
} catch (err) {
|
|
1896
|
-
detail = [red(`\uC2E4\uD328: ${err.message}`)];
|
|
1897
|
-
statusMsg = red("\uC2E4\uD328");
|
|
1898
|
-
}
|
|
1899
|
-
render();
|
|
1900
|
-
});
|
|
1901
|
-
}
|
|
1902
|
-
async function deleteSelectedMcpSession() {
|
|
1903
|
-
if (!mcpSessions[selected]) return;
|
|
1904
|
-
const s = mcpSessions[selected];
|
|
1905
|
-
detail = [bold(s.name), "", yellow("\uC0AD\uC81C \uC911...")];
|
|
1906
|
-
render();
|
|
1907
|
-
try {
|
|
1908
|
-
const { deleteMcpSession: deleteMcpSession2 } = await Promise.resolve().then(() => (init_xgen_extra(), xgen_extra_exports));
|
|
1909
|
-
await withTimeout(deleteMcpSession2(s.id), 1e4, "\uC0AD\uC81C");
|
|
1910
|
-
detail = [green("\u2713 \uC138\uC158 \uC0AD\uC81C \uC644\uB8CC!"), "", "r \uC0C8\uB85C\uACE0\uCE68"];
|
|
1911
|
-
statusMsg = green("\uC0AD\uC81C \uC644\uB8CC");
|
|
1912
|
-
} catch (err) {
|
|
1913
|
-
detail = [red(`\uC2E4\uD328: ${err.message}`)];
|
|
1914
|
-
statusMsg = red("\uC2E4\uD328");
|
|
1915
|
-
}
|
|
1916
|
-
render();
|
|
1917
|
-
}
|
|
1918
|
-
function startForm(type, title, fields, onSubmit) {
|
|
1919
|
-
formCtx = { type, fields, step: 0, values: {}, onSubmit };
|
|
1920
|
-
inputBuffer = "";
|
|
1921
|
-
detail = [
|
|
1922
|
-
bold(title),
|
|
1923
|
-
"",
|
|
1924
|
-
...fields.map((f, i) => ` ${i === 0 ? cyan("\u25B8") : " "} ${f.label}${f.required ? red("*") : ""} ${f.default ? dim(`(\uAE30\uBCF8: ${f.default})`) : ""}`),
|
|
1925
|
-
"",
|
|
1926
|
-
dim("Enter: \uB2E4\uC74C \u2502 Esc: \uCDE8\uC18C")
|
|
1927
|
-
];
|
|
1928
|
-
statusMsg = `${fields[0].label} \uC785\uB825`;
|
|
1929
|
-
render();
|
|
1930
|
-
}
|
|
1931
1578
|
function handleKey(s) {
|
|
1932
|
-
if (
|
|
1933
|
-
if (s === "\x1B"
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
inputMode = false;
|
|
1937
|
-
updateDetail();
|
|
1938
|
-
statusMsg = getHint();
|
|
1579
|
+
if (inputActive) {
|
|
1580
|
+
if (s === "\x1B") {
|
|
1581
|
+
inputActive = false;
|
|
1582
|
+
inputBuf = "";
|
|
1939
1583
|
render();
|
|
1940
1584
|
return;
|
|
1941
1585
|
}
|
|
1942
1586
|
if (s === "\r" || s === "\n") {
|
|
1943
|
-
const
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1587
|
+
const val = inputBuf.trim();
|
|
1588
|
+
inputActive = false;
|
|
1589
|
+
inputBuf = "";
|
|
1590
|
+
if (val && tab === "workflows" && workflows[sel]) {
|
|
1591
|
+
runWorkflow(workflows[sel], val);
|
|
1592
|
+
} else if (val) {
|
|
1593
|
+
addChat(`${cyan("\u276F")} ${val}`);
|
|
1594
|
+
addChat(dim(" \uC6CC\uD06C\uD50C\uB85C\uC6B0\uB97C \uC120\uD0DD\uD55C \uD6C4 \uC9C8\uBB38\uC744 \uC785\uB825\uD558\uC138\uC694."));
|
|
1947
1595
|
render();
|
|
1948
|
-
return;
|
|
1949
|
-
}
|
|
1950
|
-
formCtx.values[field.key] = value;
|
|
1951
|
-
inputBuffer = "";
|
|
1952
|
-
formCtx.step++;
|
|
1953
|
-
if (formCtx.step >= formCtx.fields.length) {
|
|
1954
|
-
const ctx = formCtx;
|
|
1955
|
-
formCtx = null;
|
|
1956
|
-
inputMode = false;
|
|
1957
|
-
ctx.onSubmit(ctx.values);
|
|
1958
1596
|
} else {
|
|
1959
|
-
const nf = formCtx.fields[formCtx.step];
|
|
1960
|
-
detail = [
|
|
1961
|
-
bold(formCtx.type.includes("tool") ? "\uC0C8 \uB3C4\uAD6C" : formCtx.type.includes("prompt") ? "\uC0C8 \uD504\uB86C\uD504\uD2B8" : formCtx.type.includes("mcp") ? "MCP" : "\uC785\uB825"),
|
|
1962
|
-
"",
|
|
1963
|
-
...formCtx.fields.map((f, i) => {
|
|
1964
|
-
const val = formCtx.values[f.key];
|
|
1965
|
-
if (val !== void 0) return ` ${green("\u2713")} ${f.label}: ${val}`;
|
|
1966
|
-
if (i === formCtx.step) return ` ${cyan("\u25B8")} ${f.label}${f.required ? red("*") : ""} ${f.default ? dim(`(\uAE30\uBCF8: ${f.default})`) : ""}`;
|
|
1967
|
-
return ` ${f.label}`;
|
|
1968
|
-
}),
|
|
1969
|
-
"",
|
|
1970
|
-
dim(`${formCtx.step + 1}/${formCtx.fields.length} \u2502 Enter \u2502 Esc`)
|
|
1971
|
-
];
|
|
1972
|
-
statusMsg = `${nf.label} \uC785\uB825`;
|
|
1973
1597
|
render();
|
|
1974
1598
|
}
|
|
1975
1599
|
return;
|
|
1976
1600
|
}
|
|
1977
1601
|
if (s === "\x7F" || s === "\b") {
|
|
1978
|
-
|
|
1602
|
+
inputBuf = inputBuf.slice(0, -1);
|
|
1979
1603
|
render();
|
|
1980
1604
|
return;
|
|
1981
1605
|
}
|
|
1982
1606
|
if (s === "") {
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
inputMode = false;
|
|
1986
|
-
updateDetail();
|
|
1607
|
+
inputActive = false;
|
|
1608
|
+
inputBuf = "";
|
|
1987
1609
|
render();
|
|
1988
1610
|
return;
|
|
1989
1611
|
}
|
|
1990
|
-
if (s.
|
|
1991
|
-
|
|
1992
|
-
render();
|
|
1993
|
-
return;
|
|
1994
|
-
}
|
|
1995
|
-
return;
|
|
1996
|
-
}
|
|
1997
|
-
if (inputMode) {
|
|
1998
|
-
if (s === "\x1B" || s === "\x1B\x1B") {
|
|
1999
|
-
inputMode = false;
|
|
2000
|
-
inputBuffer = "";
|
|
2001
|
-
updateDetail();
|
|
2002
|
-
statusMsg = getHint();
|
|
2003
|
-
render();
|
|
2004
|
-
return;
|
|
2005
|
-
}
|
|
2006
|
-
if (s === "\r" || s === "\n") {
|
|
2007
|
-
const val = inputBuffer.trim();
|
|
2008
|
-
inputMode = false;
|
|
2009
|
-
inputBuffer = "";
|
|
2010
|
-
if (val && tab === "workflows" && workflows[selected]) {
|
|
2011
|
-
runWorkflow(workflows[selected], val);
|
|
2012
|
-
} else {
|
|
2013
|
-
render();
|
|
2014
|
-
}
|
|
2015
|
-
return;
|
|
2016
|
-
}
|
|
2017
|
-
if (s === "\x7F" || s === "\b") {
|
|
2018
|
-
inputBuffer = inputBuffer.slice(0, -1);
|
|
2019
|
-
render();
|
|
2020
|
-
return;
|
|
2021
|
-
}
|
|
2022
|
-
if (s === "") {
|
|
2023
|
-
inputMode = false;
|
|
2024
|
-
inputBuffer = "";
|
|
2025
|
-
render();
|
|
2026
|
-
return;
|
|
2027
|
-
}
|
|
2028
|
-
if (s.length > 0 && s.charCodeAt(0) >= 32) {
|
|
2029
|
-
inputBuffer += s;
|
|
1612
|
+
if (s.charCodeAt(0) >= 32) {
|
|
1613
|
+
inputBuf += s;
|
|
2030
1614
|
render();
|
|
2031
1615
|
return;
|
|
2032
1616
|
}
|
|
@@ -2040,92 +1624,103 @@ async function startRawTui() {
|
|
|
2040
1624
|
loadData();
|
|
2041
1625
|
return;
|
|
2042
1626
|
}
|
|
2043
|
-
if (s ===
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
statusMsg = `${workflows[selected].name} \u2014 \uC9C8\uBB38 \uC785\uB825 \uD6C4 Enter, Esc \uCDE8\uC18C`;
|
|
1627
|
+
if (s.length === 1 && s.charCodeAt(0) >= 32 && !/^[0-9cutedvq]$/i.test(s)) {
|
|
1628
|
+
inputActive = true;
|
|
1629
|
+
inputBuf = s;
|
|
2047
1630
|
render();
|
|
2048
1631
|
return;
|
|
2049
1632
|
}
|
|
2050
|
-
if (s
|
|
1633
|
+
if (/^[cC]$/.test(s)) {
|
|
2051
1634
|
if (tab === "tools") {
|
|
2052
|
-
|
|
1635
|
+
addChat(cyan(" \uB3C4\uAD6C \uC0DD\uC131\uC740 xgen agent\uC5D0\uC11C: '\uC0C8 \uB3C4\uAD6C \uB9CC\uB4E4\uC5B4\uC918'"));
|
|
1636
|
+
render();
|
|
2053
1637
|
return;
|
|
2054
1638
|
}
|
|
2055
1639
|
if (tab === "prompts") {
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
}
|
|
2059
|
-
if (tab === "mcp") {
|
|
2060
|
-
startCreateMcpSession();
|
|
2061
|
-
return;
|
|
2062
|
-
}
|
|
2063
|
-
}
|
|
2064
|
-
if (s === "t" || s === "T") {
|
|
2065
|
-
if (tab === "tools") {
|
|
2066
|
-
testSelectedTool();
|
|
1640
|
+
addChat(cyan(" \uD504\uB86C\uD504\uD2B8 \uC0DD\uC131\uC740 xgen agent\uC5D0\uC11C: '\uD504\uB86C\uD504\uD2B8 \uB9CC\uB4E4\uC5B4\uC918'"));
|
|
1641
|
+
render();
|
|
2067
1642
|
return;
|
|
2068
1643
|
}
|
|
2069
1644
|
if (tab === "mcp") {
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
}
|
|
2073
|
-
}
|
|
2074
|
-
if (s === "u" || s === "U") {
|
|
2075
|
-
if (tab === "tools") {
|
|
2076
|
-
uploadSelectedTool();
|
|
2077
|
-
return;
|
|
2078
|
-
}
|
|
2079
|
-
if (tab === "prompts") {
|
|
2080
|
-
uploadSelectedPromptToStore();
|
|
1645
|
+
addChat(cyan(" MCP \uC138\uC158 \uC0DD\uC131\uC740 xgen agent\uC5D0\uC11C: 'MCP \uC138\uC158 \uB9CC\uB4E4\uC5B4\uC918'"));
|
|
1646
|
+
render();
|
|
2081
1647
|
return;
|
|
2082
1648
|
}
|
|
2083
1649
|
}
|
|
2084
|
-
if (s === "
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
return;
|
|
2088
|
-
}
|
|
1650
|
+
if (/^[tT]$/.test(s) && tab === "tools" && tools2[sel]) {
|
|
1651
|
+
testTool(tools2[sel]);
|
|
1652
|
+
return;
|
|
2089
1653
|
}
|
|
2090
|
-
if (s
|
|
2091
|
-
if (tab === "prompts") {
|
|
2092
|
-
|
|
1654
|
+
if (/^[dD]$/.test(s)) {
|
|
1655
|
+
if (tab === "prompts" && prompts[sel]?.uid) {
|
|
1656
|
+
sandbox = [yellow("\uC0AD\uC81C \uC911...")];
|
|
1657
|
+
render();
|
|
1658
|
+
Promise.resolve().then(() => (init_xgen_extra(), xgen_extra_exports)).then(async (m) => {
|
|
1659
|
+
try {
|
|
1660
|
+
await m.deletePrompt(prompts[sel].uid);
|
|
1661
|
+
sandbox = [green("\uC0AD\uC81C \uC644\uB8CC")];
|
|
1662
|
+
addChat(green(" \uD504\uB86C\uD504\uD2B8 \uC0AD\uC81C\uB428"));
|
|
1663
|
+
} catch (e) {
|
|
1664
|
+
sandbox = [red(e.message)];
|
|
1665
|
+
}
|
|
1666
|
+
render();
|
|
1667
|
+
});
|
|
2093
1668
|
return;
|
|
2094
1669
|
}
|
|
2095
|
-
if (tab === "mcp") {
|
|
2096
|
-
|
|
1670
|
+
if (tab === "mcp" && mcpSessions[sel]) {
|
|
1671
|
+
const sid = mcpSessions[sel].id;
|
|
1672
|
+
sandbox = [yellow("\uC0AD\uC81C \uC911...")];
|
|
1673
|
+
render();
|
|
1674
|
+
Promise.resolve().then(() => (init_xgen_extra(), xgen_extra_exports)).then(async (m) => {
|
|
1675
|
+
try {
|
|
1676
|
+
await m.deleteMcpSession(sid);
|
|
1677
|
+
sandbox = [green("\uC0AD\uC81C \uC644\uB8CC")];
|
|
1678
|
+
} catch (e) {
|
|
1679
|
+
sandbox = [red(e.message)];
|
|
1680
|
+
}
|
|
1681
|
+
render();
|
|
1682
|
+
});
|
|
2097
1683
|
return;
|
|
2098
1684
|
}
|
|
2099
1685
|
}
|
|
2100
|
-
if (s === "
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
1686
|
+
if (/^[uU]$/.test(s) && tab === "tools" && tools2[sel]?.fid) {
|
|
1687
|
+
sandbox = [yellow("\uC2A4\uD1A0\uC5B4 \uB4F1\uB85D \uC911...")];
|
|
1688
|
+
render();
|
|
1689
|
+
Promise.resolve().then(() => (init_xgen_extra(), xgen_extra_exports)).then(async (m) => {
|
|
1690
|
+
try {
|
|
1691
|
+
await m.uploadToolToStore(tools2[sel].fid, tools2[sel].desc);
|
|
1692
|
+
sandbox = [green("\uC2A4\uD1A0\uC5B4 \uB4F1\uB85D \uC644\uB8CC")];
|
|
1693
|
+
addChat(green(" \uC2A4\uD1A0\uC5B4 \uB4F1\uB85D\uB428"));
|
|
1694
|
+
} catch (e) {
|
|
1695
|
+
sandbox = [red(e.message)];
|
|
1696
|
+
}
|
|
1697
|
+
render();
|
|
1698
|
+
});
|
|
1699
|
+
return;
|
|
2105
1700
|
}
|
|
2106
|
-
const
|
|
2107
|
-
if (
|
|
2108
|
-
tab = TABS[
|
|
2109
|
-
|
|
2110
|
-
|
|
1701
|
+
const n = parseInt(s);
|
|
1702
|
+
if (n >= 1 && n <= 6) {
|
|
1703
|
+
tab = TABS[n - 1].key;
|
|
1704
|
+
sel = 0;
|
|
1705
|
+
updateSandbox();
|
|
2111
1706
|
statusMsg = getHint();
|
|
2112
1707
|
render();
|
|
2113
1708
|
return;
|
|
2114
1709
|
}
|
|
2115
1710
|
if (s === " ") {
|
|
2116
|
-
const
|
|
2117
|
-
tab = TABS[(
|
|
2118
|
-
|
|
2119
|
-
|
|
1711
|
+
const i = TABS.findIndex((t) => t.key === tab);
|
|
1712
|
+
tab = TABS[(i + 1) % TABS.length].key;
|
|
1713
|
+
sel = 0;
|
|
1714
|
+
updateSandbox();
|
|
2120
1715
|
statusMsg = getHint();
|
|
2121
1716
|
render();
|
|
2122
1717
|
return;
|
|
2123
1718
|
}
|
|
2124
1719
|
if (s === "\x1B[Z") {
|
|
2125
|
-
const
|
|
2126
|
-
tab = TABS[(
|
|
2127
|
-
|
|
2128
|
-
|
|
1720
|
+
const i = TABS.findIndex((t) => t.key === tab);
|
|
1721
|
+
tab = TABS[(i - 1 + TABS.length) % TABS.length].key;
|
|
1722
|
+
sel = 0;
|
|
1723
|
+
updateSandbox();
|
|
2129
1724
|
statusMsg = getHint();
|
|
2130
1725
|
render();
|
|
2131
1726
|
return;
|
|
@@ -2133,8 +1728,8 @@ async function startRawTui() {
|
|
|
2133
1728
|
if (s === "\x1B[A") {
|
|
2134
1729
|
const items = getItems();
|
|
2135
1730
|
if (items.length > 0) {
|
|
2136
|
-
|
|
2137
|
-
|
|
1731
|
+
sel = Math.max(0, sel - 1);
|
|
1732
|
+
updateSandbox();
|
|
2138
1733
|
render();
|
|
2139
1734
|
}
|
|
2140
1735
|
return;
|
|
@@ -2142,57 +1737,59 @@ async function startRawTui() {
|
|
|
2142
1737
|
if (s === "\x1B[B") {
|
|
2143
1738
|
const items = getItems();
|
|
2144
1739
|
if (items.length > 0) {
|
|
2145
|
-
|
|
2146
|
-
|
|
1740
|
+
sel = Math.min(items.length - 1, sel + 1);
|
|
1741
|
+
updateSandbox();
|
|
2147
1742
|
render();
|
|
2148
1743
|
}
|
|
2149
1744
|
return;
|
|
2150
1745
|
}
|
|
2151
1746
|
if (s === "\x1B[5~") {
|
|
2152
|
-
|
|
2153
|
-
|
|
1747
|
+
sel = Math.max(0, sel - 10);
|
|
1748
|
+
updateSandbox();
|
|
2154
1749
|
render();
|
|
2155
1750
|
return;
|
|
2156
1751
|
}
|
|
2157
1752
|
if (s === "\x1B[6~") {
|
|
2158
1753
|
const items = getItems();
|
|
2159
|
-
|
|
2160
|
-
|
|
1754
|
+
sel = Math.min(items.length - 1, sel + 10);
|
|
1755
|
+
updateSandbox();
|
|
2161
1756
|
render();
|
|
2162
1757
|
return;
|
|
2163
1758
|
}
|
|
2164
1759
|
if (s === "\r" || s === "\n") {
|
|
2165
1760
|
const items = getItems();
|
|
2166
1761
|
if (items.length === 0) return;
|
|
2167
|
-
if (tab === "workflows" && workflows[
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
const c = collections[selected];
|
|
2171
|
-
detail = [bold(c.name), "", yellow("\uBB38\uC11C \uB85C\uB529...")];
|
|
1762
|
+
if (tab === "workflows" && workflows[sel]) loadWorkflowStructure(workflows[sel]);
|
|
1763
|
+
else if (tab === "collections" && collections[sel]) {
|
|
1764
|
+
sandbox = [bold(collections[sel].name), yellow("\uBB38\uC11C \uB85C\uB529...")];
|
|
2172
1765
|
render();
|
|
2173
1766
|
Promise.resolve().then(() => (init_document(), document_exports)).then(async (m) => {
|
|
2174
1767
|
try {
|
|
2175
|
-
const docs = await withTimeout(m.listDocuments(String(
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
detail = [bold(c.name) + ` \u2014 ${docs.length}\uAC1C`, "", ...docs.map((d, i) => ` ${i + 1}. ${d.name || d.file_name || "?"}`).slice(0, 20)];
|
|
2180
|
-
}
|
|
2181
|
-
} catch (err) {
|
|
2182
|
-
detail = [red(`\uC2E4\uD328: ${err.message}`)];
|
|
1768
|
+
const docs = await withTimeout(m.listDocuments(String(collections[sel].id)), 5e3, "\uBB38\uC11C");
|
|
1769
|
+
sandbox = docs?.length ? [bold(collections[sel].name) + ` ${docs.length}\uAC1C`, "", ...docs.map((d, i) => ` ${i + 1}. ${d.name || d.file_name || "?"}`).slice(0, 15)] : [bold(collections[sel].name), dim("\uBB38\uC11C \uC5C6\uC74C")];
|
|
1770
|
+
} catch (e) {
|
|
1771
|
+
sandbox = [red(e.message)];
|
|
2183
1772
|
}
|
|
2184
1773
|
render();
|
|
2185
1774
|
});
|
|
2186
|
-
} else if (tab === "nodes" && nodes[
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
1775
|
+
} else if (tab === "nodes" && nodes[sel]) loadNodeDetail(nodes[sel]);
|
|
1776
|
+
else if (tab === "prompts" && prompts[sel]) {
|
|
1777
|
+
const p = prompts[sel];
|
|
1778
|
+
sandbox = [bold(p.name), `\uD0C0\uC785: ${p.type}`, `UID: ${p.uid ?? "?"}`, "", ...p.content?.split("\n").slice(0, 15) ?? [dim("\uC5C6\uC74C")]];
|
|
1779
|
+
render();
|
|
1780
|
+
} else if (tab === "tools" && tools2[sel]) testTool(tools2[sel]);
|
|
1781
|
+
else if (tab === "mcp" && mcpSessions[sel]) {
|
|
1782
|
+
sandbox = [bold(mcpSessions[sel].name), yellow("\uB3C4\uAD6C \uB85C\uB529...")];
|
|
2191
1783
|
render();
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
1784
|
+
Promise.resolve().then(() => (init_xgen_extra(), xgen_extra_exports)).then(async (m) => {
|
|
1785
|
+
try {
|
|
1786
|
+
const ts = await withTimeout(m.getMcpSessionTools(mcpSessions[sel].id), 8e3, "MCP");
|
|
1787
|
+
sandbox = ts?.length ? [bold(mcpSessions[sel].name) + ` ${ts.length}\uAC1C \uB3C4\uAD6C`, "", ...ts.map((t, i) => ` ${i + 1}. ${t.name ?? "?"} ${dim(t.description?.slice(0, 30) ?? "")}`).slice(0, 15)] : [bold(mcpSessions[sel].name), dim("\uB3C4\uAD6C \uC5C6\uC74C")];
|
|
1788
|
+
} catch (e) {
|
|
1789
|
+
sandbox = [red(e.message)];
|
|
1790
|
+
}
|
|
1791
|
+
render();
|
|
1792
|
+
});
|
|
2196
1793
|
}
|
|
2197
1794
|
return;
|
|
2198
1795
|
}
|
|
@@ -2205,18 +1802,18 @@ async function startRawTui() {
|
|
|
2205
1802
|
process.stdin.pause();
|
|
2206
1803
|
}
|
|
2207
1804
|
if (!process.stdin.isTTY) {
|
|
2208
|
-
console.error("\
|
|
1805
|
+
console.error("\uD130\uBBF8\uB110(TTY)\uC5D0\uC11C\uB9CC \uC2E4\uD589 \uAC00\uB2A5\uD569\uB2C8\uB2E4.");
|
|
2209
1806
|
return;
|
|
2210
1807
|
}
|
|
2211
1808
|
process.stdin.setRawMode(true);
|
|
2212
1809
|
process.stdin.resume();
|
|
2213
1810
|
process.stdin.setEncoding("utf8");
|
|
2214
1811
|
hideCursor();
|
|
2215
|
-
process.stdin.on("data", (
|
|
1812
|
+
process.stdin.on("data", (d) => {
|
|
2216
1813
|
try {
|
|
2217
|
-
handleKey(String(
|
|
2218
|
-
} catch (
|
|
2219
|
-
statusMsg = red(
|
|
1814
|
+
handleKey(String(d));
|
|
1815
|
+
} catch (e) {
|
|
1816
|
+
statusMsg = red(e.message);
|
|
2220
1817
|
render();
|
|
2221
1818
|
}
|
|
2222
1819
|
});
|
|
@@ -3665,6 +3262,141 @@ ID: ${d.id}
|
|
|
3665
3262
|
}
|
|
3666
3263
|
};
|
|
3667
3264
|
|
|
3265
|
+
// src/agent/tools/tool-search.ts
|
|
3266
|
+
var TOOL_INDEX = {
|
|
3267
|
+
workflow: {
|
|
3268
|
+
description: "\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uAD00\uB9AC \u2014 \uBAA9\uB85D, \uC2E4\uD589, \uC0C1\uC138, \uC774\uB825, \uC131\uB2A5, \uC2A4\uD1A0\uC5B4, \uC790\uB3D9\uC0DD\uC131",
|
|
3269
|
+
tools: ["xgen_workflow_list", "xgen_workflow_run", "xgen_workflow_info", "xgen_execution_history", "xgen_workflow_performance", "xgen_workflow_store", "xgen_workflow_generate"]
|
|
3270
|
+
},
|
|
3271
|
+
document: {
|
|
3272
|
+
description: "\uBB38\uC11C/\uCEEC\uB809\uC158 \uAD00\uB9AC \u2014 \uCEEC\uB809\uC158 \uBAA9\uB85D, \uBB38\uC11C \uBAA9\uB85D, \uC5C5\uB85C\uB4DC",
|
|
3273
|
+
tools: ["xgen_collection_list", "xgen_document_list", "xgen_document_upload"]
|
|
3274
|
+
},
|
|
3275
|
+
node: {
|
|
3276
|
+
description: "\uB178\uB4DC \uD0D0\uC0C9 \u2014 \uC804\uCCB4 \uBAA9\uB85D, \uAC80\uC0C9, \uCE74\uD14C\uACE0\uB9AC",
|
|
3277
|
+
tools: ["xgen_node_list", "xgen_node_search", "xgen_node_categories"]
|
|
3278
|
+
},
|
|
3279
|
+
prompt: {
|
|
3280
|
+
description: "\uD504\uB86C\uD504\uD2B8 \uB77C\uC774\uBE0C\uB7EC\uB9AC \u2014 \uBAA9\uB85D \uC870\uD68C",
|
|
3281
|
+
tools: ["xgen_prompt_list"]
|
|
3282
|
+
},
|
|
3283
|
+
tool: {
|
|
3284
|
+
description: "\uB3C4\uAD6C \uC2A4\uD1A0\uC5B4 \u2014 \uACF5\uAC1C \uB3C4\uAD6C, \uB0B4 \uB3C4\uAD6C",
|
|
3285
|
+
tools: ["xgen_tool_store", "xgen_user_tools"]
|
|
3286
|
+
},
|
|
3287
|
+
schedule: {
|
|
3288
|
+
description: "\uC2A4\uCF00\uC904 \uAD00\uB9AC \u2014 cron \uC791\uC5C5 \uBAA9\uB85D",
|
|
3289
|
+
tools: ["xgen_schedule_list"]
|
|
3290
|
+
},
|
|
3291
|
+
trace: {
|
|
3292
|
+
description: "\uD2B8\uB808\uC774\uC2A4/\uC778\uD130\uB799\uC158 \u2014 \uC2E4\uD589 \uCD94\uC801, \uBA54\uD0C0\uB370\uC774\uD130",
|
|
3293
|
+
tools: ["xgen_trace_list", "xgen_interaction_list"]
|
|
3294
|
+
},
|
|
3295
|
+
graph: {
|
|
3296
|
+
description: "\uC628\uD1A8\uB85C\uC9C0 GraphRAG \u2014 \uC9C8\uC758, \uADF8\uB798\uD504 \uD1B5\uACC4",
|
|
3297
|
+
tools: ["xgen_graph_rag_query", "xgen_graph_stats"]
|
|
3298
|
+
},
|
|
3299
|
+
mcp: {
|
|
3300
|
+
description: "MCP \uC138\uC158 \uAD00\uB9AC \u2014 \uC138\uC158 \uBAA9\uB85D",
|
|
3301
|
+
tools: ["xgen_mcp_sessions"]
|
|
3302
|
+
},
|
|
3303
|
+
server: {
|
|
3304
|
+
description: "\uC11C\uBC84 \uC0C1\uD0DC \uD655\uC778",
|
|
3305
|
+
tools: ["xgen_server_status"]
|
|
3306
|
+
}
|
|
3307
|
+
};
|
|
3308
|
+
var loadedTools = /* @__PURE__ */ new Set();
|
|
3309
|
+
function getToolIndexSummary() {
|
|
3310
|
+
const lines = Object.entries(TOOL_INDEX).map(
|
|
3311
|
+
([cat, info]) => ` - ${cat}: ${info.description}`
|
|
3312
|
+
);
|
|
3313
|
+
return `Available XGEN tool categories (use tool_search to load):
|
|
3314
|
+
${lines.join("\n")}`;
|
|
3315
|
+
}
|
|
3316
|
+
function searchTools(query) {
|
|
3317
|
+
const q = query.toLowerCase().trim();
|
|
3318
|
+
const matched = [];
|
|
3319
|
+
const matchedNames = [];
|
|
3320
|
+
if (TOOL_INDEX[q]) {
|
|
3321
|
+
for (const name of TOOL_INDEX[q].tools) {
|
|
3322
|
+
const def = definitions.find((d) => d.function.name === name);
|
|
3323
|
+
if (def && !loadedTools.has(name)) {
|
|
3324
|
+
matched.push(def);
|
|
3325
|
+
loadedTools.add(name);
|
|
3326
|
+
matchedNames.push(name);
|
|
3327
|
+
}
|
|
3328
|
+
}
|
|
3329
|
+
}
|
|
3330
|
+
if (matched.length === 0) {
|
|
3331
|
+
for (const def of definitions) {
|
|
3332
|
+
const name = def.function.name;
|
|
3333
|
+
const desc = def.function.description ?? "";
|
|
3334
|
+
if ((name.includes(q) || desc.toLowerCase().includes(q)) && !loadedTools.has(name)) {
|
|
3335
|
+
matched.push(def);
|
|
3336
|
+
loadedTools.add(name);
|
|
3337
|
+
matchedNames.push(name);
|
|
3338
|
+
}
|
|
3339
|
+
}
|
|
3340
|
+
}
|
|
3341
|
+
if (matched.length === 0) {
|
|
3342
|
+
for (const [cat, info] of Object.entries(TOOL_INDEX)) {
|
|
3343
|
+
if (cat.includes(q) || info.description.includes(q)) {
|
|
3344
|
+
for (const name of info.tools) {
|
|
3345
|
+
const def = definitions.find((d) => d.function.name === name);
|
|
3346
|
+
if (def && !loadedTools.has(name)) {
|
|
3347
|
+
matched.push(def);
|
|
3348
|
+
loadedTools.add(name);
|
|
3349
|
+
matchedNames.push(name);
|
|
3350
|
+
}
|
|
3351
|
+
}
|
|
3352
|
+
}
|
|
3353
|
+
}
|
|
3354
|
+
}
|
|
3355
|
+
if (matched.length === 0) {
|
|
3356
|
+
return {
|
|
3357
|
+
tools: [],
|
|
3358
|
+
summary: `"${query}"\uC5D0 \uD574\uB2F9\uD558\uB294 \uB3C4\uAD6C \uC5C6\uC74C. \uCE74\uD14C\uACE0\uB9AC: ${Object.keys(TOOL_INDEX).join(", ")}`
|
|
3359
|
+
};
|
|
3360
|
+
}
|
|
3361
|
+
return {
|
|
3362
|
+
tools: matched,
|
|
3363
|
+
summary: `${matched.length}\uAC1C \uB3C4\uAD6C \uB85C\uB4DC\uB428: ${matchedNames.join(", ")}`
|
|
3364
|
+
};
|
|
3365
|
+
}
|
|
3366
|
+
function getLoadedToolDefs() {
|
|
3367
|
+
return definitions.filter((d) => loadedTools.has(d.function.name));
|
|
3368
|
+
}
|
|
3369
|
+
function resetLoadedTools() {
|
|
3370
|
+
loadedTools.clear();
|
|
3371
|
+
}
|
|
3372
|
+
var definition8 = {
|
|
3373
|
+
type: "function",
|
|
3374
|
+
function: {
|
|
3375
|
+
name: "tool_search",
|
|
3376
|
+
description: "XGEN \uD50C\uB7AB\uD3FC \uB3C4\uAD6C\uB97C \uCE74\uD14C\uACE0\uB9AC/\uD0A4\uC6CC\uB4DC\uB85C \uAC80\uC0C9\uD558\uC5EC \uB85C\uB4DC\uD569\uB2C8\uB2E4. \uC6CC\uD06C\uD50C\uB85C\uC6B0, \uBB38\uC11C, \uB178\uB4DC, \uD504\uB86C\uD504\uD2B8, \uADF8\uB798\uD504 \uB4F1\uC758 \uB3C4\uAD6C\uB97C \uD544\uC694\uD560 \uB54C \uC774 \uB3C4\uAD6C\uB85C \uB85C\uB4DC\uD558\uC138\uC694. \uCE74\uD14C\uACE0\uB9AC: workflow, document, node, prompt, tool, graph, mcp, trace, schedule, server",
|
|
3377
|
+
parameters: {
|
|
3378
|
+
type: "object",
|
|
3379
|
+
properties: {
|
|
3380
|
+
query: {
|
|
3381
|
+
type: "string",
|
|
3382
|
+
description: "\uAC80\uC0C9 \uCE74\uD14C\uACE0\uB9AC \uB610\uB294 \uD0A4\uC6CC\uB4DC (\uC608: 'workflow', '\uB178\uB4DC', 'GraphRAG')"
|
|
3383
|
+
}
|
|
3384
|
+
},
|
|
3385
|
+
required: ["query"]
|
|
3386
|
+
}
|
|
3387
|
+
}
|
|
3388
|
+
};
|
|
3389
|
+
async function execute9(args) {
|
|
3390
|
+
const query = args.query;
|
|
3391
|
+
if (!query) return "query \uD30C\uB77C\uBBF8\uD130 \uD544\uC694. \uCE74\uD14C\uACE0\uB9AC: " + Object.keys(TOOL_INDEX).join(", ");
|
|
3392
|
+
const result = searchTools(query);
|
|
3393
|
+
return result.summary;
|
|
3394
|
+
}
|
|
3395
|
+
function getNewlyLoadedTools(query) {
|
|
3396
|
+
const result = searchTools(query);
|
|
3397
|
+
return result.tools;
|
|
3398
|
+
}
|
|
3399
|
+
|
|
3668
3400
|
// src/mcp/client.ts
|
|
3669
3401
|
import { spawn } from "child_process";
|
|
3670
3402
|
import { existsSync as existsSync3, readFileSync as readFileSync4 } from "fs";
|
|
@@ -3823,6 +3555,116 @@ var McpManager = class {
|
|
|
3823
3555
|
}
|
|
3824
3556
|
};
|
|
3825
3557
|
|
|
3558
|
+
// src/agent/hooks.ts
|
|
3559
|
+
init_store();
|
|
3560
|
+
var preHooks = [
|
|
3561
|
+
// XGEN 미연결 시 XGEN 도구 차단
|
|
3562
|
+
{
|
|
3563
|
+
match: (name) => name.startsWith("xgen_"),
|
|
3564
|
+
handler: () => {
|
|
3565
|
+
if (!getServer() || !getAuth()) {
|
|
3566
|
+
return { proceed: false, message: "XGEN \uC11C\uBC84 \uBBF8\uC5F0\uACB0. /connect\uB85C \uC5F0\uACB0\uD558\uC138\uC694." };
|
|
3567
|
+
}
|
|
3568
|
+
return { proceed: true };
|
|
3569
|
+
}
|
|
3570
|
+
},
|
|
3571
|
+
// 위험한 bash 명령 경고
|
|
3572
|
+
{
|
|
3573
|
+
match: (name) => name === "bash",
|
|
3574
|
+
handler: (_name, args) => {
|
|
3575
|
+
const cmd = String(args.command ?? "");
|
|
3576
|
+
if (/rm\s+-rf\s+[\/~]|dd\s+if=|mkfs|>\s*\/dev\/sd/.test(cmd)) {
|
|
3577
|
+
return { proceed: false, message: `\uC704\uD5D8\uD55C \uBA85\uB839\uC5B4 \uCC28\uB2E8: ${cmd.slice(0, 50)}` };
|
|
3578
|
+
}
|
|
3579
|
+
return { proceed: true };
|
|
3580
|
+
}
|
|
3581
|
+
}
|
|
3582
|
+
];
|
|
3583
|
+
var postHooks = [
|
|
3584
|
+
// 결과가 너무 길면 자동 truncate + 안내
|
|
3585
|
+
{
|
|
3586
|
+
match: () => true,
|
|
3587
|
+
handler: (_name, result) => {
|
|
3588
|
+
if (result.length > 6e3) {
|
|
3589
|
+
return {
|
|
3590
|
+
proceed: true,
|
|
3591
|
+
modifiedResult: result.slice(0, 5e3) + `
|
|
3592
|
+
|
|
3593
|
+
[... ${result.length - 5e3}\uC790 \uC0DD\uB7B5. \uC804\uCCB4 \uACB0\uACFC\uAC00 \uD544\uC694\uD558\uBA74 \uB354 \uAD6C\uCCB4\uC801\uC778 \uC870\uAC74\uC73C\uB85C \uC7AC\uC870\uD68C\uD558\uC138\uC694]`
|
|
3594
|
+
};
|
|
3595
|
+
}
|
|
3596
|
+
return { proceed: true };
|
|
3597
|
+
}
|
|
3598
|
+
}
|
|
3599
|
+
];
|
|
3600
|
+
function runPreHooks(name, args) {
|
|
3601
|
+
for (const hook of preHooks) {
|
|
3602
|
+
if (hook.match(name)) {
|
|
3603
|
+
const result = hook.handler(name, args);
|
|
3604
|
+
if (!result.proceed) return result;
|
|
3605
|
+
if (result.modifiedArgs) Object.assign(args, result.modifiedArgs);
|
|
3606
|
+
}
|
|
3607
|
+
}
|
|
3608
|
+
return { proceed: true };
|
|
3609
|
+
}
|
|
3610
|
+
function runPostHooks(name, result) {
|
|
3611
|
+
let current = result;
|
|
3612
|
+
for (const hook of postHooks) {
|
|
3613
|
+
if (hook.match(name)) {
|
|
3614
|
+
const hr = hook.handler(name, current);
|
|
3615
|
+
if (hr.modifiedResult) current = hr.modifiedResult;
|
|
3616
|
+
}
|
|
3617
|
+
}
|
|
3618
|
+
return current;
|
|
3619
|
+
}
|
|
3620
|
+
|
|
3621
|
+
// src/agent/context.ts
|
|
3622
|
+
var COMPACT_THRESHOLD = 30;
|
|
3623
|
+
var KEEP_RECENT = 10;
|
|
3624
|
+
var REMINDER_INTERVAL = 10;
|
|
3625
|
+
function compactMessages(messages) {
|
|
3626
|
+
if (messages.length <= COMPACT_THRESHOLD) return messages;
|
|
3627
|
+
const system = messages[0];
|
|
3628
|
+
const toCompress = messages.slice(1, -KEEP_RECENT);
|
|
3629
|
+
const recent = messages.slice(-KEEP_RECENT);
|
|
3630
|
+
const toolCalls = [];
|
|
3631
|
+
const userRequests = [];
|
|
3632
|
+
for (const msg of toCompress) {
|
|
3633
|
+
if (msg.role === "user" && typeof msg.content === "string") {
|
|
3634
|
+
userRequests.push(msg.content.slice(0, 80));
|
|
3635
|
+
}
|
|
3636
|
+
if (msg.role === "assistant" && typeof msg.content === "string" && msg.content) {
|
|
3637
|
+
const tc = msg.tool_calls;
|
|
3638
|
+
if (tc && Array.isArray(tc)) {
|
|
3639
|
+
for (const t of tc) {
|
|
3640
|
+
toolCalls.push(t.function?.name ?? "unknown");
|
|
3641
|
+
}
|
|
3642
|
+
}
|
|
3643
|
+
}
|
|
3644
|
+
}
|
|
3645
|
+
const summary = [
|
|
3646
|
+
`[\uC774\uC804 \uB300\uD654 \uC694\uC57D \u2014 ${toCompress.length}\uAC1C \uBA54\uC2DC\uC9C0 \uC555\uCD95]`,
|
|
3647
|
+
userRequests.length > 0 ? `\uC0AC\uC6A9\uC790 \uC694\uCCAD: ${userRequests.join(" \u2192 ")}` : "",
|
|
3648
|
+
toolCalls.length > 0 ? `\uC2E4\uD589\uB41C \uB3C4\uAD6C: ${[...new Set(toolCalls)].join(", ")}` : ""
|
|
3649
|
+
].filter(Boolean).join("\n");
|
|
3650
|
+
return [
|
|
3651
|
+
system,
|
|
3652
|
+
{ role: "system", content: summary },
|
|
3653
|
+
...recent
|
|
3654
|
+
];
|
|
3655
|
+
}
|
|
3656
|
+
function shouldInjectReminder(turnCount) {
|
|
3657
|
+
return turnCount > 0 && turnCount % REMINDER_INTERVAL === 0;
|
|
3658
|
+
}
|
|
3659
|
+
function createReminder(serverUrl, loadedTools2) {
|
|
3660
|
+
const lines = [
|
|
3661
|
+
`[System Reminder \u2014 \uD134 ${Date.now()}]`,
|
|
3662
|
+
serverUrl ? `\uC11C\uBC84: ${serverUrl} (\uC5F0\uACB0\uB428)` : "\uC11C\uBC84: \uBBF8\uC5F0\uACB0",
|
|
3663
|
+
loadedTools2 && loadedTools2.length > 0 ? `\uD65C\uC131 XGEN \uB3C4\uAD6C: ${loadedTools2.join(", ")}` : "XGEN \uB3C4\uAD6C: tool_search\uB85C \uB85C\uB4DC \uD544\uC694"
|
|
3664
|
+
];
|
|
3665
|
+
return { role: "system", content: lines.join("\n") };
|
|
3666
|
+
}
|
|
3667
|
+
|
|
3826
3668
|
// src/commands/agent.ts
|
|
3827
3669
|
init_provider();
|
|
3828
3670
|
init_ui();
|
|
@@ -3860,20 +3702,13 @@ EXAMPLES OF GOOD RESPONSES:
|
|
|
3860
3702
|
|
|
3861
3703
|
XGEN CONNECTED: ${server} as ${auth.username}
|
|
3862
3704
|
|
|
3863
|
-
|
|
3705
|
+
XGEN \uD50C\uB7AB\uD3FC \uB3C4\uAD6C\uB294 tool_search\uB85C \uD544\uC694\uD560 \uB54C \uB85C\uB4DC\uD558\uC138\uC694.
|
|
3706
|
+
tool_search("workflow") \u2192 \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uB3C4\uAD6C \uB85C\uB4DC \u2192 \uB2E4\uC74C \uD134\uC5D0\uC11C \uC0AC\uC6A9 \uAC00\uB2A5
|
|
3864
3707
|
|
|
3865
|
-
|
|
3866
|
-
DOCUMENTS: xgen_collection_list, xgen_document_list, xgen_document_upload
|
|
3867
|
-
NODES: xgen_node_list, xgen_node_search, xgen_node_categories
|
|
3868
|
-
PROMPTS: xgen_prompt_list
|
|
3869
|
-
TOOLS: xgen_tool_store, xgen_user_tools
|
|
3870
|
-
SCHEDULE: xgen_schedule_list
|
|
3871
|
-
TRACE: xgen_trace_list, xgen_interaction_list
|
|
3872
|
-
MCP: xgen_mcp_sessions
|
|
3873
|
-
ONTOLOGY: xgen_graph_rag_query, xgen_graph_stats
|
|
3874
|
-
SERVER: xgen_server_status
|
|
3708
|
+
${getToolIndexSummary()}
|
|
3875
3709
|
|
|
3876
|
-
When user says a number \u2192 find it from previous list. "\uC2E4\uD589" \u2192 execute immediately
|
|
3710
|
+
When user says a number \u2192 find it from previous list. "\uC2E4\uD589" \u2192 execute immediately.
|
|
3711
|
+
\uC6CC\uD06C\uD50C\uB85C\uC6B0/\uCEEC\uB809\uC158/\uB178\uB4DC \uB4F1 XGEN \uAD00\uB828 \uC694\uCCAD \u2192 \uBA3C\uC800 tool_search\uB85C \uD574\uB2F9 \uCE74\uD14C\uACE0\uB9AC \uB3C4\uAD6C \uB85C\uB4DC \uD6C4 \uC2E4\uD589.`;
|
|
3877
3712
|
} else {
|
|
3878
3713
|
prompt2 += `
|
|
3879
3714
|
XGEN: Not connected. User can run /connect to connect.`;
|
|
@@ -3979,7 +3814,8 @@ async function agentRepl() {
|
|
|
3979
3814
|
}
|
|
3980
3815
|
}
|
|
3981
3816
|
const client2 = createLLMClient(provider);
|
|
3982
|
-
|
|
3817
|
+
resetLoadedTools();
|
|
3818
|
+
const allTools = [...getAllToolDefs(), definition8];
|
|
3983
3819
|
const builtinNames = getToolNames();
|
|
3984
3820
|
const mcpConfig = loadMcpConfig();
|
|
3985
3821
|
if (mcpConfig && Object.keys(mcpConfig.mcpServers).length > 0) {
|
|
@@ -4150,7 +3986,7 @@ async function agentRepl() {
|
|
|
4150
3986
|
if (input === "/tools") {
|
|
4151
3987
|
console.log(`
|
|
4152
3988
|
${chalk12.bold("\uCF54\uB529")} ${builtinNames.join(", ")}`);
|
|
4153
|
-
console.log(` ${chalk12.bold("XGEN")} ${
|
|
3989
|
+
console.log(` ${chalk12.bold("XGEN")} ${xgenToolDefs.map((t) => t.function.name).join(", ")}`);
|
|
4154
3990
|
if (mcpManager?.serverCount) {
|
|
4155
3991
|
console.log(` ${chalk12.bold("MCP")} ${mcpManager.getAllTools().map((t) => t.function.name).join(", ")}`);
|
|
4156
3992
|
}
|
|
@@ -4214,6 +4050,15 @@ async function agentRepl() {
|
|
|
4214
4050
|
}
|
|
4215
4051
|
async function runLoop(client2, model, messages, tools2) {
|
|
4216
4052
|
for (let i = 0; i < 20; i++) {
|
|
4053
|
+
const compacted = compactMessages(messages);
|
|
4054
|
+
if (compacted.length < messages.length) {
|
|
4055
|
+
messages.length = 0;
|
|
4056
|
+
messages.push(...compacted);
|
|
4057
|
+
}
|
|
4058
|
+
if (shouldInjectReminder(i)) {
|
|
4059
|
+
const loadedNames = getLoadedToolDefs().map((t) => t.function.name);
|
|
4060
|
+
messages.push(createReminder(getServer() ?? void 0, loadedNames));
|
|
4061
|
+
}
|
|
4217
4062
|
let first = true;
|
|
4218
4063
|
const result = await streamChat(client2, model, messages, tools2, (delta) => {
|
|
4219
4064
|
if (first) {
|
|
@@ -4244,23 +4089,37 @@ async function runLoop(client2, model, messages, tools2) {
|
|
|
4244
4089
|
} catch {
|
|
4245
4090
|
args = {};
|
|
4246
4091
|
}
|
|
4247
|
-
const
|
|
4092
|
+
const preResult = runPreHooks(tc.name, args);
|
|
4093
|
+
if (!preResult.proceed) {
|
|
4094
|
+
console.log(chalk12.red(` \u2717 ${tc.name} \uCC28\uB2E8: ${preResult.message}`));
|
|
4095
|
+
messages.push({ role: "tool", tool_call_id: tc.id, content: preResult.message ?? "\uCC28\uB2E8\uB428" });
|
|
4096
|
+
continue;
|
|
4097
|
+
}
|
|
4098
|
+
const shortArgs = Object.entries(args).map(([, v]) => {
|
|
4248
4099
|
const s = String(v);
|
|
4249
4100
|
return s.length > 40 ? s.slice(0, 40) + "\u2026" : s;
|
|
4250
4101
|
}).join(", ");
|
|
4251
4102
|
console.log(chalk12.dim(` \u250C ${tc.name}(${shortArgs})`));
|
|
4252
4103
|
let toolResult2;
|
|
4253
|
-
if (
|
|
4104
|
+
if (tc.name === "tool_search") {
|
|
4105
|
+
toolResult2 = await execute9(args);
|
|
4106
|
+
const newTools = getNewlyLoadedTools(args.query);
|
|
4107
|
+
for (const nt of newTools) {
|
|
4108
|
+
if (!tools2.some((t) => t.function.name === nt.function.name)) {
|
|
4109
|
+
tools2.push(nt);
|
|
4110
|
+
}
|
|
4111
|
+
}
|
|
4112
|
+
} else if (isXgenTool(tc.name)) {
|
|
4254
4113
|
toolResult2 = await execute8(tc.name, args);
|
|
4255
4114
|
} else if (mcpManager?.isMcpTool(tc.name)) {
|
|
4256
4115
|
toolResult2 = await mcpManager.callTool(tc.name, args);
|
|
4257
4116
|
} else {
|
|
4258
4117
|
toolResult2 = await executeTool(tc.name, args);
|
|
4259
4118
|
}
|
|
4260
|
-
|
|
4119
|
+
toolResult2 = runPostHooks(tc.name, toolResult2);
|
|
4261
4120
|
const preview = toolResult2.split("\n")[0].slice(0, 60);
|
|
4262
4121
|
console.log(chalk12.dim(` \u2514 ${preview}${toolResult2.length > 60 ? "\u2026" : ""}`));
|
|
4263
|
-
messages.push({ role: "tool", tool_call_id: tc.id, content:
|
|
4122
|
+
messages.push({ role: "tool", tool_call_id: tc.id, content: toolResult2 });
|
|
4264
4123
|
}
|
|
4265
4124
|
}
|
|
4266
4125
|
console.log(chalk12.yellow("\n \uCD5C\uB300 \uBC18\uBCF5 \uD69F\uC218 \uB3C4\uB2EC.\n"));
|
|
@@ -4464,7 +4323,7 @@ ${result.answer}
|
|
|
4464
4323
|
}
|
|
4465
4324
|
|
|
4466
4325
|
// src/index.ts
|
|
4467
|
-
var VERSION = "2.
|
|
4326
|
+
var VERSION = "2.5.0";
|
|
4468
4327
|
var LOGO = chalk15.cyan(`
|
|
4469
4328
|
\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588 \u2588\u2588
|
|
4470
4329
|
\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588
|