openxgen 1.1.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1952 -2042
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'module'; const require = createRequire(import.meta.url);
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
5
|
var __esm = (fn, res) => function __init() {
|
|
@@ -775,6 +776,11 @@ var init_provider = __esm({
|
|
|
775
776
|
});
|
|
776
777
|
|
|
777
778
|
// src/agent/llm.ts
|
|
779
|
+
var llm_exports = {};
|
|
780
|
+
__export(llm_exports, {
|
|
781
|
+
createLLMClient: () => createLLMClient,
|
|
782
|
+
streamChat: () => streamChat
|
|
783
|
+
});
|
|
778
784
|
import OpenAI2 from "openai";
|
|
779
785
|
function createLLMClient(provider) {
|
|
780
786
|
const opts = {
|
|
@@ -828,2172 +834,2076 @@ var init_llm = __esm({
|
|
|
828
834
|
}
|
|
829
835
|
});
|
|
830
836
|
|
|
831
|
-
// src/
|
|
832
|
-
var
|
|
833
|
-
__export(
|
|
834
|
-
|
|
835
|
-
|
|
837
|
+
// src/api/document.ts
|
|
838
|
+
var document_exports = {};
|
|
839
|
+
__export(document_exports, {
|
|
840
|
+
getDocumentInfo: () => getDocumentInfo,
|
|
841
|
+
listCollections: () => listCollections,
|
|
842
|
+
listDocuments: () => listDocuments,
|
|
843
|
+
uploadDocument: () => uploadDocument
|
|
836
844
|
});
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
const
|
|
840
|
-
|
|
841
|
-
const endLine = args.end_line;
|
|
842
|
-
try {
|
|
843
|
-
const content = readFileSync2(path, "utf-8");
|
|
844
|
-
const lines = content.split("\n");
|
|
845
|
-
const sliced = lines.slice(startLine - 1, endLine ?? lines.length);
|
|
846
|
-
return sliced.map((line, i) => `${startLine + i} ${line}`).join("\n");
|
|
847
|
-
} catch (err) {
|
|
848
|
-
return `Error: ${err.message}`;
|
|
849
|
-
}
|
|
845
|
+
async function listCollections() {
|
|
846
|
+
const client2 = getClient();
|
|
847
|
+
const res = await client2.get("/api/retrieval/collections");
|
|
848
|
+
return Array.isArray(res.data) ? res.data : res.data.collections ?? [];
|
|
850
849
|
}
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
"src/agent/tools/file-read.ts"() {
|
|
854
|
-
"use strict";
|
|
855
|
-
definition = {
|
|
856
|
-
type: "function",
|
|
857
|
-
function: {
|
|
858
|
-
name: "file_read",
|
|
859
|
-
description: "\uD30C\uC77C \uB0B4\uC6A9\uC744 \uC77D\uC2B5\uB2C8\uB2E4. \uC904 \uBC88\uD638\uAC00 \uD3EC\uD568\uB429\uB2C8\uB2E4.",
|
|
860
|
-
parameters: {
|
|
861
|
-
type: "object",
|
|
862
|
-
properties: {
|
|
863
|
-
path: { type: "string", description: "\uD30C\uC77C \uACBD\uB85C" },
|
|
864
|
-
start_line: { type: "number", description: "\uC2DC\uC791 \uC904 \uBC88\uD638 (\uC120\uD0DD)" },
|
|
865
|
-
end_line: { type: "number", description: "\uB05D \uC904 \uBC88\uD638 (\uC120\uD0DD)" }
|
|
866
|
-
},
|
|
867
|
-
required: ["path"]
|
|
868
|
-
}
|
|
869
|
-
}
|
|
870
|
-
};
|
|
871
|
-
}
|
|
872
|
-
});
|
|
873
|
-
|
|
874
|
-
// src/agent/tools/file-write.ts
|
|
875
|
-
var file_write_exports = {};
|
|
876
|
-
__export(file_write_exports, {
|
|
877
|
-
definition: () => definition2,
|
|
878
|
-
execute: () => execute2
|
|
879
|
-
});
|
|
880
|
-
import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
|
|
881
|
-
import { dirname } from "path";
|
|
882
|
-
async function execute2(args) {
|
|
883
|
-
const path = args.path;
|
|
884
|
-
const content = args.content;
|
|
850
|
+
async function listDocuments(collectionId) {
|
|
851
|
+
const client2 = getClient();
|
|
885
852
|
try {
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
853
|
+
const params = {};
|
|
854
|
+
if (collectionId) params.collection_id = collectionId;
|
|
855
|
+
const res = await client2.get("/api/retrieval/documents/list", { params });
|
|
856
|
+
return res.data.documents ?? res.data ?? [];
|
|
857
|
+
} catch {
|
|
858
|
+
return [];
|
|
891
859
|
}
|
|
892
860
|
}
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
"
|
|
861
|
+
async function uploadDocument(filePath, collectionId, name) {
|
|
862
|
+
const client2 = getClient();
|
|
863
|
+
const { createReadStream, statSync } = await import("fs");
|
|
864
|
+
const { basename } = await import("path");
|
|
865
|
+
const stat = statSync(filePath);
|
|
866
|
+
const fileName = name || basename(filePath);
|
|
867
|
+
const form = new FormData();
|
|
868
|
+
const fileBlob = new Blob([createReadStream(filePath)]);
|
|
869
|
+
form.append("file", fileBlob, fileName);
|
|
870
|
+
if (collectionId) form.append("collection_id", collectionId);
|
|
871
|
+
const res = await client2.post("/api/retrieval/documents/upload", form, {
|
|
872
|
+
headers: { "Content-Type": "multipart/form-data" },
|
|
873
|
+
maxBodyLength: stat.size + 1024 * 1024
|
|
874
|
+
});
|
|
875
|
+
return res.data;
|
|
876
|
+
}
|
|
877
|
+
async function getDocumentInfo(docId) {
|
|
878
|
+
const client2 = getClient();
|
|
879
|
+
const res = await client2.get(`/api/retrieval/documents/${docId}`);
|
|
880
|
+
return res.data;
|
|
881
|
+
}
|
|
882
|
+
var init_document = __esm({
|
|
883
|
+
"src/api/document.ts"() {
|
|
896
884
|
"use strict";
|
|
897
|
-
|
|
898
|
-
type: "function",
|
|
899
|
-
function: {
|
|
900
|
-
name: "file_write",
|
|
901
|
-
description: "\uD30C\uC77C\uC744 \uC0DD\uC131\uD558\uAC70\uB098 \uB36E\uC5B4\uC501\uB2C8\uB2E4.",
|
|
902
|
-
parameters: {
|
|
903
|
-
type: "object",
|
|
904
|
-
properties: {
|
|
905
|
-
path: { type: "string", description: "\uD30C\uC77C \uACBD\uB85C" },
|
|
906
|
-
content: { type: "string", description: "\uD30C\uC77C \uB0B4\uC6A9" }
|
|
907
|
-
},
|
|
908
|
-
required: ["path", "content"]
|
|
909
|
-
}
|
|
910
|
-
}
|
|
911
|
-
};
|
|
885
|
+
init_client();
|
|
912
886
|
}
|
|
913
887
|
});
|
|
914
888
|
|
|
915
|
-
// src/
|
|
916
|
-
var
|
|
917
|
-
__export(
|
|
918
|
-
|
|
919
|
-
execute: () => execute3
|
|
889
|
+
// src/dashboard/tui.ts
|
|
890
|
+
var tui_exports = {};
|
|
891
|
+
__export(tui_exports, {
|
|
892
|
+
startTui: () => startTui
|
|
920
893
|
});
|
|
921
|
-
import
|
|
922
|
-
async function
|
|
923
|
-
const
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
894
|
+
import blessed from "blessed";
|
|
895
|
+
async function startTui() {
|
|
896
|
+
const screen = blessed.screen({
|
|
897
|
+
smartCSR: true,
|
|
898
|
+
title: "OPEN XGEN",
|
|
899
|
+
fullUnicode: true
|
|
900
|
+
});
|
|
901
|
+
const provider = getDefaultProvider();
|
|
902
|
+
const server = getServer();
|
|
903
|
+
const auth = getAuth();
|
|
904
|
+
const env = getActiveEnvironment();
|
|
905
|
+
const header = blessed.box({
|
|
906
|
+
top: 0,
|
|
907
|
+
left: 0,
|
|
908
|
+
width: "100%",
|
|
909
|
+
height: 3,
|
|
910
|
+
content: `{center}{bold}OPEN XGEN{/bold} ${provider?.model ?? "AI \uBBF8\uC124\uC815"} \xB7 ${auth?.username ?? "\uBBF8\uC5F0\uACB0"}@${env?.name ?? server?.replace("https://", "") ?? ""}{/center}`,
|
|
911
|
+
tags: true,
|
|
912
|
+
style: { fg: "white", bg: "blue" }
|
|
913
|
+
});
|
|
914
|
+
const wfPanel = blessed.list({
|
|
915
|
+
top: 3,
|
|
916
|
+
left: 0,
|
|
917
|
+
width: "50%",
|
|
918
|
+
height: "50%-2",
|
|
919
|
+
label: " \uC6CC\uD06C\uD50C\uB85C\uC6B0 ",
|
|
920
|
+
border: { type: "line" },
|
|
921
|
+
style: {
|
|
922
|
+
border: { fg: "cyan" },
|
|
923
|
+
selected: { fg: "black", bg: "cyan" },
|
|
924
|
+
item: { fg: "white" },
|
|
925
|
+
label: { fg: "cyan", bold: true }
|
|
926
|
+
},
|
|
927
|
+
keys: true,
|
|
928
|
+
vi: true,
|
|
929
|
+
mouse: true,
|
|
930
|
+
scrollbar: { ch: "\u2502", style: { fg: "cyan" } },
|
|
931
|
+
tags: true
|
|
932
|
+
});
|
|
933
|
+
const detailPanel = blessed.box({
|
|
934
|
+
top: 3,
|
|
935
|
+
left: "50%",
|
|
936
|
+
width: "50%",
|
|
937
|
+
height: "50%-2",
|
|
938
|
+
label: " \uC0C1\uC138 ",
|
|
939
|
+
border: { type: "line" },
|
|
940
|
+
scrollable: true,
|
|
941
|
+
alwaysScroll: true,
|
|
942
|
+
mouse: true,
|
|
943
|
+
tags: true,
|
|
944
|
+
style: {
|
|
945
|
+
border: { fg: "green" },
|
|
946
|
+
label: { fg: "green", bold: true }
|
|
930
947
|
}
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
948
|
+
});
|
|
949
|
+
const colPanel = blessed.list({
|
|
950
|
+
top: "50%+1",
|
|
951
|
+
left: 0,
|
|
952
|
+
width: "50%",
|
|
953
|
+
height: "50%-4",
|
|
954
|
+
label: " \uCEEC\uB809\uC158 (\uBB38\uC11C) ",
|
|
955
|
+
border: { type: "line" },
|
|
956
|
+
style: {
|
|
957
|
+
border: { fg: "yellow" },
|
|
958
|
+
selected: { fg: "black", bg: "yellow" },
|
|
959
|
+
item: { fg: "white" },
|
|
960
|
+
label: { fg: "yellow", bold: true }
|
|
961
|
+
},
|
|
962
|
+
keys: true,
|
|
963
|
+
vi: true,
|
|
964
|
+
mouse: true,
|
|
965
|
+
tags: true
|
|
966
|
+
});
|
|
967
|
+
const chatLog = blessed.log({
|
|
968
|
+
top: "50%+1",
|
|
969
|
+
left: "50%",
|
|
970
|
+
width: "50%",
|
|
971
|
+
height: "50%-7",
|
|
972
|
+
label: " AI \uCC44\uD305 ",
|
|
973
|
+
border: { type: "line" },
|
|
974
|
+
scrollable: true,
|
|
975
|
+
alwaysScroll: true,
|
|
976
|
+
mouse: true,
|
|
977
|
+
tags: true,
|
|
978
|
+
style: {
|
|
979
|
+
border: { fg: "magenta" },
|
|
980
|
+
label: { fg: "magenta", bold: true }
|
|
981
|
+
}
|
|
982
|
+
});
|
|
983
|
+
const chatInput = blessed.textbox({
|
|
984
|
+
bottom: 3,
|
|
985
|
+
left: "50%",
|
|
986
|
+
width: "50%",
|
|
987
|
+
height: 3,
|
|
988
|
+
label: " \uC785\uB825 ",
|
|
989
|
+
border: { type: "line" },
|
|
990
|
+
inputOnFocus: true,
|
|
991
|
+
style: {
|
|
992
|
+
border: { fg: "magenta" },
|
|
993
|
+
label: { fg: "magenta" }
|
|
994
|
+
}
|
|
995
|
+
});
|
|
996
|
+
const statusBar = blessed.box({
|
|
997
|
+
bottom: 0,
|
|
998
|
+
left: 0,
|
|
999
|
+
width: "100%",
|
|
1000
|
+
height: 3,
|
|
1001
|
+
content: " {bold}Tab{/bold}:\uD328\uB110\uC804\uD658 {bold}Enter{/bold}:\uC120\uD0DD {bold}r{/bold}:\uC0C8\uB85C\uACE0\uCE68 {bold}c{/bold}:\uCC44\uD305 {bold}q{/bold}:\uC885\uB8CC {bold}\u2191\u2193{/bold}:\uC774\uB3D9",
|
|
1002
|
+
tags: true,
|
|
1003
|
+
style: { fg: "white", bg: "gray" }
|
|
1004
|
+
});
|
|
1005
|
+
screen.append(header);
|
|
1006
|
+
screen.append(wfPanel);
|
|
1007
|
+
screen.append(detailPanel);
|
|
1008
|
+
screen.append(colPanel);
|
|
1009
|
+
screen.append(chatLog);
|
|
1010
|
+
screen.append(chatInput);
|
|
1011
|
+
screen.append(statusBar);
|
|
1012
|
+
let workflows = [];
|
|
1013
|
+
let collections = [];
|
|
1014
|
+
async function loadData() {
|
|
1015
|
+
if (!server || !auth) {
|
|
1016
|
+
wfPanel.setItems(["\uC11C\uBC84 \uBBF8\uC5F0\uACB0 \u2014 q \uC885\uB8CC \uD6C4 xgen agent \u2192 /connect"]);
|
|
1017
|
+
colPanel.setItems(["\uC11C\uBC84 \uBBF8\uC5F0\uACB0"]);
|
|
1018
|
+
screen.render();
|
|
1019
|
+
return;
|
|
1020
|
+
}
|
|
1021
|
+
statusBar.setContent(" \uB85C\uB529 \uC911...");
|
|
1022
|
+
screen.render();
|
|
1023
|
+
try {
|
|
1024
|
+
const { getWorkflowListDetail: getWorkflowListDetail2 } = await Promise.resolve().then(() => (init_workflow(), workflow_exports));
|
|
1025
|
+
const wfs = await getWorkflowListDetail2();
|
|
1026
|
+
workflows = wfs.map((w) => ({
|
|
1027
|
+
name: w.workflow_name,
|
|
1028
|
+
id: (w.workflow_id ?? w.id ?? "").toString(),
|
|
1029
|
+
deployed: !!w.is_deployed,
|
|
1030
|
+
deployKey: w.deploy_key,
|
|
1031
|
+
nodeCount: w.node_count
|
|
1032
|
+
}));
|
|
1033
|
+
wfPanel.setItems(workflows.map((w) => {
|
|
1034
|
+
const tag = w.deployed ? "{green-fg}[\uBC30\uD3EC]{/green-fg}" : "";
|
|
1035
|
+
return ` ${w.name} ${tag}`;
|
|
1036
|
+
}));
|
|
1037
|
+
} catch (err) {
|
|
1038
|
+
wfPanel.setItems([`\uC624\uB958: ${err.message}`]);
|
|
1039
|
+
}
|
|
1040
|
+
try {
|
|
1041
|
+
const { listCollections: listCollections2 } = await Promise.resolve().then(() => (init_document(), document_exports));
|
|
1042
|
+
const cols = await listCollections2();
|
|
1043
|
+
collections = cols.map((c) => ({
|
|
1044
|
+
name: c.collection_make_name,
|
|
1045
|
+
docs: c.total_documents,
|
|
1046
|
+
chunks: c.total_chunks,
|
|
1047
|
+
shared: c.is_shared,
|
|
1048
|
+
group: c.share_group ?? void 0
|
|
1049
|
+
}));
|
|
1050
|
+
colPanel.setItems(collections.map((c) => {
|
|
1051
|
+
const shared = c.shared ? `{yellow-fg}[${c.group}]{/yellow-fg}` : "";
|
|
1052
|
+
return ` ${c.name} ${shared} \u2014 ${c.docs}\uBB38\uC11C ${c.chunks}\uCCAD\uD06C`;
|
|
1053
|
+
}));
|
|
1054
|
+
} catch {
|
|
1055
|
+
colPanel.setItems(["\uCEEC\uB809\uC158 \uB85C\uB4DC \uC2E4\uD328"]);
|
|
1056
|
+
}
|
|
1057
|
+
statusBar.setContent(" {bold}Tab{/bold}:\uD328\uB110\uC804\uD658 {bold}Enter{/bold}:\uC120\uD0DD {bold}r{/bold}:\uC0C8\uB85C\uACE0\uCE68 {bold}c{/bold}:\uCC44\uD305 {bold}q{/bold}:\uC885\uB8CC {bold}\u2191\u2193{/bold}:\uC774\uB3D9");
|
|
1058
|
+
screen.render();
|
|
1059
|
+
}
|
|
1060
|
+
wfPanel.on("select item", (_item, index) => {
|
|
1061
|
+
const w = workflows[index];
|
|
1062
|
+
if (!w) return;
|
|
1063
|
+
detailPanel.setContent([
|
|
1064
|
+
`{bold}${w.name}{/bold}`,
|
|
1065
|
+
"",
|
|
1066
|
+
`ID: ${w.id}`,
|
|
1067
|
+
`\uBC30\uD3EC: ${w.deployed ? "{green-fg}Yes{/green-fg}" : "No"}`,
|
|
1068
|
+
w.deployKey ? `Deploy Key: ${w.deployKey}` : "",
|
|
1069
|
+
w.nodeCount ? `\uB178\uB4DC: ${w.nodeCount}\uAC1C` : "",
|
|
1070
|
+
"",
|
|
1071
|
+
w.deployed ? "{green-fg}Enter\uB85C \uC2E4\uD589{/green-fg}" : "{gray-fg}\uBBF8\uBC30\uD3EC \u2014 \uC2E4\uD589 \uBD88\uAC00{/gray-fg}"
|
|
1072
|
+
].filter(Boolean).join("\n"));
|
|
1073
|
+
screen.render();
|
|
1074
|
+
});
|
|
1075
|
+
wfPanel.on("select", async (_item, index) => {
|
|
1076
|
+
const w = workflows[index];
|
|
1077
|
+
if (!w || !w.deployed || !w.deployKey) {
|
|
1078
|
+
detailPanel.setContent("{red-fg}\uBC30\uD3EC\uB41C \uC6CC\uD06C\uD50C\uB85C\uC6B0\uB9CC \uC2E4\uD589 \uAC00\uB2A5\uD569\uB2C8\uB2E4.{/red-fg}");
|
|
1079
|
+
screen.render();
|
|
1080
|
+
return;
|
|
1081
|
+
}
|
|
1082
|
+
detailPanel.setContent(`{yellow-fg}${w.name} \uC2E4\uD589 \uC911...{/yellow-fg}`);
|
|
1083
|
+
screen.render();
|
|
1084
|
+
try {
|
|
1085
|
+
const { executeWorkflow: executeWorkflow2 } = await Promise.resolve().then(() => (init_workflow(), workflow_exports));
|
|
1086
|
+
const { randomUUID: randomUUID4 } = await import("crypto");
|
|
1087
|
+
const result = await executeWorkflow2({
|
|
1088
|
+
workflow_id: w.id,
|
|
1089
|
+
workflow_name: w.name,
|
|
1090
|
+
input_data: "\uD14C\uC2A4\uD2B8 \uC2E4\uD589",
|
|
1091
|
+
interaction_id: `cli_${randomUUID4().slice(0, 8)}`,
|
|
1092
|
+
deploy_key: w.deployKey
|
|
1093
|
+
});
|
|
1094
|
+
if (result.content) {
|
|
1095
|
+
detailPanel.setContent(`{green-fg}\uACB0\uACFC:{/green-fg}
|
|
960
1096
|
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
});
|
|
967
|
-
import { execSync } from "child_process";
|
|
968
|
-
async function execute4(args) {
|
|
969
|
-
const command = args.command;
|
|
970
|
-
try {
|
|
971
|
-
const output = execSync(command, {
|
|
972
|
-
encoding: "utf-8",
|
|
973
|
-
timeout: 3e4,
|
|
974
|
-
maxBuffer: 1024 * 1024,
|
|
975
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
976
|
-
});
|
|
977
|
-
return output || "(no output)";
|
|
978
|
-
} catch (err) {
|
|
979
|
-
const e = err;
|
|
980
|
-
return (e.stdout || "") + (e.stderr || "") || `Error: ${e.message}`;
|
|
981
|
-
}
|
|
982
|
-
}
|
|
983
|
-
var definition4;
|
|
984
|
-
var init_bash = __esm({
|
|
985
|
-
"src/agent/tools/bash.ts"() {
|
|
986
|
-
"use strict";
|
|
987
|
-
definition4 = {
|
|
988
|
-
type: "function",
|
|
989
|
-
function: {
|
|
990
|
-
name: "bash",
|
|
991
|
-
description: "\uC178 \uBA85\uB839\uC5B4\uB97C \uC2E4\uD589\uD569\uB2C8\uB2E4. stdout + stderr\uB97C \uBC18\uD658\uD569\uB2C8\uB2E4.",
|
|
992
|
-
parameters: {
|
|
993
|
-
type: "object",
|
|
994
|
-
properties: {
|
|
995
|
-
command: { type: "string", description: "\uC2E4\uD589\uD560 \uBA85\uB839\uC5B4" }
|
|
996
|
-
},
|
|
997
|
-
required: ["command"]
|
|
998
|
-
}
|
|
1097
|
+
${String(result.content).slice(0, 500)}`);
|
|
1098
|
+
} else if (result.error) {
|
|
1099
|
+
detailPanel.setContent(`{red-fg}\uC624\uB958:{/red-fg} ${result.error}`);
|
|
1100
|
+
} else {
|
|
1101
|
+
detailPanel.setContent(JSON.stringify(result, null, 2).slice(0, 500));
|
|
999
1102
|
}
|
|
1000
|
-
}
|
|
1001
|
-
|
|
1002
|
-
}
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
}
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
});
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1103
|
+
} catch (err) {
|
|
1104
|
+
detailPanel.setContent(`{red-fg}\uC2E4\uD589 \uC2E4\uD328:{/red-fg} ${err.message}`);
|
|
1105
|
+
}
|
|
1106
|
+
screen.render();
|
|
1107
|
+
});
|
|
1108
|
+
colPanel.on("select item", (_item, index) => {
|
|
1109
|
+
const c = collections[index];
|
|
1110
|
+
if (!c) return;
|
|
1111
|
+
detailPanel.setContent([
|
|
1112
|
+
`{bold}${c.name}{/bold}`,
|
|
1113
|
+
"",
|
|
1114
|
+
`\uBB38\uC11C: ${c.docs}\uAC1C`,
|
|
1115
|
+
`\uCCAD\uD06C: ${c.chunks}\uAC1C`,
|
|
1116
|
+
`\uACF5\uC720: ${c.shared ? `Yes (${c.group})` : "No"}`
|
|
1117
|
+
].join("\n"));
|
|
1118
|
+
screen.render();
|
|
1119
|
+
});
|
|
1120
|
+
chatInput.on("submit", async (value) => {
|
|
1121
|
+
if (!value.trim()) {
|
|
1122
|
+
chatInput.clearValue();
|
|
1123
|
+
chatInput.focus();
|
|
1124
|
+
screen.render();
|
|
1125
|
+
return;
|
|
1126
|
+
}
|
|
1127
|
+
chatLog.log(`{blue-fg}You:{/blue-fg} ${value}`);
|
|
1128
|
+
chatInput.clearValue();
|
|
1129
|
+
screen.render();
|
|
1130
|
+
try {
|
|
1131
|
+
const provider2 = getDefaultProvider();
|
|
1132
|
+
if (!provider2) {
|
|
1133
|
+
chatLog.log("{red-fg}\uD504\uB85C\uBC14\uC774\uB354 \uBBF8\uC124\uC815{/red-fg}");
|
|
1134
|
+
chatInput.focus();
|
|
1135
|
+
screen.render();
|
|
1136
|
+
return;
|
|
1137
|
+
}
|
|
1138
|
+
const { createLLMClient: createLLMClient2, streamChat: streamChat2 } = await Promise.resolve().then(() => (init_llm(), llm_exports));
|
|
1139
|
+
const client2 = createLLMClient2(provider2);
|
|
1140
|
+
const result = await streamChat2(client2, provider2.model, [
|
|
1141
|
+
{ role: "system", content: "You are OPEN XGEN. Be concise. Respond in Korean. Max 3 sentences." },
|
|
1142
|
+
{ role: "user", content: value }
|
|
1143
|
+
]);
|
|
1144
|
+
chatLog.log(`{green-fg}AI:{/green-fg} ${result.content || "(no response)"}`);
|
|
1145
|
+
} catch (err) {
|
|
1146
|
+
chatLog.log(`{red-fg}\uC624\uB958:{/red-fg} ${err.message}`);
|
|
1147
|
+
}
|
|
1148
|
+
chatInput.focus();
|
|
1149
|
+
screen.render();
|
|
1150
|
+
});
|
|
1151
|
+
const panels = [wfPanel, colPanel, chatInput];
|
|
1152
|
+
let activePanel = 0;
|
|
1153
|
+
function focusPanel(idx) {
|
|
1154
|
+
activePanel = idx;
|
|
1155
|
+
panels[idx].focus();
|
|
1156
|
+
screen.render();
|
|
1157
|
+
}
|
|
1158
|
+
screen.key(["tab"], () => {
|
|
1159
|
+
activePanel = (activePanel + 1) % panels.length;
|
|
1160
|
+
focusPanel(activePanel);
|
|
1161
|
+
});
|
|
1162
|
+
screen.key(["S-tab"], () => {
|
|
1163
|
+
activePanel = (activePanel - 1 + panels.length) % panels.length;
|
|
1164
|
+
focusPanel(activePanel);
|
|
1165
|
+
});
|
|
1166
|
+
screen.key(["r"], async () => {
|
|
1167
|
+
await loadData();
|
|
1168
|
+
});
|
|
1169
|
+
screen.key(["c"], () => {
|
|
1170
|
+
focusPanel(2);
|
|
1171
|
+
});
|
|
1172
|
+
screen.key(["q", "C-c"], () => {
|
|
1173
|
+
screen.destroy();
|
|
1174
|
+
process.exit(0);
|
|
1175
|
+
});
|
|
1176
|
+
setInterval(async () => {
|
|
1177
|
+
try {
|
|
1178
|
+
await loadData();
|
|
1179
|
+
} catch {
|
|
1180
|
+
}
|
|
1181
|
+
}, 3e4);
|
|
1182
|
+
await loadData();
|
|
1183
|
+
focusPanel(0);
|
|
1184
|
+
screen.render();
|
|
1029
1185
|
}
|
|
1030
|
-
var
|
|
1031
|
-
|
|
1032
|
-
"src/agent/tools/grep.ts"() {
|
|
1186
|
+
var init_tui = __esm({
|
|
1187
|
+
"src/dashboard/tui.ts"() {
|
|
1033
1188
|
"use strict";
|
|
1034
|
-
|
|
1035
|
-
type: "function",
|
|
1036
|
-
function: {
|
|
1037
|
-
name: "grep",
|
|
1038
|
-
description: "\uD30C\uC77C\uC5D0\uC11C \uD328\uD134\uC744 \uAC80\uC0C9\uD569\uB2C8\uB2E4 (\uC7AC\uADC0, \uC904 \uBC88\uD638 \uD3EC\uD568).",
|
|
1039
|
-
parameters: {
|
|
1040
|
-
type: "object",
|
|
1041
|
-
properties: {
|
|
1042
|
-
pattern: { type: "string", description: "\uAC80\uC0C9 \uD328\uD134 (\uC815\uADDC\uC2DD)" },
|
|
1043
|
-
path: { type: "string", description: "\uAC80\uC0C9 \uB514\uB809\uD1A0\uB9AC \uB610\uB294 \uD30C\uC77C (\uAE30\uBCF8: .)" },
|
|
1044
|
-
glob: { type: "string", description: "\uD30C\uC77C \uD544\uD130 (\uC608: *.ts)" }
|
|
1045
|
-
},
|
|
1046
|
-
required: ["pattern"]
|
|
1047
|
-
}
|
|
1048
|
-
}
|
|
1049
|
-
};
|
|
1189
|
+
init_store();
|
|
1050
1190
|
}
|
|
1051
1191
|
});
|
|
1052
1192
|
|
|
1053
|
-
// src/
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
if (
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1193
|
+
// src/index.ts
|
|
1194
|
+
import { Command } from "commander";
|
|
1195
|
+
import chalk15 from "chalk";
|
|
1196
|
+
|
|
1197
|
+
// src/commands/config.ts
|
|
1198
|
+
init_store();
|
|
1199
|
+
init_client();
|
|
1200
|
+
init_format();
|
|
1201
|
+
import chalk2 from "chalk";
|
|
1202
|
+
function registerConfigCommand(program2) {
|
|
1203
|
+
const config = program2.command("config").description("XGEN CLI \uC124\uC815 \uAD00\uB9AC");
|
|
1204
|
+
config.command("set-server <url>").description("XGEN \uC11C\uBC84 URL \uC124\uC815").action((url) => {
|
|
1205
|
+
if (!url.startsWith("http://") && !url.startsWith("https://")) {
|
|
1206
|
+
printError("URL\uC740 http:// \uB610\uB294 https://\uB85C \uC2DC\uC791\uD574\uC57C \uD569\uB2C8\uB2E4");
|
|
1207
|
+
process.exit(1);
|
|
1208
|
+
}
|
|
1209
|
+
setServer(url);
|
|
1210
|
+
resetClient();
|
|
1211
|
+
printSuccess(`\uC11C\uBC84 \uC124\uC815 \uC644\uB8CC: ${chalk2.underline(url)}`);
|
|
1212
|
+
});
|
|
1213
|
+
config.command("get-server").description("\uD604\uC7AC \uC124\uC815\uB41C \uC11C\uBC84 URL \uD655\uC778").action(() => {
|
|
1214
|
+
const server = getServer();
|
|
1215
|
+
if (server) {
|
|
1216
|
+
console.log(server);
|
|
1217
|
+
} else {
|
|
1218
|
+
printError("\uC11C\uBC84\uAC00 \uC124\uC815\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4");
|
|
1219
|
+
console.log(" \uC124\uC815: xgen config set-server <url>");
|
|
1220
|
+
}
|
|
1221
|
+
});
|
|
1222
|
+
config.command("list").description("\uC804\uCCB4 \uC124\uC815 \uD655\uC778").action(() => {
|
|
1223
|
+
const cfg = getConfig();
|
|
1224
|
+
console.log(chalk2.bold("\nXGEN CLI \uC124\uC815"));
|
|
1225
|
+
console.log(chalk2.gray("\u2500".repeat(40)));
|
|
1226
|
+
printKeyValue("\uC11C\uBC84", cfg.server);
|
|
1227
|
+
printKeyValue("\uAE30\uBCF8 \uC6CC\uD06C\uD50C\uB85C\uC6B0", cfg.defaultWorkflow);
|
|
1228
|
+
printKeyValue("\uD14C\uB9C8", cfg.theme);
|
|
1229
|
+
printKeyValue("\uC2A4\uD2B8\uB9BC \uB85C\uADF8", String(cfg.streamLogs));
|
|
1230
|
+
console.log();
|
|
1231
|
+
});
|
|
1232
|
+
config.command("set <key> <value>").description("\uC124\uC815 \uAC12 \uBCC0\uACBD").action((key, value) => {
|
|
1233
|
+
const allowedKeys = ["defaultWorkflow", "theme", "streamLogs"];
|
|
1234
|
+
if (!allowedKeys.includes(key)) {
|
|
1235
|
+
printError(`\uC54C \uC218 \uC5C6\uB294 \uC124\uC815 \uD0A4: ${key}`);
|
|
1236
|
+
console.log(` \uC0AC\uC6A9 \uAC00\uB2A5: ${allowedKeys.join(", ")}`);
|
|
1237
|
+
process.exit(1);
|
|
1238
|
+
}
|
|
1239
|
+
const parsed = key === "streamLogs" ? value === "true" : value;
|
|
1240
|
+
setConfig({ [key]: parsed });
|
|
1241
|
+
printSuccess(`${key} = ${value}`);
|
|
1242
|
+
});
|
|
1079
1243
|
}
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1244
|
+
|
|
1245
|
+
// src/commands/login.ts
|
|
1246
|
+
init_auth();
|
|
1247
|
+
init_store();
|
|
1248
|
+
init_format();
|
|
1249
|
+
import chalk3 from "chalk";
|
|
1250
|
+
import { createInterface } from "readline";
|
|
1251
|
+
function prompt(question, hidden = false) {
|
|
1252
|
+
return new Promise((resolve) => {
|
|
1253
|
+
const rl = createInterface({
|
|
1254
|
+
input: process.stdin,
|
|
1255
|
+
output: process.stdout
|
|
1256
|
+
});
|
|
1257
|
+
if (hidden) {
|
|
1258
|
+
process.stdout.write(question);
|
|
1259
|
+
const stdin = process.stdin;
|
|
1260
|
+
const wasRaw = stdin.isRaw;
|
|
1261
|
+
if (stdin.isTTY) stdin.setRawMode(true);
|
|
1262
|
+
let password = "";
|
|
1263
|
+
const onData = (ch) => {
|
|
1264
|
+
const c = ch.toString("utf8");
|
|
1265
|
+
if (c === "\n" || c === "\r" || c === "") {
|
|
1266
|
+
if (stdin.isTTY) stdin.setRawMode(wasRaw ?? false);
|
|
1267
|
+
stdin.removeListener("data", onData);
|
|
1268
|
+
process.stdout.write("\n");
|
|
1269
|
+
rl.close();
|
|
1270
|
+
resolve(password);
|
|
1271
|
+
} else if (c === "") {
|
|
1272
|
+
process.exit(0);
|
|
1273
|
+
} else if (c === "\x7F" || c === "\b") {
|
|
1274
|
+
if (password.length > 0) {
|
|
1275
|
+
password = password.slice(0, -1);
|
|
1276
|
+
process.stdout.write("\b \b");
|
|
1094
1277
|
}
|
|
1278
|
+
} else {
|
|
1279
|
+
password += c;
|
|
1280
|
+
process.stdout.write("*");
|
|
1095
1281
|
}
|
|
1096
|
-
}
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
execute: () => execute7
|
|
1106
|
-
});
|
|
1107
|
-
import { execSync as execSync4 } from "child_process";
|
|
1108
|
-
import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync4, existsSync as existsSync2, rmSync } from "fs";
|
|
1109
|
-
import { join as join2 } from "path";
|
|
1110
|
-
import { tmpdir } from "os";
|
|
1111
|
-
function ensureSandbox() {
|
|
1112
|
-
if (!existsSync2(SANDBOX_DIR)) {
|
|
1113
|
-
mkdirSync3(SANDBOX_DIR, { recursive: true });
|
|
1114
|
-
}
|
|
1115
|
-
return SANDBOX_DIR;
|
|
1282
|
+
};
|
|
1283
|
+
stdin.on("data", onData);
|
|
1284
|
+
} else {
|
|
1285
|
+
rl.question(question, (answer) => {
|
|
1286
|
+
rl.close();
|
|
1287
|
+
resolve(answer.trim());
|
|
1288
|
+
});
|
|
1289
|
+
}
|
|
1290
|
+
});
|
|
1116
1291
|
}
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1292
|
+
function registerLoginCommand(program2) {
|
|
1293
|
+
program2.command("login").description("XGEN \uC11C\uBC84\uC5D0 \uB85C\uADF8\uC778").option("-e, --email <email>", "\uC774\uBA54\uC77C").option("-p, --password <password>", "\uBE44\uBC00\uBC88\uD638").action(async (opts) => {
|
|
1294
|
+
const server = requireServer();
|
|
1295
|
+
printHeader("XGEN Login");
|
|
1296
|
+
console.log(chalk3.gray(`\uC11C\uBC84: ${server}
|
|
1297
|
+
`));
|
|
1298
|
+
let email = opts.email;
|
|
1299
|
+
let password = opts.password;
|
|
1300
|
+
if (!email) {
|
|
1301
|
+
email = await prompt(chalk3.white("\uC774\uBA54\uC77C: "));
|
|
1302
|
+
}
|
|
1303
|
+
if (!password) {
|
|
1304
|
+
password = await prompt(chalk3.white("\uBE44\uBC00\uBC88\uD638: "), true);
|
|
1305
|
+
}
|
|
1306
|
+
if (!email || !password) {
|
|
1307
|
+
printError("\uC774\uBA54\uC77C\uACFC \uBE44\uBC00\uBC88\uD638\uB97C \uBAA8\uB450 \uC785\uB825\uD558\uC138\uC694");
|
|
1308
|
+
process.exit(1);
|
|
1309
|
+
}
|
|
1310
|
+
try {
|
|
1311
|
+
const result = await apiLogin(email, password);
|
|
1312
|
+
if (result.success && result.access_token) {
|
|
1313
|
+
setAuth({
|
|
1314
|
+
accessToken: result.access_token,
|
|
1315
|
+
refreshToken: result.refresh_token ?? "",
|
|
1316
|
+
userId: result.user_id ?? "",
|
|
1317
|
+
username: result.username ?? "",
|
|
1318
|
+
isAdmin: false,
|
|
1319
|
+
expiresAt: null
|
|
1134
1320
|
});
|
|
1321
|
+
console.log();
|
|
1322
|
+
printSuccess(`\uB85C\uADF8\uC778 \uC131\uACF5! ${chalk3.bold(result.username ?? email)}`);
|
|
1135
1323
|
} else {
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
execSync4(`npm install ${pkgList}`, {
|
|
1139
|
-
cwd: runDir,
|
|
1140
|
-
encoding: "utf-8",
|
|
1141
|
-
timeout: 6e4,
|
|
1142
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
1143
|
-
});
|
|
1324
|
+
printError(result.message || "\uB85C\uADF8\uC778 \uC2E4\uD328");
|
|
1325
|
+
process.exit(1);
|
|
1144
1326
|
}
|
|
1327
|
+
} catch (err) {
|
|
1328
|
+
const msg = err?.response?.data?.message ?? err?.response?.data?.detail ?? err.message;
|
|
1329
|
+
printError(`\uB85C\uADF8\uC778 \uC2E4\uD328: ${msg}`);
|
|
1330
|
+
process.exit(1);
|
|
1145
1331
|
}
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
filename = "script.mjs";
|
|
1158
|
-
writeFileSync4(join2(runDir, filename), code, "utf-8");
|
|
1159
|
-
cmd = `node ${filename}`;
|
|
1332
|
+
});
|
|
1333
|
+
program2.command("logout").description("\uB85C\uADF8\uC544\uC6C3").action(async () => {
|
|
1334
|
+
const { clearAuth: clearAuth2 } = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
1335
|
+
clearAuth2();
|
|
1336
|
+
printSuccess("\uB85C\uADF8\uC544\uC6C3 \uC644\uB8CC");
|
|
1337
|
+
});
|
|
1338
|
+
program2.command("whoami").description("\uD604\uC7AC \uB85C\uADF8\uC778\uB41C \uC0AC\uC6A9\uC790 \uC815\uBCF4").action(async () => {
|
|
1339
|
+
const auth = getAuth();
|
|
1340
|
+
if (!auth) {
|
|
1341
|
+
printError("\uB85C\uADF8\uC778\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. xgen login \uC2E4\uD589\uD558\uC138\uC694");
|
|
1342
|
+
process.exit(1);
|
|
1160
1343
|
}
|
|
1161
|
-
const
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
});
|
|
1168
|
-
return output || "(no output)";
|
|
1169
|
-
} catch (err) {
|
|
1170
|
-
const e = err;
|
|
1171
|
-
return (e.stdout || "") + (e.stderr || "") || `Error: ${e.message}`;
|
|
1172
|
-
} finally {
|
|
1344
|
+
const server = requireServer();
|
|
1345
|
+
console.log(chalk3.bold("\n\uD604\uC7AC \uC0AC\uC6A9\uC790"));
|
|
1346
|
+
console.log(chalk3.gray("\u2500".repeat(30)));
|
|
1347
|
+
console.log(` ${chalk3.gray("\uC11C\uBC84:")} ${server}`);
|
|
1348
|
+
console.log(` ${chalk3.gray("\uC0AC\uC6A9\uC790:")} ${chalk3.bold(auth.username)}`);
|
|
1349
|
+
console.log(` ${chalk3.gray("User ID:")} ${auth.userId}`);
|
|
1173
1350
|
try {
|
|
1174
|
-
|
|
1351
|
+
const { apiValidate: apiValidate2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
|
|
1352
|
+
const result = await apiValidate2(auth.accessToken);
|
|
1353
|
+
if (result.valid) {
|
|
1354
|
+
console.log(` ${chalk3.gray("\uC0C1\uD0DC:")} ${chalk3.green("\uD65C\uC131")}`);
|
|
1355
|
+
if (result.is_admin) {
|
|
1356
|
+
console.log(` ${chalk3.gray("\uAD8C\uD55C:")} ${chalk3.yellow("\uAD00\uB9AC\uC790")}`);
|
|
1357
|
+
}
|
|
1358
|
+
if (result.user_type) {
|
|
1359
|
+
console.log(` ${chalk3.gray("\uC720\uD615:")} ${result.user_type}`);
|
|
1360
|
+
}
|
|
1361
|
+
} else {
|
|
1362
|
+
console.log(` ${chalk3.gray("\uC0C1\uD0DC:")} ${chalk3.red("\uD1A0\uD070 \uB9CC\uB8CC")}`);
|
|
1363
|
+
}
|
|
1175
1364
|
} catch {
|
|
1365
|
+
console.log(` ${chalk3.gray("\uC0C1\uD0DC:")} ${chalk3.yellow("\uAC80\uC99D \uBD88\uAC00 (\uC11C\uBC84 \uC5F0\uACB0 \uC2E4\uD328)")}`);
|
|
1176
1366
|
}
|
|
1177
|
-
|
|
1367
|
+
console.log();
|
|
1368
|
+
});
|
|
1178
1369
|
}
|
|
1179
|
-
var SANDBOX_DIR, definition7;
|
|
1180
|
-
var init_sandbox = __esm({
|
|
1181
|
-
"src/agent/tools/sandbox.ts"() {
|
|
1182
|
-
"use strict";
|
|
1183
|
-
SANDBOX_DIR = join2(tmpdir(), "xgen-sandbox");
|
|
1184
|
-
definition7 = {
|
|
1185
|
-
type: "function",
|
|
1186
|
-
function: {
|
|
1187
|
-
name: "sandbox_run",
|
|
1188
|
-
description: "\uACA9\uB9AC\uB41C \uC0CC\uB4DC\uBC15\uC2A4\uC5D0\uC11C \uCF54\uB4DC\uB97C \uC2E4\uD589\uD569\uB2C8\uB2E4. Node.js \uB610\uB294 Python \uCF54\uB4DC\uB97C \uC548\uC804\uD558\uAC8C \uC2E4\uD589\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4. npm \uD328\uD0A4\uC9C0 \uC124\uCE58\uB3C4 \uAC00\uB2A5\uD569\uB2C8\uB2E4.",
|
|
1189
|
-
parameters: {
|
|
1190
|
-
type: "object",
|
|
1191
|
-
properties: {
|
|
1192
|
-
language: {
|
|
1193
|
-
type: "string",
|
|
1194
|
-
enum: ["javascript", "typescript", "python"],
|
|
1195
|
-
description: "\uC2E4\uD589\uD560 \uC5B8\uC5B4"
|
|
1196
|
-
},
|
|
1197
|
-
code: { type: "string", description: "\uC2E4\uD589\uD560 \uCF54\uB4DC" },
|
|
1198
|
-
packages: {
|
|
1199
|
-
type: "array",
|
|
1200
|
-
items: { type: "string" },
|
|
1201
|
-
description: "\uC124\uCE58\uD560 \uD328\uD0A4\uC9C0 (npm \uB610\uB294 pip)"
|
|
1202
|
-
}
|
|
1203
|
-
},
|
|
1204
|
-
required: ["language", "code"]
|
|
1205
|
-
}
|
|
1206
|
-
}
|
|
1207
|
-
};
|
|
1208
|
-
}
|
|
1209
|
-
});
|
|
1210
1370
|
|
|
1211
|
-
// src/
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
return tool.execute(args);
|
|
1219
|
-
}
|
|
1220
|
-
function getToolNames() {
|
|
1221
|
-
return tools.map((t) => t.definition.function.name);
|
|
1222
|
-
}
|
|
1223
|
-
var tools, toolMap;
|
|
1224
|
-
var init_tools = __esm({
|
|
1225
|
-
"src/agent/tools/index.ts"() {
|
|
1226
|
-
"use strict";
|
|
1227
|
-
init_file_read();
|
|
1228
|
-
init_file_write();
|
|
1229
|
-
init_file_edit();
|
|
1230
|
-
init_bash();
|
|
1231
|
-
init_grep();
|
|
1232
|
-
init_list_files();
|
|
1233
|
-
init_sandbox();
|
|
1234
|
-
tools = [file_read_exports, file_write_exports, file_edit_exports, bash_exports, grep_exports, list_files_exports, sandbox_exports];
|
|
1235
|
-
toolMap = /* @__PURE__ */ new Map();
|
|
1236
|
-
for (const t of tools) {
|
|
1237
|
-
toolMap.set(t.definition.function.name, t);
|
|
1238
|
-
}
|
|
1239
|
-
}
|
|
1240
|
-
});
|
|
1241
|
-
|
|
1242
|
-
// src/api/document.ts
|
|
1243
|
-
var document_exports = {};
|
|
1244
|
-
__export(document_exports, {
|
|
1245
|
-
getDocumentInfo: () => getDocumentInfo,
|
|
1246
|
-
listCollections: () => listCollections,
|
|
1247
|
-
listDocuments: () => listDocuments,
|
|
1248
|
-
uploadDocument: () => uploadDocument
|
|
1249
|
-
});
|
|
1250
|
-
async function listCollections() {
|
|
1251
|
-
const client2 = getClient();
|
|
1252
|
-
const res = await client2.get("/api/retrieval/collections");
|
|
1253
|
-
return Array.isArray(res.data) ? res.data : res.data.collections ?? [];
|
|
1254
|
-
}
|
|
1255
|
-
async function listDocuments(collectionId) {
|
|
1256
|
-
const client2 = getClient();
|
|
1371
|
+
// src/commands/workflow/list.ts
|
|
1372
|
+
init_store();
|
|
1373
|
+
init_workflow();
|
|
1374
|
+
init_format();
|
|
1375
|
+
import chalk4 from "chalk";
|
|
1376
|
+
async function workflowList(opts) {
|
|
1377
|
+
requireAuth();
|
|
1257
1378
|
try {
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1379
|
+
if (opts.detail) {
|
|
1380
|
+
const workflows = await getWorkflowListDetail();
|
|
1381
|
+
if (!workflows || workflows.length === 0) {
|
|
1382
|
+
console.log(chalk4.yellow("\n\uC6CC\uD06C\uD50C\uB85C\uC6B0\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.\n"));
|
|
1383
|
+
return;
|
|
1384
|
+
}
|
|
1385
|
+
printHeader(`\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D (${workflows.length}\uAC1C)`);
|
|
1386
|
+
console.log();
|
|
1387
|
+
printTable(
|
|
1388
|
+
["#", "ID", "\uC774\uB984", "\uBC30\uD3EC", "\uC5C5\uB370\uC774\uD2B8"],
|
|
1389
|
+
workflows.map((w, i) => [
|
|
1390
|
+
String(i + 1),
|
|
1391
|
+
(w.workflow_id ?? w.id ?? "-").slice(0, 12),
|
|
1392
|
+
truncate(w.workflow_name ?? "-", 30),
|
|
1393
|
+
w.is_deployed ? chalk4.green("\uBC30\uD3EC\uB428") : chalk4.gray("\uBBF8\uBC30\uD3EC"),
|
|
1394
|
+
formatDate(w.updated_at)
|
|
1395
|
+
])
|
|
1396
|
+
);
|
|
1397
|
+
} else {
|
|
1398
|
+
const workflows = await listWorkflows();
|
|
1399
|
+
if (!workflows || workflows.length === 0) {
|
|
1400
|
+
console.log(chalk4.yellow("\n\uC6CC\uD06C\uD50C\uB85C\uC6B0\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.\n"));
|
|
1401
|
+
return;
|
|
1402
|
+
}
|
|
1403
|
+
printHeader(`\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D (${workflows.length}\uAC1C)`);
|
|
1404
|
+
console.log();
|
|
1405
|
+
printTable(
|
|
1406
|
+
["#", "ID", "\uC774\uB984"],
|
|
1407
|
+
workflows.map((w, i) => [
|
|
1408
|
+
String(i + 1),
|
|
1409
|
+
(w.workflow_id ?? w.id ?? "-").slice(0, 12),
|
|
1410
|
+
w.workflow_name ?? "-"
|
|
1411
|
+
])
|
|
1412
|
+
);
|
|
1413
|
+
}
|
|
1414
|
+
console.log();
|
|
1415
|
+
} catch (err) {
|
|
1416
|
+
const msg = err.message;
|
|
1417
|
+
printError(`\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D \uC870\uD68C \uC2E4\uD328: ${msg}`);
|
|
1418
|
+
process.exit(1);
|
|
1264
1419
|
}
|
|
1265
1420
|
}
|
|
1266
|
-
async function uploadDocument(filePath, collectionId, name) {
|
|
1267
|
-
const client2 = getClient();
|
|
1268
|
-
const { createReadStream, statSync } = await import("fs");
|
|
1269
|
-
const { basename } = await import("path");
|
|
1270
|
-
const stat = statSync(filePath);
|
|
1271
|
-
const fileName = name || basename(filePath);
|
|
1272
|
-
const form = new FormData();
|
|
1273
|
-
const fileBlob = new Blob([createReadStream(filePath)]);
|
|
1274
|
-
form.append("file", fileBlob, fileName);
|
|
1275
|
-
if (collectionId) form.append("collection_id", collectionId);
|
|
1276
|
-
const res = await client2.post("/api/retrieval/documents/upload", form, {
|
|
1277
|
-
headers: { "Content-Type": "multipart/form-data" },
|
|
1278
|
-
maxBodyLength: stat.size + 1024 * 1024
|
|
1279
|
-
});
|
|
1280
|
-
return res.data;
|
|
1281
|
-
}
|
|
1282
|
-
async function getDocumentInfo(docId) {
|
|
1283
|
-
const client2 = getClient();
|
|
1284
|
-
const res = await client2.get(`/api/retrieval/documents/${docId}`);
|
|
1285
|
-
return res.data;
|
|
1286
|
-
}
|
|
1287
|
-
var init_document = __esm({
|
|
1288
|
-
"src/api/document.ts"() {
|
|
1289
|
-
"use strict";
|
|
1290
|
-
init_client();
|
|
1291
|
-
}
|
|
1292
|
-
});
|
|
1293
1421
|
|
|
1294
|
-
// src/
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1422
|
+
// src/commands/workflow/info.ts
|
|
1423
|
+
init_store();
|
|
1424
|
+
init_workflow();
|
|
1425
|
+
init_format();
|
|
1426
|
+
import chalk5 from "chalk";
|
|
1427
|
+
async function workflowInfo(workflowId) {
|
|
1428
|
+
requireAuth();
|
|
1301
1429
|
try {
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1430
|
+
const detail = await getWorkflowDetail(workflowId);
|
|
1431
|
+
printHeader(`\uC6CC\uD06C\uD50C\uB85C\uC6B0: ${detail.workflow_name ?? workflowId}`);
|
|
1432
|
+
console.log();
|
|
1433
|
+
printKeyValue("ID", detail.id);
|
|
1434
|
+
printKeyValue("\uC774\uB984", detail.workflow_name);
|
|
1435
|
+
printKeyValue("\uC124\uBA85", detail.description ?? "(\uC5C6\uC74C)");
|
|
1436
|
+
if (detail.nodes && Array.isArray(detail.nodes)) {
|
|
1437
|
+
console.log();
|
|
1438
|
+
console.log(chalk5.bold(" \uB178\uB4DC \uAD6C\uC131:"));
|
|
1439
|
+
for (const node of detail.nodes) {
|
|
1440
|
+
const label = node.data?.label ?? node.id;
|
|
1441
|
+
const type = node.data?.type ?? "unknown";
|
|
1442
|
+
console.log(` ${chalk5.cyan("\u2022")} ${label} ${chalk5.gray(`(${type})`)}`);
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
if (detail.parameters && Object.keys(detail.parameters).length > 0) {
|
|
1446
|
+
console.log();
|
|
1447
|
+
console.log(chalk5.bold(" \uD30C\uB77C\uBBF8\uD130:"));
|
|
1448
|
+
for (const [key, val] of Object.entries(detail.parameters)) {
|
|
1449
|
+
console.log(` ${chalk5.gray(key)}: ${JSON.stringify(val)}`);
|
|
1450
|
+
}
|
|
1317
1451
|
}
|
|
1452
|
+
console.log();
|
|
1318
1453
|
} catch (err) {
|
|
1319
|
-
|
|
1454
|
+
const msg = err.message;
|
|
1455
|
+
printError(`\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC870\uD68C \uC2E4\uD328: ${msg}`);
|
|
1456
|
+
process.exit(1);
|
|
1320
1457
|
}
|
|
1321
1458
|
}
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1459
|
+
|
|
1460
|
+
// src/commands/workflow/run.ts
|
|
1461
|
+
init_store();
|
|
1462
|
+
init_workflow();
|
|
1463
|
+
import chalk7 from "chalk";
|
|
1464
|
+
import { randomUUID } from "crypto";
|
|
1465
|
+
|
|
1466
|
+
// src/utils/sse.ts
|
|
1467
|
+
async function parseSSEStream(stream, onEvent, onDone, onError) {
|
|
1468
|
+
let buffer = "";
|
|
1469
|
+
return new Promise((resolve, reject) => {
|
|
1470
|
+
stream.on("data", (chunk) => {
|
|
1471
|
+
buffer += chunk.toString();
|
|
1472
|
+
const parts = buffer.split("\n\n");
|
|
1473
|
+
buffer = parts.pop() ?? "";
|
|
1474
|
+
for (const part of parts) {
|
|
1475
|
+
const lines = part.split("\n");
|
|
1476
|
+
let data = "";
|
|
1477
|
+
for (const line of lines) {
|
|
1478
|
+
if (line.startsWith("data: ")) {
|
|
1479
|
+
data += line.slice(6);
|
|
1480
|
+
} else if (line.startsWith("data:")) {
|
|
1481
|
+
data += line.slice(5);
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
if (!data) continue;
|
|
1485
|
+
try {
|
|
1486
|
+
const event = JSON.parse(data);
|
|
1487
|
+
onEvent(event);
|
|
1488
|
+
} catch {
|
|
1489
|
+
onEvent({ type: "token", content: data });
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
});
|
|
1493
|
+
stream.on("end", () => {
|
|
1494
|
+
if (buffer.trim()) {
|
|
1495
|
+
const lines = buffer.split("\n");
|
|
1496
|
+
for (const line of lines) {
|
|
1497
|
+
if (line.startsWith("data: ")) {
|
|
1498
|
+
try {
|
|
1499
|
+
const event = JSON.parse(line.slice(6));
|
|
1500
|
+
onEvent(event);
|
|
1501
|
+
} catch {
|
|
1502
|
+
onEvent({ type: "token", content: line.slice(6) });
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
onDone?.();
|
|
1508
|
+
resolve();
|
|
1509
|
+
});
|
|
1510
|
+
stream.on("error", (err) => {
|
|
1511
|
+
onError?.(err);
|
|
1512
|
+
reject(err);
|
|
1513
|
+
});
|
|
1347
1514
|
});
|
|
1348
|
-
if (result.content) return String(result.content);
|
|
1349
|
-
if (result.success === false) return `\uC624\uB958: ${result.error ?? result.message}`;
|
|
1350
|
-
return JSON.stringify(result, null, 2).slice(0, 2e3);
|
|
1351
|
-
}
|
|
1352
|
-
async function workflowInfo2(args) {
|
|
1353
|
-
const { getWorkflowDetail: getWorkflowDetail2 } = await Promise.resolve().then(() => (init_workflow(), workflow_exports));
|
|
1354
|
-
const detail = await getWorkflowDetail2(args.workflow_id);
|
|
1355
|
-
const nodes = detail.nodes?.length ?? 0;
|
|
1356
|
-
const edges = detail.edges?.length ?? 0;
|
|
1357
|
-
return `\uC6CC\uD06C\uD50C\uB85C\uC6B0: ${detail.workflow_name}
|
|
1358
|
-
ID: ${detail.id}
|
|
1359
|
-
\uB178\uB4DC: ${nodes}\uAC1C
|
|
1360
|
-
\uC5E3\uC9C0: ${edges}\uAC1C`;
|
|
1361
1515
|
}
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
}
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
}
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1516
|
+
|
|
1517
|
+
// src/commands/workflow/run.ts
|
|
1518
|
+
init_format();
|
|
1519
|
+
|
|
1520
|
+
// src/utils/markdown.ts
|
|
1521
|
+
import chalk6 from "chalk";
|
|
1522
|
+
var CODE_BLOCK_RE = /```(\w*)\n([\s\S]*?)```/g;
|
|
1523
|
+
var INLINE_CODE_RE = /`([^`]+)`/g;
|
|
1524
|
+
var BOLD_RE = /\*\*(.+?)\*\*/g;
|
|
1525
|
+
var HEADING_RE = /^(#{1,3})\s+(.+)$/gm;
|
|
1526
|
+
var LIST_RE = /^(\s*)[-*]\s+(.+)$/gm;
|
|
1527
|
+
var LINK_RE = /\[([^\]]+)\]\(([^)]+)\)/g;
|
|
1528
|
+
function renderMarkdown(text) {
|
|
1529
|
+
let result = text;
|
|
1530
|
+
result = result.replace(CODE_BLOCK_RE, (_match, lang, code) => {
|
|
1531
|
+
const trimmed = code.trimEnd();
|
|
1532
|
+
const header = lang ? chalk6.gray(` \u2500\u2500 ${lang} \u2500\u2500`) : chalk6.gray(" \u2500\u2500 code \u2500\u2500");
|
|
1533
|
+
const lines = trimmed.split("\n").map((l) => chalk6.white(` ${l}`)).join("\n");
|
|
1534
|
+
return `
|
|
1535
|
+
${header}
|
|
1536
|
+
${lines}
|
|
1537
|
+
${chalk6.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}
|
|
1538
|
+
`;
|
|
1539
|
+
});
|
|
1540
|
+
result = result.replace(INLINE_CODE_RE, (_m, code) => chalk6.cyan(`\`${code}\``));
|
|
1541
|
+
result = result.replace(BOLD_RE, (_m, text2) => chalk6.bold(text2));
|
|
1542
|
+
result = result.replace(HEADING_RE, (_m, hashes, text2) => {
|
|
1543
|
+
if (hashes.length === 1) return chalk6.bold.underline(text2);
|
|
1544
|
+
if (hashes.length === 2) return chalk6.bold(text2);
|
|
1545
|
+
return chalk6.bold.dim(text2);
|
|
1546
|
+
});
|
|
1547
|
+
result = result.replace(LIST_RE, (_m, indent, text2) => `${indent}${chalk6.cyan("\u2022")} ${text2}`);
|
|
1548
|
+
result = result.replace(LINK_RE, (_m, label, url) => `${chalk6.blue.underline(label)} ${chalk6.gray(`(${url})`)}`);
|
|
1549
|
+
return result;
|
|
1389
1550
|
}
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
}
|
|
1404
|
-
{
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1551
|
+
|
|
1552
|
+
// src/commands/workflow/run.ts
|
|
1553
|
+
async function workflowRun(workflowId, input, opts) {
|
|
1554
|
+
const auth = requireAuth();
|
|
1555
|
+
let workflowName = workflowId;
|
|
1556
|
+
try {
|
|
1557
|
+
const detail = await getWorkflowDetail(workflowId);
|
|
1558
|
+
workflowName = detail.workflow_name ?? workflowId;
|
|
1559
|
+
} catch {
|
|
1560
|
+
}
|
|
1561
|
+
if (!input) {
|
|
1562
|
+
if (opts.interactive || !process.stdin.isTTY) {
|
|
1563
|
+
const { createInterface: createInterface7 } = await import("readline");
|
|
1564
|
+
const rl = createInterface7({ input: process.stdin, output: process.stdout });
|
|
1565
|
+
input = await new Promise((resolve) => {
|
|
1566
|
+
rl.question(chalk7.cyan("\uC785\uB825> "), (answer) => {
|
|
1567
|
+
rl.close();
|
|
1568
|
+
resolve(answer.trim());
|
|
1569
|
+
});
|
|
1570
|
+
});
|
|
1571
|
+
} else {
|
|
1572
|
+
printError("\uC785\uB825\uAC12\uC774 \uD544\uC694\uD569\uB2C8\uB2E4. \uC0AC\uC6A9\uBC95:");
|
|
1573
|
+
console.log(' xgen workflow run <id> "\uC785\uB825 \uD14D\uC2A4\uFFFD\uFFFD\uFFFD"');
|
|
1574
|
+
console.log(" xgen workflow run -i <id>");
|
|
1575
|
+
process.exit(1);
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1578
|
+
if (!input) {
|
|
1579
|
+
printError("\uC785\uB825\uAC12\uC774 \uBE44\uC5B4\uC788\uC2B5\uB2C8\uB2E4");
|
|
1580
|
+
process.exit(1);
|
|
1581
|
+
}
|
|
1582
|
+
const interactionId = `cli_${randomUUID().slice(0, 8)}`;
|
|
1583
|
+
printHeader(`\uC2E4\uD589: ${workflowName}`);
|
|
1584
|
+
printInfo(`\uC785\uB825: ${input}`);
|
|
1585
|
+
console.log();
|
|
1586
|
+
try {
|
|
1587
|
+
const stream = await executeWorkflowStream({
|
|
1588
|
+
workflow_id: workflowId,
|
|
1589
|
+
workflow_name: workflowName,
|
|
1590
|
+
input_data: input,
|
|
1591
|
+
interaction_id: interactionId
|
|
1592
|
+
});
|
|
1593
|
+
let hasOutput = false;
|
|
1594
|
+
let fullResponse = "";
|
|
1595
|
+
await parseSSEStream(
|
|
1596
|
+
stream,
|
|
1597
|
+
(event) => {
|
|
1598
|
+
switch (event.type) {
|
|
1599
|
+
case "token":
|
|
1600
|
+
if (event.content) {
|
|
1601
|
+
if (!hasOutput) {
|
|
1602
|
+
hasOutput = true;
|
|
1603
|
+
console.log();
|
|
1604
|
+
}
|
|
1605
|
+
process.stdout.write(event.content);
|
|
1606
|
+
fullResponse += event.content;
|
|
1607
|
+
}
|
|
1608
|
+
break;
|
|
1609
|
+
case "log":
|
|
1610
|
+
if (opts.logs && event.content) {
|
|
1611
|
+
process.stderr.write(chalk7.gray(`[LOG] ${event.content}
|
|
1612
|
+
`));
|
|
1613
|
+
}
|
|
1614
|
+
break;
|
|
1615
|
+
case "node_status":
|
|
1616
|
+
if (opts.logs) {
|
|
1617
|
+
const nodeName = event.node_name ?? event.node_id ?? "?";
|
|
1618
|
+
const status = event.status ?? "?";
|
|
1619
|
+
process.stderr.write(
|
|
1620
|
+
chalk7.gray(`[\uB178\uB4DC] ${nodeName}: ${status}
|
|
1621
|
+
`)
|
|
1622
|
+
);
|
|
1623
|
+
}
|
|
1624
|
+
break;
|
|
1625
|
+
case "tool":
|
|
1626
|
+
if (opts.logs) {
|
|
1627
|
+
process.stderr.write(chalk7.gray(`[\uB3C4\uAD6C] ${JSON.stringify(event.data)}
|
|
1628
|
+
`));
|
|
1629
|
+
}
|
|
1630
|
+
break;
|
|
1631
|
+
case "complete":
|
|
1632
|
+
break;
|
|
1633
|
+
case "error":
|
|
1634
|
+
console.log();
|
|
1635
|
+
printError(event.error ?? event.content ?? "\uC54C \uC218 \uC5C6\uB294 \uC624\uB958");
|
|
1636
|
+
break;
|
|
1637
|
+
default:
|
|
1638
|
+
if (event.content) {
|
|
1639
|
+
if (!hasOutput) {
|
|
1640
|
+
process.stdout.write(chalk7.green("\uC751\uB2F5: "));
|
|
1641
|
+
hasOutput = true;
|
|
1642
|
+
}
|
|
1643
|
+
process.stdout.write(event.content);
|
|
1644
|
+
}
|
|
1419
1645
|
}
|
|
1420
1646
|
},
|
|
1421
|
-
{
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
type: "object",
|
|
1428
|
-
properties: {
|
|
1429
|
-
workflow_id: { type: "string", description: "\uC6CC\uD06C\uD50C\uB85C\uC6B0 ID" }
|
|
1430
|
-
},
|
|
1431
|
-
required: ["workflow_id"]
|
|
1647
|
+
() => {
|
|
1648
|
+
if (hasOutput) {
|
|
1649
|
+
console.log();
|
|
1650
|
+
if (fullResponse.includes("```") || fullResponse.includes("**")) {
|
|
1651
|
+
console.log(chalk7.gray("\u2500".repeat(40)));
|
|
1652
|
+
console.log(renderMarkdown(fullResponse));
|
|
1432
1653
|
}
|
|
1433
1654
|
}
|
|
1655
|
+
console.log();
|
|
1656
|
+
console.log(chalk7.gray(`\uC138\uC158: ${interactionId}`));
|
|
1434
1657
|
},
|
|
1435
|
-
{
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
name: "xgen_collection_list",
|
|
1439
|
-
description: "XGEN \uC11C\uBC84\uC758 \uBB38\uC11C \uCEEC\uB809\uC158(\uC9C0\uC2DD\uBCA0\uC774\uC2A4) \uBAA9\uB85D\uC744 \uAC00\uC838\uC635\uB2C8\uB2E4. \uBB38\uC11C \uC218, \uCCAD\uD06C \uC218, \uACF5\uC720 \uC0C1\uD0DC \uB4F1 \uD3EC\uD568.",
|
|
1440
|
-
parameters: { type: "object", properties: {} }
|
|
1441
|
-
}
|
|
1442
|
-
},
|
|
1443
|
-
{
|
|
1444
|
-
type: "function",
|
|
1445
|
-
function: {
|
|
1446
|
-
name: "xgen_server_status",
|
|
1447
|
-
description: "XGEN \uC11C\uBC84 \uC0C1\uD0DC\uB97C \uD655\uC778\uD569\uB2C8\uB2E4.",
|
|
1448
|
-
parameters: { type: "object", properties: {} }
|
|
1449
|
-
}
|
|
1450
|
-
},
|
|
1451
|
-
{
|
|
1452
|
-
type: "function",
|
|
1453
|
-
function: {
|
|
1454
|
-
name: "xgen_execution_history",
|
|
1455
|
-
description: "\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC2E4\uD589 \uC774\uB825\uC744 \uAC00\uC838\uC635\uB2C8\uB2E4.",
|
|
1456
|
-
parameters: {
|
|
1457
|
-
type: "object",
|
|
1458
|
-
properties: {
|
|
1459
|
-
limit: { type: "number", description: "\uAC00\uC838\uC62C \uC774\uB825 \uC218 (\uAE30\uBCF8 10)" }
|
|
1460
|
-
}
|
|
1461
|
-
}
|
|
1462
|
-
}
|
|
1658
|
+
(err) => {
|
|
1659
|
+
console.log();
|
|
1660
|
+
printError(`\uC2A4\uD2B8\uB9AC\uBC0D \uC624\uB958: ${err.message}`);
|
|
1463
1661
|
}
|
|
1464
|
-
|
|
1662
|
+
);
|
|
1663
|
+
} catch (err) {
|
|
1664
|
+
const msg = err?.response?.data?.detail ?? err.message;
|
|
1665
|
+
printError(`\uC2E4\uD589 \uC2E4\uD328: ${msg}`);
|
|
1666
|
+
process.exit(1);
|
|
1465
1667
|
}
|
|
1466
|
-
}
|
|
1668
|
+
}
|
|
1467
1669
|
|
|
1468
|
-
// src/
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
import
|
|
1473
|
-
function
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1670
|
+
// src/commands/workflow/history.ts
|
|
1671
|
+
init_store();
|
|
1672
|
+
init_workflow();
|
|
1673
|
+
init_format();
|
|
1674
|
+
import chalk8 from "chalk";
|
|
1675
|
+
async function workflowHistory(workflowId, opts = {}) {
|
|
1676
|
+
requireAuth();
|
|
1677
|
+
const limit = opts.limit ?? 20;
|
|
1678
|
+
try {
|
|
1679
|
+
const logs = await getIOLogs(workflowId, limit);
|
|
1680
|
+
if (!logs || logs.length === 0) {
|
|
1681
|
+
console.log(chalk8.yellow("\n\uC2E4\uD589 \uC774\uB825\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.\n"));
|
|
1682
|
+
return;
|
|
1683
|
+
}
|
|
1684
|
+
printHeader(`\uC2E4\uD589 \uC774\uB825 (\uCD5C\uADFC ${logs.length}\uAC74)`);
|
|
1685
|
+
console.log();
|
|
1686
|
+
for (const log of logs) {
|
|
1687
|
+
console.log(
|
|
1688
|
+
` ${chalk8.gray(formatDate(log.created_at))} ${chalk8.cyan(log.interaction_id)}`
|
|
1689
|
+
);
|
|
1690
|
+
console.log(` ${chalk8.white("\uC785\uB825:")} ${truncate(log.input_data, 60)}`);
|
|
1691
|
+
console.log(
|
|
1692
|
+
` ${chalk8.green("\uCD9C\uB825:")} ${truncate(log.output_data, 60)}`
|
|
1693
|
+
);
|
|
1694
|
+
if (log.execution_time) {
|
|
1695
|
+
console.log(
|
|
1696
|
+
` ${chalk8.gray("\uC2DC\uAC04:")} ${(log.execution_time / 1e3).toFixed(1)}s`
|
|
1697
|
+
);
|
|
1485
1698
|
}
|
|
1699
|
+
console.log();
|
|
1486
1700
|
}
|
|
1701
|
+
} catch (err) {
|
|
1702
|
+
const msg = err.message;
|
|
1703
|
+
printError(`\uC774\uB825 \uC870\uD68C \uC2E4\uD328: ${msg}`);
|
|
1704
|
+
process.exit(1);
|
|
1487
1705
|
}
|
|
1488
|
-
return null;
|
|
1489
1706
|
}
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1707
|
+
|
|
1708
|
+
// src/commands/workflow/index.ts
|
|
1709
|
+
function registerWorkflowCommand(program2) {
|
|
1710
|
+
const wf = program2.command("workflow").alias("wf").description("\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uAD00\uB9AC \uBC0F \uC2E4\uD589");
|
|
1711
|
+
wf.command("list").alias("ls").description("\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D \uC870\uD68C").option("-d, --detail", "\uC0C1\uC138 \uC815\uBCF4 \uD3EC\uD568").action((opts) => workflowList(opts));
|
|
1712
|
+
wf.command("info <workflow-id>").description("\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC0C1\uC138 \uC815\uBCF4").action((id) => workflowInfo(id));
|
|
1713
|
+
wf.command("run <workflow-id> [input]").description("\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC2E4\uD589").option("-i, --interactive", "\uC778\uD130\uB799\uD2F0\uBE0C \uBAA8\uB4DC (\uC785\uB825 \uD504\uB86C\uD504\uD2B8)").option("-l, --logs", "\uB514\uBC84\uADF8 \uB85C\uADF8 \uD45C\uC2DC").action((id, input, opts) => workflowRun(id, input, opts));
|
|
1714
|
+
wf.command("history [workflow-id]").description("\uC2E4\uD589 \uC774\uB825 \uC870\uD68C").option("-n, --limit <number>", "\uC870\uD68C \uAC74\uC218", "20").action((id, opts) => workflowHistory(id, { limit: parseInt(opts.limit) }));
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1717
|
+
// src/commands/chat.ts
|
|
1718
|
+
init_store();
|
|
1719
|
+
init_workflow();
|
|
1720
|
+
import chalk9 from "chalk";
|
|
1721
|
+
import { createInterface as createInterface2 } from "readline";
|
|
1722
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
1723
|
+
init_format();
|
|
1724
|
+
var CHAT_BANNER = `
|
|
1725
|
+
${chalk9.cyan("\u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E")}
|
|
1726
|
+
${chalk9.cyan("\u2502")} ${chalk9.white.bold("XGEN")} ${chalk9.gray("\u2014 \uC6CC\uD06C\uD50C\uB85C\uC6B0 AI \uD130\uBBF8\uB110")} ${chalk9.cyan("\u2502")}
|
|
1727
|
+
${chalk9.cyan("\u2502")} ${chalk9.gray("/help \uB3C4\uC6C0\uB9D0 /workflows \uC804\uD658 /exit")} ${chalk9.cyan("\u2502")}
|
|
1728
|
+
${chalk9.cyan("\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F")}`;
|
|
1729
|
+
function printHelp() {
|
|
1730
|
+
console.log(`
|
|
1731
|
+
${chalk9.bold("\uC2AC\uB798\uC2DC \uCEE4\uB9E8\uB4DC")}
|
|
1732
|
+
${chalk9.cyan("/workflows")} \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D \uBCF4\uAE30 & \uC804\uD658
|
|
1733
|
+
${chalk9.cyan("/switch")} \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBC88\uD638\uB85C \uC804\uD658 (\uC608: /switch 3)
|
|
1734
|
+
${chalk9.cyan("/history")} \uD604\uC7AC \uC138\uC158 \uB300\uD654 \uC774\uB825
|
|
1735
|
+
${chalk9.cyan("/clear")} \uD654\uBA74 \uC9C0\uC6B0\uAE30
|
|
1736
|
+
${chalk9.cyan("/info")} \uD604\uC7AC \uC5F0\uACB0 \uC815\uBCF4
|
|
1737
|
+
${chalk9.cyan("/help")} \uC774 \uB3C4\uC6C0\uB9D0
|
|
1738
|
+
${chalk9.cyan("/exit")} \uC885\uB8CC (Ctrl+C\uB3C4 \uAC00\uB2A5)
|
|
1739
|
+
`);
|
|
1740
|
+
}
|
|
1741
|
+
async function promptLine(rl, promptStr) {
|
|
1742
|
+
return new Promise((resolve) => {
|
|
1743
|
+
rl.question(promptStr, (answer) => resolve(answer));
|
|
1744
|
+
});
|
|
1745
|
+
}
|
|
1746
|
+
async function chat(workflowId) {
|
|
1747
|
+
const auth = requireAuth();
|
|
1748
|
+
const server = getServer();
|
|
1749
|
+
let workflows = [];
|
|
1750
|
+
try {
|
|
1751
|
+
workflows = await listWorkflows();
|
|
1752
|
+
} catch {
|
|
1753
|
+
printError("\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D\uC744 \uBD88\uB7EC\uC62C \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
|
|
1754
|
+
process.exit(1);
|
|
1755
|
+
}
|
|
1756
|
+
if (workflows.length === 0) {
|
|
1757
|
+
printError("\uC0AC\uC6A9 \uAC00\uB2A5\uD55C \uC6CC\uD06C\uD50C\uB85C\uC6B0\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4");
|
|
1758
|
+
process.exit(1);
|
|
1759
|
+
}
|
|
1760
|
+
let current;
|
|
1761
|
+
if (workflowId) {
|
|
1762
|
+
const found = workflows.find((w) => w.id === workflowId || w.workflow_name === workflowId);
|
|
1763
|
+
current = found ?? { id: workflowId, workflow_name: workflowId };
|
|
1764
|
+
} else {
|
|
1765
|
+
console.log(CHAT_BANNER);
|
|
1766
|
+
console.log(chalk9.gray(` \uC11C\uBC84: ${server} | \uC0AC\uC6A9\uC790: ${auth.username}
|
|
1767
|
+
`));
|
|
1768
|
+
console.log(chalk9.bold(" \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC120\uD0DD:\n"));
|
|
1769
|
+
workflows.forEach((w, i) => {
|
|
1770
|
+
console.log(` ${chalk9.cyan(String(i + 1).padStart(3))} ${w.workflow_name}`);
|
|
1771
|
+
});
|
|
1772
|
+
console.log();
|
|
1773
|
+
const rl2 = createInterface2({ input: process.stdin, output: process.stdout });
|
|
1774
|
+
const answer = await promptLine(rl2, chalk9.cyan(" \uBC88\uD638> "));
|
|
1775
|
+
rl2.close();
|
|
1776
|
+
const idx = parseInt(answer.trim()) - 1;
|
|
1777
|
+
if (isNaN(idx) || idx < 0 || idx >= workflows.length) {
|
|
1778
|
+
current = workflows[0];
|
|
1779
|
+
} else {
|
|
1780
|
+
current = workflows[idx];
|
|
1781
|
+
}
|
|
1782
|
+
}
|
|
1783
|
+
const sessionId = randomUUID2().slice(0, 8);
|
|
1784
|
+
let turnCount = 0;
|
|
1785
|
+
const history = [];
|
|
1786
|
+
console.log();
|
|
1787
|
+
console.log(chalk9.cyan("\u2500".repeat(42)));
|
|
1788
|
+
console.log(chalk9.white.bold(` ${current.workflow_name}`));
|
|
1789
|
+
console.log(chalk9.cyan("\u2500".repeat(42)));
|
|
1790
|
+
console.log(chalk9.gray(" \uBA54\uC2DC\uC9C0\uB97C \uC785\uB825\uD558\uC138\uC694. /help \uB85C \uB3C4\uC6C0\uB9D0.\n"));
|
|
1791
|
+
const rl = createInterface2({
|
|
1792
|
+
input: process.stdin,
|
|
1793
|
+
output: process.stdout
|
|
1794
|
+
});
|
|
1795
|
+
const getPrompt = () => chalk9.cyan("\u276F ");
|
|
1796
|
+
const processInput = async (line) => {
|
|
1797
|
+
const input = line.trim();
|
|
1798
|
+
if (!input) return;
|
|
1799
|
+
if (input.startsWith("/")) {
|
|
1800
|
+
const [cmd, ...args] = input.slice(1).split(" ");
|
|
1801
|
+
switch (cmd.toLowerCase()) {
|
|
1802
|
+
case "exit":
|
|
1803
|
+
case "quit":
|
|
1804
|
+
case "q":
|
|
1805
|
+
console.log(chalk9.gray("\n \uC885\uB8CC\uD569\uB2C8\uB2E4.\n"));
|
|
1806
|
+
rl.close();
|
|
1807
|
+
process.exit(0);
|
|
1808
|
+
break;
|
|
1809
|
+
case "help":
|
|
1810
|
+
case "h":
|
|
1811
|
+
printHelp();
|
|
1812
|
+
break;
|
|
1813
|
+
case "clear":
|
|
1814
|
+
case "cls":
|
|
1815
|
+
console.clear();
|
|
1816
|
+
console.log(chalk9.white.bold(` ${current.workflow_name}`));
|
|
1817
|
+
console.log(chalk9.cyan("\u2500".repeat(42)));
|
|
1818
|
+
break;
|
|
1819
|
+
case "workflows":
|
|
1820
|
+
case "wf":
|
|
1821
|
+
console.log();
|
|
1822
|
+
workflows.forEach((w, i) => {
|
|
1823
|
+
const marker = w.id === current.id ? chalk9.green("\u25B8") : " ";
|
|
1824
|
+
console.log(` ${marker} ${chalk9.cyan(String(i + 1).padStart(2))} ${w.workflow_name}`);
|
|
1554
1825
|
});
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
type: "function",
|
|
1570
|
-
function: {
|
|
1571
|
-
name: `mcp_${this.serverName}_${t.name}`,
|
|
1572
|
-
description: `[MCP:${this.serverName}] ${t.description ?? t.name}`,
|
|
1573
|
-
parameters: t.inputSchema ?? { type: "object", properties: {} }
|
|
1574
|
-
}
|
|
1575
|
-
}));
|
|
1576
|
-
}
|
|
1577
|
-
stop() {
|
|
1578
|
-
this.process?.kill();
|
|
1579
|
-
this.process = null;
|
|
1580
|
-
}
|
|
1581
|
-
};
|
|
1582
|
-
McpManager = class {
|
|
1583
|
-
clients = /* @__PURE__ */ new Map();
|
|
1584
|
-
async startAll(config) {
|
|
1585
|
-
for (const [name, serverConfig] of Object.entries(config.mcpServers)) {
|
|
1586
|
-
if (serverConfig.type !== "stdio") continue;
|
|
1587
|
-
try {
|
|
1588
|
-
const client2 = new McpClient(name, serverConfig);
|
|
1589
|
-
await client2.start();
|
|
1590
|
-
await client2.listTools();
|
|
1591
|
-
this.clients.set(name, client2);
|
|
1592
|
-
} catch (err) {
|
|
1593
|
-
console.error(`MCP [${name}] \uC2DC\uC791 \uC2E4\uD328:`, err.message);
|
|
1826
|
+
console.log(chalk9.gray("\n /switch <\uBC88\uD638> \uB85C \uC804\uD658\n"));
|
|
1827
|
+
break;
|
|
1828
|
+
case "switch":
|
|
1829
|
+
case "sw": {
|
|
1830
|
+
const num = parseInt(args[0]);
|
|
1831
|
+
if (isNaN(num) || num < 1 || num > workflows.length) {
|
|
1832
|
+
console.log(chalk9.yellow(` 1~${workflows.length} \uC0AC\uC774 \uBC88\uD638\uB97C \uC785\uB825\uD558\uC138\uC694`));
|
|
1833
|
+
} else {
|
|
1834
|
+
current = workflows[num - 1];
|
|
1835
|
+
turnCount = 0;
|
|
1836
|
+
history.length = 0;
|
|
1837
|
+
console.log(chalk9.green(`
|
|
1838
|
+
\uC804\uD658: ${current.workflow_name}
|
|
1839
|
+
`));
|
|
1594
1840
|
}
|
|
1841
|
+
break;
|
|
1595
1842
|
}
|
|
1843
|
+
case "history":
|
|
1844
|
+
case "hist":
|
|
1845
|
+
if (history.length === 0) {
|
|
1846
|
+
console.log(chalk9.gray(" \uB300\uD654 \uC774\uB825\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.\n"));
|
|
1847
|
+
} else {
|
|
1848
|
+
console.log();
|
|
1849
|
+
for (const h of history) {
|
|
1850
|
+
const label = h.role === "user" ? chalk9.cyan("\uB098") : chalk9.green("AI");
|
|
1851
|
+
const text = h.content.length > 80 ? h.content.slice(0, 80) + "..." : h.content;
|
|
1852
|
+
console.log(` ${label}: ${text}`);
|
|
1853
|
+
}
|
|
1854
|
+
console.log();
|
|
1855
|
+
}
|
|
1856
|
+
break;
|
|
1857
|
+
case "info":
|
|
1858
|
+
console.log(`
|
|
1859
|
+
${chalk9.gray("\uC11C\uBC84:")} ${server}
|
|
1860
|
+
${chalk9.gray("\uC0AC\uC6A9\uC790:")} ${auth.username}
|
|
1861
|
+
${chalk9.gray("\uC6CC\uD06C\uD50C\uB85C\uC6B0:")} ${current.workflow_name}
|
|
1862
|
+
${chalk9.gray("\uC138\uC158:")} ${sessionId}
|
|
1863
|
+
${chalk9.gray("\uD134:")} ${turnCount}
|
|
1864
|
+
`);
|
|
1865
|
+
break;
|
|
1866
|
+
default:
|
|
1867
|
+
console.log(chalk9.yellow(` \uC54C \uC218 \uC5C6\uB294 \uCEE4\uB9E8\uB4DC: /${cmd}. /help \uCC38\uACE0`));
|
|
1596
1868
|
}
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1869
|
+
rl.prompt();
|
|
1870
|
+
return;
|
|
1871
|
+
}
|
|
1872
|
+
turnCount++;
|
|
1873
|
+
const interactionId = `${sessionId}_t${turnCount}`;
|
|
1874
|
+
history.push({ role: "user", content: input });
|
|
1875
|
+
process.stdout.write(chalk9.gray(" thinking..."));
|
|
1876
|
+
try {
|
|
1877
|
+
const stream = await executeWorkflowStream({
|
|
1878
|
+
workflow_id: current.id,
|
|
1879
|
+
workflow_name: current.workflow_name,
|
|
1880
|
+
input_data: input,
|
|
1881
|
+
interaction_id: interactionId
|
|
1882
|
+
});
|
|
1883
|
+
process.stdout.write("\r" + " ".repeat(20) + "\r");
|
|
1884
|
+
let fullResponse = "";
|
|
1885
|
+
let hasOutput = false;
|
|
1886
|
+
await parseSSEStream(
|
|
1887
|
+
stream,
|
|
1888
|
+
(event) => {
|
|
1889
|
+
if ((event.type === "token" || !event.type) && event.content) {
|
|
1890
|
+
if (!hasOutput) {
|
|
1891
|
+
hasOutput = true;
|
|
1892
|
+
console.log();
|
|
1893
|
+
}
|
|
1894
|
+
process.stdout.write(event.content);
|
|
1895
|
+
fullResponse += event.content;
|
|
1896
|
+
} else if (event.type === "error") {
|
|
1897
|
+
process.stdout.write("\r" + " ".repeat(20) + "\r");
|
|
1898
|
+
printError(event.error ?? event.content ?? "\uC624\uB958");
|
|
1899
|
+
}
|
|
1900
|
+
},
|
|
1901
|
+
() => {
|
|
1902
|
+
if (hasOutput) {
|
|
1903
|
+
console.log();
|
|
1904
|
+
console.log();
|
|
1905
|
+
}
|
|
1906
|
+
if (fullResponse) {
|
|
1907
|
+
history.push({ role: "assistant", content: fullResponse });
|
|
1908
|
+
}
|
|
1909
|
+
},
|
|
1910
|
+
(err) => {
|
|
1911
|
+
process.stdout.write("\r" + " ".repeat(20) + "\r");
|
|
1912
|
+
printError(`\uC2A4\uD2B8\uB9AC\uBC0D \uC624\uB958: ${err.message}`);
|
|
1619
1913
|
}
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
}
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1914
|
+
);
|
|
1915
|
+
} catch (err) {
|
|
1916
|
+
process.stdout.write("\r" + " ".repeat(20) + "\r");
|
|
1917
|
+
const msg = err?.response?.data?.detail ?? err.message;
|
|
1918
|
+
printError(`\uC2E4\uD589 \uC2E4\uD328: ${msg}`);
|
|
1919
|
+
}
|
|
1920
|
+
rl.prompt();
|
|
1921
|
+
};
|
|
1922
|
+
rl.setPrompt(getPrompt());
|
|
1923
|
+
rl.prompt();
|
|
1924
|
+
rl.on("line", (line) => {
|
|
1925
|
+
processInput(line).then(() => {
|
|
1926
|
+
});
|
|
1927
|
+
});
|
|
1928
|
+
rl.on("close", () => {
|
|
1929
|
+
console.log(chalk9.gray("\n \uC885\uB8CC\uD569\uB2C8\uB2E4.\n"));
|
|
1930
|
+
process.exit(0);
|
|
1931
|
+
});
|
|
1932
|
+
process.on("SIGINT", () => {
|
|
1933
|
+
console.log(chalk9.gray("\n \uC885\uB8CC\uD569\uB2C8\uB2E4.\n"));
|
|
1934
|
+
process.exit(0);
|
|
1935
|
+
});
|
|
1936
|
+
}
|
|
1937
|
+
function registerChatCommand(program2) {
|
|
1938
|
+
program2.command("chat [workflow-id]").description("\uC778\uD130\uB799\uD2F0\uBE0C \uB300\uD654 \uBAA8\uB4DC").action((workflowId) => chat(workflowId));
|
|
1939
|
+
}
|
|
1940
|
+
|
|
1941
|
+
// src/index.ts
|
|
1942
|
+
init_provider();
|
|
1631
1943
|
|
|
1632
1944
|
// src/commands/agent.ts
|
|
1945
|
+
init_store();
|
|
1946
|
+
init_llm();
|
|
1633
1947
|
import chalk12 from "chalk";
|
|
1634
1948
|
import { createInterface as createInterface5 } from "readline";
|
|
1635
|
-
function buildSystemPrompt() {
|
|
1636
|
-
const server = getServer();
|
|
1637
|
-
const auth = getAuth();
|
|
1638
|
-
const env = getActiveEnvironment();
|
|
1639
|
-
let prompt2 = `You are OPEN XGEN. Terminal AI agent.
|
|
1640
1949
|
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1950
|
+
// src/agent/tools/file-read.ts
|
|
1951
|
+
var file_read_exports = {};
|
|
1952
|
+
__export(file_read_exports, {
|
|
1953
|
+
definition: () => definition,
|
|
1954
|
+
execute: () => execute
|
|
1955
|
+
});
|
|
1956
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
1957
|
+
var definition = {
|
|
1958
|
+
type: "function",
|
|
1959
|
+
function: {
|
|
1960
|
+
name: "file_read",
|
|
1961
|
+
description: "\uD30C\uC77C \uB0B4\uC6A9\uC744 \uC77D\uC2B5\uB2C8\uB2E4. \uC904 \uBC88\uD638\uAC00 \uD3EC\uD568\uB429\uB2C8\uB2E4.",
|
|
1962
|
+
parameters: {
|
|
1963
|
+
type: "object",
|
|
1964
|
+
properties: {
|
|
1965
|
+
path: { type: "string", description: "\uD30C\uC77C \uACBD\uB85C" },
|
|
1966
|
+
start_line: { type: "number", description: "\uC2DC\uC791 \uC904 \uBC88\uD638 (\uC120\uD0DD)" },
|
|
1967
|
+
end_line: { type: "number", description: "\uB05D \uC904 \uBC88\uD638 (\uC120\uD0DD)" }
|
|
1968
|
+
},
|
|
1969
|
+
required: ["path"]
|
|
1970
|
+
}
|
|
1662
1971
|
}
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1972
|
+
};
|
|
1973
|
+
async function execute(args) {
|
|
1974
|
+
const path = args.path;
|
|
1975
|
+
const startLine = args.start_line || 1;
|
|
1976
|
+
const endLine = args.end_line;
|
|
1977
|
+
try {
|
|
1978
|
+
const content = readFileSync2(path, "utf-8");
|
|
1979
|
+
const lines = content.split("\n");
|
|
1980
|
+
const sliced = lines.slice(startLine - 1, endLine ?? lines.length);
|
|
1981
|
+
return sliced.map((line, i) => `${startLine + i} ${line}`).join("\n");
|
|
1982
|
+
} catch (err) {
|
|
1983
|
+
return `Error: ${err.message}`;
|
|
1670
1984
|
}
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1985
|
+
}
|
|
1986
|
+
|
|
1987
|
+
// src/agent/tools/file-write.ts
|
|
1988
|
+
var file_write_exports = {};
|
|
1989
|
+
__export(file_write_exports, {
|
|
1990
|
+
definition: () => definition2,
|
|
1991
|
+
execute: () => execute2
|
|
1992
|
+
});
|
|
1993
|
+
import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
|
|
1994
|
+
import { dirname } from "path";
|
|
1995
|
+
var definition2 = {
|
|
1996
|
+
type: "function",
|
|
1997
|
+
function: {
|
|
1998
|
+
name: "file_write",
|
|
1999
|
+
description: "\uD30C\uC77C\uC744 \uC0DD\uC131\uD558\uAC70\uB098 \uB36E\uC5B4\uC501\uB2C8\uB2E4.",
|
|
2000
|
+
parameters: {
|
|
2001
|
+
type: "object",
|
|
2002
|
+
properties: {
|
|
2003
|
+
path: { type: "string", description: "\uD30C\uC77C \uACBD\uB85C" },
|
|
2004
|
+
content: { type: "string", description: "\uD30C\uC77C \uB0B4\uC6A9" }
|
|
2005
|
+
},
|
|
2006
|
+
required: ["path", "content"]
|
|
1681
2007
|
}
|
|
1682
2008
|
}
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
const
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
2009
|
+
};
|
|
2010
|
+
async function execute2(args) {
|
|
2011
|
+
const path = args.path;
|
|
2012
|
+
const content = args.content;
|
|
2013
|
+
try {
|
|
2014
|
+
mkdirSync2(dirname(path), { recursive: true });
|
|
2015
|
+
writeFileSync2(path, content, "utf-8");
|
|
2016
|
+
return `\uD30C\uC77C \uC791\uC131 \uC644\uB8CC: ${path}`;
|
|
2017
|
+
} catch (err) {
|
|
2018
|
+
return `Error: ${err.message}`;
|
|
1692
2019
|
}
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
2020
|
+
}
|
|
2021
|
+
|
|
2022
|
+
// src/agent/tools/file-edit.ts
|
|
2023
|
+
var file_edit_exports = {};
|
|
2024
|
+
__export(file_edit_exports, {
|
|
2025
|
+
definition: () => definition3,
|
|
2026
|
+
execute: () => execute3
|
|
2027
|
+
});
|
|
2028
|
+
import { readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
2029
|
+
var definition3 = {
|
|
2030
|
+
type: "function",
|
|
2031
|
+
function: {
|
|
2032
|
+
name: "file_edit",
|
|
2033
|
+
description: "\uD30C\uC77C\uC5D0\uC11C \uD2B9\uC815 \uD14D\uC2A4\uD2B8\uB97C \uCC3E\uC544 \uAD50\uCCB4\uD569\uB2C8\uB2E4.",
|
|
2034
|
+
parameters: {
|
|
2035
|
+
type: "object",
|
|
2036
|
+
properties: {
|
|
2037
|
+
path: { type: "string", description: "\uD30C\uC77C \uACBD\uB85C" },
|
|
2038
|
+
old_text: { type: "string", description: "\uAD50\uCCB4\uD560 \uAE30\uC874 \uD14D\uC2A4\uD2B8" },
|
|
2039
|
+
new_text: { type: "string", description: "\uC0C8 \uD14D\uC2A4\uD2B8" }
|
|
2040
|
+
},
|
|
2041
|
+
required: ["path", "old_text", "new_text"]
|
|
1712
2042
|
}
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
`);
|
|
1724
|
-
continue;
|
|
2043
|
+
}
|
|
2044
|
+
};
|
|
2045
|
+
async function execute3(args) {
|
|
2046
|
+
const path = args.path;
|
|
2047
|
+
const oldText = args.old_text;
|
|
2048
|
+
const newText = args.new_text;
|
|
2049
|
+
try {
|
|
2050
|
+
const content = readFileSync3(path, "utf-8");
|
|
2051
|
+
if (!content.includes(oldText)) {
|
|
2052
|
+
return `Error: \uD14D\uC2A4\uD2B8\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4`;
|
|
1725
2053
|
}
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
2054
|
+
const updated = content.replace(oldText, newText);
|
|
2055
|
+
writeFileSync3(path, updated, "utf-8");
|
|
2056
|
+
return `\uD30C\uC77C \uC218\uC815 \uC644\uB8CC: ${path}`;
|
|
2057
|
+
} catch (err) {
|
|
2058
|
+
return `Error: ${err.message}`;
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
2061
|
+
|
|
2062
|
+
// src/agent/tools/bash.ts
|
|
2063
|
+
var bash_exports = {};
|
|
2064
|
+
__export(bash_exports, {
|
|
2065
|
+
definition: () => definition4,
|
|
2066
|
+
execute: () => execute4
|
|
2067
|
+
});
|
|
2068
|
+
import { execSync } from "child_process";
|
|
2069
|
+
var definition4 = {
|
|
2070
|
+
type: "function",
|
|
2071
|
+
function: {
|
|
2072
|
+
name: "bash",
|
|
2073
|
+
description: "\uC178 \uBA85\uB839\uC5B4\uB97C \uC2E4\uD589\uD569\uB2C8\uB2E4. stdout + stderr\uB97C \uBC18\uD658\uD569\uB2C8\uB2E4.",
|
|
2074
|
+
parameters: {
|
|
2075
|
+
type: "object",
|
|
2076
|
+
properties: {
|
|
2077
|
+
command: { type: "string", description: "\uC2E4\uD589\uD560 \uBA85\uB839\uC5B4" }
|
|
2078
|
+
},
|
|
2079
|
+
required: ["command"]
|
|
1731
2080
|
}
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
2081
|
+
}
|
|
2082
|
+
};
|
|
2083
|
+
async function execute4(args) {
|
|
2084
|
+
const command = args.command;
|
|
2085
|
+
try {
|
|
2086
|
+
const output = execSync(command, {
|
|
2087
|
+
encoding: "utf-8",
|
|
2088
|
+
timeout: 3e4,
|
|
2089
|
+
maxBuffer: 1024 * 1024,
|
|
2090
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
2091
|
+
});
|
|
2092
|
+
return output || "(no output)";
|
|
2093
|
+
} catch (err) {
|
|
2094
|
+
const e = err;
|
|
2095
|
+
return (e.stdout || "") + (e.stderr || "") || `Error: ${e.message}`;
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
|
|
2099
|
+
// src/agent/tools/grep.ts
|
|
2100
|
+
var grep_exports = {};
|
|
2101
|
+
__export(grep_exports, {
|
|
2102
|
+
definition: () => definition5,
|
|
2103
|
+
execute: () => execute5
|
|
2104
|
+
});
|
|
2105
|
+
import { execSync as execSync2 } from "child_process";
|
|
2106
|
+
var definition5 = {
|
|
2107
|
+
type: "function",
|
|
2108
|
+
function: {
|
|
2109
|
+
name: "grep",
|
|
2110
|
+
description: "\uD30C\uC77C\uC5D0\uC11C \uD328\uD134\uC744 \uAC80\uC0C9\uD569\uB2C8\uB2E4 (\uC7AC\uADC0, \uC904 \uBC88\uD638 \uD3EC\uD568).",
|
|
2111
|
+
parameters: {
|
|
2112
|
+
type: "object",
|
|
2113
|
+
properties: {
|
|
2114
|
+
pattern: { type: "string", description: "\uAC80\uC0C9 \uD328\uD134 (\uC815\uADDC\uC2DD)" },
|
|
2115
|
+
path: { type: "string", description: "\uAC80\uC0C9 \uB514\uB809\uD1A0\uB9AC \uB610\uB294 \uD30C\uC77C (\uAE30\uBCF8: .)" },
|
|
2116
|
+
glob: { type: "string", description: "\uD30C\uC77C \uD544\uD130 (\uC608: *.ts)" }
|
|
2117
|
+
},
|
|
2118
|
+
required: ["pattern"]
|
|
1746
2119
|
}
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
2120
|
+
}
|
|
2121
|
+
};
|
|
2122
|
+
async function execute5(args) {
|
|
2123
|
+
const pattern = args.pattern;
|
|
2124
|
+
const path = args.path || ".";
|
|
2125
|
+
const glob = args.glob;
|
|
2126
|
+
try {
|
|
2127
|
+
let cmd = `grep -rn --color=never "${pattern.replace(/"/g, '\\"')}" "${path}"`;
|
|
2128
|
+
if (glob) cmd += ` --include="${glob}"`;
|
|
2129
|
+
cmd += " | head -50";
|
|
2130
|
+
const output = execSync2(cmd, {
|
|
2131
|
+
encoding: "utf-8",
|
|
2132
|
+
timeout: 1e4,
|
|
2133
|
+
maxBuffer: 512 * 1024,
|
|
2134
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
2135
|
+
});
|
|
2136
|
+
return output || "\uC77C\uCE58\uD558\uB294 \uACB0\uACFC \uC5C6\uC74C";
|
|
2137
|
+
} catch {
|
|
2138
|
+
return "\uC77C\uCE58\uD558\uB294 \uACB0\uACFC \uC5C6\uC74C";
|
|
2139
|
+
}
|
|
2140
|
+
}
|
|
2141
|
+
|
|
2142
|
+
// src/agent/tools/list-files.ts
|
|
2143
|
+
var list_files_exports = {};
|
|
2144
|
+
__export(list_files_exports, {
|
|
2145
|
+
definition: () => definition6,
|
|
2146
|
+
execute: () => execute6
|
|
2147
|
+
});
|
|
2148
|
+
import { execSync as execSync3 } from "child_process";
|
|
2149
|
+
var definition6 = {
|
|
2150
|
+
type: "function",
|
|
2151
|
+
function: {
|
|
2152
|
+
name: "list_files",
|
|
2153
|
+
description: "\uB514\uB809\uD1A0\uB9AC\uC758 \uD30C\uC77C/\uD3F4\uB354 \uBAA9\uB85D\uC744 \uBC18\uD658\uD569\uB2C8\uB2E4. glob \uD328\uD134 \uC9C0\uC6D0.",
|
|
2154
|
+
parameters: {
|
|
2155
|
+
type: "object",
|
|
2156
|
+
properties: {
|
|
2157
|
+
path: { type: "string", description: "\uB514\uB809\uD1A0\uB9AC \uACBD\uB85C (\uAE30\uBCF8: .)" },
|
|
2158
|
+
pattern: { type: "string", description: "glob \uD328\uD134 (\uC608: **/*.ts)" }
|
|
1753
2159
|
}
|
|
1754
|
-
console.log();
|
|
1755
|
-
continue;
|
|
1756
2160
|
}
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
}
|
|
1767
|
-
|
|
1768
|
-
const { guidedProviderSetup: setup } = await Promise.resolve().then(() => (init_provider(), provider_exports));
|
|
1769
|
-
await setup();
|
|
1770
|
-
console.log(chalk12.gray(" \uD504\uB85C\uBC14\uC774\uB354 \uBCC0\uACBD\uB428. /exit \uD6C4 \uC7AC\uC2DC\uC791\uD558\uC138\uC694.\n"));
|
|
1771
|
-
continue;
|
|
1772
|
-
}
|
|
1773
|
-
messages.push({ role: "user", content: input });
|
|
1774
|
-
try {
|
|
1775
|
-
await runLoop(client2, provider.model, messages, allTools);
|
|
1776
|
-
} catch (err) {
|
|
1777
|
-
console.log(chalk12.red(`
|
|
1778
|
-
\uC624\uB958: ${err.message}
|
|
1779
|
-
`));
|
|
2161
|
+
}
|
|
2162
|
+
};
|
|
2163
|
+
async function execute6(args) {
|
|
2164
|
+
const path = args.path || ".";
|
|
2165
|
+
const pattern = args.pattern;
|
|
2166
|
+
try {
|
|
2167
|
+
let cmd;
|
|
2168
|
+
if (pattern) {
|
|
2169
|
+
cmd = `find "${path}" -name "${pattern}" -type f | head -100`;
|
|
2170
|
+
} else {
|
|
2171
|
+
cmd = `ls -la "${path}"`;
|
|
1780
2172
|
}
|
|
2173
|
+
const output = execSync3(cmd, {
|
|
2174
|
+
encoding: "utf-8",
|
|
2175
|
+
timeout: 1e4,
|
|
2176
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
2177
|
+
});
|
|
2178
|
+
return output || "(empty)";
|
|
2179
|
+
} catch (err) {
|
|
2180
|
+
return `Error: ${err.message}`;
|
|
1781
2181
|
}
|
|
1782
2182
|
}
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
}
|
|
1798
|
-
messages.push({
|
|
1799
|
-
role: "assistant",
|
|
1800
|
-
content: result.content || null,
|
|
1801
|
-
tool_calls: result.toolCalls.map((tc) => ({
|
|
1802
|
-
id: tc.id,
|
|
1803
|
-
type: "function",
|
|
1804
|
-
function: { name: tc.name, arguments: tc.arguments }
|
|
1805
|
-
}))
|
|
1806
|
-
});
|
|
1807
|
-
for (const tc of result.toolCalls) {
|
|
1808
|
-
let args;
|
|
1809
|
-
try {
|
|
1810
|
-
args = JSON.parse(tc.arguments);
|
|
1811
|
-
} catch {
|
|
1812
|
-
args = {};
|
|
1813
|
-
}
|
|
1814
|
-
const shortArgs = Object.entries(args).map(([k, v]) => {
|
|
1815
|
-
const s = String(v);
|
|
1816
|
-
return `${k}=${s.length > 30 ? s.slice(0, 30) + "\u2026" : s}`;
|
|
1817
|
-
}).join(" ");
|
|
1818
|
-
console.log(chalk12.gray(` \u2699 ${chalk12.white(tc.name)} ${shortArgs}`));
|
|
1819
|
-
let toolResult;
|
|
1820
|
-
if (isXgenTool(tc.name)) {
|
|
1821
|
-
toolResult = await execute8(tc.name, args);
|
|
1822
|
-
} else if (mcpManager?.isMcpTool(tc.name)) {
|
|
1823
|
-
toolResult = await mcpManager.callTool(tc.name, args);
|
|
1824
|
-
} else {
|
|
1825
|
-
toolResult = await executeTool(tc.name, args);
|
|
1826
|
-
}
|
|
1827
|
-
const truncated = toolResult.length > 4e3 ? toolResult.slice(0, 4e3) + "\n\u2026(truncated)" : toolResult;
|
|
1828
|
-
messages.push({ role: "tool", tool_call_id: tc.id, content: truncated });
|
|
1829
|
-
}
|
|
2183
|
+
|
|
2184
|
+
// src/agent/tools/sandbox.ts
|
|
2185
|
+
var sandbox_exports = {};
|
|
2186
|
+
__export(sandbox_exports, {
|
|
2187
|
+
definition: () => definition7,
|
|
2188
|
+
execute: () => execute7
|
|
2189
|
+
});
|
|
2190
|
+
import { execSync as execSync4 } from "child_process";
|
|
2191
|
+
import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync4, existsSync as existsSync2, rmSync } from "fs";
|
|
2192
|
+
import { join as join2 } from "path";
|
|
2193
|
+
import { tmpdir } from "os";
|
|
2194
|
+
var SANDBOX_DIR = join2(tmpdir(), "xgen-sandbox");
|
|
2195
|
+
function ensureSandbox() {
|
|
2196
|
+
if (!existsSync2(SANDBOX_DIR)) {
|
|
2197
|
+
mkdirSync3(SANDBOX_DIR, { recursive: true });
|
|
1830
2198
|
}
|
|
1831
|
-
|
|
2199
|
+
return SANDBOX_DIR;
|
|
1832
2200
|
}
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
if (!url) return;
|
|
2201
|
+
var definition7 = {
|
|
2202
|
+
type: "function",
|
|
2203
|
+
function: {
|
|
2204
|
+
name: "sandbox_run",
|
|
2205
|
+
description: "\uACA9\uB9AC\uB41C \uC0CC\uB4DC\uBC15\uC2A4\uC5D0\uC11C \uCF54\uB4DC\uB97C \uC2E4\uD589\uD569\uB2C8\uB2E4. Node.js \uB610\uB294 Python \uCF54\uB4DC\uB97C \uC548\uC804\uD558\uAC8C \uC2E4\uD589\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4. npm \uD328\uD0A4\uC9C0 \uC124\uCE58\uB3C4 \uAC00\uB2A5\uD569\uB2C8\uB2E4.",
|
|
2206
|
+
parameters: {
|
|
2207
|
+
type: "object",
|
|
2208
|
+
properties: {
|
|
2209
|
+
language: {
|
|
2210
|
+
type: "string",
|
|
2211
|
+
enum: ["javascript", "typescript", "python"],
|
|
2212
|
+
description: "\uC2E4\uD589\uD560 \uC5B8\uC5B4"
|
|
2213
|
+
},
|
|
2214
|
+
code: { type: "string", description: "\uC2E4\uD589\uD560 \uCF54\uB4DC" },
|
|
2215
|
+
packages: {
|
|
2216
|
+
type: "array",
|
|
2217
|
+
items: { type: "string" },
|
|
2218
|
+
description: "\uC124\uCE58\uD560 \uD328\uD0A4\uC9C0 (npm \uB610\uB294 pip)"
|
|
2219
|
+
}
|
|
2220
|
+
},
|
|
2221
|
+
required: ["language", "code"]
|
|
2222
|
+
}
|
|
1856
2223
|
}
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
const
|
|
1861
|
-
const
|
|
1862
|
-
|
|
2224
|
+
};
|
|
2225
|
+
async function execute7(args) {
|
|
2226
|
+
const language = args.language;
|
|
2227
|
+
const code = args.code;
|
|
2228
|
+
const packages = args.packages ?? [];
|
|
2229
|
+
const dir = ensureSandbox();
|
|
2230
|
+
const runId = `run_${Date.now()}`;
|
|
2231
|
+
const runDir = join2(dir, runId);
|
|
2232
|
+
mkdirSync3(runDir, { recursive: true });
|
|
1863
2233
|
try {
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
2234
|
+
if (packages.length > 0) {
|
|
2235
|
+
if (language === "python") {
|
|
2236
|
+
const pkgList = packages.join(" ");
|
|
2237
|
+
execSync4(`pip install ${pkgList}`, {
|
|
2238
|
+
cwd: runDir,
|
|
2239
|
+
encoding: "utf-8",
|
|
2240
|
+
timeout: 6e4,
|
|
2241
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
2242
|
+
});
|
|
2243
|
+
} else {
|
|
2244
|
+
execSync4("npm init -y", { cwd: runDir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
2245
|
+
const pkgList = packages.join(" ");
|
|
2246
|
+
execSync4(`npm install ${pkgList}`, {
|
|
2247
|
+
cwd: runDir,
|
|
2248
|
+
encoding: "utf-8",
|
|
2249
|
+
timeout: 6e4,
|
|
2250
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
2251
|
+
});
|
|
2252
|
+
}
|
|
2253
|
+
}
|
|
2254
|
+
let cmd;
|
|
2255
|
+
let filename;
|
|
2256
|
+
if (language === "python") {
|
|
2257
|
+
filename = "script.py";
|
|
2258
|
+
writeFileSync4(join2(runDir, filename), code, "utf-8");
|
|
2259
|
+
cmd = `python3 ${filename}`;
|
|
2260
|
+
} else if (language === "typescript") {
|
|
2261
|
+
filename = "script.ts";
|
|
2262
|
+
writeFileSync4(join2(runDir, filename), code, "utf-8");
|
|
2263
|
+
cmd = `npx tsx ${filename}`;
|
|
1870
2264
|
} else {
|
|
1871
|
-
|
|
1872
|
-
|
|
2265
|
+
filename = "script.mjs";
|
|
2266
|
+
writeFileSync4(join2(runDir, filename), code, "utf-8");
|
|
2267
|
+
cmd = `node ${filename}`;
|
|
1873
2268
|
}
|
|
2269
|
+
const output = execSync4(cmd, {
|
|
2270
|
+
cwd: runDir,
|
|
2271
|
+
encoding: "utf-8",
|
|
2272
|
+
timeout: 3e4,
|
|
2273
|
+
maxBuffer: 1024 * 1024,
|
|
2274
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
2275
|
+
});
|
|
2276
|
+
return output || "(no output)";
|
|
1874
2277
|
} catch (err) {
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
}
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
if (!envs.length) {
|
|
1883
|
-
console.log(chalk12.gray("\n \uD658\uACBD \uC5C6\uC74C. /connect\uB85C \uBA3C\uC800 \uC5F0\uACB0\uD558\uC138\uC694.\n"));
|
|
1884
|
-
return;
|
|
1885
|
-
}
|
|
1886
|
-
const active = getActiveEnvironment();
|
|
1887
|
-
console.log();
|
|
1888
|
-
envs.forEach((e, i) => {
|
|
1889
|
-
const mark = e.id === active?.id ? chalk12.green("\u25CF ") : " ";
|
|
1890
|
-
console.log(` ${mark}${chalk12.cyan(`${i + 1}.`)} ${e.name} ${chalk12.gray(e.url)}`);
|
|
1891
|
-
});
|
|
1892
|
-
console.log();
|
|
1893
|
-
const ci = parseInt(await ask(chalk12.cyan(" \u276F "))) - 1;
|
|
1894
|
-
if (ci >= 0 && ci < envs.length) {
|
|
1895
|
-
switchEnvironment2(envs[ci].id);
|
|
1896
|
-
console.log(chalk12.green(` \u2713 ${envs[ci].name}
|
|
1897
|
-
`));
|
|
2278
|
+
const e = err;
|
|
2279
|
+
return (e.stdout || "") + (e.stderr || "") || `Error: ${e.message}`;
|
|
2280
|
+
} finally {
|
|
2281
|
+
try {
|
|
2282
|
+
rmSync(runDir, { recursive: true, force: true });
|
|
2283
|
+
} catch {
|
|
2284
|
+
}
|
|
1898
2285
|
}
|
|
1899
2286
|
}
|
|
1900
|
-
function registerAgentCommand(program2) {
|
|
1901
|
-
program2.command("agent").description("OPEN XGEN AI \uC5D0\uC774\uC804\uD2B8").action(async () => {
|
|
1902
|
-
await agentRepl();
|
|
1903
|
-
});
|
|
1904
|
-
}
|
|
1905
|
-
var mcpManager;
|
|
1906
|
-
var init_agent = __esm({
|
|
1907
|
-
"src/commands/agent.ts"() {
|
|
1908
|
-
"use strict";
|
|
1909
|
-
init_store();
|
|
1910
|
-
init_llm();
|
|
1911
|
-
init_tools();
|
|
1912
|
-
init_xgen_api();
|
|
1913
|
-
init_client2();
|
|
1914
|
-
init_provider();
|
|
1915
|
-
init_ui();
|
|
1916
|
-
mcpManager = null;
|
|
1917
|
-
}
|
|
1918
|
-
});
|
|
1919
2287
|
|
|
1920
|
-
// src/
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
function renderHeader(activeTab, tabs, env) {
|
|
1926
|
-
const w = W2();
|
|
1927
|
-
const title = chalk15.cyan.bold(" OPEN XGEN ");
|
|
1928
|
-
const envTag = env ? chalk15.gray(` \xB7 ${env}`) : "";
|
|
1929
|
-
const tabBar = tabs.map((t) => {
|
|
1930
|
-
if (t === activeTab) return chalk15.bgCyan.black(` ${t} `);
|
|
1931
|
-
return chalk15.gray(` ${t} `);
|
|
1932
|
-
}).join(chalk15.gray("\u2502"));
|
|
1933
|
-
console.log(chalk15.bgGray.black(" ".repeat(w)));
|
|
1934
|
-
console.log(chalk15.bgGray.black(`${title}${envTag}${" ".repeat(Math.max(0, w - stripAnsi(title + envTag).length))}`));
|
|
1935
|
-
console.log(chalk15.gray("\u2500".repeat(w)));
|
|
1936
|
-
console.log(tabBar);
|
|
1937
|
-
console.log(chalk15.gray("\u2500".repeat(w)));
|
|
1938
|
-
}
|
|
1939
|
-
function renderStatusBar(text) {
|
|
1940
|
-
const w = W2();
|
|
1941
|
-
const padded = ` ${text}${" ".repeat(Math.max(0, w - text.length - 1))}`;
|
|
1942
|
-
console.log(chalk15.gray("\u2500".repeat(w)));
|
|
1943
|
-
console.log(chalk15.bgGray.black(padded));
|
|
1944
|
-
}
|
|
1945
|
-
function renderList(items, selected, title, startRow) {
|
|
1946
|
-
if (title) console.log(chalk15.bold(` ${title}`));
|
|
1947
|
-
console.log();
|
|
1948
|
-
const pageSize = H() - 12;
|
|
1949
|
-
const start = Math.max(0, selected - pageSize + 3);
|
|
1950
|
-
const visible = items.slice(start, start + pageSize);
|
|
1951
|
-
visible.forEach((item, i) => {
|
|
1952
|
-
const idx = start + i;
|
|
1953
|
-
const cursor = idx === selected ? chalk15.cyan("\u25B8 ") : " ";
|
|
1954
|
-
const num = chalk15.gray(`${String(idx + 1).padStart(3)}.`);
|
|
1955
|
-
const tag = item.tag ? ` ${item.tag}` : "";
|
|
1956
|
-
const line = `${cursor}${num} ${item.label}${tag}`;
|
|
1957
|
-
if (idx === selected) {
|
|
1958
|
-
console.log(chalk15.white.bold(line));
|
|
1959
|
-
if (item.detail) console.log(chalk15.gray(` ${item.detail}`));
|
|
1960
|
-
} else {
|
|
1961
|
-
console.log(line);
|
|
1962
|
-
}
|
|
1963
|
-
});
|
|
1964
|
-
if (items.length > pageSize) {
|
|
1965
|
-
console.log(chalk15.gray(`
|
|
1966
|
-
${start + 1}-${Math.min(start + pageSize, items.length)} / ${items.length}`));
|
|
1967
|
-
}
|
|
2288
|
+
// src/agent/tools/index.ts
|
|
2289
|
+
var tools = [file_read_exports, file_write_exports, file_edit_exports, bash_exports, grep_exports, list_files_exports, sandbox_exports];
|
|
2290
|
+
var toolMap = /* @__PURE__ */ new Map();
|
|
2291
|
+
for (const t of tools) {
|
|
2292
|
+
toolMap.set(t.definition.function.name, t);
|
|
1968
2293
|
}
|
|
1969
|
-
function
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
const pad = Math.max(0, w - clean.length - 1);
|
|
1977
|
-
console.log(chalk15.cyan(` \u2502 `) + line + " ".repeat(pad) + chalk15.cyan("\u2502"));
|
|
1978
|
-
}
|
|
1979
|
-
console.log(chalk15.cyan(` \u2514${"\u2500".repeat(w)}\u2518`));
|
|
2294
|
+
function getAllToolDefs() {
|
|
2295
|
+
return tools.map((t) => t.definition);
|
|
2296
|
+
}
|
|
2297
|
+
async function executeTool(name, args) {
|
|
2298
|
+
const tool = toolMap.get(name);
|
|
2299
|
+
if (!tool) return `Unknown tool: ${name}`;
|
|
2300
|
+
return tool.execute(args);
|
|
1980
2301
|
}
|
|
1981
|
-
function
|
|
1982
|
-
return
|
|
2302
|
+
function getToolNames() {
|
|
2303
|
+
return tools.map((t) => t.definition.function.name);
|
|
1983
2304
|
}
|
|
1984
|
-
var W2, H;
|
|
1985
|
-
var init_renderer = __esm({
|
|
1986
|
-
"src/dashboard/renderer.ts"() {
|
|
1987
|
-
"use strict";
|
|
1988
|
-
W2 = () => Math.min(process.stdout.columns || 80, 100);
|
|
1989
|
-
H = () => Math.min(process.stdout.rows || 30, 40);
|
|
1990
|
-
}
|
|
1991
|
-
});
|
|
1992
2305
|
|
|
1993
|
-
// src/
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
}
|
|
2019
|
-
if (key === " ") {
|
|
2020
|
-
state.activeTab = (state.activeTab + 1) % TABS.length;
|
|
2021
|
-
state.selectedIdx = 0;
|
|
2022
|
-
render(state);
|
|
2023
|
-
return;
|
|
2306
|
+
// src/agent/tools/xgen-api.ts
|
|
2307
|
+
init_store();
|
|
2308
|
+
var definitions = [
|
|
2309
|
+
{
|
|
2310
|
+
type: "function",
|
|
2311
|
+
function: {
|
|
2312
|
+
name: "xgen_workflow_list",
|
|
2313
|
+
description: "XGEN \uC11C\uBC84\uC5D0\uC11C \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D\uC744 \uAC00\uC838\uC635\uB2C8\uB2E4.",
|
|
2314
|
+
parameters: { type: "object", properties: {} }
|
|
2315
|
+
}
|
|
2316
|
+
},
|
|
2317
|
+
{
|
|
2318
|
+
type: "function",
|
|
2319
|
+
function: {
|
|
2320
|
+
name: "xgen_workflow_run",
|
|
2321
|
+
description: "XGEN \uC6CC\uD06C\uD50C\uB85C\uC6B0\uB97C \uC2E4\uD589\uD569\uB2C8\uB2E4. \uBC30\uD3EC\uB41C \uC6CC\uD06C\uD50C\uB85C\uC6B0\uB9CC \uC2E4\uD589 \uAC00\uB2A5.",
|
|
2322
|
+
parameters: {
|
|
2323
|
+
type: "object",
|
|
2324
|
+
properties: {
|
|
2325
|
+
workflow_id: { type: "string", description: "\uC6CC\uD06C\uD50C\uB85C\uC6B0 ID" },
|
|
2326
|
+
workflow_name: { type: "string", description: "\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC774\uB984" },
|
|
2327
|
+
input_data: { type: "string", description: "\uC785\uB825 \uBA54\uC2DC\uC9C0" },
|
|
2328
|
+
deploy_key: { type: "string", description: "\uBC30\uD3EC \uD0A4 (\uBC30\uD3EC\uB41C \uC6CC\uD06C\uD50C\uB85C\uC6B0)" }
|
|
2329
|
+
},
|
|
2330
|
+
required: ["workflow_id", "workflow_name", "input_data"]
|
|
2024
2331
|
}
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2332
|
+
}
|
|
2333
|
+
},
|
|
2334
|
+
{
|
|
2335
|
+
type: "function",
|
|
2336
|
+
function: {
|
|
2337
|
+
name: "xgen_workflow_info",
|
|
2338
|
+
description: "\uD2B9\uC815 \uC6CC\uD06C\uD50C\uB85C\uC6B0\uC758 \uC0C1\uC138 \uC815\uBCF4(\uB178\uB4DC, \uC5E3\uC9C0 \uB4F1)\uB97C \uAC00\uC838\uC635\uB2C8\uB2E4.",
|
|
2339
|
+
parameters: {
|
|
2340
|
+
type: "object",
|
|
2341
|
+
properties: {
|
|
2342
|
+
workflow_id: { type: "string", description: "\uC6CC\uD06C\uD50C\uB85C\uC6B0 ID" }
|
|
2343
|
+
},
|
|
2344
|
+
required: ["workflow_id"]
|
|
2030
2345
|
}
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2346
|
+
}
|
|
2347
|
+
},
|
|
2348
|
+
{
|
|
2349
|
+
type: "function",
|
|
2350
|
+
function: {
|
|
2351
|
+
name: "xgen_collection_list",
|
|
2352
|
+
description: "XGEN \uC11C\uBC84\uC758 \uBB38\uC11C \uCEEC\uB809\uC158(\uC9C0\uC2DD\uBCA0\uC774\uC2A4) \uBAA9\uB85D\uC744 \uAC00\uC838\uC635\uB2C8\uB2E4. \uBB38\uC11C \uC218, \uCCAD\uD06C \uC218, \uACF5\uC720 \uC0C1\uD0DC \uB4F1 \uD3EC\uD568.",
|
|
2353
|
+
parameters: { type: "object", properties: {} }
|
|
2354
|
+
}
|
|
2355
|
+
},
|
|
2356
|
+
{
|
|
2357
|
+
type: "function",
|
|
2358
|
+
function: {
|
|
2359
|
+
name: "xgen_server_status",
|
|
2360
|
+
description: "XGEN \uC11C\uBC84 \uC0C1\uD0DC\uB97C \uD655\uC778\uD569\uB2C8\uB2E4.",
|
|
2361
|
+
parameters: { type: "object", properties: {} }
|
|
2362
|
+
}
|
|
2363
|
+
},
|
|
2364
|
+
{
|
|
2365
|
+
type: "function",
|
|
2366
|
+
function: {
|
|
2367
|
+
name: "xgen_execution_history",
|
|
2368
|
+
description: "\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC2E4\uD589 \uC774\uB825\uC744 \uAC00\uC838\uC635\uB2C8\uB2E4.",
|
|
2369
|
+
parameters: {
|
|
2370
|
+
type: "object",
|
|
2371
|
+
properties: {
|
|
2372
|
+
limit: { type: "number", description: "\uAC00\uC838\uC62C \uC774\uB825 \uC218 (\uAE30\uBCF8 10)" }
|
|
2373
|
+
}
|
|
2035
2374
|
}
|
|
2036
|
-
|
|
2037
|
-
const max = getCurrentListLength(state) - 1;
|
|
2038
|
-
state.selectedIdx = Math.min(max, state.selectedIdx + 1);
|
|
2039
|
-
render(state);
|
|
2040
|
-
return;
|
|
2041
|
-
}
|
|
2042
|
-
if (key === "\r") {
|
|
2043
|
-
await handleEnter(state, rl);
|
|
2044
|
-
return;
|
|
2045
|
-
}
|
|
2046
|
-
const num = parseInt(key);
|
|
2047
|
-
if (num >= 1 && num <= 5) {
|
|
2048
|
-
state.activeTab = num - 1;
|
|
2049
|
-
state.selectedIdx = 0;
|
|
2050
|
-
render(state);
|
|
2051
|
-
return;
|
|
2052
|
-
}
|
|
2053
|
-
if (key === "c") {
|
|
2054
|
-
state.activeTab = 0;
|
|
2055
|
-
render(state);
|
|
2056
|
-
return;
|
|
2057
|
-
}
|
|
2058
|
-
if (key === "w") {
|
|
2059
|
-
state.activeTab = 1;
|
|
2060
|
-
render(state);
|
|
2061
|
-
return;
|
|
2062
|
-
}
|
|
2063
|
-
if (key === "d") {
|
|
2064
|
-
state.activeTab = 2;
|
|
2065
|
-
render(state);
|
|
2066
|
-
return;
|
|
2067
|
-
}
|
|
2068
|
-
if (key === "o") {
|
|
2069
|
-
state.activeTab = 3;
|
|
2070
|
-
render(state);
|
|
2071
|
-
return;
|
|
2072
|
-
}
|
|
2073
|
-
if (key === "s") {
|
|
2074
|
-
state.activeTab = 4;
|
|
2075
|
-
render(state);
|
|
2076
|
-
return;
|
|
2077
|
-
}
|
|
2078
|
-
if (key === "r") {
|
|
2079
|
-
await loadData(state);
|
|
2080
|
-
render(state);
|
|
2081
|
-
return;
|
|
2082
|
-
}
|
|
2083
|
-
if (key === "q") {
|
|
2084
|
-
cleanup(rl);
|
|
2085
|
-
process.exit(0);
|
|
2086
|
-
}
|
|
2087
|
-
});
|
|
2088
|
-
} else {
|
|
2089
|
-
cleanup(rl);
|
|
2090
|
-
await agentRepl();
|
|
2375
|
+
}
|
|
2091
2376
|
}
|
|
2092
|
-
|
|
2093
|
-
function
|
|
2094
|
-
clearScreen();
|
|
2095
|
-
const env = getActiveEnvironment();
|
|
2096
|
-
const auth = getAuth();
|
|
2377
|
+
];
|
|
2378
|
+
async function execute8(name, args) {
|
|
2097
2379
|
const server = getServer();
|
|
2098
|
-
const
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2380
|
+
const auth = getAuth();
|
|
2381
|
+
if (!server || !auth) {
|
|
2382
|
+
return "XGEN \uC11C\uBC84\uC5D0 \uC5F0\uACB0\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. /connect \uBA85\uB839\uC73C\uB85C \uC5F0\uACB0\uD558\uC138\uC694.";
|
|
2383
|
+
}
|
|
2384
|
+
try {
|
|
2385
|
+
switch (name) {
|
|
2386
|
+
case "xgen_workflow_list":
|
|
2387
|
+
return await workflowList2();
|
|
2388
|
+
case "xgen_workflow_run":
|
|
2389
|
+
return await workflowRun2(args);
|
|
2390
|
+
case "xgen_workflow_info":
|
|
2391
|
+
return await workflowInfo2(args);
|
|
2392
|
+
case "xgen_collection_list":
|
|
2393
|
+
return await collectionList();
|
|
2394
|
+
case "xgen_server_status":
|
|
2395
|
+
return await serverStatus();
|
|
2396
|
+
case "xgen_execution_history":
|
|
2397
|
+
return await executionHistory(args);
|
|
2398
|
+
default:
|
|
2399
|
+
return `Unknown XGEN tool: ${name}`;
|
|
2400
|
+
}
|
|
2401
|
+
} catch (err) {
|
|
2402
|
+
return `XGEN API \uC624\uB958: ${err.message}`;
|
|
2118
2403
|
}
|
|
2119
|
-
const provider = getDefaultProvider();
|
|
2120
|
-
const statusText = `${provider?.name ?? "AI \uBBF8\uC124\uC815"} \xB7 ${provider?.model ?? ""} \u2502 Tab:\uC804\uD658 \u2191\u2193:\uC120\uD0DD Enter:\uC2E4\uD589 r:\uC0C8\uB85C\uACE0\uCE68 q:\uC885\uB8CC`;
|
|
2121
|
-
renderStatusBar(statusText);
|
|
2122
2404
|
}
|
|
2123
|
-
function
|
|
2124
|
-
|
|
2125
|
-
console.log();
|
|
2126
|
-
console.log(chalk16.gray(" Enter\uB97C \uB20C\uB7EC AI \uCC44\uD305 \uBAA8\uB4DC\uB85C \uC9C4\uC785\uD569\uB2C8\uB2E4."));
|
|
2127
|
-
console.log(chalk16.gray(" \uCC44\uD305\uC5D0\uC11C \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC2E4\uD589, \uD30C\uC77C \uD3B8\uC9D1, \uCF54\uB4DC \uC2E4\uD589 \uBAA8\uB450 \uAC00\uB2A5\uD569\uB2C8\uB2E4."));
|
|
2128
|
-
console.log();
|
|
2129
|
-
console.log(chalk16.gray(" \uC608\uC2DC:"));
|
|
2130
|
-
console.log(chalk16.white(' "\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D \uBCF4\uC5EC\uC918"'));
|
|
2131
|
-
console.log(chalk16.white(' "\uC7AC\uC9C1\uC99D\uBA85\uC11C \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC2E4\uD589\uD574\uC918"'));
|
|
2132
|
-
console.log(chalk16.white(' "\uC774 \uD3F4\uB354\uC5D0 \uC788\uB294 \uD30C\uC77C \uBB50 \uC788\uC5B4?"'));
|
|
2133
|
-
console.log(chalk16.white(' "Python\uC73C\uB85C fibonacci \uD568\uC218 \uB9CC\uB4E4\uC5B4\uC918"'));
|
|
2134
|
-
console.log();
|
|
2405
|
+
function isXgenTool(name) {
|
|
2406
|
+
return name.startsWith("xgen_");
|
|
2135
2407
|
}
|
|
2136
|
-
function
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2408
|
+
async function workflowList2() {
|
|
2409
|
+
const { getWorkflowListDetail: getWorkflowListDetail2 } = await Promise.resolve().then(() => (init_workflow(), workflow_exports));
|
|
2410
|
+
const wfs = await getWorkflowListDetail2();
|
|
2411
|
+
if (!wfs.length) return "\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC5C6\uC74C.";
|
|
2412
|
+
return wfs.map((w, i) => {
|
|
2413
|
+
const deployed = w.is_deployed;
|
|
2414
|
+
const dk = w.deploy_key;
|
|
2415
|
+
const tag = deployed ? " [\uBC30\uD3EC\uB428]" : "";
|
|
2416
|
+
return `${i + 1}. ${w.workflow_name}${tag}
|
|
2417
|
+
ID: ${w.workflow_id ?? w.id}
|
|
2418
|
+
deploy_key: ${dk || "\uC5C6\uC74C"}`;
|
|
2419
|
+
}).join("\n");
|
|
2143
2420
|
}
|
|
2144
|
-
function
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2421
|
+
async function workflowRun2(args) {
|
|
2422
|
+
const { executeWorkflow: executeWorkflow2 } = await Promise.resolve().then(() => (init_workflow(), workflow_exports));
|
|
2423
|
+
const { randomUUID: randomUUID4 } = await import("crypto");
|
|
2424
|
+
const result = await executeWorkflow2({
|
|
2425
|
+
workflow_id: args.workflow_id,
|
|
2426
|
+
workflow_name: args.workflow_name,
|
|
2427
|
+
input_data: args.input_data,
|
|
2428
|
+
interaction_id: `cli_${randomUUID4().slice(0, 8)}`,
|
|
2429
|
+
deploy_key: args.deploy_key
|
|
2430
|
+
});
|
|
2431
|
+
if (result.content) return String(result.content);
|
|
2432
|
+
if (result.success === false) return `\uC624\uB958: ${result.error ?? result.message}`;
|
|
2433
|
+
return JSON.stringify(result, null, 2).slice(0, 2e3);
|
|
2150
2434
|
}
|
|
2151
|
-
function
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2435
|
+
async function workflowInfo2(args) {
|
|
2436
|
+
const { getWorkflowDetail: getWorkflowDetail2 } = await Promise.resolve().then(() => (init_workflow(), workflow_exports));
|
|
2437
|
+
const detail = await getWorkflowDetail2(args.workflow_id);
|
|
2438
|
+
const nodes = detail.nodes?.length ?? 0;
|
|
2439
|
+
const edges = detail.edges?.length ?? 0;
|
|
2440
|
+
return `\uC6CC\uD06C\uD50C\uB85C\uC6B0: ${detail.workflow_name}
|
|
2441
|
+
ID: ${detail.id}
|
|
2442
|
+
\uB178\uB4DC: ${nodes}\uAC1C
|
|
2443
|
+
\uC5E3\uC9C0: ${edges}\uAC1C`;
|
|
2157
2444
|
}
|
|
2158
|
-
function
|
|
2159
|
-
const
|
|
2445
|
+
async function collectionList() {
|
|
2446
|
+
const { listCollections: listCollections2 } = await Promise.resolve().then(() => (init_document(), document_exports));
|
|
2447
|
+
const cols = await listCollections2();
|
|
2448
|
+
if (!cols.length) return "\uCEEC\uB809\uC158 \uC5C6\uC74C.";
|
|
2449
|
+
return cols.map((c, i) => {
|
|
2450
|
+
const shared = c.is_shared ? ` [\uACF5\uC720:${c.share_group}]` : "";
|
|
2451
|
+
return `${i + 1}. ${c.collection_make_name}${shared}
|
|
2452
|
+
\uBB38\uC11C: ${c.total_documents}\uAC1C \xB7 \uCCAD\uD06C: ${c.total_chunks}\uAC1C \xB7 \uBAA8\uB378: ${c.init_embedding_model ?? "-"}`;
|
|
2453
|
+
}).join("\n");
|
|
2454
|
+
}
|
|
2455
|
+
async function serverStatus() {
|
|
2160
2456
|
const server = getServer();
|
|
2161
2457
|
const auth = getAuth();
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
`\uC11C\uBC84: ${server ?? chalk16.red("\uBBF8\uC5F0\uACB0")}`,
|
|
2166
|
-
`\uC0AC\uC6A9\uC790: ${auth?.username ?? "-"}`,
|
|
2167
|
-
`\uD658\uACBD: ${env?.name ?? "-"}`
|
|
2168
|
-
];
|
|
2169
|
-
renderPanel("\uD604\uC7AC \uC124\uC815", lines);
|
|
2170
|
-
console.log();
|
|
2171
|
-
console.log(chalk16.gray(" Enter \u2192 AI \uCC44\uD305\uC5D0\uC11C /connect, /provider, /env \uC0AC\uC6A9"));
|
|
2458
|
+
return `\uC11C\uBC84: ${server}
|
|
2459
|
+
\uC0AC\uC6A9\uC790: ${auth?.username}
|
|
2460
|
+
User ID: ${auth?.userId}`;
|
|
2172
2461
|
}
|
|
2173
|
-
function
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2462
|
+
async function executionHistory(args) {
|
|
2463
|
+
const { getIOLogs: getIOLogs2 } = await Promise.resolve().then(() => (init_workflow(), workflow_exports));
|
|
2464
|
+
const limit = args.limit || 10;
|
|
2465
|
+
const logs = await getIOLogs2(void 0, limit);
|
|
2466
|
+
if (!logs.length) return "\uC2E4\uD589 \uC774\uB825 \uC5C6\uC74C.";
|
|
2467
|
+
return logs.map(
|
|
2468
|
+
(l, i) => `${i + 1}. [${l.created_at ?? ""}]
|
|
2469
|
+
\uC785\uB825: ${(l.input_data ?? "").slice(0, 80)}
|
|
2470
|
+
\uCD9C\uB825: ${(l.output_data ?? "").slice(0, 80)}`
|
|
2471
|
+
).join("\n");
|
|
2182
2472
|
}
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2473
|
+
|
|
2474
|
+
// src/mcp/client.ts
|
|
2475
|
+
import { spawn } from "child_process";
|
|
2476
|
+
import { existsSync as existsSync3, readFileSync as readFileSync4 } from "fs";
|
|
2477
|
+
import { join as join3 } from "path";
|
|
2478
|
+
import { createInterface as createInterface4 } from "readline";
|
|
2479
|
+
var McpClient = class {
|
|
2480
|
+
process = null;
|
|
2481
|
+
requestId = 0;
|
|
2482
|
+
pending = /* @__PURE__ */ new Map();
|
|
2483
|
+
serverName;
|
|
2484
|
+
config;
|
|
2485
|
+
tools = [];
|
|
2486
|
+
constructor(serverName, config) {
|
|
2487
|
+
this.serverName = serverName;
|
|
2488
|
+
this.config = config;
|
|
2489
|
+
}
|
|
2490
|
+
async start() {
|
|
2491
|
+
this.process = spawn(this.config.command, this.config.args ?? [], {
|
|
2492
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
2493
|
+
env: { ...process.env, ...this.config.env }
|
|
2494
|
+
});
|
|
2495
|
+
const rl = createInterface4({ input: this.process.stdout });
|
|
2496
|
+
rl.on("line", (line) => {
|
|
2497
|
+
try {
|
|
2498
|
+
const msg = JSON.parse(line);
|
|
2499
|
+
if (msg.id !== void 0 && this.pending.has(msg.id)) {
|
|
2500
|
+
const p = this.pending.get(msg.id);
|
|
2501
|
+
this.pending.delete(msg.id);
|
|
2502
|
+
if (msg.error) {
|
|
2503
|
+
p.reject(new Error(msg.error.message));
|
|
2504
|
+
} else {
|
|
2505
|
+
p.resolve(msg.result);
|
|
2506
|
+
}
|
|
2507
|
+
}
|
|
2508
|
+
} catch {
|
|
2509
|
+
}
|
|
2510
|
+
});
|
|
2511
|
+
this.process.on("error", (err) => {
|
|
2512
|
+
console.error(`MCP [${this.serverName}] \uD504\uB85C\uC138\uC2A4 \uC624\uB958:`, err.message);
|
|
2513
|
+
});
|
|
2514
|
+
await this.send("initialize", {
|
|
2515
|
+
protocolVersion: "2024-11-05",
|
|
2516
|
+
capabilities: {},
|
|
2517
|
+
clientInfo: { name: "open-xgen", version: "0.3.0" }
|
|
2518
|
+
});
|
|
2519
|
+
await this.send("notifications/initialized", {});
|
|
2520
|
+
}
|
|
2521
|
+
send(method, params) {
|
|
2522
|
+
return new Promise((resolve, reject) => {
|
|
2523
|
+
const id = ++this.requestId;
|
|
2524
|
+
const request = { jsonrpc: "2.0", id, method, params };
|
|
2525
|
+
this.pending.set(id, { resolve, reject });
|
|
2526
|
+
const timeout = setTimeout(() => {
|
|
2527
|
+
this.pending.delete(id);
|
|
2528
|
+
reject(new Error(`MCP \uC694\uCCAD \uD0C0\uC784\uC544\uC6C3: ${method}`));
|
|
2529
|
+
}, 15e3);
|
|
2530
|
+
this.pending.set(id, {
|
|
2531
|
+
resolve: (v) => {
|
|
2532
|
+
clearTimeout(timeout);
|
|
2533
|
+
resolve(v);
|
|
2534
|
+
},
|
|
2535
|
+
reject: (e) => {
|
|
2536
|
+
clearTimeout(timeout);
|
|
2537
|
+
reject(e);
|
|
2538
|
+
}
|
|
2539
|
+
});
|
|
2540
|
+
this.process?.stdin?.write(JSON.stringify(request) + "\n");
|
|
2541
|
+
});
|
|
2189
2542
|
}
|
|
2190
|
-
|
|
2191
|
-
const
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
\u2713 ${selected.label} \uC120\uD0DD\uB428
|
|
2195
|
-
`));
|
|
2196
|
-
await agentRepl();
|
|
2197
|
-
await dashboard();
|
|
2198
|
-
return;
|
|
2543
|
+
async listTools() {
|
|
2544
|
+
const result = await this.send("tools/list", {});
|
|
2545
|
+
this.tools = result.tools ?? [];
|
|
2546
|
+
return this.tools;
|
|
2199
2547
|
}
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
const auth = getAuth();
|
|
2204
|
-
if (!server || !auth) return;
|
|
2205
|
-
try {
|
|
2206
|
-
const { getWorkflowListDetail: getWorkflowListDetail2 } = await Promise.resolve().then(() => (init_workflow(), workflow_exports));
|
|
2207
|
-
const wfs = await getWorkflowListDetail2();
|
|
2208
|
-
state.workflows = wfs.map((w) => {
|
|
2209
|
-
const deployed = w.is_deployed;
|
|
2210
|
-
return {
|
|
2211
|
-
label: w.workflow_name,
|
|
2212
|
-
detail: (w.workflow_id ?? w.id ?? "").toString(),
|
|
2213
|
-
tag: deployed ? chalk16.green("[\uBC30\uD3EC]") : void 0
|
|
2214
|
-
};
|
|
2215
|
-
});
|
|
2216
|
-
} catch {
|
|
2548
|
+
async callTool(name, args) {
|
|
2549
|
+
const result = await this.send("tools/call", { name, arguments: args });
|
|
2550
|
+
return result.content?.map((c) => c.text ?? "").join("\n") ?? "";
|
|
2217
2551
|
}
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2552
|
+
getOpenAITools() {
|
|
2553
|
+
return this.tools.map((t) => ({
|
|
2554
|
+
type: "function",
|
|
2555
|
+
function: {
|
|
2556
|
+
name: `mcp_${this.serverName}_${t.name}`,
|
|
2557
|
+
description: `[MCP:${this.serverName}] ${t.description ?? t.name}`,
|
|
2558
|
+
parameters: t.inputSchema ?? { type: "object", properties: {} }
|
|
2559
|
+
}
|
|
2225
2560
|
}));
|
|
2226
|
-
} catch {
|
|
2227
2561
|
}
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
rl.close();
|
|
2232
|
-
clearScreen();
|
|
2233
|
-
}
|
|
2234
|
-
var TABS;
|
|
2235
|
-
var init_dashboard = __esm({
|
|
2236
|
-
"src/dashboard/index.ts"() {
|
|
2237
|
-
"use strict";
|
|
2238
|
-
init_renderer();
|
|
2239
|
-
init_store();
|
|
2240
|
-
init_agent();
|
|
2241
|
-
TABS = ["\u{1F4AC} Chat", "\u{1F4CB} Workflows", "\u{1F4C4} Documents", "\u{1F50D} Ontology", "\u2699 Settings"];
|
|
2562
|
+
stop() {
|
|
2563
|
+
this.process?.kill();
|
|
2564
|
+
this.process = null;
|
|
2242
2565
|
}
|
|
2243
|
-
}
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
if (!url.startsWith("http://") && !url.startsWith("https://")) {
|
|
2258
|
-
printError("URL\uC740 http:// \uB610\uB294 https://\uB85C \uC2DC\uC791\uD574\uC57C \uD569\uB2C8\uB2E4");
|
|
2259
|
-
process.exit(1);
|
|
2566
|
+
};
|
|
2567
|
+
function loadMcpConfig(dir) {
|
|
2568
|
+
const searchPaths = [
|
|
2569
|
+
dir ? join3(dir, ".mcp.json") : null,
|
|
2570
|
+
join3(process.cwd(), ".mcp.json"),
|
|
2571
|
+
join3(process.env.HOME ?? "", ".mcp.json")
|
|
2572
|
+
].filter(Boolean);
|
|
2573
|
+
for (const p of searchPaths) {
|
|
2574
|
+
if (existsSync3(p)) {
|
|
2575
|
+
try {
|
|
2576
|
+
return JSON.parse(readFileSync4(p, "utf-8"));
|
|
2577
|
+
} catch {
|
|
2578
|
+
continue;
|
|
2579
|
+
}
|
|
2260
2580
|
}
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2581
|
+
}
|
|
2582
|
+
return null;
|
|
2583
|
+
}
|
|
2584
|
+
var McpManager = class {
|
|
2585
|
+
clients = /* @__PURE__ */ new Map();
|
|
2586
|
+
async startAll(config) {
|
|
2587
|
+
for (const [name, serverConfig] of Object.entries(config.mcpServers)) {
|
|
2588
|
+
if (serverConfig.type !== "stdio") continue;
|
|
2589
|
+
try {
|
|
2590
|
+
const client2 = new McpClient(name, serverConfig);
|
|
2591
|
+
await client2.start();
|
|
2592
|
+
await client2.listTools();
|
|
2593
|
+
this.clients.set(name, client2);
|
|
2594
|
+
} catch (err) {
|
|
2595
|
+
console.error(`MCP [${name}] \uC2DC\uC791 \uC2E4\uD328:`, err.message);
|
|
2596
|
+
}
|
|
2272
2597
|
}
|
|
2273
|
-
}
|
|
2274
|
-
|
|
2275
|
-
const
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
printKeyValue("\uC11C\uBC84", cfg.server);
|
|
2279
|
-
printKeyValue("\uAE30\uBCF8 \uC6CC\uD06C\uD50C\uB85C\uC6B0", cfg.defaultWorkflow);
|
|
2280
|
-
printKeyValue("\uD14C\uB9C8", cfg.theme);
|
|
2281
|
-
printKeyValue("\uC2A4\uD2B8\uB9BC \uB85C\uADF8", String(cfg.streamLogs));
|
|
2282
|
-
console.log();
|
|
2283
|
-
});
|
|
2284
|
-
config.command("set <key> <value>").description("\uC124\uC815 \uAC12 \uBCC0\uACBD").action((key, value) => {
|
|
2285
|
-
const allowedKeys = ["defaultWorkflow", "theme", "streamLogs"];
|
|
2286
|
-
if (!allowedKeys.includes(key)) {
|
|
2287
|
-
printError(`\uC54C \uC218 \uC5C6\uB294 \uC124\uC815 \uD0A4: ${key}`);
|
|
2288
|
-
console.log(` \uC0AC\uC6A9 \uAC00\uB2A5: ${allowedKeys.join(", ")}`);
|
|
2289
|
-
process.exit(1);
|
|
2598
|
+
}
|
|
2599
|
+
getAllTools() {
|
|
2600
|
+
const tools2 = [];
|
|
2601
|
+
for (const client2 of this.clients.values()) {
|
|
2602
|
+
tools2.push(...client2.getOpenAITools());
|
|
2290
2603
|
}
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
}
|
|
2604
|
+
return tools2;
|
|
2605
|
+
}
|
|
2606
|
+
async callTool(fullName, args) {
|
|
2607
|
+
const parts = fullName.split("_");
|
|
2608
|
+
if (parts.length < 3 || parts[0] !== "mcp") return `Unknown MCP tool: ${fullName}`;
|
|
2609
|
+
const serverName = parts[1];
|
|
2610
|
+
const toolName = parts.slice(2).join("_");
|
|
2611
|
+
const client2 = this.clients.get(serverName);
|
|
2612
|
+
if (!client2) return `MCP \uC11C\uBC84\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${serverName}`;
|
|
2613
|
+
return client2.callTool(toolName, args);
|
|
2614
|
+
}
|
|
2615
|
+
isMcpTool(name) {
|
|
2616
|
+
return name.startsWith("mcp_");
|
|
2617
|
+
}
|
|
2618
|
+
stopAll() {
|
|
2619
|
+
for (const client2 of this.clients.values()) {
|
|
2620
|
+
client2.stop();
|
|
2621
|
+
}
|
|
2622
|
+
this.clients.clear();
|
|
2623
|
+
}
|
|
2624
|
+
get serverCount() {
|
|
2625
|
+
return this.clients.size;
|
|
2626
|
+
}
|
|
2627
|
+
getServerNames() {
|
|
2628
|
+
return [...this.clients.keys()];
|
|
2629
|
+
}
|
|
2630
|
+
};
|
|
2296
2631
|
|
|
2297
|
-
// src/commands/
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
}
|
|
2330
|
-
} else {
|
|
2331
|
-
password += c;
|
|
2332
|
-
process.stdout.write("*");
|
|
2333
|
-
}
|
|
2334
|
-
};
|
|
2335
|
-
stdin.on("data", onData);
|
|
2336
|
-
} else {
|
|
2337
|
-
rl.question(question, (answer) => {
|
|
2338
|
-
rl.close();
|
|
2339
|
-
resolve(answer.trim());
|
|
2340
|
-
});
|
|
2341
|
-
}
|
|
2342
|
-
});
|
|
2632
|
+
// src/commands/agent.ts
|
|
2633
|
+
init_provider();
|
|
2634
|
+
init_ui();
|
|
2635
|
+
function buildSystemPrompt() {
|
|
2636
|
+
const server = getServer();
|
|
2637
|
+
const auth = getAuth();
|
|
2638
|
+
const env = getActiveEnvironment();
|
|
2639
|
+
let prompt2 = `You are OPEN XGEN. Terminal AI agent.
|
|
2640
|
+
|
|
2641
|
+
CRITICAL RULES:
|
|
2642
|
+
- Be extremely concise. No menus, no numbered lists of options, no "what would you like to do" questions.
|
|
2643
|
+
- Just DO things. If the user says "\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D" \u2192 call xgen_workflow_list immediately, show results.
|
|
2644
|
+
- If the user says a number after seeing a list, treat it as selection and act on it.
|
|
2645
|
+
- If the user says "\uC2E4\uD589" or "run" \u2192 call the tool immediately with the context you have.
|
|
2646
|
+
- Never ask "which option do you prefer" or show menus. Infer intent and act.
|
|
2647
|
+
- Respond in the user's language. Korean if they speak Korean.
|
|
2648
|
+
- Max 2-3 sentences per response unless showing data.
|
|
2649
|
+
|
|
2650
|
+
TOOLS:
|
|
2651
|
+
- Coding: file_read, file_write, file_edit, bash, grep, list_files, sandbox_run
|
|
2652
|
+
- XGEN: xgen_workflow_list, xgen_workflow_run, xgen_workflow_info, xgen_doc_list, xgen_ontology_query, xgen_server_status, xgen_execution_history`;
|
|
2653
|
+
if (server && auth) {
|
|
2654
|
+
prompt2 += `
|
|
2655
|
+
|
|
2656
|
+
XGEN CONNECTED: ${server} as ${auth.username} (${env?.name ?? "default"})
|
|
2657
|
+
- Workflow execute uses deploy_key for deployed workflows.
|
|
2658
|
+
- If workflow execution returns 404, it means the Istio routing blocks direct stream access. Use deploy endpoint.`;
|
|
2659
|
+
} else {
|
|
2660
|
+
prompt2 += `
|
|
2661
|
+
XGEN: Not connected. Tell user to run /connect.`;
|
|
2662
|
+
}
|
|
2663
|
+
return prompt2;
|
|
2343
2664
|
}
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2665
|
+
var mcpManager = null;
|
|
2666
|
+
async function agentRepl() {
|
|
2667
|
+
let provider = getDefaultProvider();
|
|
2668
|
+
if (!provider) {
|
|
2669
|
+
provider = await guidedProviderSetup();
|
|
2670
|
+
if (!provider) process.exit(1);
|
|
2671
|
+
}
|
|
2672
|
+
const client2 = createLLMClient(provider);
|
|
2673
|
+
const allTools = [...getAllToolDefs(), ...definitions];
|
|
2674
|
+
const builtinNames = getToolNames();
|
|
2675
|
+
const mcpConfig = loadMcpConfig();
|
|
2676
|
+
if (mcpConfig && Object.keys(mcpConfig.mcpServers).length > 0) {
|
|
2677
|
+
mcpManager = new McpManager();
|
|
2678
|
+
try {
|
|
2679
|
+
await mcpManager.startAll(mcpConfig);
|
|
2680
|
+
if (mcpManager.serverCount > 0) allTools.push(...mcpManager.getAllTools());
|
|
2681
|
+
} catch {
|
|
2682
|
+
}
|
|
2683
|
+
}
|
|
2684
|
+
const messages = [{ role: "system", content: buildSystemPrompt() }];
|
|
2685
|
+
console.log(welcome());
|
|
2686
|
+
console.log();
|
|
2687
|
+
const server = getServer();
|
|
2688
|
+
const auth = getAuth();
|
|
2689
|
+
const env = getActiveEnvironment();
|
|
2690
|
+
console.log(chalk12.gray(` ${provider.name} \xB7 ${provider.model}`));
|
|
2691
|
+
if (server && auth) {
|
|
2692
|
+
console.log(chalk12.gray(` ${env?.name ?? "XGEN"} \xB7 ${auth.username}@${server.replace("https://", "")}`));
|
|
2693
|
+
}
|
|
2694
|
+
console.log(chalk12.gray(` ${builtinNames.length} \uB3C4\uAD6C + ${definitions.length} XGEN${mcpManager?.serverCount ? ` + ${mcpManager.getAllTools().length} MCP` : ""}`));
|
|
2695
|
+
console.log(chalk12.gray(` /help \xB7 /connect \xB7 /env \xB7 /provider \xB7 /exit
|
|
2349
2696
|
`));
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2697
|
+
const rl = createInterface5({ input: process.stdin, output: process.stdout });
|
|
2698
|
+
const askUser = () => new Promise((resolve) => rl.question(chalk12.cyan(" \u276F "), (a) => resolve(a.trim())));
|
|
2699
|
+
process.on("SIGINT", () => {
|
|
2700
|
+
console.log(chalk12.gray("\n \u{1F44B}\n"));
|
|
2701
|
+
mcpManager?.stopAll();
|
|
2702
|
+
rl.close();
|
|
2703
|
+
process.exit(0);
|
|
2704
|
+
});
|
|
2705
|
+
while (true) {
|
|
2706
|
+
const input = await askUser();
|
|
2707
|
+
if (!input) continue;
|
|
2708
|
+
if (input === "/exit" || input === "exit") {
|
|
2709
|
+
console.log(chalk12.gray("\n \u{1F44B}\n"));
|
|
2710
|
+
mcpManager?.stopAll();
|
|
2711
|
+
rl.close();
|
|
2712
|
+
break;
|
|
2354
2713
|
}
|
|
2355
|
-
if (
|
|
2356
|
-
|
|
2714
|
+
if (input === "/help") {
|
|
2715
|
+
console.log(`
|
|
2716
|
+
${chalk12.bold("\uC2AC\uB798\uC2DC \uCEE4\uB9E8\uB4DC")}
|
|
2717
|
+
${chalk12.cyan("/connect")} XGEN \uC11C\uBC84 \uC5F0\uACB0 + \uB85C\uADF8\uC778
|
|
2718
|
+
${chalk12.cyan("/env")} \uD658\uACBD \uC804\uD658 (\uBCF8\uC0AC/\uC81C\uC8FC/\uB86F\uB370\uBAB0)
|
|
2719
|
+
${chalk12.cyan("/provider")} \uD504\uB85C\uBC14\uC774\uB354 \uBCC0\uACBD
|
|
2720
|
+
${chalk12.cyan("/tools")} \uC0AC\uC6A9 \uAC00\uB2A5\uD55C \uB3C4\uAD6C \uBAA9\uB85D
|
|
2721
|
+
${chalk12.cyan("/status")} \uD604\uC7AC \uC5F0\uACB0 \uC0C1\uD0DC
|
|
2722
|
+
${chalk12.cyan("/clear")} \uB300\uD654 \uCD08\uAE30\uD654
|
|
2723
|
+
${chalk12.cyan("/exit")} \uC885\uB8CC
|
|
2724
|
+
`);
|
|
2725
|
+
continue;
|
|
2357
2726
|
}
|
|
2358
|
-
if (
|
|
2359
|
-
|
|
2360
|
-
|
|
2727
|
+
if (input === "/clear") {
|
|
2728
|
+
messages.length = 0;
|
|
2729
|
+
messages.push({ role: "system", content: buildSystemPrompt() });
|
|
2730
|
+
console.log(chalk12.gray(" \uB300\uD654 \uCD08\uAE30\uD654\uB428.\n"));
|
|
2731
|
+
continue;
|
|
2361
2732
|
}
|
|
2362
|
-
|
|
2363
|
-
const
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
});
|
|
2373
|
-
console.log();
|
|
2374
|
-
printSuccess(`\uB85C\uADF8\uC778 \uC131\uACF5! ${chalk3.bold(result.username ?? email)}`);
|
|
2375
|
-
} else {
|
|
2376
|
-
printError(result.message || "\uB85C\uADF8\uC778 \uC2E4\uD328");
|
|
2377
|
-
process.exit(1);
|
|
2733
|
+
if (input === "/status") {
|
|
2734
|
+
const p = getDefaultProvider();
|
|
2735
|
+
const s = getServer();
|
|
2736
|
+
const a = getAuth();
|
|
2737
|
+
const e = getActiveEnvironment();
|
|
2738
|
+
console.log();
|
|
2739
|
+
console.log(` ${chalk12.bold("\uD504\uB85C\uBC14\uC774\uB354")} ${p ? `${p.name} \xB7 ${p.model}` : chalk12.red("\uBBF8\uC124\uC815")}`);
|
|
2740
|
+
console.log(` ${chalk12.bold("\uC11C\uBC84")} ${s && a ? `${a.username}@${s.replace("https://", "")}` : chalk12.red("\uBBF8\uC5F0\uACB0")}`);
|
|
2741
|
+
console.log(` ${chalk12.bold("\uD658\uACBD")} ${e?.name ?? "\uC5C6\uC74C"} (${getEnvironments().length}\uAC1C \uB4F1\uB85D)`);
|
|
2742
|
+
if (mcpManager?.serverCount) {
|
|
2743
|
+
console.log(` ${chalk12.bold("MCP")} ${mcpManager.getServerNames().join(", ")}`);
|
|
2378
2744
|
}
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
printError(`\uB85C\uADF8\uC778 \uC2E4\uD328: ${msg}`);
|
|
2382
|
-
process.exit(1);
|
|
2745
|
+
console.log();
|
|
2746
|
+
continue;
|
|
2383
2747
|
}
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
});
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
printError("\uB85C\uADF8\uC778\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. xgen login \uC2E4\uD589\uD558\uC138\uC694");
|
|
2394
|
-
process.exit(1);
|
|
2748
|
+
if (input === "/tools") {
|
|
2749
|
+
console.log(`
|
|
2750
|
+
${chalk12.bold("\uCF54\uB529")} ${builtinNames.join(", ")}`);
|
|
2751
|
+
console.log(` ${chalk12.bold("XGEN")} ${definitions.map((t) => t.function.name).join(", ")}`);
|
|
2752
|
+
if (mcpManager?.serverCount) {
|
|
2753
|
+
console.log(` ${chalk12.bold("MCP")} ${mcpManager.getAllTools().map((t) => t.function.name).join(", ")}`);
|
|
2754
|
+
}
|
|
2755
|
+
console.log();
|
|
2756
|
+
continue;
|
|
2395
2757
|
}
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2758
|
+
if (input === "/connect") {
|
|
2759
|
+
await connectServer();
|
|
2760
|
+
messages[0] = { role: "system", content: buildSystemPrompt() };
|
|
2761
|
+
continue;
|
|
2762
|
+
}
|
|
2763
|
+
if (input === "/env") {
|
|
2764
|
+
await switchEnv();
|
|
2765
|
+
messages[0] = { role: "system", content: buildSystemPrompt() };
|
|
2766
|
+
continue;
|
|
2767
|
+
}
|
|
2768
|
+
if (input === "/provider") {
|
|
2769
|
+
const { guidedProviderSetup: setup } = await Promise.resolve().then(() => (init_provider(), provider_exports));
|
|
2770
|
+
await setup();
|
|
2771
|
+
console.log(chalk12.gray(" \uD504\uB85C\uBC14\uC774\uB354 \uBCC0\uACBD\uB428. /exit \uD6C4 \uC7AC\uC2DC\uC791\uD558\uC138\uC694.\n"));
|
|
2772
|
+
continue;
|
|
2773
|
+
}
|
|
2774
|
+
messages.push({ role: "user", content: input });
|
|
2402
2775
|
try {
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
console.log(` ${chalk3.gray("\uAD8C\uD55C:")} ${chalk3.yellow("\uAD00\uB9AC\uC790")}`);
|
|
2409
|
-
}
|
|
2410
|
-
if (result.user_type) {
|
|
2411
|
-
console.log(` ${chalk3.gray("\uC720\uD615:")} ${result.user_type}`);
|
|
2412
|
-
}
|
|
2413
|
-
} else {
|
|
2414
|
-
console.log(` ${chalk3.gray("\uC0C1\uD0DC:")} ${chalk3.red("\uD1A0\uD070 \uB9CC\uB8CC")}`);
|
|
2415
|
-
}
|
|
2416
|
-
} catch {
|
|
2417
|
-
console.log(` ${chalk3.gray("\uC0C1\uD0DC:")} ${chalk3.yellow("\uAC80\uC99D \uBD88\uAC00 (\uC11C\uBC84 \uC5F0\uACB0 \uC2E4\uD328)")}`);
|
|
2776
|
+
await runLoop(client2, provider.model, messages, allTools);
|
|
2777
|
+
} catch (err) {
|
|
2778
|
+
console.log(chalk12.red(`
|
|
2779
|
+
\uC624\uB958: ${err.message}
|
|
2780
|
+
`));
|
|
2418
2781
|
}
|
|
2419
|
-
|
|
2420
|
-
});
|
|
2782
|
+
}
|
|
2421
2783
|
}
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
requireAuth();
|
|
2430
|
-
try {
|
|
2431
|
-
if (opts.detail) {
|
|
2432
|
-
const workflows = await getWorkflowListDetail();
|
|
2433
|
-
if (!workflows || workflows.length === 0) {
|
|
2434
|
-
console.log(chalk4.yellow("\n\uC6CC\uD06C\uD50C\uB85C\uC6B0\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.\n"));
|
|
2435
|
-
return;
|
|
2436
|
-
}
|
|
2437
|
-
printHeader(`\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D (${workflows.length}\uAC1C)`);
|
|
2438
|
-
console.log();
|
|
2439
|
-
printTable(
|
|
2440
|
-
["#", "ID", "\uC774\uB984", "\uBC30\uD3EC", "\uC5C5\uB370\uC774\uD2B8"],
|
|
2441
|
-
workflows.map((w, i) => [
|
|
2442
|
-
String(i + 1),
|
|
2443
|
-
(w.workflow_id ?? w.id ?? "-").slice(0, 12),
|
|
2444
|
-
truncate(w.workflow_name ?? "-", 30),
|
|
2445
|
-
w.is_deployed ? chalk4.green("\uBC30\uD3EC\uB428") : chalk4.gray("\uBBF8\uBC30\uD3EC"),
|
|
2446
|
-
formatDate(w.updated_at)
|
|
2447
|
-
])
|
|
2448
|
-
);
|
|
2449
|
-
} else {
|
|
2450
|
-
const workflows = await listWorkflows();
|
|
2451
|
-
if (!workflows || workflows.length === 0) {
|
|
2452
|
-
console.log(chalk4.yellow("\n\uC6CC\uD06C\uD50C\uB85C\uC6B0\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.\n"));
|
|
2453
|
-
return;
|
|
2454
|
-
}
|
|
2455
|
-
printHeader(`\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D (${workflows.length}\uAC1C)`);
|
|
2456
|
-
console.log();
|
|
2457
|
-
printTable(
|
|
2458
|
-
["#", "ID", "\uC774\uB984"],
|
|
2459
|
-
workflows.map((w, i) => [
|
|
2460
|
-
String(i + 1),
|
|
2461
|
-
(w.workflow_id ?? w.id ?? "-").slice(0, 12),
|
|
2462
|
-
w.workflow_name ?? "-"
|
|
2463
|
-
])
|
|
2464
|
-
);
|
|
2465
|
-
}
|
|
2466
|
-
console.log();
|
|
2467
|
-
} catch (err) {
|
|
2468
|
-
const msg = err.message;
|
|
2469
|
-
printError(`\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D \uC870\uD68C \uC2E4\uD328: ${msg}`);
|
|
2470
|
-
process.exit(1);
|
|
2471
|
-
}
|
|
2472
|
-
}
|
|
2473
|
-
|
|
2474
|
-
// src/commands/workflow/info.ts
|
|
2475
|
-
init_store();
|
|
2476
|
-
init_workflow();
|
|
2477
|
-
init_format();
|
|
2478
|
-
import chalk5 from "chalk";
|
|
2479
|
-
async function workflowInfo(workflowId) {
|
|
2480
|
-
requireAuth();
|
|
2481
|
-
try {
|
|
2482
|
-
const detail = await getWorkflowDetail(workflowId);
|
|
2483
|
-
printHeader(`\uC6CC\uD06C\uD50C\uB85C\uC6B0: ${detail.workflow_name ?? workflowId}`);
|
|
2484
|
-
console.log();
|
|
2485
|
-
printKeyValue("ID", detail.id);
|
|
2486
|
-
printKeyValue("\uC774\uB984", detail.workflow_name);
|
|
2487
|
-
printKeyValue("\uC124\uBA85", detail.description ?? "(\uC5C6\uC74C)");
|
|
2488
|
-
if (detail.nodes && Array.isArray(detail.nodes)) {
|
|
2489
|
-
console.log();
|
|
2490
|
-
console.log(chalk5.bold(" \uB178\uB4DC \uAD6C\uC131:"));
|
|
2491
|
-
for (const node of detail.nodes) {
|
|
2492
|
-
const label = node.data?.label ?? node.id;
|
|
2493
|
-
const type = node.data?.type ?? "unknown";
|
|
2494
|
-
console.log(` ${chalk5.cyan("\u2022")} ${label} ${chalk5.gray(`(${type})`)}`);
|
|
2495
|
-
}
|
|
2496
|
-
}
|
|
2497
|
-
if (detail.parameters && Object.keys(detail.parameters).length > 0) {
|
|
2498
|
-
console.log();
|
|
2499
|
-
console.log(chalk5.bold(" \uD30C\uB77C\uBBF8\uD130:"));
|
|
2500
|
-
for (const [key, val] of Object.entries(detail.parameters)) {
|
|
2501
|
-
console.log(` ${chalk5.gray(key)}: ${JSON.stringify(val)}`);
|
|
2502
|
-
}
|
|
2503
|
-
}
|
|
2504
|
-
console.log();
|
|
2505
|
-
} catch (err) {
|
|
2506
|
-
const msg = err.message;
|
|
2507
|
-
printError(`\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC870\uD68C \uC2E4\uD328: ${msg}`);
|
|
2508
|
-
process.exit(1);
|
|
2509
|
-
}
|
|
2510
|
-
}
|
|
2511
|
-
|
|
2512
|
-
// src/commands/workflow/run.ts
|
|
2513
|
-
init_store();
|
|
2514
|
-
init_workflow();
|
|
2515
|
-
import chalk7 from "chalk";
|
|
2516
|
-
import { randomUUID } from "crypto";
|
|
2517
|
-
|
|
2518
|
-
// src/utils/sse.ts
|
|
2519
|
-
async function parseSSEStream(stream, onEvent, onDone, onError) {
|
|
2520
|
-
let buffer = "";
|
|
2521
|
-
return new Promise((resolve, reject) => {
|
|
2522
|
-
stream.on("data", (chunk) => {
|
|
2523
|
-
buffer += chunk.toString();
|
|
2524
|
-
const parts = buffer.split("\n\n");
|
|
2525
|
-
buffer = parts.pop() ?? "";
|
|
2526
|
-
for (const part of parts) {
|
|
2527
|
-
const lines = part.split("\n");
|
|
2528
|
-
let data = "";
|
|
2529
|
-
for (const line of lines) {
|
|
2530
|
-
if (line.startsWith("data: ")) {
|
|
2531
|
-
data += line.slice(6);
|
|
2532
|
-
} else if (line.startsWith("data:")) {
|
|
2533
|
-
data += line.slice(5);
|
|
2534
|
-
}
|
|
2535
|
-
}
|
|
2536
|
-
if (!data) continue;
|
|
2537
|
-
try {
|
|
2538
|
-
const event = JSON.parse(data);
|
|
2539
|
-
onEvent(event);
|
|
2540
|
-
} catch {
|
|
2541
|
-
onEvent({ type: "token", content: data });
|
|
2542
|
-
}
|
|
2543
|
-
}
|
|
2544
|
-
});
|
|
2545
|
-
stream.on("end", () => {
|
|
2546
|
-
if (buffer.trim()) {
|
|
2547
|
-
const lines = buffer.split("\n");
|
|
2548
|
-
for (const line of lines) {
|
|
2549
|
-
if (line.startsWith("data: ")) {
|
|
2550
|
-
try {
|
|
2551
|
-
const event = JSON.parse(line.slice(6));
|
|
2552
|
-
onEvent(event);
|
|
2553
|
-
} catch {
|
|
2554
|
-
onEvent({ type: "token", content: line.slice(6) });
|
|
2555
|
-
}
|
|
2556
|
-
}
|
|
2557
|
-
}
|
|
2784
|
+
async function runLoop(client2, model, messages, tools2) {
|
|
2785
|
+
for (let i = 0; i < 20; i++) {
|
|
2786
|
+
let first = true;
|
|
2787
|
+
const result = await streamChat(client2, model, messages, tools2, (delta) => {
|
|
2788
|
+
if (first) {
|
|
2789
|
+
process.stdout.write(chalk12.green("\n ") + "");
|
|
2790
|
+
first = false;
|
|
2558
2791
|
}
|
|
2559
|
-
|
|
2560
|
-
resolve();
|
|
2561
|
-
});
|
|
2562
|
-
stream.on("error", (err) => {
|
|
2563
|
-
onError?.(err);
|
|
2564
|
-
reject(err);
|
|
2565
|
-
});
|
|
2566
|
-
});
|
|
2567
|
-
}
|
|
2568
|
-
|
|
2569
|
-
// src/commands/workflow/run.ts
|
|
2570
|
-
init_format();
|
|
2571
|
-
|
|
2572
|
-
// src/utils/markdown.ts
|
|
2573
|
-
import chalk6 from "chalk";
|
|
2574
|
-
var CODE_BLOCK_RE = /```(\w*)\n([\s\S]*?)```/g;
|
|
2575
|
-
var INLINE_CODE_RE = /`([^`]+)`/g;
|
|
2576
|
-
var BOLD_RE = /\*\*(.+?)\*\*/g;
|
|
2577
|
-
var HEADING_RE = /^(#{1,3})\s+(.+)$/gm;
|
|
2578
|
-
var LIST_RE = /^(\s*)[-*]\s+(.+)$/gm;
|
|
2579
|
-
var LINK_RE = /\[([^\]]+)\]\(([^)]+)\)/g;
|
|
2580
|
-
function renderMarkdown(text) {
|
|
2581
|
-
let result = text;
|
|
2582
|
-
result = result.replace(CODE_BLOCK_RE, (_match, lang, code) => {
|
|
2583
|
-
const trimmed = code.trimEnd();
|
|
2584
|
-
const header = lang ? chalk6.gray(` \u2500\u2500 ${lang} \u2500\u2500`) : chalk6.gray(" \u2500\u2500 code \u2500\u2500");
|
|
2585
|
-
const lines = trimmed.split("\n").map((l) => chalk6.white(` ${l}`)).join("\n");
|
|
2586
|
-
return `
|
|
2587
|
-
${header}
|
|
2588
|
-
${lines}
|
|
2589
|
-
${chalk6.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}
|
|
2590
|
-
`;
|
|
2591
|
-
});
|
|
2592
|
-
result = result.replace(INLINE_CODE_RE, (_m, code) => chalk6.cyan(`\`${code}\``));
|
|
2593
|
-
result = result.replace(BOLD_RE, (_m, text2) => chalk6.bold(text2));
|
|
2594
|
-
result = result.replace(HEADING_RE, (_m, hashes, text2) => {
|
|
2595
|
-
if (hashes.length === 1) return chalk6.bold.underline(text2);
|
|
2596
|
-
if (hashes.length === 2) return chalk6.bold(text2);
|
|
2597
|
-
return chalk6.bold.dim(text2);
|
|
2598
|
-
});
|
|
2599
|
-
result = result.replace(LIST_RE, (_m, indent, text2) => `${indent}${chalk6.cyan("\u2022")} ${text2}`);
|
|
2600
|
-
result = result.replace(LINK_RE, (_m, label, url) => `${chalk6.blue.underline(label)} ${chalk6.gray(`(${url})`)}`);
|
|
2601
|
-
return result;
|
|
2602
|
-
}
|
|
2603
|
-
|
|
2604
|
-
// src/commands/workflow/run.ts
|
|
2605
|
-
async function workflowRun(workflowId, input, opts) {
|
|
2606
|
-
const auth = requireAuth();
|
|
2607
|
-
let workflowName = workflowId;
|
|
2608
|
-
try {
|
|
2609
|
-
const detail = await getWorkflowDetail(workflowId);
|
|
2610
|
-
workflowName = detail.workflow_name ?? workflowId;
|
|
2611
|
-
} catch {
|
|
2612
|
-
}
|
|
2613
|
-
if (!input) {
|
|
2614
|
-
if (opts.interactive || !process.stdin.isTTY) {
|
|
2615
|
-
const { createInterface: createInterface8 } = await import("readline");
|
|
2616
|
-
const rl = createInterface8({ input: process.stdin, output: process.stdout });
|
|
2617
|
-
input = await new Promise((resolve) => {
|
|
2618
|
-
rl.question(chalk7.cyan("\uC785\uB825> "), (answer) => {
|
|
2619
|
-
rl.close();
|
|
2620
|
-
resolve(answer.trim());
|
|
2621
|
-
});
|
|
2622
|
-
});
|
|
2623
|
-
} else {
|
|
2624
|
-
printError("\uC785\uB825\uAC12\uC774 \uD544\uC694\uD569\uB2C8\uB2E4. \uC0AC\uC6A9\uBC95:");
|
|
2625
|
-
console.log(' xgen workflow run <id> "\uC785\uB825 \uD14D\uC2A4\uFFFD\uFFFD\uFFFD"');
|
|
2626
|
-
console.log(" xgen workflow run -i <id>");
|
|
2627
|
-
process.exit(1);
|
|
2628
|
-
}
|
|
2629
|
-
}
|
|
2630
|
-
if (!input) {
|
|
2631
|
-
printError("\uC785\uB825\uAC12\uC774 \uBE44\uC5B4\uC788\uC2B5\uB2C8\uB2E4");
|
|
2632
|
-
process.exit(1);
|
|
2633
|
-
}
|
|
2634
|
-
const interactionId = `cli_${randomUUID().slice(0, 8)}`;
|
|
2635
|
-
printHeader(`\uC2E4\uD589: ${workflowName}`);
|
|
2636
|
-
printInfo(`\uC785\uB825: ${input}`);
|
|
2637
|
-
console.log();
|
|
2638
|
-
try {
|
|
2639
|
-
const stream = await executeWorkflowStream({
|
|
2640
|
-
workflow_id: workflowId,
|
|
2641
|
-
workflow_name: workflowName,
|
|
2642
|
-
input_data: input,
|
|
2643
|
-
interaction_id: interactionId
|
|
2792
|
+
process.stdout.write(delta);
|
|
2644
2793
|
});
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
stream,
|
|
2649
|
-
(event) => {
|
|
2650
|
-
switch (event.type) {
|
|
2651
|
-
case "token":
|
|
2652
|
-
if (event.content) {
|
|
2653
|
-
if (!hasOutput) {
|
|
2654
|
-
hasOutput = true;
|
|
2655
|
-
console.log();
|
|
2656
|
-
}
|
|
2657
|
-
process.stdout.write(event.content);
|
|
2658
|
-
fullResponse += event.content;
|
|
2659
|
-
}
|
|
2660
|
-
break;
|
|
2661
|
-
case "log":
|
|
2662
|
-
if (opts.logs && event.content) {
|
|
2663
|
-
process.stderr.write(chalk7.gray(`[LOG] ${event.content}
|
|
2664
|
-
`));
|
|
2665
|
-
}
|
|
2666
|
-
break;
|
|
2667
|
-
case "node_status":
|
|
2668
|
-
if (opts.logs) {
|
|
2669
|
-
const nodeName = event.node_name ?? event.node_id ?? "?";
|
|
2670
|
-
const status = event.status ?? "?";
|
|
2671
|
-
process.stderr.write(
|
|
2672
|
-
chalk7.gray(`[\uB178\uB4DC] ${nodeName}: ${status}
|
|
2673
|
-
`)
|
|
2674
|
-
);
|
|
2675
|
-
}
|
|
2676
|
-
break;
|
|
2677
|
-
case "tool":
|
|
2678
|
-
if (opts.logs) {
|
|
2679
|
-
process.stderr.write(chalk7.gray(`[\uB3C4\uAD6C] ${JSON.stringify(event.data)}
|
|
2680
|
-
`));
|
|
2681
|
-
}
|
|
2682
|
-
break;
|
|
2683
|
-
case "complete":
|
|
2684
|
-
break;
|
|
2685
|
-
case "error":
|
|
2686
|
-
console.log();
|
|
2687
|
-
printError(event.error ?? event.content ?? "\uC54C \uC218 \uC5C6\uB294 \uC624\uB958");
|
|
2688
|
-
break;
|
|
2689
|
-
default:
|
|
2690
|
-
if (event.content) {
|
|
2691
|
-
if (!hasOutput) {
|
|
2692
|
-
process.stdout.write(chalk7.green("\uC751\uB2F5: "));
|
|
2693
|
-
hasOutput = true;
|
|
2694
|
-
}
|
|
2695
|
-
process.stdout.write(event.content);
|
|
2696
|
-
}
|
|
2697
|
-
}
|
|
2698
|
-
},
|
|
2699
|
-
() => {
|
|
2700
|
-
if (hasOutput) {
|
|
2701
|
-
console.log();
|
|
2702
|
-
if (fullResponse.includes("```") || fullResponse.includes("**")) {
|
|
2703
|
-
console.log(chalk7.gray("\u2500".repeat(40)));
|
|
2704
|
-
console.log(renderMarkdown(fullResponse));
|
|
2705
|
-
}
|
|
2706
|
-
}
|
|
2707
|
-
console.log();
|
|
2708
|
-
console.log(chalk7.gray(`\uC138\uC158: ${interactionId}`));
|
|
2709
|
-
},
|
|
2710
|
-
(err) => {
|
|
2711
|
-
console.log();
|
|
2712
|
-
printError(`\uC2A4\uD2B8\uB9AC\uBC0D \uC624\uB958: ${err.message}`);
|
|
2713
|
-
}
|
|
2714
|
-
);
|
|
2715
|
-
} catch (err) {
|
|
2716
|
-
const msg = err?.response?.data?.detail ?? err.message;
|
|
2717
|
-
printError(`\uC2E4\uD589 \uC2E4\uD328: ${msg}`);
|
|
2718
|
-
process.exit(1);
|
|
2719
|
-
}
|
|
2720
|
-
}
|
|
2721
|
-
|
|
2722
|
-
// src/commands/workflow/history.ts
|
|
2723
|
-
init_store();
|
|
2724
|
-
init_workflow();
|
|
2725
|
-
init_format();
|
|
2726
|
-
import chalk8 from "chalk";
|
|
2727
|
-
async function workflowHistory(workflowId, opts = {}) {
|
|
2728
|
-
requireAuth();
|
|
2729
|
-
const limit = opts.limit ?? 20;
|
|
2730
|
-
try {
|
|
2731
|
-
const logs = await getIOLogs(workflowId, limit);
|
|
2732
|
-
if (!logs || logs.length === 0) {
|
|
2733
|
-
console.log(chalk8.yellow("\n\uC2E4\uD589 \uC774\uB825\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.\n"));
|
|
2794
|
+
if (result.content) process.stdout.write("\n\n");
|
|
2795
|
+
if (result.toolCalls.length === 0) {
|
|
2796
|
+
if (result.content) messages.push({ role: "assistant", content: result.content });
|
|
2734
2797
|
return;
|
|
2735
2798
|
}
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
}
|
|
2768
|
-
|
|
2769
|
-
// src/commands/chat.ts
|
|
2770
|
-
init_store();
|
|
2771
|
-
init_workflow();
|
|
2772
|
-
import chalk9 from "chalk";
|
|
2773
|
-
import { createInterface as createInterface2 } from "readline";
|
|
2774
|
-
import { randomUUID as randomUUID2 } from "crypto";
|
|
2775
|
-
init_format();
|
|
2776
|
-
var CHAT_BANNER = `
|
|
2777
|
-
${chalk9.cyan("\u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E")}
|
|
2778
|
-
${chalk9.cyan("\u2502")} ${chalk9.white.bold("XGEN")} ${chalk9.gray("\u2014 \uC6CC\uD06C\uD50C\uB85C\uC6B0 AI \uD130\uBBF8\uB110")} ${chalk9.cyan("\u2502")}
|
|
2779
|
-
${chalk9.cyan("\u2502")} ${chalk9.gray("/help \uB3C4\uC6C0\uB9D0 /workflows \uC804\uD658 /exit")} ${chalk9.cyan("\u2502")}
|
|
2780
|
-
${chalk9.cyan("\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F")}`;
|
|
2781
|
-
function printHelp() {
|
|
2782
|
-
console.log(`
|
|
2783
|
-
${chalk9.bold("\uC2AC\uB798\uC2DC \uCEE4\uB9E8\uB4DC")}
|
|
2784
|
-
${chalk9.cyan("/workflows")} \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D \uBCF4\uAE30 & \uC804\uD658
|
|
2785
|
-
${chalk9.cyan("/switch")} \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBC88\uD638\uB85C \uC804\uD658 (\uC608: /switch 3)
|
|
2786
|
-
${chalk9.cyan("/history")} \uD604\uC7AC \uC138\uC158 \uB300\uD654 \uC774\uB825
|
|
2787
|
-
${chalk9.cyan("/clear")} \uD654\uBA74 \uC9C0\uC6B0\uAE30
|
|
2788
|
-
${chalk9.cyan("/info")} \uD604\uC7AC \uC5F0\uACB0 \uC815\uBCF4
|
|
2789
|
-
${chalk9.cyan("/help")} \uC774 \uB3C4\uC6C0\uB9D0
|
|
2790
|
-
${chalk9.cyan("/exit")} \uC885\uB8CC (Ctrl+C\uB3C4 \uAC00\uB2A5)
|
|
2791
|
-
`);
|
|
2792
|
-
}
|
|
2793
|
-
async function promptLine(rl, promptStr) {
|
|
2794
|
-
return new Promise((resolve) => {
|
|
2795
|
-
rl.question(promptStr, (answer) => resolve(answer));
|
|
2796
|
-
});
|
|
2797
|
-
}
|
|
2798
|
-
async function chat(workflowId) {
|
|
2799
|
-
const auth = requireAuth();
|
|
2800
|
-
const server = getServer();
|
|
2801
|
-
let workflows = [];
|
|
2802
|
-
try {
|
|
2803
|
-
workflows = await listWorkflows();
|
|
2804
|
-
} catch {
|
|
2805
|
-
printError("\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D\uC744 \uBD88\uB7EC\uC62C \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
|
|
2806
|
-
process.exit(1);
|
|
2807
|
-
}
|
|
2808
|
-
if (workflows.length === 0) {
|
|
2809
|
-
printError("\uC0AC\uC6A9 \uAC00\uB2A5\uD55C \uC6CC\uD06C\uD50C\uB85C\uC6B0\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4");
|
|
2810
|
-
process.exit(1);
|
|
2799
|
+
messages.push({
|
|
2800
|
+
role: "assistant",
|
|
2801
|
+
content: result.content || null,
|
|
2802
|
+
tool_calls: result.toolCalls.map((tc) => ({
|
|
2803
|
+
id: tc.id,
|
|
2804
|
+
type: "function",
|
|
2805
|
+
function: { name: tc.name, arguments: tc.arguments }
|
|
2806
|
+
}))
|
|
2807
|
+
});
|
|
2808
|
+
for (const tc of result.toolCalls) {
|
|
2809
|
+
let args;
|
|
2810
|
+
try {
|
|
2811
|
+
args = JSON.parse(tc.arguments);
|
|
2812
|
+
} catch {
|
|
2813
|
+
args = {};
|
|
2814
|
+
}
|
|
2815
|
+
const shortArgs = Object.entries(args).map(([k, v]) => {
|
|
2816
|
+
const s = String(v);
|
|
2817
|
+
return `${k}=${s.length > 30 ? s.slice(0, 30) + "\u2026" : s}`;
|
|
2818
|
+
}).join(" ");
|
|
2819
|
+
console.log(chalk12.gray(` \u2699 ${chalk12.white(tc.name)} ${shortArgs}`));
|
|
2820
|
+
let toolResult;
|
|
2821
|
+
if (isXgenTool(tc.name)) {
|
|
2822
|
+
toolResult = await execute8(tc.name, args);
|
|
2823
|
+
} else if (mcpManager?.isMcpTool(tc.name)) {
|
|
2824
|
+
toolResult = await mcpManager.callTool(tc.name, args);
|
|
2825
|
+
} else {
|
|
2826
|
+
toolResult = await executeTool(tc.name, args);
|
|
2827
|
+
}
|
|
2828
|
+
const truncated = toolResult.length > 4e3 ? toolResult.slice(0, 4e3) + "\n\u2026(truncated)" : toolResult;
|
|
2829
|
+
messages.push({ role: "tool", tool_call_id: tc.id, content: truncated });
|
|
2830
|
+
}
|
|
2811
2831
|
}
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2832
|
+
console.log(chalk12.yellow("\n \uCD5C\uB300 \uBC18\uBCF5 \uD69F\uC218 \uB3C4\uB2EC.\n"));
|
|
2833
|
+
}
|
|
2834
|
+
async function connectServer() {
|
|
2835
|
+
const { setServer: setServer2, setAuth: setAuth2 } = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
2836
|
+
const { addEnvironment: addEnvironment2 } = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
2837
|
+
console.log(chalk12.bold("\n XGEN \uC11C\uBC84 \uC5F0\uACB0\n"));
|
|
2838
|
+
const presets = [
|
|
2839
|
+
{ id: "hq", name: "\uBCF8\uC0AC", url: "https://xgen.x2bee.com", email: "admin@plateer.com" },
|
|
2840
|
+
{ id: "jeju", name: "\uC81C\uC8FC", url: "https://jeju-xgen.x2bee.com", email: "admin@plateer.com" },
|
|
2841
|
+
{ id: "lotte", name: "\uB86F\uB370\uBAB0", url: "https://lotteimall-xgen.x2bee.com" }
|
|
2842
|
+
];
|
|
2843
|
+
presets.forEach((p, i) => console.log(` ${chalk12.cyan(`${i + 1}.`)} ${p.name} ${chalk12.gray(p.url)}`));
|
|
2844
|
+
console.log(` ${chalk12.cyan("4.")} \uC9C1\uC811 \uC785\uB825`);
|
|
2845
|
+
console.log();
|
|
2846
|
+
const choice = await ask(chalk12.cyan(" \u276F "));
|
|
2847
|
+
let url;
|
|
2848
|
+
let email;
|
|
2849
|
+
const ci = parseInt(choice) - 1;
|
|
2850
|
+
if (ci >= 0 && ci < presets.length) {
|
|
2851
|
+
url = presets[ci].url;
|
|
2852
|
+
email = presets[ci].email;
|
|
2853
|
+
addEnvironment2({ ...presets[ci], description: presets[ci].name });
|
|
2816
2854
|
} else {
|
|
2817
|
-
|
|
2818
|
-
|
|
2855
|
+
url = await ask(chalk12.white(" URL: "));
|
|
2856
|
+
if (!url) return;
|
|
2857
|
+
}
|
|
2858
|
+
setServer2(url);
|
|
2859
|
+
console.log(chalk12.green(` \u2713 ${url}
|
|
2860
|
+
`));
|
|
2861
|
+
const inputEmail = email || await ask(chalk12.white(" \uC774\uBA54\uC77C: "));
|
|
2862
|
+
const pw = await ask(chalk12.white(" \uBE44\uBC00\uBC88\uD638: "));
|
|
2863
|
+
if (!inputEmail || !pw) return;
|
|
2864
|
+
try {
|
|
2865
|
+
const { apiLogin: apiLogin2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
|
|
2866
|
+
const result = await apiLogin2(inputEmail, pw);
|
|
2867
|
+
if (result.success && result.access_token) {
|
|
2868
|
+
setAuth2({ accessToken: result.access_token, refreshToken: result.refresh_token ?? "", userId: result.user_id ?? "", username: result.username ?? "", isAdmin: false, expiresAt: null });
|
|
2869
|
+
console.log(chalk12.green(` \u2713 ${result.username} \uB85C\uADF8\uC778\uB428
|
|
2819
2870
|
`));
|
|
2820
|
-
console.log(chalk9.bold(" \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC120\uD0DD:\n"));
|
|
2821
|
-
workflows.forEach((w, i) => {
|
|
2822
|
-
console.log(` ${chalk9.cyan(String(i + 1).padStart(3))} ${w.workflow_name}`);
|
|
2823
|
-
});
|
|
2824
|
-
console.log();
|
|
2825
|
-
const rl2 = createInterface2({ input: process.stdin, output: process.stdout });
|
|
2826
|
-
const answer = await promptLine(rl2, chalk9.cyan(" \uBC88\uD638> "));
|
|
2827
|
-
rl2.close();
|
|
2828
|
-
const idx = parseInt(answer.trim()) - 1;
|
|
2829
|
-
if (isNaN(idx) || idx < 0 || idx >= workflows.length) {
|
|
2830
|
-
current = workflows[0];
|
|
2831
2871
|
} else {
|
|
2832
|
-
|
|
2872
|
+
console.log(chalk12.red(` \u2717 ${result.message}
|
|
2873
|
+
`));
|
|
2833
2874
|
}
|
|
2875
|
+
} catch (err) {
|
|
2876
|
+
console.log(chalk12.red(` \u2717 ${err.message}
|
|
2877
|
+
`));
|
|
2834
2878
|
}
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
const
|
|
2879
|
+
}
|
|
2880
|
+
async function switchEnv() {
|
|
2881
|
+
const { getEnvironments: getEnvs, switchEnvironment: switchEnvironment2 } = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
2882
|
+
const envs = getEnvs();
|
|
2883
|
+
if (!envs.length) {
|
|
2884
|
+
console.log(chalk12.gray("\n \uD658\uACBD \uC5C6\uC74C. /connect\uB85C \uBA3C\uC800 \uC5F0\uACB0\uD558\uC138\uC694.\n"));
|
|
2885
|
+
return;
|
|
2886
|
+
}
|
|
2887
|
+
const active = getActiveEnvironment();
|
|
2838
2888
|
console.log();
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
console.log(chalk9.gray(" \uBA54\uC2DC\uC9C0\uB97C \uC785\uB825\uD558\uC138\uC694. /help \uB85C \uB3C4\uC6C0\uB9D0.\n"));
|
|
2843
|
-
const rl = createInterface2({
|
|
2844
|
-
input: process.stdin,
|
|
2845
|
-
output: process.stdout
|
|
2889
|
+
envs.forEach((e, i) => {
|
|
2890
|
+
const mark = e.id === active?.id ? chalk12.green("\u25CF ") : " ";
|
|
2891
|
+
console.log(` ${mark}${chalk12.cyan(`${i + 1}.`)} ${e.name} ${chalk12.gray(e.url)}`);
|
|
2846
2892
|
});
|
|
2847
|
-
|
|
2848
|
-
const
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
const [cmd, ...args] = input.slice(1).split(" ");
|
|
2853
|
-
switch (cmd.toLowerCase()) {
|
|
2854
|
-
case "exit":
|
|
2855
|
-
case "quit":
|
|
2856
|
-
case "q":
|
|
2857
|
-
console.log(chalk9.gray("\n \uC885\uB8CC\uD569\uB2C8\uB2E4.\n"));
|
|
2858
|
-
rl.close();
|
|
2859
|
-
process.exit(0);
|
|
2860
|
-
break;
|
|
2861
|
-
case "help":
|
|
2862
|
-
case "h":
|
|
2863
|
-
printHelp();
|
|
2864
|
-
break;
|
|
2865
|
-
case "clear":
|
|
2866
|
-
case "cls":
|
|
2867
|
-
console.clear();
|
|
2868
|
-
console.log(chalk9.white.bold(` ${current.workflow_name}`));
|
|
2869
|
-
console.log(chalk9.cyan("\u2500".repeat(42)));
|
|
2870
|
-
break;
|
|
2871
|
-
case "workflows":
|
|
2872
|
-
case "wf":
|
|
2873
|
-
console.log();
|
|
2874
|
-
workflows.forEach((w, i) => {
|
|
2875
|
-
const marker = w.id === current.id ? chalk9.green("\u25B8") : " ";
|
|
2876
|
-
console.log(` ${marker} ${chalk9.cyan(String(i + 1).padStart(2))} ${w.workflow_name}`);
|
|
2877
|
-
});
|
|
2878
|
-
console.log(chalk9.gray("\n /switch <\uBC88\uD638> \uB85C \uC804\uD658\n"));
|
|
2879
|
-
break;
|
|
2880
|
-
case "switch":
|
|
2881
|
-
case "sw": {
|
|
2882
|
-
const num = parseInt(args[0]);
|
|
2883
|
-
if (isNaN(num) || num < 1 || num > workflows.length) {
|
|
2884
|
-
console.log(chalk9.yellow(` 1~${workflows.length} \uC0AC\uC774 \uBC88\uD638\uB97C \uC785\uB825\uD558\uC138\uC694`));
|
|
2885
|
-
} else {
|
|
2886
|
-
current = workflows[num - 1];
|
|
2887
|
-
turnCount = 0;
|
|
2888
|
-
history.length = 0;
|
|
2889
|
-
console.log(chalk9.green(`
|
|
2890
|
-
\uC804\uD658: ${current.workflow_name}
|
|
2893
|
+
console.log();
|
|
2894
|
+
const ci = parseInt(await ask(chalk12.cyan(" \u276F "))) - 1;
|
|
2895
|
+
if (ci >= 0 && ci < envs.length) {
|
|
2896
|
+
switchEnvironment2(envs[ci].id);
|
|
2897
|
+
console.log(chalk12.green(` \u2713 ${envs[ci].name}
|
|
2891
2898
|
`));
|
|
2892
|
-
|
|
2893
|
-
break;
|
|
2894
|
-
}
|
|
2895
|
-
case "history":
|
|
2896
|
-
case "hist":
|
|
2897
|
-
if (history.length === 0) {
|
|
2898
|
-
console.log(chalk9.gray(" \uB300\uD654 \uC774\uB825\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.\n"));
|
|
2899
|
-
} else {
|
|
2900
|
-
console.log();
|
|
2901
|
-
for (const h of history) {
|
|
2902
|
-
const label = h.role === "user" ? chalk9.cyan("\uB098") : chalk9.green("AI");
|
|
2903
|
-
const text = h.content.length > 80 ? h.content.slice(0, 80) + "..." : h.content;
|
|
2904
|
-
console.log(` ${label}: ${text}`);
|
|
2905
|
-
}
|
|
2906
|
-
console.log();
|
|
2907
|
-
}
|
|
2908
|
-
break;
|
|
2909
|
-
case "info":
|
|
2910
|
-
console.log(`
|
|
2911
|
-
${chalk9.gray("\uC11C\uBC84:")} ${server}
|
|
2912
|
-
${chalk9.gray("\uC0AC\uC6A9\uC790:")} ${auth.username}
|
|
2913
|
-
${chalk9.gray("\uC6CC\uD06C\uD50C\uB85C\uC6B0:")} ${current.workflow_name}
|
|
2914
|
-
${chalk9.gray("\uC138\uC158:")} ${sessionId}
|
|
2915
|
-
${chalk9.gray("\uD134:")} ${turnCount}
|
|
2916
|
-
`);
|
|
2917
|
-
break;
|
|
2918
|
-
default:
|
|
2919
|
-
console.log(chalk9.yellow(` \uC54C \uC218 \uC5C6\uB294 \uCEE4\uB9E8\uB4DC: /${cmd}. /help \uCC38\uACE0`));
|
|
2920
|
-
}
|
|
2921
|
-
rl.prompt();
|
|
2922
|
-
return;
|
|
2923
|
-
}
|
|
2924
|
-
turnCount++;
|
|
2925
|
-
const interactionId = `${sessionId}_t${turnCount}`;
|
|
2926
|
-
history.push({ role: "user", content: input });
|
|
2927
|
-
process.stdout.write(chalk9.gray(" thinking..."));
|
|
2928
|
-
try {
|
|
2929
|
-
const stream = await executeWorkflowStream({
|
|
2930
|
-
workflow_id: current.id,
|
|
2931
|
-
workflow_name: current.workflow_name,
|
|
2932
|
-
input_data: input,
|
|
2933
|
-
interaction_id: interactionId
|
|
2934
|
-
});
|
|
2935
|
-
process.stdout.write("\r" + " ".repeat(20) + "\r");
|
|
2936
|
-
let fullResponse = "";
|
|
2937
|
-
let hasOutput = false;
|
|
2938
|
-
await parseSSEStream(
|
|
2939
|
-
stream,
|
|
2940
|
-
(event) => {
|
|
2941
|
-
if ((event.type === "token" || !event.type) && event.content) {
|
|
2942
|
-
if (!hasOutput) {
|
|
2943
|
-
hasOutput = true;
|
|
2944
|
-
console.log();
|
|
2945
|
-
}
|
|
2946
|
-
process.stdout.write(event.content);
|
|
2947
|
-
fullResponse += event.content;
|
|
2948
|
-
} else if (event.type === "error") {
|
|
2949
|
-
process.stdout.write("\r" + " ".repeat(20) + "\r");
|
|
2950
|
-
printError(event.error ?? event.content ?? "\uC624\uB958");
|
|
2951
|
-
}
|
|
2952
|
-
},
|
|
2953
|
-
() => {
|
|
2954
|
-
if (hasOutput) {
|
|
2955
|
-
console.log();
|
|
2956
|
-
console.log();
|
|
2957
|
-
}
|
|
2958
|
-
if (fullResponse) {
|
|
2959
|
-
history.push({ role: "assistant", content: fullResponse });
|
|
2960
|
-
}
|
|
2961
|
-
},
|
|
2962
|
-
(err) => {
|
|
2963
|
-
process.stdout.write("\r" + " ".repeat(20) + "\r");
|
|
2964
|
-
printError(`\uC2A4\uD2B8\uB9AC\uBC0D \uC624\uB958: ${err.message}`);
|
|
2965
|
-
}
|
|
2966
|
-
);
|
|
2967
|
-
} catch (err) {
|
|
2968
|
-
process.stdout.write("\r" + " ".repeat(20) + "\r");
|
|
2969
|
-
const msg = err?.response?.data?.detail ?? err.message;
|
|
2970
|
-
printError(`\uC2E4\uD589 \uC2E4\uD328: ${msg}`);
|
|
2971
|
-
}
|
|
2972
|
-
rl.prompt();
|
|
2973
|
-
};
|
|
2974
|
-
rl.setPrompt(getPrompt());
|
|
2975
|
-
rl.prompt();
|
|
2976
|
-
rl.on("line", (line) => {
|
|
2977
|
-
processInput(line).then(() => {
|
|
2978
|
-
});
|
|
2979
|
-
});
|
|
2980
|
-
rl.on("close", () => {
|
|
2981
|
-
console.log(chalk9.gray("\n \uC885\uB8CC\uD569\uB2C8\uB2E4.\n"));
|
|
2982
|
-
process.exit(0);
|
|
2983
|
-
});
|
|
2984
|
-
process.on("SIGINT", () => {
|
|
2985
|
-
console.log(chalk9.gray("\n \uC885\uB8CC\uD569\uB2C8\uB2E4.\n"));
|
|
2986
|
-
process.exit(0);
|
|
2987
|
-
});
|
|
2899
|
+
}
|
|
2988
2900
|
}
|
|
2989
|
-
function
|
|
2990
|
-
program2.command("
|
|
2901
|
+
function registerAgentCommand(program2) {
|
|
2902
|
+
program2.command("agent").description("OPEN XGEN AI \uC5D0\uC774\uC804\uD2B8").action(async () => {
|
|
2903
|
+
await agentRepl();
|
|
2904
|
+
});
|
|
2991
2905
|
}
|
|
2992
2906
|
|
|
2993
|
-
// src/index.ts
|
|
2994
|
-
init_provider();
|
|
2995
|
-
init_agent();
|
|
2996
|
-
|
|
2997
2907
|
// src/commands/doc.ts
|
|
2998
2908
|
init_store();
|
|
2999
2909
|
init_document();
|
|
@@ -3149,42 +3059,42 @@ ${result.answer}
|
|
|
3149
3059
|
|
|
3150
3060
|
// src/index.ts
|
|
3151
3061
|
var VERSION = "0.3.0";
|
|
3152
|
-
var LOGO =
|
|
3062
|
+
var LOGO = chalk15.cyan(`
|
|
3153
3063
|
\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588 \u2588\u2588
|
|
3154
3064
|
\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588
|
|
3155
3065
|
\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588
|
|
3156
3066
|
\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588
|
|
3157
3067
|
\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588
|
|
3158
|
-
`) +
|
|
3068
|
+
`) + chalk15.white.bold(`
|
|
3159
3069
|
\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588 \u2588\u2588
|
|
3160
3070
|
\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588
|
|
3161
3071
|
\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588
|
|
3162
3072
|
\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588
|
|
3163
3073
|
\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588
|
|
3164
|
-
`) +
|
|
3074
|
+
`) + chalk15.gray(` v${VERSION}
|
|
3165
3075
|
`);
|
|
3166
3076
|
var BANNER = LOGO;
|
|
3167
3077
|
var program = new Command();
|
|
3168
3078
|
program.name("xgen").description("OPEN XGEN \u2014 AI Coding Agent + XGEN Platform CLI").version(VERSION).addHelpText("before", BANNER).addHelpText(
|
|
3169
3079
|
"after",
|
|
3170
3080
|
`
|
|
3171
|
-
${
|
|
3172
|
-
${
|
|
3173
|
-
${
|
|
3174
|
-
${
|
|
3175
|
-
${
|
|
3081
|
+
${chalk15.bold("\uC2DC\uC791\uD558\uAE30:")}
|
|
3082
|
+
${chalk15.cyan("xgen provider add")} AI \uD504\uB85C\uBC14\uC774\uB354 \uC124\uC815
|
|
3083
|
+
${chalk15.cyan("xgen agent")} AI \uCF54\uB529 \uC5D0\uC774\uC804\uD2B8
|
|
3084
|
+
${chalk15.cyan("xgen config set-server")} <url> XGEN \uC11C\uBC84 \uC5F0\uACB0
|
|
3085
|
+
${chalk15.cyan("xgen login")} \uC11C\uBC84 \uB85C\uADF8\uC778
|
|
3176
3086
|
|
|
3177
|
-
${
|
|
3178
|
-
${
|
|
3179
|
-
${
|
|
3180
|
-
${
|
|
3087
|
+
${chalk15.bold("AI \uC5D0\uC774\uC804\uD2B8:")}
|
|
3088
|
+
${chalk15.cyan("xgen agent")} \uCF54\uB529 \uC5D0\uC774\uC804\uD2B8 (\uD30C\uC77C, \uD130\uBBF8\uB110, \uAC80\uC0C9)
|
|
3089
|
+
${chalk15.cyan("xgen provider ls")} \uD504\uB85C\uBC14\uC774\uB354 \uBAA9\uB85D
|
|
3090
|
+
${chalk15.cyan("xgen provider add")} \uD504\uB85C\uBC14\uC774\uB354 \uCD94\uAC00
|
|
3181
3091
|
|
|
3182
|
-
${
|
|
3183
|
-
${
|
|
3184
|
-
${
|
|
3185
|
-
${
|
|
3186
|
-
${
|
|
3187
|
-
${
|
|
3092
|
+
${chalk15.bold("XGEN \uD50C\uB7AB\uD3FC:")}
|
|
3093
|
+
${chalk15.cyan("xgen chat")} \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uB300\uD654
|
|
3094
|
+
${chalk15.cyan("xgen wf ls")} \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D
|
|
3095
|
+
${chalk15.cyan("xgen wf run")} <id> "\uC9C8\uBB38" \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC2E4\uD589
|
|
3096
|
+
${chalk15.cyan("xgen doc ls")} \uBB38\uC11C \uBAA9\uB85D
|
|
3097
|
+
${chalk15.cyan("xgen ont query")} "\uC9C8\uBB38" \uC628\uD1A8\uB85C\uC9C0 \uC9C8\uC758
|
|
3188
3098
|
`
|
|
3189
3099
|
);
|
|
3190
3100
|
registerConfigCommand(program);
|
|
@@ -3197,15 +3107,15 @@ registerDocCommand(program);
|
|
|
3197
3107
|
registerOntologyCommand(program);
|
|
3198
3108
|
if (process.argv.length <= 2) {
|
|
3199
3109
|
if (process.stdin.isTTY) {
|
|
3200
|
-
Promise.resolve().then(() => (
|
|
3201
|
-
({
|
|
3202
|
-
console.error(
|
|
3110
|
+
Promise.resolve().then(() => (init_tui(), tui_exports)).then(
|
|
3111
|
+
({ startTui: startTui2 }) => startTui2().catch((err) => {
|
|
3112
|
+
console.error(chalk15.red(`\uC624\uB958: ${err.message}`));
|
|
3203
3113
|
process.exit(1);
|
|
3204
3114
|
})
|
|
3205
3115
|
);
|
|
3206
3116
|
} else {
|
|
3207
3117
|
agentRepl().catch((err) => {
|
|
3208
|
-
console.error(
|
|
3118
|
+
console.error(chalk15.red(`\uC624\uB958: ${err.message}`));
|
|
3209
3119
|
process.exit(1);
|
|
3210
3120
|
});
|
|
3211
3121
|
}
|