openxgen 2.3.0 → 2.4.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 +940 -98
- 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,28 +1222,44 @@ var raw_tui_exports = {};
|
|
|
1113
1222
|
__export(raw_tui_exports, {
|
|
1114
1223
|
startRawTui: () => startRawTui
|
|
1115
1224
|
});
|
|
1225
|
+
function withTimeout(p, ms = 5e3, label = "API") {
|
|
1226
|
+
return new Promise((resolve, reject) => {
|
|
1227
|
+
const t = setTimeout(() => reject(new Error(`${label} \uD0C0\uC784\uC544\uC6C3 (${ms}ms)`)), ms);
|
|
1228
|
+
p.then((v) => {
|
|
1229
|
+
clearTimeout(t);
|
|
1230
|
+
resolve(v);
|
|
1231
|
+
}, (e) => {
|
|
1232
|
+
clearTimeout(t);
|
|
1233
|
+
reject(e);
|
|
1234
|
+
});
|
|
1235
|
+
});
|
|
1236
|
+
}
|
|
1116
1237
|
async function startRawTui() {
|
|
1117
1238
|
const provider = getDefaultProvider();
|
|
1118
1239
|
const server = getServer();
|
|
1119
1240
|
const auth = getAuth();
|
|
1120
|
-
const serverDisplay = auth && server ? `${auth.username}@${server.replace(
|
|
1241
|
+
const serverDisplay = auth && server ? `${auth.username}@${server.replace(/https?:\/\//, "")}` : "\uBBF8\uC5F0\uACB0";
|
|
1121
1242
|
let tab = "workflows";
|
|
1122
1243
|
let selected = 0;
|
|
1123
1244
|
let inputMode = false;
|
|
1124
1245
|
let inputBuffer = "";
|
|
1125
|
-
let
|
|
1246
|
+
let formCtx = null;
|
|
1126
1247
|
let workflows = [];
|
|
1127
1248
|
let collections = [];
|
|
1128
1249
|
let nodes = [];
|
|
1129
1250
|
let prompts = [];
|
|
1130
1251
|
let tools2 = [];
|
|
1252
|
+
let mcpSessions = [];
|
|
1131
1253
|
let detail = ["\u2190 \uD56D\uBAA9\uC744 \uC120\uD0DD\uD558\uC138\uC694"];
|
|
1132
1254
|
let statusMsg = "\uB85C\uB529...";
|
|
1255
|
+
let errors = [];
|
|
1133
1256
|
async function loadData() {
|
|
1134
|
-
statusMsg = "\uB85C\uB529...";
|
|
1257
|
+
statusMsg = "\uB370\uC774\uD130 \uB85C\uB529 \uC911...";
|
|
1258
|
+
errors = [];
|
|
1135
1259
|
render();
|
|
1136
1260
|
if (!server || !auth) {
|
|
1137
1261
|
statusMsg = "\uC11C\uBC84 \uBBF8\uC5F0\uACB0";
|
|
1262
|
+
detail = [red("\uC11C\uBC84 \uBBF8\uC5F0\uACB0"), "", cyan(" xgen config set-server <URL>"), cyan(" xgen login"), "", "\uD6C4 r \uC0C8\uB85C\uACE0\uCE68"];
|
|
1138
1263
|
render();
|
|
1139
1264
|
return;
|
|
1140
1265
|
}
|
|
@@ -1144,134 +1269,737 @@ async function startRawTui() {
|
|
|
1144
1269
|
Promise.resolve().then(() => (init_document(), document_exports)),
|
|
1145
1270
|
Promise.resolve().then(() => (init_xgen_extra(), xgen_extra_exports))
|
|
1146
1271
|
]);
|
|
1147
|
-
const
|
|
1148
|
-
wfMod.getWorkflowListDetail(),
|
|
1149
|
-
docMod.listCollections(),
|
|
1150
|
-
extraMod.listNodes(),
|
|
1151
|
-
extraMod.listPrompts(),
|
|
1152
|
-
extraMod.listToolStore()
|
|
1272
|
+
const results = await Promise.allSettled([
|
|
1273
|
+
withTimeout(wfMod.getWorkflowListDetail(), 3e3, "\uC6CC\uD06C\uD50C\uB85C\uC6B0"),
|
|
1274
|
+
withTimeout(docMod.listCollections(), 3e3, "\uCEEC\uB809\uC158"),
|
|
1275
|
+
withTimeout(extraMod.listNodes(), 3e3, "\uB178\uB4DC"),
|
|
1276
|
+
withTimeout(extraMod.listPrompts(), 3e3, "\uD504\uB86C\uD504\uD2B8"),
|
|
1277
|
+
withTimeout(extraMod.listToolStore(), 3e3, "\uB3C4\uAD6C"),
|
|
1278
|
+
withTimeout(extraMod.listMcpSessions(), 3e3, "MCP").catch(() => [])
|
|
1153
1279
|
]);
|
|
1154
|
-
|
|
1155
|
-
if (
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1280
|
+
const [wfR, colR, nodeR, promptR, toolR, mcpR] = results;
|
|
1281
|
+
if (wfR.status === "fulfilled") {
|
|
1282
|
+
workflows = wfR.value.map((w) => ({
|
|
1283
|
+
name: w.workflow_name ?? w.name ?? "?",
|
|
1284
|
+
id: w.workflow_id ?? w.id ?? "",
|
|
1285
|
+
deployed: w.deploy_status === "deployed" || w.deploy_status === "DEPLOYED" || !!w.is_deployed
|
|
1286
|
+
}));
|
|
1287
|
+
} else errors.push(`\uC6CC\uD06C\uD50C\uB85C\uC6B0: ${wfR.reason?.message ?? "\uC2E4\uD328"}`);
|
|
1288
|
+
if (colR.status === "fulfilled") {
|
|
1289
|
+
collections = colR.value.map((c) => ({
|
|
1290
|
+
name: c.collection_make_name ?? c.collection_name ?? c.name ?? "?",
|
|
1291
|
+
id: c.id ?? c.collection_id ?? "",
|
|
1292
|
+
docs: c.total_documents ?? 0,
|
|
1293
|
+
chunks: c.total_chunks ?? 0
|
|
1294
|
+
}));
|
|
1295
|
+
} else errors.push(`\uCEEC\uB809\uC158: ${colR.reason?.message ?? "\uC2E4\uD328"}`);
|
|
1296
|
+
if (nodeR.status === "fulfilled") {
|
|
1297
|
+
nodes = [];
|
|
1298
|
+
const raw = nodeR.value;
|
|
1299
|
+
for (const cat of raw) {
|
|
1300
|
+
const catName = cat.categoryName ?? cat.categoryId ?? "";
|
|
1301
|
+
const fns = cat.functions ?? cat.nodes ?? [];
|
|
1302
|
+
if (Array.isArray(fns)) {
|
|
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
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
} else errors.push(`\uB178\uB4DC: ${nodeR.reason?.message ?? "\uC2E4\uD328"}`);
|
|
1326
|
+
if (promptR.status === "fulfilled") {
|
|
1327
|
+
prompts = promptR.value.map((p) => ({
|
|
1328
|
+
name: p.prompt_title ?? p.name ?? p.title ?? "?",
|
|
1329
|
+
type: p.prompt_type ?? p.type ?? "",
|
|
1330
|
+
uid: p.prompt_uid ?? p.uid,
|
|
1331
|
+
content: p.prompt_content ?? p.content,
|
|
1332
|
+
dbId: p.id
|
|
1333
|
+
}));
|
|
1334
|
+
} else errors.push(`\uD504\uB86C\uD504\uD2B8: ${promptR.reason?.message ?? "\uC2E4\uD328"}`);
|
|
1335
|
+
if (toolR.status === "fulfilled") {
|
|
1336
|
+
tools2 = toolR.value.map((t) => {
|
|
1337
|
+
const fd = t.function_data ?? {};
|
|
1338
|
+
return {
|
|
1339
|
+
name: fd.function_name ?? t.function_name ?? t.name ?? t.tool_name ?? "?",
|
|
1340
|
+
desc: (fd.description ?? t.description ?? "").slice(0, 50),
|
|
1341
|
+
id: t.id,
|
|
1342
|
+
functionId: fd.function_id ?? t.function_id ?? t.function_upload_id,
|
|
1343
|
+
apiUrl: fd.api_url ?? t.api_url,
|
|
1344
|
+
status: fd.status ?? t.status
|
|
1345
|
+
};
|
|
1346
|
+
});
|
|
1347
|
+
} else errors.push(`\uB3C4\uAD6C: ${toolR.reason?.message ?? "\uC2E4\uD328"}`);
|
|
1348
|
+
if (mcpR.status === "fulfilled" && Array.isArray(mcpR.value)) {
|
|
1349
|
+
mcpSessions = mcpR.value.map((s) => ({
|
|
1350
|
+
id: s.session_id ?? s.id ?? "",
|
|
1351
|
+
name: s.session_name ?? s.name ?? "\uC774\uB984\uC5C6\uC74C",
|
|
1352
|
+
type: s.server_type ?? "?",
|
|
1353
|
+
status: s.status ?? "unknown",
|
|
1354
|
+
command: s.server_command
|
|
1355
|
+
}));
|
|
1356
|
+
}
|
|
1357
|
+
} catch (err) {
|
|
1358
|
+
errors.push(`\uC804\uCCB4: ${err.message}`);
|
|
1160
1359
|
}
|
|
1161
|
-
|
|
1360
|
+
selected = 0;
|
|
1361
|
+
updateDetail();
|
|
1362
|
+
statusMsg = errors.length > 0 ? `\u26A0 ${errors.length}\uAC1C \uC624\uB958 \u2502 r \uC7AC\uC2DC\uB3C4` : getHint();
|
|
1363
|
+
if (errors.length > 0) detail = [red("\uB85C\uB4DC \uC624\uB958:"), "", ...errors.map((e) => yellow(` \u2022 ${e}`))];
|
|
1162
1364
|
render();
|
|
1163
1365
|
}
|
|
1366
|
+
function getHint() {
|
|
1367
|
+
const hints = {
|
|
1368
|
+
workflows: "\u2191\u2193 \u2502 Enter \uB178\uB4DC\uAD6C\uC870/\uC2E4\uD589 \u2502 1-6 \uD0ED \u2502 r \u2502 q",
|
|
1369
|
+
collections: "\u2191\u2193 \u2502 Enter \uBB38\uC11C\uBAA9\uB85D \u2502 1-6 \uD0ED \u2502 r \u2502 q",
|
|
1370
|
+
nodes: "\u2191\u2193 \u2502 Enter \uC0C1\uC138(\uD30C\uB77C\uBBF8\uD130) \u2502 1-6 \uD0ED \u2502 r \u2502 q",
|
|
1371
|
+
prompts: "\u2191\u2193 \u2502 Enter \uB0B4\uC6A9 \u2502 c\uC0DD\uC131 e\uC218\uC815 d\uC0AD\uC81C u\uC2A4\uD1A0\uC5B4 v\uBC84\uC804 \u2502 q",
|
|
1372
|
+
tools: "\u2191\u2193 \u2502 Enter/t \uD14C\uC2A4\uD2B8 \u2502 c\uC0DD\uC131 u\uC2A4\uD1A0\uC5B4\uB4F1\uB85D \u2502 q",
|
|
1373
|
+
mcp: "\u2191\u2193 \u2502 Enter \uB3C4\uAD6C\uBAA9\uB85D \u2502 c\uC138\uC158\uC0DD\uC131 t\uB3C4\uAD6C\uD638\uCD9C d\uC0AD\uC81C \u2502 q"
|
|
1374
|
+
};
|
|
1375
|
+
return hints[tab];
|
|
1376
|
+
}
|
|
1164
1377
|
function getItems() {
|
|
1165
1378
|
switch (tab) {
|
|
1166
1379
|
case "workflows":
|
|
1167
|
-
return workflows.map((w) => ({ label: `${w.deployed ? "\u25CF" : "\u25CB"} ${w.name}`, sub: w.id.slice(0,
|
|
1380
|
+
return workflows.map((w) => ({ label: `${w.deployed ? green("\u25CF") : dim("\u25CB")} ${w.name}`, sub: w.id.slice(0, 16) }));
|
|
1168
1381
|
case "collections":
|
|
1169
1382
|
return collections.map((c) => ({ label: c.name, sub: `${c.docs}\uBB38\uC11C ${c.chunks}\uCCAD\uD06C` }));
|
|
1170
1383
|
case "nodes":
|
|
1171
|
-
return nodes.map((n) => ({ label: n.name, sub: n.desc }));
|
|
1384
|
+
return nodes.map((n) => ({ label: n.name, sub: n.category ? `[${n.category}] ${n.desc}` : n.desc }));
|
|
1172
1385
|
case "prompts":
|
|
1173
1386
|
return prompts.map((p) => ({ label: p.name, sub: `[${p.type}]` }));
|
|
1174
1387
|
case "tools":
|
|
1175
|
-
return tools2.map((t) =>
|
|
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
|
+
});
|
|
1392
|
+
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
|
+
});
|
|
1176
1397
|
}
|
|
1177
1398
|
}
|
|
1178
1399
|
function updateDetail() {
|
|
1179
1400
|
const items = getItems();
|
|
1180
|
-
if (
|
|
1401
|
+
if (items.length === 0) {
|
|
1402
|
+
const createHint = tab === "tools" ? "c \uB3C4\uAD6C \uC0DD\uC131" : tab === "prompts" ? "c \uD504\uB86C\uD504\uD2B8 \uC0DD\uC131" : tab === "mcp" ? "c MCP \uC138\uC158 \uC0DD\uC131" : "";
|
|
1403
|
+
detail = [dim("\uB370\uC774\uD130 \uC5C6\uC74C"), "", dim(createHint)];
|
|
1404
|
+
return;
|
|
1405
|
+
}
|
|
1406
|
+
if (selected < 0) selected = 0;
|
|
1407
|
+
if (selected >= items.length) selected = items.length - 1;
|
|
1181
1408
|
if (tab === "workflows" && workflows[selected]) {
|
|
1182
1409
|
const w = workflows[selected];
|
|
1183
|
-
detail = [
|
|
1410
|
+
detail = [
|
|
1411
|
+
bold(w.name),
|
|
1412
|
+
"",
|
|
1413
|
+
`ID ${w.id || dim("\uC5C6\uC74C")}`,
|
|
1414
|
+
`\uBC30\uD3EC ${w.deployed ? green("\u25CF Yes") : red("\u25CB No")}`,
|
|
1415
|
+
"",
|
|
1416
|
+
cyan("Enter") + " \uB178\uB4DC/\uC5E3\uC9C0 \uAD6C\uC870 \uBCF4\uAE30",
|
|
1417
|
+
cyan("i") + " \uC9C8\uBB38 \uC785\uB825 \uD6C4 \uC2E4\uD589"
|
|
1418
|
+
];
|
|
1184
1419
|
} else if (tab === "collections" && collections[selected]) {
|
|
1185
1420
|
const c = collections[selected];
|
|
1186
|
-
detail = [bold(c.name), "", `\uBB38\uC11C
|
|
1421
|
+
detail = [bold(c.name), "", `\uBB38\uC11C ${c.docs}\uAC1C`, `\uCCAD\uD06C ${c.chunks}\uAC1C`, "", cyan("Enter") + " \uBB38\uC11C \uBAA9\uB85D"];
|
|
1187
1422
|
} else if (tab === "nodes" && nodes[selected]) {
|
|
1188
1423
|
const n = nodes[selected];
|
|
1189
|
-
detail = [
|
|
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
|
+
];
|
|
1190
1432
|
} else if (tab === "prompts" && prompts[selected]) {
|
|
1191
1433
|
const p = prompts[selected];
|
|
1192
|
-
|
|
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
|
+
];
|
|
1193
1444
|
} else if (tab === "tools" && tools2[selected]) {
|
|
1194
1445
|
const t = tools2[selected];
|
|
1195
|
-
detail = [
|
|
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`
|
|
1468
|
+
];
|
|
1196
1469
|
}
|
|
1197
1470
|
}
|
|
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
|
+
}
|
|
1198
1477
|
function render() {
|
|
1199
1478
|
const cols = process.stdout.columns || 120;
|
|
1200
1479
|
const rows = process.stdout.rows || 30;
|
|
1201
|
-
const leftW = Math.floor(cols
|
|
1202
|
-
const rightW = cols - leftW;
|
|
1480
|
+
const leftW = Math.floor(cols * 0.5);
|
|
1481
|
+
const rightW = cols - leftW - 1;
|
|
1203
1482
|
const listH = rows - 5;
|
|
1204
1483
|
clear();
|
|
1205
1484
|
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}`);
|
|
1485
|
+
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("v2.4")} ${dim(serverDisplay)} \u2502 ${tabStr}`);
|
|
1211
1487
|
moveTo(2, 1);
|
|
1212
|
-
process.stdout.write(dim("\u2500".repeat(
|
|
1488
|
+
process.stdout.write(dim("\u2500".repeat(leftW) + "\u252C" + "\u2500".repeat(rightW)));
|
|
1213
1489
|
const items = getItems();
|
|
1214
|
-
const
|
|
1215
|
-
const
|
|
1216
|
-
for (let i = 0; i <
|
|
1490
|
+
const vis = Math.max(1, listH);
|
|
1491
|
+
const scr = items.length <= vis ? 0 : Math.max(0, Math.min(selected - Math.floor(vis / 2), items.length - vis));
|
|
1492
|
+
for (let i = 0; i < vis; i++) {
|
|
1217
1493
|
moveTo(3 + i, 1);
|
|
1218
|
-
const idx =
|
|
1494
|
+
const idx = scr + i;
|
|
1495
|
+
let left;
|
|
1219
1496
|
if (idx < items.length) {
|
|
1220
1497
|
const item = items[idx];
|
|
1221
|
-
const
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
process.stdout.write(idx === selected ? inverse(trimmed.padEnd(leftW - 1)) : trimmed);
|
|
1498
|
+
const sub = item.sub ? dim(` ${item.sub}`) : "";
|
|
1499
|
+
left = padVisual(`${idx === selected ? "\u25B8" : " "} ${String(idx + 1).padStart(2)}. ${item.label}${sub}`, leftW);
|
|
1500
|
+
if (idx === selected) left = inverse(left);
|
|
1225
1501
|
} else {
|
|
1226
|
-
|
|
1502
|
+
left = " ".repeat(leftW);
|
|
1227
1503
|
}
|
|
1504
|
+
process.stdout.write(left);
|
|
1228
1505
|
process.stdout.write(dim("\u2502"));
|
|
1229
|
-
if (i < detail.length) {
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1506
|
+
if (i < detail.length) process.stdout.write(` ${detail[i]}`);
|
|
1507
|
+
}
|
|
1508
|
+
if (items.length === 0) {
|
|
1509
|
+
moveTo(4, 3);
|
|
1510
|
+
process.stdout.write(dim("(\uD56D\uBAA9 \uC5C6\uC74C)"));
|
|
1233
1511
|
}
|
|
1234
1512
|
moveTo(rows - 2, 1);
|
|
1235
|
-
process.stdout.write(dim("\u2500".repeat(
|
|
1513
|
+
process.stdout.write(dim("\u2500".repeat(leftW) + "\u2534" + "\u2500".repeat(rightW)));
|
|
1236
1514
|
moveTo(rows - 1, 1);
|
|
1237
|
-
if (inputMode) {
|
|
1238
|
-
const
|
|
1239
|
-
process.stdout.write(` ${
|
|
1515
|
+
if (inputMode || formCtx) {
|
|
1516
|
+
const pr = formCtx ? `${formCtx.fields[formCtx.step].label}${formCtx.fields[formCtx.step].required ? "*" : ""} \u276F ` : "\u276F ";
|
|
1517
|
+
process.stdout.write(` ${cyan(pr)}${inputBuffer}`);
|
|
1240
1518
|
showCursor();
|
|
1241
1519
|
} else {
|
|
1242
|
-
process.stdout.write(dim(
|
|
1520
|
+
process.stdout.write(dim(` ${getHint()}`));
|
|
1243
1521
|
hideCursor();
|
|
1244
1522
|
}
|
|
1245
1523
|
moveTo(rows, 1);
|
|
1246
1524
|
process.stdout.write(dim(` ${statusMsg}`.slice(0, cols)));
|
|
1247
1525
|
}
|
|
1248
|
-
async function
|
|
1249
|
-
detail = [
|
|
1526
|
+
async function runWorkflow(wf, input) {
|
|
1527
|
+
detail = [bold(wf.name), "", `\uC785\uB825: ${input}`, "", yellow("\uC2E4\uD589 \uC911...")];
|
|
1250
1528
|
render();
|
|
1251
1529
|
try {
|
|
1252
1530
|
const { executeWorkflow: executeWorkflow2 } = await Promise.resolve().then(() => (init_workflow(), workflow_exports));
|
|
1253
1531
|
const { randomUUID: randomUUID4 } = await import("crypto");
|
|
1254
|
-
const r = await executeWorkflow2({
|
|
1532
|
+
const r = await withTimeout(executeWorkflow2({
|
|
1255
1533
|
workflow_id: wf.id,
|
|
1256
1534
|
workflow_name: wf.name,
|
|
1257
1535
|
input_data: input,
|
|
1258
1536
|
interaction_id: `tui_${randomUUID4().slice(0, 8)}`,
|
|
1259
1537
|
user_id: auth?.userId ? parseInt(auth.userId) : 1
|
|
1260
|
-
});
|
|
1261
|
-
const content = r
|
|
1262
|
-
detail = [bold(wf.name), "", `\uC785\uB825: ${input}`, "", "\uACB0\uACFC:", ...String(content).split("\n").slice(0, 15)];
|
|
1538
|
+
}), 3e4, "\uC2E4\uD589");
|
|
1539
|
+
const content = r?.content ?? r?.message ?? r?.result ?? JSON.stringify(r).slice(0, 500);
|
|
1540
|
+
detail = [bold(wf.name), "", `\uC785\uB825: ${input}`, "", green("\uACB0\uACFC:"), ...String(content).split("\n").slice(0, 15)];
|
|
1541
|
+
} catch (err) {
|
|
1542
|
+
detail = [bold(wf.name), "", red(`\uC2E4\uD328: ${err.message}`)];
|
|
1543
|
+
}
|
|
1544
|
+
statusMsg = getHint();
|
|
1545
|
+
render();
|
|
1546
|
+
}
|
|
1547
|
+
async function loadWorkflowStructure(wf) {
|
|
1548
|
+
detail = [bold(wf.name), "", yellow("\uB178\uB4DC/\uC5E3\uC9C0 \uB85C\uB529...")];
|
|
1549
|
+
render();
|
|
1550
|
+
try {
|
|
1551
|
+
const { getWorkflowDetail: getWorkflowDetail2 } = await Promise.resolve().then(() => (init_workflow(), workflow_exports));
|
|
1552
|
+
const data = await withTimeout(getWorkflowDetail2(wf.id), 1e4, "\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uB85C\uB4DC");
|
|
1553
|
+
const wfData = data?.workflow_data ?? data;
|
|
1554
|
+
const ns = wfData?.nodes ?? data?.nodes ?? [];
|
|
1555
|
+
const es = wfData?.edges ?? data?.edges ?? [];
|
|
1556
|
+
detail = [
|
|
1557
|
+
bold(wf.name),
|
|
1558
|
+
"",
|
|
1559
|
+
`\uB178\uB4DC ${ns.length}\uAC1C \uC5E3\uC9C0 ${es.length}\uAC1C`,
|
|
1560
|
+
"",
|
|
1561
|
+
bold("\uB178\uB4DC:"),
|
|
1562
|
+
...ns.slice(0, 15).map((n, i) => {
|
|
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`)] : [],
|
|
1568
|
+
"",
|
|
1569
|
+
bold("\uC5F0\uACB0:"),
|
|
1570
|
+
...es.slice(0, 8).map((e) => {
|
|
1571
|
+
const src = ns.find((n) => n.id === e.source);
|
|
1572
|
+
const tgt = ns.find((n) => n.id === e.target);
|
|
1573
|
+
const srcName = src?.data?.label ?? src?.data?.nodeName ?? e.source;
|
|
1574
|
+
const tgtName = tgt?.data?.label ?? tgt?.data?.nodeName ?? e.target;
|
|
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"
|
|
1580
|
+
];
|
|
1581
|
+
} catch (err) {
|
|
1582
|
+
detail = [bold(wf.name), "", red(`\uB85C\uB4DC \uC2E4\uD328: ${err.message}`)];
|
|
1583
|
+
}
|
|
1584
|
+
render();
|
|
1585
|
+
}
|
|
1586
|
+
async function loadNodeDetail(n) {
|
|
1587
|
+
if (!n.id) {
|
|
1588
|
+
detail = [bold(n.name), "", red("\uB178\uB4DC ID \uC5C6\uC74C")];
|
|
1589
|
+
render();
|
|
1590
|
+
return;
|
|
1591
|
+
}
|
|
1592
|
+
detail = [bold(n.name), "", yellow("\uC0C1\uC138 \uB85C\uB529...")];
|
|
1593
|
+
render();
|
|
1594
|
+
try {
|
|
1595
|
+
const { getNodeDetail: getNodeDetail2 } = await Promise.resolve().then(() => (init_xgen_extra(), xgen_extra_exports));
|
|
1596
|
+
const d = await withTimeout(getNodeDetail2(n.id), 8e3, "\uB178\uB4DC \uC0C1\uC138");
|
|
1597
|
+
const inputs = d?.inputs ?? d?.inputPorts ?? [];
|
|
1598
|
+
const outputs = d?.outputs ?? d?.outputPorts ?? [];
|
|
1599
|
+
const params = d?.parameters ?? d?.params ?? d?.defaultParams ?? {};
|
|
1600
|
+
const paramKeys = typeof params === "object" ? Object.keys(params) : [];
|
|
1601
|
+
detail = [
|
|
1602
|
+
bold(d?.nodeName ?? d?.name ?? n.name),
|
|
1603
|
+
"",
|
|
1604
|
+
`ID ${d?.nodeId ?? d?.id ?? n.id}`,
|
|
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 ?? "")}`),
|
|
1613
|
+
"",
|
|
1614
|
+
bold(`\uD30C\uB77C\uBBF8\uD130 (${paramKeys.length}):`),
|
|
1615
|
+
...paramKeys.slice(0, 8).map((k) => ` \u2022 ${k}: ${dim(String(params[k]).slice(0, 30))}`)
|
|
1616
|
+
];
|
|
1617
|
+
} catch (err) {
|
|
1618
|
+
detail = [bold(n.name), "", red(`\uC2E4\uD328: ${err.message}`)];
|
|
1619
|
+
}
|
|
1620
|
+
render();
|
|
1621
|
+
}
|
|
1622
|
+
function startCreatePrompt() {
|
|
1623
|
+
startForm("create-prompt", "\uC0C8 \uD504\uB86C\uD504\uD2B8 \uC0DD\uC131", [
|
|
1624
|
+
{ key: "prompt_title", label: "\uC81C\uBAA9", required: true },
|
|
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")];
|
|
1713
|
+
render();
|
|
1714
|
+
return;
|
|
1715
|
+
}
|
|
1716
|
+
const p = prompts[selected];
|
|
1717
|
+
detail = [bold(p.name), "", yellow("\uBC84\uC804 \uB85C\uB529...")];
|
|
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}`];
|
|
1777
|
+
render();
|
|
1778
|
+
try {
|
|
1779
|
+
const { apiTest: apiTest2 } = await Promise.resolve().then(() => (init_xgen_extra(), xgen_extra_exports));
|
|
1780
|
+
const r = await withTimeout(apiTest2({ api_url: t.apiUrl, api_method: "GET", api_timeout: 15 }), 2e4, "\uD14C\uC2A4\uD2B8");
|
|
1781
|
+
const ok = r?.success ?? (r?.data?.status && r.data.status < 400);
|
|
1782
|
+
const st = r?.data?.status ?? "?";
|
|
1783
|
+
const resp = r?.data?.response;
|
|
1784
|
+
const lines = (typeof resp === "string" ? resp : JSON.stringify(resp ?? {}, null, 2)).split("\n").slice(0, 12);
|
|
1785
|
+
detail = [bold(t.name), "", ok ? green(`\u2713 ${st} OK`) : red(`\u2717 ${st} FAIL`), "", bold("\uC751\uB2F5:"), ...lines];
|
|
1786
|
+
statusMsg = ok ? green("\uD14C\uC2A4\uD2B8 \uC131\uACF5") : red("\uD14C\uC2A4\uD2B8 \uC2E4\uD328");
|
|
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");
|
|
1263
1807
|
} catch (err) {
|
|
1264
|
-
detail = [`\uC2E4\
|
|
1808
|
+
detail = [red(`\uC2E4\uD328: ${err.message}`)];
|
|
1809
|
+
statusMsg = red("\uC2E4\uD328");
|
|
1265
1810
|
}
|
|
1266
1811
|
render();
|
|
1267
1812
|
}
|
|
1268
|
-
function
|
|
1269
|
-
|
|
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
|
+
function handleKey(s) {
|
|
1932
|
+
if (formCtx) {
|
|
1933
|
+
if (s === "\x1B" || s === "\x1B\x1B") {
|
|
1934
|
+
formCtx = null;
|
|
1935
|
+
inputBuffer = "";
|
|
1936
|
+
inputMode = false;
|
|
1937
|
+
updateDetail();
|
|
1938
|
+
statusMsg = getHint();
|
|
1939
|
+
render();
|
|
1940
|
+
return;
|
|
1941
|
+
}
|
|
1942
|
+
if (s === "\r" || s === "\n") {
|
|
1943
|
+
const field = formCtx.fields[formCtx.step];
|
|
1944
|
+
const value = inputBuffer.trim() || field.default || "";
|
|
1945
|
+
if (field.required && !value) {
|
|
1946
|
+
statusMsg = red(`${field.label} \uD544\uC218`);
|
|
1947
|
+
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
|
+
} 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
|
+
render();
|
|
1974
|
+
}
|
|
1975
|
+
return;
|
|
1976
|
+
}
|
|
1977
|
+
if (s === "\x7F" || s === "\b") {
|
|
1978
|
+
inputBuffer = inputBuffer.slice(0, -1);
|
|
1979
|
+
render();
|
|
1980
|
+
return;
|
|
1981
|
+
}
|
|
1982
|
+
if (s === "") {
|
|
1983
|
+
formCtx = null;
|
|
1984
|
+
inputBuffer = "";
|
|
1985
|
+
inputMode = false;
|
|
1986
|
+
updateDetail();
|
|
1987
|
+
render();
|
|
1988
|
+
return;
|
|
1989
|
+
}
|
|
1990
|
+
if (s.length > 0 && s.charCodeAt(0) >= 32) {
|
|
1991
|
+
inputBuffer += s;
|
|
1992
|
+
render();
|
|
1993
|
+
return;
|
|
1994
|
+
}
|
|
1995
|
+
return;
|
|
1996
|
+
}
|
|
1270
1997
|
if (inputMode) {
|
|
1271
1998
|
if (s === "\x1B" || s === "\x1B\x1B") {
|
|
1272
1999
|
inputMode = false;
|
|
1273
2000
|
inputBuffer = "";
|
|
1274
|
-
|
|
2001
|
+
updateDetail();
|
|
2002
|
+
statusMsg = getHint();
|
|
1275
2003
|
render();
|
|
1276
2004
|
return;
|
|
1277
2005
|
}
|
|
@@ -1279,11 +2007,11 @@ async function startRawTui() {
|
|
|
1279
2007
|
const val = inputBuffer.trim();
|
|
1280
2008
|
inputMode = false;
|
|
1281
2009
|
inputBuffer = "";
|
|
1282
|
-
if (val &&
|
|
1283
|
-
|
|
1284
|
-
|
|
2010
|
+
if (val && tab === "workflows" && workflows[selected]) {
|
|
2011
|
+
runWorkflow(workflows[selected], val);
|
|
2012
|
+
} else {
|
|
2013
|
+
render();
|
|
1285
2014
|
}
|
|
1286
|
-
render();
|
|
1287
2015
|
return;
|
|
1288
2016
|
}
|
|
1289
2017
|
if (s === "\x7F" || s === "\b") {
|
|
@@ -1291,6 +2019,12 @@ async function startRawTui() {
|
|
|
1291
2019
|
render();
|
|
1292
2020
|
return;
|
|
1293
2021
|
}
|
|
2022
|
+
if (s === "") {
|
|
2023
|
+
inputMode = false;
|
|
2024
|
+
inputBuffer = "";
|
|
2025
|
+
render();
|
|
2026
|
+
return;
|
|
2027
|
+
}
|
|
1294
2028
|
if (s.length > 0 && s.charCodeAt(0) >= 32) {
|
|
1295
2029
|
inputBuffer += s;
|
|
1296
2030
|
render();
|
|
@@ -1302,20 +2036,79 @@ async function startRawTui() {
|
|
|
1302
2036
|
cleanup();
|
|
1303
2037
|
process.exit(0);
|
|
1304
2038
|
}
|
|
1305
|
-
if (s === "r") {
|
|
2039
|
+
if (s === "r" || s === "R") {
|
|
1306
2040
|
loadData();
|
|
1307
2041
|
return;
|
|
1308
2042
|
}
|
|
1309
|
-
if (s === "i") {
|
|
2043
|
+
if (s === "i" && tab === "workflows" && workflows[selected]) {
|
|
1310
2044
|
inputMode = true;
|
|
2045
|
+
inputBuffer = "";
|
|
2046
|
+
statusMsg = `${workflows[selected].name} \u2014 \uC9C8\uBB38 \uC785\uB825 \uD6C4 Enter, Esc \uCDE8\uC18C`;
|
|
1311
2047
|
render();
|
|
1312
2048
|
return;
|
|
1313
2049
|
}
|
|
2050
|
+
if (s === "c" || s === "C") {
|
|
2051
|
+
if (tab === "tools") {
|
|
2052
|
+
startCreateTool();
|
|
2053
|
+
return;
|
|
2054
|
+
}
|
|
2055
|
+
if (tab === "prompts") {
|
|
2056
|
+
startCreatePrompt();
|
|
2057
|
+
return;
|
|
2058
|
+
}
|
|
2059
|
+
if (tab === "mcp") {
|
|
2060
|
+
startCreateMcpSession();
|
|
2061
|
+
return;
|
|
2062
|
+
}
|
|
2063
|
+
}
|
|
2064
|
+
if (s === "t" || s === "T") {
|
|
2065
|
+
if (tab === "tools") {
|
|
2066
|
+
testSelectedTool();
|
|
2067
|
+
return;
|
|
2068
|
+
}
|
|
2069
|
+
if (tab === "mcp") {
|
|
2070
|
+
startMcpToolCall();
|
|
2071
|
+
return;
|
|
2072
|
+
}
|
|
2073
|
+
}
|
|
2074
|
+
if (s === "u" || s === "U") {
|
|
2075
|
+
if (tab === "tools") {
|
|
2076
|
+
uploadSelectedTool();
|
|
2077
|
+
return;
|
|
2078
|
+
}
|
|
2079
|
+
if (tab === "prompts") {
|
|
2080
|
+
uploadSelectedPromptToStore();
|
|
2081
|
+
return;
|
|
2082
|
+
}
|
|
2083
|
+
}
|
|
2084
|
+
if (s === "e" || s === "E") {
|
|
2085
|
+
if (tab === "prompts") {
|
|
2086
|
+
startEditPrompt();
|
|
2087
|
+
return;
|
|
2088
|
+
}
|
|
2089
|
+
}
|
|
2090
|
+
if (s === "d" || s === "D") {
|
|
2091
|
+
if (tab === "prompts") {
|
|
2092
|
+
deleteSelectedPrompt();
|
|
2093
|
+
return;
|
|
2094
|
+
}
|
|
2095
|
+
if (tab === "mcp") {
|
|
2096
|
+
deleteSelectedMcpSession();
|
|
2097
|
+
return;
|
|
2098
|
+
}
|
|
2099
|
+
}
|
|
2100
|
+
if (s === "v" || s === "V") {
|
|
2101
|
+
if (tab === "prompts") {
|
|
2102
|
+
showPromptVersions();
|
|
2103
|
+
return;
|
|
2104
|
+
}
|
|
2105
|
+
}
|
|
1314
2106
|
const tabNum = parseInt(s);
|
|
1315
|
-
if (tabNum >= 1 && tabNum <=
|
|
2107
|
+
if (tabNum >= 1 && tabNum <= 6) {
|
|
1316
2108
|
tab = TABS[tabNum - 1].key;
|
|
1317
2109
|
selected = 0;
|
|
1318
2110
|
updateDetail();
|
|
2111
|
+
statusMsg = getHint();
|
|
1319
2112
|
render();
|
|
1320
2113
|
return;
|
|
1321
2114
|
}
|
|
@@ -1324,48 +2117,82 @@ async function startRawTui() {
|
|
|
1324
2117
|
tab = TABS[(idx + 1) % TABS.length].key;
|
|
1325
2118
|
selected = 0;
|
|
1326
2119
|
updateDetail();
|
|
2120
|
+
statusMsg = getHint();
|
|
2121
|
+
render();
|
|
2122
|
+
return;
|
|
2123
|
+
}
|
|
2124
|
+
if (s === "\x1B[Z") {
|
|
2125
|
+
const idx = TABS.findIndex((t) => t.key === tab);
|
|
2126
|
+
tab = TABS[(idx - 1 + TABS.length) % TABS.length].key;
|
|
2127
|
+
selected = 0;
|
|
2128
|
+
updateDetail();
|
|
2129
|
+
statusMsg = getHint();
|
|
1327
2130
|
render();
|
|
1328
2131
|
return;
|
|
1329
2132
|
}
|
|
1330
2133
|
if (s === "\x1B[A") {
|
|
1331
2134
|
const items = getItems();
|
|
1332
|
-
|
|
2135
|
+
if (items.length > 0) {
|
|
2136
|
+
selected = Math.max(0, selected - 1);
|
|
2137
|
+
updateDetail();
|
|
2138
|
+
render();
|
|
2139
|
+
}
|
|
2140
|
+
return;
|
|
2141
|
+
}
|
|
2142
|
+
if (s === "\x1B[B") {
|
|
2143
|
+
const items = getItems();
|
|
2144
|
+
if (items.length > 0) {
|
|
2145
|
+
selected = Math.min(items.length - 1, selected + 1);
|
|
2146
|
+
updateDetail();
|
|
2147
|
+
render();
|
|
2148
|
+
}
|
|
2149
|
+
return;
|
|
2150
|
+
}
|
|
2151
|
+
if (s === "\x1B[5~") {
|
|
2152
|
+
selected = Math.max(0, selected - 10);
|
|
1333
2153
|
updateDetail();
|
|
1334
2154
|
render();
|
|
1335
2155
|
return;
|
|
1336
2156
|
}
|
|
1337
|
-
if (s === "\x1B[
|
|
2157
|
+
if (s === "\x1B[6~") {
|
|
1338
2158
|
const items = getItems();
|
|
1339
|
-
selected = Math.min(items.length - 1, selected +
|
|
2159
|
+
selected = Math.min(items.length - 1, selected + 10);
|
|
1340
2160
|
updateDetail();
|
|
1341
2161
|
render();
|
|
1342
2162
|
return;
|
|
1343
2163
|
}
|
|
1344
2164
|
if (s === "\r" || s === "\n") {
|
|
2165
|
+
const items = getItems();
|
|
2166
|
+
if (items.length === 0) return;
|
|
1345
2167
|
if (tab === "workflows" && workflows[selected]) {
|
|
1346
|
-
|
|
1347
|
-
inputMode = true;
|
|
1348
|
-
statusMsg = `${runTarget.name} \u2014 \uC785\uB825 \uD6C4 Enter \uC2E4\uD589, Esc \uCDE8\uC18C`;
|
|
1349
|
-
render();
|
|
2168
|
+
loadWorkflowStructure(workflows[selected]);
|
|
1350
2169
|
} else if (tab === "collections" && collections[selected]) {
|
|
1351
2170
|
const c = collections[selected];
|
|
1352
|
-
detail = [
|
|
2171
|
+
detail = [bold(c.name), "", yellow("\uBB38\uC11C \uB85C\uB529...")];
|
|
1353
2172
|
render();
|
|
1354
2173
|
Promise.resolve().then(() => (init_document(), document_exports)).then(async (m) => {
|
|
1355
2174
|
try {
|
|
1356
|
-
const docs = await m.listDocuments(String(
|
|
1357
|
-
if (!docs
|
|
1358
|
-
detail = [bold(c.name), "", "\uBB38\uC11C \uC5C6\uC74C"];
|
|
2175
|
+
const docs = await withTimeout(m.listDocuments(String(c.id)), 8e3, "\uBB38\uC11C");
|
|
2176
|
+
if (!docs?.length) {
|
|
2177
|
+
detail = [bold(c.name), "", dim("\uBB38\uC11C \uC5C6\uC74C")];
|
|
1359
2178
|
} else {
|
|
1360
|
-
detail = [bold(c.name) + ` \u2014 ${docs.length}\uAC1C
|
|
1361
|
-
(d, i) => ` ${i + 1}. ${d.name || d.file_name || "\uC774\uB984\uC5C6\uC74C"}`
|
|
1362
|
-
).slice(0, 15)];
|
|
2179
|
+
detail = [bold(c.name) + ` \u2014 ${docs.length}\uAC1C`, "", ...docs.map((d, i) => ` ${i + 1}. ${d.name || d.file_name || "?"}`).slice(0, 20)];
|
|
1363
2180
|
}
|
|
1364
2181
|
} catch (err) {
|
|
1365
|
-
detail = [`\
|
|
2182
|
+
detail = [red(`\uC2E4\uD328: ${err.message}`)];
|
|
1366
2183
|
}
|
|
1367
2184
|
render();
|
|
1368
2185
|
});
|
|
2186
|
+
} else if (tab === "nodes" && nodes[selected]) {
|
|
2187
|
+
loadNodeDetail(nodes[selected]);
|
|
2188
|
+
} else if (tab === "prompts" && prompts[selected]) {
|
|
2189
|
+
const p = prompts[selected];
|
|
2190
|
+
detail = [bold(p.name), `\uD0C0\uC785: ${p.type}`, `UID: ${p.uid || "?"}`, "", bold("\uB0B4\uC6A9:"), "", ...p.content ? p.content.split("\n").slice(0, 18) : [dim("\uC5C6\uC74C")]];
|
|
2191
|
+
render();
|
|
2192
|
+
} else if (tab === "tools" && tools2[selected]) {
|
|
2193
|
+
testSelectedTool();
|
|
2194
|
+
} else if (tab === "mcp" && mcpSessions[selected]) {
|
|
2195
|
+
loadMcpTools();
|
|
1369
2196
|
}
|
|
1370
2197
|
return;
|
|
1371
2198
|
}
|
|
@@ -1373,9 +2200,7 @@ async function startRawTui() {
|
|
|
1373
2200
|
function cleanup() {
|
|
1374
2201
|
showCursor();
|
|
1375
2202
|
clear();
|
|
1376
|
-
if (process.stdin.isTTY && process.stdin.isRaw)
|
|
1377
|
-
process.stdin.setRawMode(false);
|
|
1378
|
-
}
|
|
2203
|
+
if (process.stdin.isTTY && process.stdin.isRaw) process.stdin.setRawMode(false);
|
|
1379
2204
|
process.stdin.removeAllListeners("data");
|
|
1380
2205
|
process.stdin.pause();
|
|
1381
2206
|
}
|
|
@@ -1389,10 +2214,13 @@ async function startRawTui() {
|
|
|
1389
2214
|
hideCursor();
|
|
1390
2215
|
process.stdin.on("data", (data) => {
|
|
1391
2216
|
try {
|
|
1392
|
-
handleKey(data);
|
|
1393
|
-
} catch {
|
|
2217
|
+
handleKey(String(data));
|
|
2218
|
+
} catch (err) {
|
|
2219
|
+
statusMsg = red(`\uC624\uB958: ${err.message}`);
|
|
2220
|
+
render();
|
|
1394
2221
|
}
|
|
1395
2222
|
});
|
|
2223
|
+
process.stdout.on("resize", () => render());
|
|
1396
2224
|
process.on("SIGINT", () => {
|
|
1397
2225
|
cleanup();
|
|
1398
2226
|
process.exit(0);
|
|
@@ -1400,11 +2228,11 @@ async function startRawTui() {
|
|
|
1400
2228
|
process.on("exit", () => {
|
|
1401
2229
|
showCursor();
|
|
1402
2230
|
});
|
|
1403
|
-
|
|
2231
|
+
loadData();
|
|
1404
2232
|
await new Promise(() => {
|
|
1405
2233
|
});
|
|
1406
2234
|
}
|
|
1407
|
-
var TABS, CSI, clear, moveTo, dim, bold, inverse, hideCursor, showCursor;
|
|
2235
|
+
var TABS, CSI, clear, moveTo, dim, bold, inverse, red, green, yellow, cyan, hideCursor, showCursor;
|
|
1408
2236
|
var init_raw_tui = __esm({
|
|
1409
2237
|
"src/dashboard/raw-tui.ts"() {
|
|
1410
2238
|
"use strict";
|
|
@@ -1414,7 +2242,8 @@ var init_raw_tui = __esm({
|
|
|
1414
2242
|
{ key: "collections", label: "\uCEEC\uB809\uC158", num: "2" },
|
|
1415
2243
|
{ key: "nodes", label: "\uB178\uB4DC", num: "3" },
|
|
1416
2244
|
{ key: "prompts", label: "\uD504\uB86C\uD504\uD2B8", num: "4" },
|
|
1417
|
-
{ key: "tools", label: "\uB3C4\uAD6C", num: "5" }
|
|
2245
|
+
{ key: "tools", label: "\uB3C4\uAD6C", num: "5" },
|
|
2246
|
+
{ key: "mcp", label: "MCP", num: "6" }
|
|
1418
2247
|
];
|
|
1419
2248
|
CSI = "\x1B[";
|
|
1420
2249
|
clear = () => process.stdout.write(`${CSI}2J${CSI}H`);
|
|
@@ -1422,6 +2251,10 @@ var init_raw_tui = __esm({
|
|
|
1422
2251
|
dim = (s) => `${CSI}2m${s}${CSI}0m`;
|
|
1423
2252
|
bold = (s) => `${CSI}1m${s}${CSI}0m`;
|
|
1424
2253
|
inverse = (s) => `${CSI}7m${s}${CSI}0m`;
|
|
2254
|
+
red = (s) => `${CSI}31m${s}${CSI}0m`;
|
|
2255
|
+
green = (s) => `${CSI}32m${s}${CSI}0m`;
|
|
2256
|
+
yellow = (s) => `${CSI}33m${s}${CSI}0m`;
|
|
2257
|
+
cyan = (s) => `${CSI}36m${s}${CSI}0m`;
|
|
1425
2258
|
hideCursor = () => process.stdout.write(`${CSI}?25l`);
|
|
1426
2259
|
showCursor = () => process.stdout.write(`${CSI}?25h`);
|
|
1427
2260
|
}
|
|
@@ -3631,7 +4464,7 @@ ${result.answer}
|
|
|
3631
4464
|
}
|
|
3632
4465
|
|
|
3633
4466
|
// src/index.ts
|
|
3634
|
-
var VERSION = "2.
|
|
4467
|
+
var VERSION = "2.4.0";
|
|
3635
4468
|
var LOGO = chalk15.cyan(`
|
|
3636
4469
|
\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
4470
|
\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588
|
|
@@ -3663,11 +4496,17 @@ ${chalk15.bold("AI \uC5D0\uC774\uC804\uD2B8:")}
|
|
|
3663
4496
|
${chalk15.cyan("xgen provider add")} \uD504\uB85C\uBC14\uC774\uB354 \uCD94\uAC00
|
|
3664
4497
|
|
|
3665
4498
|
${chalk15.bold("XGEN \uD50C\uB7AB\uD3FC:")}
|
|
4499
|
+
${chalk15.cyan("xgen dash")} TUI \uB300\uC2DC\uBCF4\uB4DC (\uC870\uD68C/\uD14C\uC2A4\uD2B8/\uC0DD\uC131)
|
|
3666
4500
|
${chalk15.cyan("xgen chat")} \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uB300\uD654
|
|
3667
4501
|
${chalk15.cyan("xgen wf ls")} \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D
|
|
3668
4502
|
${chalk15.cyan("xgen wf run")} <id> "\uC9C8\uBB38" \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC2E4\uD589
|
|
3669
4503
|
${chalk15.cyan("xgen doc ls")} \uBB38\uC11C \uBAA9\uB85D
|
|
3670
4504
|
${chalk15.cyan("xgen ont query")} "\uC9C8\uBB38" \uC628\uD1A8\uB85C\uC9C0 \uC9C8\uC758
|
|
4505
|
+
|
|
4506
|
+
${chalk15.bold("\uB300\uC2DC\uBCF4\uB4DC (xgen dash):")}
|
|
4507
|
+
${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
|
|
4508
|
+
${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
|
|
4509
|
+
\uD0ED: \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uCEEC\uB809\uC158 \uB178\uB4DC \uD504\uB86C\uD504\uD2B8 \uB3C4\uAD6C MCP
|
|
3671
4510
|
`
|
|
3672
4511
|
);
|
|
3673
4512
|
registerConfigCommand(program);
|
|
@@ -3679,6 +4518,9 @@ registerAgentCommand(program);
|
|
|
3679
4518
|
registerDocCommand(program);
|
|
3680
4519
|
registerOntologyCommand(program);
|
|
3681
4520
|
program.command("dash").alias("dashboard").description("XGEN TUI \uB300\uC2DC\uBCF4\uB4DC").action(async () => {
|
|
4521
|
+
process.stdin.removeAllListeners();
|
|
4522
|
+
process.stdin.pause();
|
|
4523
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
3682
4524
|
const { startRawTui: startRawTui2 } = await Promise.resolve().then(() => (init_raw_tui(), raw_tui_exports));
|
|
3683
4525
|
await startRawTui2();
|
|
3684
4526
|
});
|