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