openxgen 2.3.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/README.md +72 -31
- package/dist/index.js +864 -163
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -894,23 +894,40 @@ var init_provider = __esm({
|
|
|
894
894
|
// src/api/xgen-extra.ts
|
|
895
895
|
var xgen_extra_exports = {};
|
|
896
896
|
__export(xgen_extra_exports, {
|
|
897
|
+
apiTest: () => apiTest,
|
|
898
|
+
changePromptVersion: () => changePromptVersion,
|
|
899
|
+
createMcpSession: () => createMcpSession,
|
|
897
900
|
createPrompt: () => createPrompt,
|
|
901
|
+
deleteMcpSession: () => deleteMcpSession,
|
|
902
|
+
deletePrompt: () => deletePrompt,
|
|
898
903
|
generateWorkflow: () => generateWorkflow,
|
|
904
|
+
getMcpSession: () => getMcpSession,
|
|
905
|
+
getMcpSessionTools: () => getMcpSessionTools,
|
|
899
906
|
getNodeCategories: () => getNodeCategories,
|
|
900
907
|
getNodeDetail: () => getNodeDetail,
|
|
908
|
+
getNodeParameters: () => getNodeParameters,
|
|
909
|
+
getNodeTags: () => getNodeTags,
|
|
901
910
|
getSchedulerStatus: () => getSchedulerStatus,
|
|
902
911
|
getTraceDetail: () => getTraceDetail,
|
|
903
912
|
getWorkflowPerformance: () => getWorkflowPerformance,
|
|
904
913
|
listInteractions: () => listInteractions,
|
|
905
914
|
listMcpSessions: () => listMcpSessions,
|
|
906
915
|
listNodes: () => listNodes,
|
|
916
|
+
listPromptStore: () => listPromptStore,
|
|
917
|
+
listPromptVersions: () => listPromptVersions,
|
|
907
918
|
listPrompts: () => listPrompts,
|
|
908
919
|
listSchedules: () => listSchedules,
|
|
909
920
|
listToolStore: () => listToolStore,
|
|
910
921
|
listTraces: () => listTraces,
|
|
911
922
|
listUserTools: () => listUserTools,
|
|
912
923
|
listWorkflowStore: () => listWorkflowStore,
|
|
913
|
-
|
|
924
|
+
saveTool: () => saveTool,
|
|
925
|
+
searchNodes: () => searchNodes,
|
|
926
|
+
sendMcpRequest: () => sendMcpRequest,
|
|
927
|
+
toolTest: () => toolTest,
|
|
928
|
+
updatePrompt: () => updatePrompt,
|
|
929
|
+
uploadPromptToStore: () => uploadPromptToStore,
|
|
930
|
+
uploadToolToStore: () => uploadToolToStore
|
|
914
931
|
});
|
|
915
932
|
async function listNodes() {
|
|
916
933
|
const client2 = getClient();
|
|
@@ -939,11 +956,6 @@ async function listPrompts(opts) {
|
|
|
939
956
|
const res = await client2.get("/api/prompt/list", { params });
|
|
940
957
|
return res.data.prompts ?? res.data ?? [];
|
|
941
958
|
}
|
|
942
|
-
async function createPrompt(data) {
|
|
943
|
-
const client2 = getClient();
|
|
944
|
-
const res = await client2.post("/api/prompt/create", data);
|
|
945
|
-
return res.data;
|
|
946
|
-
}
|
|
947
959
|
async function listToolStore() {
|
|
948
960
|
const client2 = getClient();
|
|
949
961
|
const res = await client2.get("/api/tools/store/list");
|
|
@@ -1000,11 +1012,108 @@ async function getWorkflowPerformance(workflowId, workflowName) {
|
|
|
1000
1012
|
});
|
|
1001
1013
|
return res.data;
|
|
1002
1014
|
}
|
|
1015
|
+
async function saveTool(functionName, content) {
|
|
1016
|
+
const client2 = getClient();
|
|
1017
|
+
const res = await client2.post("/api/tools/storage/save", { function_name: functionName, content });
|
|
1018
|
+
return res.data;
|
|
1019
|
+
}
|
|
1020
|
+
async function apiTest(params) {
|
|
1021
|
+
const client2 = getClient();
|
|
1022
|
+
const res = await client2.post("/api/tools/storage/api-test", params);
|
|
1023
|
+
return res.data;
|
|
1024
|
+
}
|
|
1025
|
+
async function toolTest(toolId, functionId) {
|
|
1026
|
+
const client2 = getClient();
|
|
1027
|
+
const res = await client2.post(`/api/tools/storage/tool-test?tool_id=${toolId}&function_id=${functionId}`);
|
|
1028
|
+
return res.data;
|
|
1029
|
+
}
|
|
1030
|
+
async function uploadToolToStore(functionUploadId, description, tags) {
|
|
1031
|
+
const client2 = getClient();
|
|
1032
|
+
const res = await client2.post("/api/tools/store/upload", {
|
|
1033
|
+
function_upload_id: functionUploadId,
|
|
1034
|
+
description: description ?? "",
|
|
1035
|
+
tags: tags ?? []
|
|
1036
|
+
});
|
|
1037
|
+
return res.data;
|
|
1038
|
+
}
|
|
1039
|
+
async function createPrompt(data) {
|
|
1040
|
+
const client2 = getClient();
|
|
1041
|
+
const res = await client2.post("/api/prompt/create", data);
|
|
1042
|
+
return res.data;
|
|
1043
|
+
}
|
|
1044
|
+
async function updatePrompt(data) {
|
|
1045
|
+
const client2 = getClient();
|
|
1046
|
+
const res = await client2.post("/api/prompt/update", data);
|
|
1047
|
+
return res.data;
|
|
1048
|
+
}
|
|
1049
|
+
async function deletePrompt(promptUid) {
|
|
1050
|
+
const client2 = getClient();
|
|
1051
|
+
const res = await client2.post("/api/prompt/delete", { prompt_uid: promptUid });
|
|
1052
|
+
return res.data;
|
|
1053
|
+
}
|
|
1054
|
+
async function getNodeTags() {
|
|
1055
|
+
const client2 = getClient();
|
|
1056
|
+
const res = await client2.get("/api/node/tags");
|
|
1057
|
+
return res.data ?? [];
|
|
1058
|
+
}
|
|
1059
|
+
async function getNodeParameters(nodeId) {
|
|
1060
|
+
const client2 = getClient();
|
|
1061
|
+
const res = await client2.get(`/api/node/parameters/categorized/${nodeId}`);
|
|
1062
|
+
return res.data;
|
|
1063
|
+
}
|
|
1064
|
+
async function listPromptStore() {
|
|
1065
|
+
const client2 = getClient();
|
|
1066
|
+
const res = await client2.post("/api/prompt/store/list");
|
|
1067
|
+
return res.data.prompts ?? res.data ?? [];
|
|
1068
|
+
}
|
|
1069
|
+
async function uploadPromptToStore(promptId) {
|
|
1070
|
+
const client2 = getClient();
|
|
1071
|
+
const res = await client2.post(`/api/prompt/store/upload`, null, { params: { prompt_id: promptId } });
|
|
1072
|
+
return res.data;
|
|
1073
|
+
}
|
|
1074
|
+
async function listPromptVersions(promptUid) {
|
|
1075
|
+
const client2 = getClient();
|
|
1076
|
+
const res = await client2.get("/api/prompt/version/list", { params: { prompt_uid: promptUid } });
|
|
1077
|
+
return res.data.versions ?? res.data ?? [];
|
|
1078
|
+
}
|
|
1079
|
+
async function changePromptVersion(promptUid, version) {
|
|
1080
|
+
const client2 = getClient();
|
|
1081
|
+
const res = await client2.post("/api/prompt/version/change", { prompt_uid: promptUid, version });
|
|
1082
|
+
return res.data;
|
|
1083
|
+
}
|
|
1003
1084
|
async function listMcpSessions() {
|
|
1004
1085
|
const client2 = getClient();
|
|
1005
1086
|
const res = await client2.get("/api/mcp/sessions");
|
|
1006
1087
|
return res.data.sessions ?? res.data ?? [];
|
|
1007
1088
|
}
|
|
1089
|
+
async function createMcpSession(data) {
|
|
1090
|
+
const client2 = getClient();
|
|
1091
|
+
const res = await client2.post("/api/mcp/sessions", data);
|
|
1092
|
+
return res.data;
|
|
1093
|
+
}
|
|
1094
|
+
async function getMcpSession(sessionId) {
|
|
1095
|
+
const client2 = getClient();
|
|
1096
|
+
const res = await client2.get(`/api/mcp/sessions/${sessionId}`);
|
|
1097
|
+
return res.data;
|
|
1098
|
+
}
|
|
1099
|
+
async function deleteMcpSession(sessionId) {
|
|
1100
|
+
const client2 = getClient();
|
|
1101
|
+
await client2.delete(`/api/mcp/sessions/${sessionId}`);
|
|
1102
|
+
}
|
|
1103
|
+
async function getMcpSessionTools(sessionId) {
|
|
1104
|
+
const client2 = getClient();
|
|
1105
|
+
const res = await client2.get(`/api/mcp/sessions/${sessionId}/tools`);
|
|
1106
|
+
return res.data.tools ?? res.data ?? [];
|
|
1107
|
+
}
|
|
1108
|
+
async function sendMcpRequest(sessionId, method, params) {
|
|
1109
|
+
const client2 = getClient();
|
|
1110
|
+
const res = await client2.post("/api/mcp/mcp-request", {
|
|
1111
|
+
session_id: sessionId,
|
|
1112
|
+
method,
|
|
1113
|
+
params
|
|
1114
|
+
});
|
|
1115
|
+
return res.data;
|
|
1116
|
+
}
|
|
1008
1117
|
var init_xgen_extra = __esm({
|
|
1009
1118
|
"src/api/xgen-extra.ts"() {
|
|
1010
1119
|
"use strict";
|
|
@@ -1113,186 +1222,395 @@ var raw_tui_exports = {};
|
|
|
1113
1222
|
__export(raw_tui_exports, {
|
|
1114
1223
|
startRawTui: () => startRawTui
|
|
1115
1224
|
});
|
|
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);
|
|
1234
|
+
p.then((v) => {
|
|
1235
|
+
clearTimeout(t);
|
|
1236
|
+
res(v);
|
|
1237
|
+
}, (e) => {
|
|
1238
|
+
clearTimeout(t);
|
|
1239
|
+
rej(e);
|
|
1240
|
+
});
|
|
1241
|
+
});
|
|
1242
|
+
}
|
|
1116
1243
|
async function startRawTui() {
|
|
1117
1244
|
const provider = getDefaultProvider();
|
|
1118
1245
|
const server = getServer();
|
|
1119
1246
|
const auth = getAuth();
|
|
1120
|
-
const
|
|
1247
|
+
const sv = auth && server ? `${auth.username}@${server.replace(/https?:\/\//, "")}` : "\uBBF8\uC5F0\uACB0";
|
|
1121
1248
|
let tab = "workflows";
|
|
1122
|
-
let
|
|
1123
|
-
let
|
|
1124
|
-
let
|
|
1125
|
-
let runTarget = null;
|
|
1249
|
+
let sel = 0;
|
|
1250
|
+
let inputBuf = "";
|
|
1251
|
+
let inputActive = false;
|
|
1126
1252
|
let workflows = [];
|
|
1127
1253
|
let collections = [];
|
|
1128
1254
|
let nodes = [];
|
|
1129
1255
|
let prompts = [];
|
|
1130
1256
|
let tools2 = [];
|
|
1131
|
-
let
|
|
1257
|
+
let mcpSessions = [];
|
|
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)")];
|
|
1132
1260
|
let statusMsg = "\uB85C\uB529...";
|
|
1133
1261
|
async function loadData() {
|
|
1134
|
-
statusMsg = "\uB85C\uB529...";
|
|
1262
|
+
statusMsg = "\uB85C\uB529 \uC911...";
|
|
1135
1263
|
render();
|
|
1136
1264
|
if (!server || !auth) {
|
|
1137
1265
|
statusMsg = "\uC11C\uBC84 \uBBF8\uC5F0\uACB0";
|
|
1266
|
+
sandbox = [red("\uC11C\uBC84 \uBBF8\uC5F0\uACB0"), "", cyan(" xgen config set-server <URL>"), cyan(" xgen login")];
|
|
1138
1267
|
render();
|
|
1139
1268
|
return;
|
|
1140
1269
|
}
|
|
1270
|
+
const errors = [];
|
|
1141
1271
|
try {
|
|
1142
|
-
const [
|
|
1272
|
+
const [wf, doc, ex] = await Promise.all([
|
|
1143
1273
|
Promise.resolve().then(() => (init_workflow(), workflow_exports)),
|
|
1144
1274
|
Promise.resolve().then(() => (init_document(), document_exports)),
|
|
1145
1275
|
Promise.resolve().then(() => (init_xgen_extra(), xgen_extra_exports))
|
|
1146
1276
|
]);
|
|
1147
|
-
const
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
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(() => [])
|
|
1153
1284
|
]);
|
|
1154
|
-
if (
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
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") {
|
|
1299
|
+
nodes = [];
|
|
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 ?? ""}` });
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
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);
|
|
1160
1337
|
}
|
|
1161
|
-
|
|
1338
|
+
sel = 0;
|
|
1339
|
+
updateSandbox();
|
|
1340
|
+
statusMsg = errors.length > 0 ? `\u26A0 ${errors.length}\uAC1C \uC624\uB958 \u2502 r \uC7AC\uC2DC\uB3C4` : getHint();
|
|
1341
|
+
if (errors.length > 0) sandbox = [red("\uC624\uB958:"), ...errors.map((e) => yellow(` \u2022 ${e}`))];
|
|
1162
1342
|
render();
|
|
1163
1343
|
}
|
|
1344
|
+
function getHint() {
|
|
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"
|
|
1352
|
+
};
|
|
1353
|
+
return h[tab];
|
|
1354
|
+
}
|
|
1164
1355
|
function getItems() {
|
|
1165
1356
|
switch (tab) {
|
|
1166
1357
|
case "workflows":
|
|
1167
|
-
return workflows.map((w) => ({ label: `${w.deployed ? "\u25CF" : "\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) }));
|
|
1168
1359
|
case "collections":
|
|
1169
|
-
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` }));
|
|
1170
1361
|
case "nodes":
|
|
1171
|
-
return nodes.map((n) => ({ label: n.name, sub: n.
|
|
1362
|
+
return nodes.map((n) => ({ label: n.name, sub: n.category }));
|
|
1172
1363
|
case "prompts":
|
|
1173
1364
|
return prompts.map((p) => ({ label: p.name, sub: `[${p.type}]` }));
|
|
1174
1365
|
case "tools":
|
|
1175
|
-
return tools2.map((t) => ({ label: t.name
|
|
1366
|
+
return tools2.map((t) => ({ label: `${t.status === "active" ? green("\u25CF") : dim("\u25CB")} ${t.name}`, sub: t.desc }));
|
|
1367
|
+
case "mcp":
|
|
1368
|
+
return mcpSessions.map((s) => ({ label: `${s.status === "running" ? green("\u25CF") : dim("\u25CB")} ${s.name}`, sub: s.type }));
|
|
1176
1369
|
}
|
|
1177
1370
|
}
|
|
1178
|
-
function
|
|
1371
|
+
function updateSandbox() {
|
|
1179
1372
|
const items = getItems();
|
|
1180
|
-
if (
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1373
|
+
if (items.length === 0) {
|
|
1374
|
+
sandbox = [dim("\uB370\uC774\uD130 \uC5C6\uC74C")];
|
|
1375
|
+
return;
|
|
1376
|
+
}
|
|
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 = [
|
|
1382
|
+
bold(w.name),
|
|
1383
|
+
`ID: ${w.id}`,
|
|
1384
|
+
`\uBC30\uD3EC: ${w.deployed ? green("Yes") : red("No")}`,
|
|
1385
|
+
"",
|
|
1386
|
+
cyan("Enter") + " \uB178\uB4DC\uAD6C\uC870",
|
|
1387
|
+
dim("\uC9C8\uBB38 \uC785\uB825 \u2192 \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC2E4\uD589")
|
|
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"];
|
|
1196
1404
|
}
|
|
1197
1405
|
}
|
|
1198
1406
|
function render() {
|
|
1199
1407
|
const cols = process.stdout.columns || 120;
|
|
1200
1408
|
const rows = process.stdout.rows || 30;
|
|
1201
|
-
const leftW = Math.floor(cols
|
|
1202
|
-
const rightW = cols - leftW;
|
|
1203
|
-
const
|
|
1409
|
+
const leftW = Math.floor(cols * 0.35);
|
|
1410
|
+
const rightW = cols - leftW - 1;
|
|
1411
|
+
const topH = Math.floor((rows - 4) * 0.55);
|
|
1412
|
+
const botH = rows - 4 - topH;
|
|
1204
1413
|
clear();
|
|
1205
1414
|
moveTo(1, 1);
|
|
1206
|
-
const tabStr = TABS.map((t) => {
|
|
1207
|
-
|
|
1208
|
-
return `[${t.num}]${active ? bold("\u25B8" + t.label) : dim(t.label)}`;
|
|
1209
|
-
}).join(" ");
|
|
1210
|
-
process.stdout.write(` ${bold("OPEN XGEN")} ${dim(provider?.model ?? "")} ${serverDisplay} \u2502 ${tabStr}`);
|
|
1415
|
+
const tabStr = TABS.map((t) => tab === t.key ? inverse(` ${t.num}:${t.label} `) : dim(` ${t.num}:${t.label} `)).join("");
|
|
1416
|
+
process.stdout.write(` ${bold(cyan("OPEN XGEN"))} ${dim("v3")} ${dim(sv)} \u2502 ${tabStr}`);
|
|
1211
1417
|
moveTo(2, 1);
|
|
1212
|
-
process.stdout.write(dim("\u2500".repeat(
|
|
1418
|
+
process.stdout.write(dim("\u2500".repeat(leftW) + "\u252C" + "\u2500".repeat(rightW)));
|
|
1213
1419
|
const items = getItems();
|
|
1214
|
-
const
|
|
1215
|
-
const
|
|
1216
|
-
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++) {
|
|
1217
1423
|
moveTo(3 + i, 1);
|
|
1218
|
-
const idx =
|
|
1424
|
+
const idx = scr + i;
|
|
1425
|
+
let left;
|
|
1219
1426
|
if (idx < items.length) {
|
|
1220
1427
|
const item = items[idx];
|
|
1221
|
-
const
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
process.stdout.write(idx === selected ? inverse(trimmed.padEnd(leftW - 1)) : trimmed);
|
|
1428
|
+
const sub = item.sub ? dim(` ${item.sub}`) : "";
|
|
1429
|
+
left = padV(`${idx === sel ? "\u25B8" : " "} ${String(idx + 1).padStart(2)}. ${item.label}${sub}`, leftW);
|
|
1430
|
+
if (idx === sel) left = inverse(left);
|
|
1225
1431
|
} else {
|
|
1226
|
-
|
|
1432
|
+
left = " ".repeat(leftW);
|
|
1227
1433
|
}
|
|
1434
|
+
process.stdout.write(left);
|
|
1228
1435
|
process.stdout.write(dim("\u2502"));
|
|
1229
|
-
if (i <
|
|
1230
|
-
|
|
1231
|
-
|
|
1436
|
+
if (i < sandbox.length) process.stdout.write(` ${sandbox[i]}`);
|
|
1437
|
+
}
|
|
1438
|
+
moveTo(3 + topH, 1);
|
|
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));
|
|
1232
1448
|
}
|
|
1233
1449
|
}
|
|
1234
|
-
moveTo(rows - 2, 1);
|
|
1235
|
-
process.stdout.write(dim("\u2500".repeat(cols)));
|
|
1236
1450
|
moveTo(rows - 1, 1);
|
|
1237
|
-
if (
|
|
1238
|
-
const
|
|
1239
|
-
process.stdout.write(` ${
|
|
1451
|
+
if (inputActive) {
|
|
1452
|
+
const ctx = tab === "workflows" && workflows[sel] ? `${workflows[sel].name} ` : "";
|
|
1453
|
+
process.stdout.write(` ${cyan(ctx + "\u276F")} ${inputBuf}`);
|
|
1240
1454
|
showCursor();
|
|
1241
1455
|
} else {
|
|
1242
|
-
process.stdout.write(dim(
|
|
1456
|
+
process.stdout.write(dim(` ${getHint()}`));
|
|
1243
1457
|
hideCursor();
|
|
1244
1458
|
}
|
|
1245
1459
|
moveTo(rows, 1);
|
|
1246
1460
|
process.stdout.write(dim(` ${statusMsg}`.slice(0, cols)));
|
|
1247
1461
|
}
|
|
1248
|
-
|
|
1249
|
-
|
|
1462
|
+
function addChat(line) {
|
|
1463
|
+
chatLines.push(line);
|
|
1464
|
+
if (chatLines.length > 200) chatLines = chatLines.slice(-100);
|
|
1465
|
+
}
|
|
1466
|
+
async function runWorkflow(wf, input) {
|
|
1467
|
+
addChat(`${cyan("\u276F")} ${input}`);
|
|
1468
|
+
addChat(yellow(` ${wf.name} \uC2E4\uD589 \uC911...`));
|
|
1469
|
+
sandbox = [bold(wf.name), "", yellow("\uC2E4\uD589 \uC911...")];
|
|
1250
1470
|
render();
|
|
1251
1471
|
try {
|
|
1252
1472
|
const { executeWorkflow: executeWorkflow2 } = await Promise.resolve().then(() => (init_workflow(), workflow_exports));
|
|
1253
1473
|
const { randomUUID: randomUUID4 } = await import("crypto");
|
|
1254
|
-
const r = await executeWorkflow2({
|
|
1474
|
+
const r = await withTimeout(executeWorkflow2({
|
|
1255
1475
|
workflow_id: wf.id,
|
|
1256
1476
|
workflow_name: wf.name,
|
|
1257
1477
|
input_data: input,
|
|
1258
1478
|
interaction_id: `tui_${randomUUID4().slice(0, 8)}`,
|
|
1259
1479
|
user_id: auth?.userId ? parseInt(auth.userId) : 1
|
|
1260
|
-
});
|
|
1261
|
-
const content = r
|
|
1262
|
-
|
|
1480
|
+
}), 3e4, "\uC2E4\uD589");
|
|
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)];
|
|
1487
|
+
} catch (err) {
|
|
1488
|
+
addChat(red(` \uC2E4\uD328: ${err.message}`));
|
|
1489
|
+
sandbox = [bold(wf.name), "", red(`\uC2E4\uD328: ${err.message}`)];
|
|
1490
|
+
}
|
|
1491
|
+
statusMsg = getHint();
|
|
1492
|
+
render();
|
|
1493
|
+
}
|
|
1494
|
+
async function loadWorkflowStructure(wf) {
|
|
1495
|
+
sandbox = [bold(wf.name), "", yellow("\uB178\uB4DC/\uC5E3\uC9C0 \uB85C\uB529...")];
|
|
1496
|
+
render();
|
|
1497
|
+
try {
|
|
1498
|
+
const { getWorkflowDetail: getWorkflowDetail2 } = await Promise.resolve().then(() => (init_workflow(), workflow_exports));
|
|
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 = [
|
|
1504
|
+
bold(wf.name),
|
|
1505
|
+
`\uB178\uB4DC ${ns.length}\uAC1C \uC5E3\uC9C0 ${es.length}\uAC1C`,
|
|
1506
|
+
"",
|
|
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`)] : [],
|
|
1509
|
+
"",
|
|
1510
|
+
bold("\uC5F0\uACB0:"),
|
|
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
|
+
})
|
|
1516
|
+
];
|
|
1517
|
+
} catch (err) {
|
|
1518
|
+
sandbox = [bold(wf.name), "", red(err.message)];
|
|
1519
|
+
}
|
|
1520
|
+
render();
|
|
1521
|
+
}
|
|
1522
|
+
async function loadNodeDetail(n) {
|
|
1523
|
+
if (!n.id) {
|
|
1524
|
+
sandbox = [red("\uB178\uB4DC ID \uC5C6\uC74C")];
|
|
1525
|
+
render();
|
|
1526
|
+
return;
|
|
1527
|
+
}
|
|
1528
|
+
sandbox = [bold(n.name), yellow("\uB85C\uB529...")];
|
|
1529
|
+
render();
|
|
1530
|
+
try {
|
|
1531
|
+
const { getNodeDetail: getNodeDetail2 } = await Promise.resolve().then(() => (init_xgen_extra(), xgen_extra_exports));
|
|
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 ?? "?"}`,
|
|
1541
|
+
"",
|
|
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))}`)
|
|
1548
|
+
];
|
|
1549
|
+
} catch (err) {
|
|
1550
|
+
sandbox = [red(err.message)];
|
|
1551
|
+
}
|
|
1552
|
+
render();
|
|
1553
|
+
}
|
|
1554
|
+
async function testTool(t) {
|
|
1555
|
+
if (!t.url) {
|
|
1556
|
+
sandbox = [red("URL \uC5C6\uC74C")];
|
|
1557
|
+
render();
|
|
1558
|
+
return;
|
|
1559
|
+
}
|
|
1560
|
+
sandbox = [bold(t.name), yellow(`\uD14C\uC2A4\uD2B8: ${t.url}`)];
|
|
1561
|
+
addChat(yellow(` \uB3C4\uAD6C \uD14C\uC2A4\uD2B8: ${t.name}`));
|
|
1562
|
+
render();
|
|
1563
|
+
try {
|
|
1564
|
+
const { apiTest: apiTest2 } = await Promise.resolve().then(() => (init_xgen_extra(), xgen_extra_exports));
|
|
1565
|
+
const r = await withTimeout(apiTest2({ api_url: t.url, api_method: "GET", api_timeout: 10 }), 15e3, "\uD14C\uC2A4\uD2B8");
|
|
1566
|
+
const ok = r?.success ?? (r?.data?.status && r.data.status < 400);
|
|
1567
|
+
const st = r?.data?.status ?? "?";
|
|
1568
|
+
const resp = r?.data?.response;
|
|
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`));
|
|
1263
1572
|
} catch (err) {
|
|
1264
|
-
|
|
1573
|
+
sandbox = [red(err.message)];
|
|
1574
|
+
addChat(red(` \uC2E4\uD328: ${err.message}`));
|
|
1265
1575
|
}
|
|
1266
1576
|
render();
|
|
1267
1577
|
}
|
|
1268
|
-
function handleKey(
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
inputBuffer = "";
|
|
1274
|
-
runTarget = null;
|
|
1578
|
+
function handleKey(s) {
|
|
1579
|
+
if (inputActive) {
|
|
1580
|
+
if (s === "\x1B") {
|
|
1581
|
+
inputActive = false;
|
|
1582
|
+
inputBuf = "";
|
|
1275
1583
|
render();
|
|
1276
1584
|
return;
|
|
1277
1585
|
}
|
|
1278
1586
|
if (s === "\r" || s === "\n") {
|
|
1279
|
-
const val =
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
if (val &&
|
|
1283
|
-
|
|
1284
|
-
|
|
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."));
|
|
1595
|
+
render();
|
|
1596
|
+
} else {
|
|
1597
|
+
render();
|
|
1285
1598
|
}
|
|
1286
|
-
render();
|
|
1287
1599
|
return;
|
|
1288
1600
|
}
|
|
1289
1601
|
if (s === "\x7F" || s === "\b") {
|
|
1290
|
-
|
|
1602
|
+
inputBuf = inputBuf.slice(0, -1);
|
|
1603
|
+
render();
|
|
1604
|
+
return;
|
|
1605
|
+
}
|
|
1606
|
+
if (s === "") {
|
|
1607
|
+
inputActive = false;
|
|
1608
|
+
inputBuf = "";
|
|
1291
1609
|
render();
|
|
1292
1610
|
return;
|
|
1293
1611
|
}
|
|
1294
|
-
if (s.
|
|
1295
|
-
|
|
1612
|
+
if (s.charCodeAt(0) >= 32) {
|
|
1613
|
+
inputBuf += s;
|
|
1296
1614
|
render();
|
|
1297
1615
|
return;
|
|
1298
1616
|
}
|
|
@@ -1302,67 +1620,173 @@ async function startRawTui() {
|
|
|
1302
1620
|
cleanup();
|
|
1303
1621
|
process.exit(0);
|
|
1304
1622
|
}
|
|
1305
|
-
if (s === "r") {
|
|
1623
|
+
if (s === "r" || s === "R") {
|
|
1306
1624
|
loadData();
|
|
1307
1625
|
return;
|
|
1308
1626
|
}
|
|
1309
|
-
if (s ===
|
|
1310
|
-
|
|
1627
|
+
if (s.length === 1 && s.charCodeAt(0) >= 32 && !/^[0-9cutedvq]$/i.test(s)) {
|
|
1628
|
+
inputActive = true;
|
|
1629
|
+
inputBuf = s;
|
|
1311
1630
|
render();
|
|
1312
1631
|
return;
|
|
1313
1632
|
}
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1633
|
+
if (/^[cC]$/.test(s)) {
|
|
1634
|
+
if (tab === "tools") {
|
|
1635
|
+
addChat(cyan(" \uB3C4\uAD6C \uC0DD\uC131\uC740 xgen agent\uC5D0\uC11C: '\uC0C8 \uB3C4\uAD6C \uB9CC\uB4E4\uC5B4\uC918'"));
|
|
1636
|
+
render();
|
|
1637
|
+
return;
|
|
1638
|
+
}
|
|
1639
|
+
if (tab === "prompts") {
|
|
1640
|
+
addChat(cyan(" \uD504\uB86C\uD504\uD2B8 \uC0DD\uC131\uC740 xgen agent\uC5D0\uC11C: '\uD504\uB86C\uD504\uD2B8 \uB9CC\uB4E4\uC5B4\uC918'"));
|
|
1641
|
+
render();
|
|
1642
|
+
return;
|
|
1643
|
+
}
|
|
1644
|
+
if (tab === "mcp") {
|
|
1645
|
+
addChat(cyan(" MCP \uC138\uC158 \uC0DD\uC131\uC740 xgen agent\uC5D0\uC11C: 'MCP \uC138\uC158 \uB9CC\uB4E4\uC5B4\uC918'"));
|
|
1646
|
+
render();
|
|
1647
|
+
return;
|
|
1648
|
+
}
|
|
1649
|
+
}
|
|
1650
|
+
if (/^[tT]$/.test(s) && tab === "tools" && tools2[sel]) {
|
|
1651
|
+
testTool(tools2[sel]);
|
|
1652
|
+
return;
|
|
1653
|
+
}
|
|
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
|
+
});
|
|
1668
|
+
return;
|
|
1669
|
+
}
|
|
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
|
+
});
|
|
1683
|
+
return;
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
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;
|
|
1700
|
+
}
|
|
1701
|
+
const n = parseInt(s);
|
|
1702
|
+
if (n >= 1 && n <= 6) {
|
|
1703
|
+
tab = TABS[n - 1].key;
|
|
1704
|
+
sel = 0;
|
|
1705
|
+
updateSandbox();
|
|
1706
|
+
statusMsg = getHint();
|
|
1319
1707
|
render();
|
|
1320
1708
|
return;
|
|
1321
1709
|
}
|
|
1322
1710
|
if (s === " ") {
|
|
1323
|
-
const
|
|
1324
|
-
tab = TABS[(
|
|
1325
|
-
|
|
1326
|
-
|
|
1711
|
+
const i = TABS.findIndex((t) => t.key === tab);
|
|
1712
|
+
tab = TABS[(i + 1) % TABS.length].key;
|
|
1713
|
+
sel = 0;
|
|
1714
|
+
updateSandbox();
|
|
1715
|
+
statusMsg = getHint();
|
|
1716
|
+
render();
|
|
1717
|
+
return;
|
|
1718
|
+
}
|
|
1719
|
+
if (s === "\x1B[Z") {
|
|
1720
|
+
const i = TABS.findIndex((t) => t.key === tab);
|
|
1721
|
+
tab = TABS[(i - 1 + TABS.length) % TABS.length].key;
|
|
1722
|
+
sel = 0;
|
|
1723
|
+
updateSandbox();
|
|
1724
|
+
statusMsg = getHint();
|
|
1327
1725
|
render();
|
|
1328
1726
|
return;
|
|
1329
1727
|
}
|
|
1330
1728
|
if (s === "\x1B[A") {
|
|
1331
1729
|
const items = getItems();
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1730
|
+
if (items.length > 0) {
|
|
1731
|
+
sel = Math.max(0, sel - 1);
|
|
1732
|
+
updateSandbox();
|
|
1733
|
+
render();
|
|
1734
|
+
}
|
|
1335
1735
|
return;
|
|
1336
1736
|
}
|
|
1337
1737
|
if (s === "\x1B[B") {
|
|
1338
1738
|
const items = getItems();
|
|
1339
|
-
|
|
1340
|
-
|
|
1739
|
+
if (items.length > 0) {
|
|
1740
|
+
sel = Math.min(items.length - 1, sel + 1);
|
|
1741
|
+
updateSandbox();
|
|
1742
|
+
render();
|
|
1743
|
+
}
|
|
1744
|
+
return;
|
|
1745
|
+
}
|
|
1746
|
+
if (s === "\x1B[5~") {
|
|
1747
|
+
sel = Math.max(0, sel - 10);
|
|
1748
|
+
updateSandbox();
|
|
1749
|
+
render();
|
|
1750
|
+
return;
|
|
1751
|
+
}
|
|
1752
|
+
if (s === "\x1B[6~") {
|
|
1753
|
+
const items = getItems();
|
|
1754
|
+
sel = Math.min(items.length - 1, sel + 10);
|
|
1755
|
+
updateSandbox();
|
|
1341
1756
|
render();
|
|
1342
1757
|
return;
|
|
1343
1758
|
}
|
|
1344
1759
|
if (s === "\r" || s === "\n") {
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
} else if (tab === "collections" && collections[selected]) {
|
|
1351
|
-
const c = collections[selected];
|
|
1352
|
-
detail = [`${c.name} \uBB38\uC11C \uB85C\uB529...`];
|
|
1760
|
+
const items = getItems();
|
|
1761
|
+
if (items.length === 0) return;
|
|
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...")];
|
|
1353
1765
|
render();
|
|
1354
1766
|
Promise.resolve().then(() => (init_document(), document_exports)).then(async (m) => {
|
|
1355
1767
|
try {
|
|
1356
|
-
const docs = await m.listDocuments(String(collections[
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
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)];
|
|
1772
|
+
}
|
|
1773
|
+
render();
|
|
1774
|
+
});
|
|
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...")];
|
|
1783
|
+
render();
|
|
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)];
|
|
1366
1790
|
}
|
|
1367
1791
|
render();
|
|
1368
1792
|
});
|
|
@@ -1373,26 +1797,27 @@ async function startRawTui() {
|
|
|
1373
1797
|
function cleanup() {
|
|
1374
1798
|
showCursor();
|
|
1375
1799
|
clear();
|
|
1376
|
-
if (process.stdin.isTTY && process.stdin.isRaw)
|
|
1377
|
-
process.stdin.setRawMode(false);
|
|
1378
|
-
}
|
|
1800
|
+
if (process.stdin.isTTY && process.stdin.isRaw) process.stdin.setRawMode(false);
|
|
1379
1801
|
process.stdin.removeAllListeners("data");
|
|
1380
1802
|
process.stdin.pause();
|
|
1381
1803
|
}
|
|
1382
1804
|
if (!process.stdin.isTTY) {
|
|
1383
|
-
console.error("\
|
|
1805
|
+
console.error("\uD130\uBBF8\uB110(TTY)\uC5D0\uC11C\uB9CC \uC2E4\uD589 \uAC00\uB2A5\uD569\uB2C8\uB2E4.");
|
|
1384
1806
|
return;
|
|
1385
1807
|
}
|
|
1386
1808
|
process.stdin.setRawMode(true);
|
|
1387
1809
|
process.stdin.resume();
|
|
1388
1810
|
process.stdin.setEncoding("utf8");
|
|
1389
1811
|
hideCursor();
|
|
1390
|
-
process.stdin.on("data", (
|
|
1812
|
+
process.stdin.on("data", (d) => {
|
|
1391
1813
|
try {
|
|
1392
|
-
handleKey(
|
|
1393
|
-
} catch {
|
|
1814
|
+
handleKey(String(d));
|
|
1815
|
+
} catch (e) {
|
|
1816
|
+
statusMsg = red(e.message);
|
|
1817
|
+
render();
|
|
1394
1818
|
}
|
|
1395
1819
|
});
|
|
1820
|
+
process.stdout.on("resize", () => render());
|
|
1396
1821
|
process.on("SIGINT", () => {
|
|
1397
1822
|
cleanup();
|
|
1398
1823
|
process.exit(0);
|
|
@@ -1400,11 +1825,11 @@ async function startRawTui() {
|
|
|
1400
1825
|
process.on("exit", () => {
|
|
1401
1826
|
showCursor();
|
|
1402
1827
|
});
|
|
1403
|
-
|
|
1828
|
+
loadData();
|
|
1404
1829
|
await new Promise(() => {
|
|
1405
1830
|
});
|
|
1406
1831
|
}
|
|
1407
|
-
var TABS, CSI, clear, moveTo, dim, bold, inverse, hideCursor, showCursor;
|
|
1832
|
+
var TABS, CSI, clear, moveTo, dim, bold, inverse, red, green, yellow, cyan, hideCursor, showCursor;
|
|
1408
1833
|
var init_raw_tui = __esm({
|
|
1409
1834
|
"src/dashboard/raw-tui.ts"() {
|
|
1410
1835
|
"use strict";
|
|
@@ -1414,7 +1839,8 @@ var init_raw_tui = __esm({
|
|
|
1414
1839
|
{ key: "collections", label: "\uCEEC\uB809\uC158", num: "2" },
|
|
1415
1840
|
{ key: "nodes", label: "\uB178\uB4DC", num: "3" },
|
|
1416
1841
|
{ key: "prompts", label: "\uD504\uB86C\uD504\uD2B8", num: "4" },
|
|
1417
|
-
{ key: "tools", label: "\uB3C4\uAD6C", num: "5" }
|
|
1842
|
+
{ key: "tools", label: "\uB3C4\uAD6C", num: "5" },
|
|
1843
|
+
{ key: "mcp", label: "MCP", num: "6" }
|
|
1418
1844
|
];
|
|
1419
1845
|
CSI = "\x1B[";
|
|
1420
1846
|
clear = () => process.stdout.write(`${CSI}2J${CSI}H`);
|
|
@@ -1422,6 +1848,10 @@ var init_raw_tui = __esm({
|
|
|
1422
1848
|
dim = (s) => `${CSI}2m${s}${CSI}0m`;
|
|
1423
1849
|
bold = (s) => `${CSI}1m${s}${CSI}0m`;
|
|
1424
1850
|
inverse = (s) => `${CSI}7m${s}${CSI}0m`;
|
|
1851
|
+
red = (s) => `${CSI}31m${s}${CSI}0m`;
|
|
1852
|
+
green = (s) => `${CSI}32m${s}${CSI}0m`;
|
|
1853
|
+
yellow = (s) => `${CSI}33m${s}${CSI}0m`;
|
|
1854
|
+
cyan = (s) => `${CSI}36m${s}${CSI}0m`;
|
|
1425
1855
|
hideCursor = () => process.stdout.write(`${CSI}?25l`);
|
|
1426
1856
|
showCursor = () => process.stdout.write(`${CSI}?25h`);
|
|
1427
1857
|
}
|
|
@@ -2832,6 +3262,141 @@ ID: ${d.id}
|
|
|
2832
3262
|
}
|
|
2833
3263
|
};
|
|
2834
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
|
+
|
|
2835
3400
|
// src/mcp/client.ts
|
|
2836
3401
|
import { spawn } from "child_process";
|
|
2837
3402
|
import { existsSync as existsSync3, readFileSync as readFileSync4 } from "fs";
|
|
@@ -2990,6 +3555,116 @@ var McpManager = class {
|
|
|
2990
3555
|
}
|
|
2991
3556
|
};
|
|
2992
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
|
+
|
|
2993
3668
|
// src/commands/agent.ts
|
|
2994
3669
|
init_provider();
|
|
2995
3670
|
init_ui();
|
|
@@ -3027,20 +3702,13 @@ EXAMPLES OF GOOD RESPONSES:
|
|
|
3027
3702
|
|
|
3028
3703
|
XGEN CONNECTED: ${server} as ${auth.username}
|
|
3029
3704
|
|
|
3030
|
-
|
|
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
|
|
3031
3707
|
|
|
3032
|
-
|
|
3033
|
-
DOCUMENTS: xgen_collection_list, xgen_document_list, xgen_document_upload
|
|
3034
|
-
NODES: xgen_node_list, xgen_node_search, xgen_node_categories
|
|
3035
|
-
PROMPTS: xgen_prompt_list
|
|
3036
|
-
TOOLS: xgen_tool_store, xgen_user_tools
|
|
3037
|
-
SCHEDULE: xgen_schedule_list
|
|
3038
|
-
TRACE: xgen_trace_list, xgen_interaction_list
|
|
3039
|
-
MCP: xgen_mcp_sessions
|
|
3040
|
-
ONTOLOGY: xgen_graph_rag_query, xgen_graph_stats
|
|
3041
|
-
SERVER: xgen_server_status
|
|
3708
|
+
${getToolIndexSummary()}
|
|
3042
3709
|
|
|
3043
|
-
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.`;
|
|
3044
3712
|
} else {
|
|
3045
3713
|
prompt2 += `
|
|
3046
3714
|
XGEN: Not connected. User can run /connect to connect.`;
|
|
@@ -3146,7 +3814,8 @@ async function agentRepl() {
|
|
|
3146
3814
|
}
|
|
3147
3815
|
}
|
|
3148
3816
|
const client2 = createLLMClient(provider);
|
|
3149
|
-
|
|
3817
|
+
resetLoadedTools();
|
|
3818
|
+
const allTools = [...getAllToolDefs(), definition8];
|
|
3150
3819
|
const builtinNames = getToolNames();
|
|
3151
3820
|
const mcpConfig = loadMcpConfig();
|
|
3152
3821
|
if (mcpConfig && Object.keys(mcpConfig.mcpServers).length > 0) {
|
|
@@ -3317,7 +3986,7 @@ async function agentRepl() {
|
|
|
3317
3986
|
if (input === "/tools") {
|
|
3318
3987
|
console.log(`
|
|
3319
3988
|
${chalk12.bold("\uCF54\uB529")} ${builtinNames.join(", ")}`);
|
|
3320
|
-
console.log(` ${chalk12.bold("XGEN")} ${
|
|
3989
|
+
console.log(` ${chalk12.bold("XGEN")} ${xgenToolDefs.map((t) => t.function.name).join(", ")}`);
|
|
3321
3990
|
if (mcpManager?.serverCount) {
|
|
3322
3991
|
console.log(` ${chalk12.bold("MCP")} ${mcpManager.getAllTools().map((t) => t.function.name).join(", ")}`);
|
|
3323
3992
|
}
|
|
@@ -3381,6 +4050,15 @@ async function agentRepl() {
|
|
|
3381
4050
|
}
|
|
3382
4051
|
async function runLoop(client2, model, messages, tools2) {
|
|
3383
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
|
+
}
|
|
3384
4062
|
let first = true;
|
|
3385
4063
|
const result = await streamChat(client2, model, messages, tools2, (delta) => {
|
|
3386
4064
|
if (first) {
|
|
@@ -3411,23 +4089,37 @@ async function runLoop(client2, model, messages, tools2) {
|
|
|
3411
4089
|
} catch {
|
|
3412
4090
|
args = {};
|
|
3413
4091
|
}
|
|
3414
|
-
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]) => {
|
|
3415
4099
|
const s = String(v);
|
|
3416
4100
|
return s.length > 40 ? s.slice(0, 40) + "\u2026" : s;
|
|
3417
4101
|
}).join(", ");
|
|
3418
4102
|
console.log(chalk12.dim(` \u250C ${tc.name}(${shortArgs})`));
|
|
3419
4103
|
let toolResult2;
|
|
3420
|
-
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)) {
|
|
3421
4113
|
toolResult2 = await execute8(tc.name, args);
|
|
3422
4114
|
} else if (mcpManager?.isMcpTool(tc.name)) {
|
|
3423
4115
|
toolResult2 = await mcpManager.callTool(tc.name, args);
|
|
3424
4116
|
} else {
|
|
3425
4117
|
toolResult2 = await executeTool(tc.name, args);
|
|
3426
4118
|
}
|
|
3427
|
-
|
|
4119
|
+
toolResult2 = runPostHooks(tc.name, toolResult2);
|
|
3428
4120
|
const preview = toolResult2.split("\n")[0].slice(0, 60);
|
|
3429
4121
|
console.log(chalk12.dim(` \u2514 ${preview}${toolResult2.length > 60 ? "\u2026" : ""}`));
|
|
3430
|
-
messages.push({ role: "tool", tool_call_id: tc.id, content:
|
|
4122
|
+
messages.push({ role: "tool", tool_call_id: tc.id, content: toolResult2 });
|
|
3431
4123
|
}
|
|
3432
4124
|
}
|
|
3433
4125
|
console.log(chalk12.yellow("\n \uCD5C\uB300 \uBC18\uBCF5 \uD69F\uC218 \uB3C4\uB2EC.\n"));
|
|
@@ -3631,7 +4323,7 @@ ${result.answer}
|
|
|
3631
4323
|
}
|
|
3632
4324
|
|
|
3633
4325
|
// src/index.ts
|
|
3634
|
-
var VERSION = "2.
|
|
4326
|
+
var VERSION = "2.5.0";
|
|
3635
4327
|
var LOGO = chalk15.cyan(`
|
|
3636
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
|
|
3637
4329
|
\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588
|
|
@@ -3663,11 +4355,17 @@ ${chalk15.bold("AI \uC5D0\uC774\uC804\uD2B8:")}
|
|
|
3663
4355
|
${chalk15.cyan("xgen provider add")} \uD504\uB85C\uBC14\uC774\uB354 \uCD94\uAC00
|
|
3664
4356
|
|
|
3665
4357
|
${chalk15.bold("XGEN \uD50C\uB7AB\uD3FC:")}
|
|
4358
|
+
${chalk15.cyan("xgen dash")} TUI \uB300\uC2DC\uBCF4\uB4DC (\uC870\uD68C/\uD14C\uC2A4\uD2B8/\uC0DD\uC131)
|
|
3666
4359
|
${chalk15.cyan("xgen chat")} \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uB300\uD654
|
|
3667
4360
|
${chalk15.cyan("xgen wf ls")} \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D
|
|
3668
4361
|
${chalk15.cyan("xgen wf run")} <id> "\uC9C8\uBB38" \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC2E4\uD589
|
|
3669
4362
|
${chalk15.cyan("xgen doc ls")} \uBB38\uC11C \uBAA9\uB85D
|
|
3670
4363
|
${chalk15.cyan("xgen ont query")} "\uC9C8\uBB38" \uC628\uD1A8\uB85C\uC9C0 \uC9C8\uC758
|
|
4364
|
+
|
|
4365
|
+
${chalk15.bold("\uB300\uC2DC\uBCF4\uB4DC (xgen dash):")}
|
|
4366
|
+
${chalk15.gray("\u2191\u2193")} \uC774\uB3D9 ${chalk15.gray("Enter")} \uC0C1\uC138/\uC2E4\uD589 ${chalk15.gray("1-6")} \uD0ED\uC804\uD658 ${chalk15.gray("r")} \uC0C8\uB85C\uACE0\uCE68 ${chalk15.gray("q")} \uC885\uB8CC
|
|
4367
|
+
${chalk15.gray("c")} \uC0DD\uC131 ${chalk15.gray("e")} \uC218\uC815 ${chalk15.gray("d")} \uC0AD\uC81C ${chalk15.gray("t")} \uD14C\uC2A4\uD2B8 ${chalk15.gray("u")} \uC2A4\uD1A0\uC5B4\uB4F1\uB85D ${chalk15.gray("v")} \uBC84\uC804
|
|
4368
|
+
\uD0ED: \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uCEEC\uB809\uC158 \uB178\uB4DC \uD504\uB86C\uD504\uD2B8 \uB3C4\uAD6C MCP
|
|
3671
4369
|
`
|
|
3672
4370
|
);
|
|
3673
4371
|
registerConfigCommand(program);
|
|
@@ -3679,6 +4377,9 @@ registerAgentCommand(program);
|
|
|
3679
4377
|
registerDocCommand(program);
|
|
3680
4378
|
registerOntologyCommand(program);
|
|
3681
4379
|
program.command("dash").alias("dashboard").description("XGEN TUI \uB300\uC2DC\uBCF4\uB4DC").action(async () => {
|
|
4380
|
+
process.stdin.removeAllListeners();
|
|
4381
|
+
process.stdin.pause();
|
|
4382
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
3682
4383
|
const { startRawTui: startRawTui2 } = await Promise.resolve().then(() => (init_raw_tui(), raw_tui_exports));
|
|
3683
4384
|
await startRawTui2();
|
|
3684
4385
|
});
|