openxgen 0.6.0 → 1.0.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
@@ -400,6 +400,10 @@ async function executeWorkflowStream(request) {
400
400
  }
401
401
  async function executeWorkflow(request) {
402
402
  const client2 = getClient();
403
+ if (request.deploy_key) {
404
+ const res2 = await client2.post("/api/workflow/execute/deploy/result", request);
405
+ return res2.data;
406
+ }
403
407
  const res = await client2.post("/api/workflow/execute/based_id", request);
404
408
  return res.data;
405
409
  }
@@ -422,622 +426,156 @@ var init_workflow = __esm({
422
426
  }
423
427
  });
424
428
 
425
- // src/utils/sse.ts
426
- async function parseSSEStream(stream, onEvent, onDone, onError) {
427
- let buffer = "";
428
- return new Promise((resolve, reject) => {
429
- stream.on("data", (chunk) => {
430
- buffer += chunk.toString();
431
- const parts = buffer.split("\n\n");
432
- buffer = parts.pop() ?? "";
433
- for (const part of parts) {
434
- const lines = part.split("\n");
435
- let data = "";
436
- for (const line of lines) {
437
- if (line.startsWith("data: ")) {
438
- data += line.slice(6);
439
- } else if (line.startsWith("data:")) {
440
- data += line.slice(5);
441
- }
442
- }
443
- if (!data) continue;
444
- try {
445
- const event = JSON.parse(data);
446
- onEvent(event);
447
- } catch {
448
- onEvent({ type: "token", content: data });
449
- }
450
- }
451
- });
452
- stream.on("end", () => {
453
- if (buffer.trim()) {
454
- const lines = buffer.split("\n");
455
- for (const line of lines) {
456
- if (line.startsWith("data: ")) {
457
- try {
458
- const event = JSON.parse(line.slice(6));
459
- onEvent(event);
460
- } catch {
461
- onEvent({ type: "token", content: line.slice(6) });
462
- }
463
- }
464
- }
465
- }
466
- onDone?.();
467
- resolve();
468
- });
469
- stream.on("error", (err) => {
470
- onError?.(err);
471
- reject(err);
472
- });
429
+ // src/utils/ui.ts
430
+ import chalk10 from "chalk";
431
+ import { createInterface as createInterface3 } from "readline";
432
+ function box(lines, color = "cyan") {
433
+ const c = chalk10[color];
434
+ const inner = W - 4;
435
+ const top = c(" \u256D" + "\u2500".repeat(inner) + "\u256E");
436
+ const bot = c(" \u2570" + "\u2500".repeat(inner) + "\u256F");
437
+ const body = lines.map((line) => {
438
+ const clean = line.replace(/\x1b\[[0-9;]*m/g, "");
439
+ const pad = Math.max(0, inner - clean.length);
440
+ return c(" \u2502 ") + line + " ".repeat(pad) + c(" \u2502");
473
441
  });
442
+ return [top, ...body, bot].join("\n");
474
443
  }
475
- var init_sse = __esm({
476
- "src/utils/sse.ts"() {
477
- "use strict";
478
- }
479
- });
480
-
481
- // src/utils/markdown.ts
482
- import chalk6 from "chalk";
483
- function renderMarkdown(text) {
484
- let result = text;
485
- result = result.replace(CODE_BLOCK_RE, (_match, lang, code) => {
486
- const trimmed = code.trimEnd();
487
- const header = lang ? chalk6.gray(` \u2500\u2500 ${lang} \u2500\u2500`) : chalk6.gray(" \u2500\u2500 code \u2500\u2500");
488
- const lines = trimmed.split("\n").map((l) => chalk6.white(` ${l}`)).join("\n");
489
- return `
490
- ${header}
491
- ${lines}
492
- ${chalk6.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}
493
- `;
494
- });
495
- result = result.replace(INLINE_CODE_RE, (_m, code) => chalk6.cyan(`\`${code}\``));
496
- result = result.replace(BOLD_RE, (_m, text2) => chalk6.bold(text2));
497
- result = result.replace(HEADING_RE, (_m, hashes, text2) => {
498
- if (hashes.length === 1) return chalk6.bold.underline(text2);
499
- if (hashes.length === 2) return chalk6.bold(text2);
500
- return chalk6.bold.dim(text2);
444
+ function ask(question) {
445
+ return new Promise((resolve) => {
446
+ const rl = createInterface3({ input: process.stdin, output: process.stdout });
447
+ rl.question(question, (answer) => {
448
+ rl.close();
449
+ resolve(answer.trim());
450
+ });
501
451
  });
502
- result = result.replace(LIST_RE, (_m, indent, text2) => `${indent}${chalk6.cyan("\u2022")} ${text2}`);
503
- result = result.replace(LINK_RE, (_m, label, url) => `${chalk6.blue.underline(label)} ${chalk6.gray(`(${url})`)}`);
504
- return result;
505
452
  }
506
- var CODE_BLOCK_RE, INLINE_CODE_RE, BOLD_RE, HEADING_RE, LIST_RE, LINK_RE;
507
- var init_markdown = __esm({
508
- "src/utils/markdown.ts"() {
453
+ function welcome() {
454
+ const logo = chalk10.cyan(`
455
+ \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588 \u2588\u2588
456
+ \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588
457
+ \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588
458
+ \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588
459
+ \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588`) + chalk10.white.bold(`
460
+ \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588 \u2588\u2588
461
+ \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588
462
+ \u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588
463
+ \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588
464
+ \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588`);
465
+ return logo;
466
+ }
467
+ var W;
468
+ var init_ui = __esm({
469
+ "src/utils/ui.ts"() {
509
470
  "use strict";
510
- CODE_BLOCK_RE = /```(\w*)\n([\s\S]*?)```/g;
511
- INLINE_CODE_RE = /`([^`]+)`/g;
512
- BOLD_RE = /\*\*(.+?)\*\*/g;
513
- HEADING_RE = /^(#{1,3})\s+(.+)$/gm;
514
- LIST_RE = /^(\s*)[-*]\s+(.+)$/gm;
515
- LINK_RE = /\[([^\]]+)\]\(([^)]+)\)/g;
471
+ W = Math.min(process.stdout.columns || 60, 70);
516
472
  }
517
473
  });
518
474
 
519
- // src/commands/workflow/run.ts
520
- var run_exports = {};
521
- __export(run_exports, {
522
- workflowRun: () => workflowRun
475
+ // src/commands/provider.ts
476
+ var provider_exports = {};
477
+ __export(provider_exports, {
478
+ guidedProviderSetup: () => guidedProviderSetup,
479
+ registerProviderCommand: () => registerProviderCommand
523
480
  });
524
- import chalk7 from "chalk";
525
- import { randomUUID } from "crypto";
526
- async function workflowRun(workflowId, input, opts) {
527
- const auth = requireAuth();
528
- let workflowName = workflowId;
529
- try {
530
- const detail = await getWorkflowDetail(workflowId);
531
- workflowName = detail.workflow_name ?? workflowId;
532
- } catch {
481
+ import chalk11 from "chalk";
482
+ import OpenAI from "openai";
483
+ function detectEnvKey(preset) {
484
+ if (!preset.envKey) return null;
485
+ return process.env[preset.envKey] ?? null;
486
+ }
487
+ async function guidedProviderSetup() {
488
+ console.log();
489
+ console.log(box(["OPEN XGEN \u2014 \uD504\uB85C\uBC14\uC774\uB354 \uC124\uC815", "", chalk11.gray("AI \uC5D0\uC774\uC804\uD2B8\uC5D0 \uC0AC\uC6A9\uD560 LLM\uC744 \uC120\uD0DD\uD558\uC138\uC694.")]));
490
+ console.log();
491
+ console.log(chalk11.bold(" \uD504\uB85C\uBC14\uC774\uB354 \uC120\uD0DD:\n"));
492
+ PRESETS.forEach((p, i) => {
493
+ const envDetected = detectEnvKey(p);
494
+ const envTag = envDetected ? chalk11.green(" [\uD0A4 \uAC10\uC9C0\uB428]") : "";
495
+ const free = !p.needsKey ? chalk11.green(" [\uBB34\uB8CC]") : "";
496
+ console.log(` ${chalk11.cyan(`${String(i + 1).padStart(2)}.`)} ${p.label}${free}${envTag}`);
497
+ console.log(` ${chalk11.gray(p.defaultModel)}`);
498
+ });
499
+ console.log();
500
+ const choice = await ask(chalk11.cyan(" \uBC88\uD638: "));
501
+ const idx = parseInt(choice) - 1;
502
+ if (isNaN(idx) || idx < 0 || idx >= PRESETS.length) {
503
+ console.log(chalk11.red(" \uC798\uBABB\uB41C \uC120\uD0DD.\n"));
504
+ return null;
533
505
  }
534
- if (!input) {
535
- if (opts.interactive || !process.stdin.isTTY) {
536
- const { createInterface: createInterface7 } = await import("readline");
537
- const rl = createInterface7({ input: process.stdin, output: process.stdout });
538
- input = await new Promise((resolve) => {
539
- rl.question(chalk7.cyan("\uC785\uB825> "), (answer) => {
540
- rl.close();
541
- resolve(answer.trim());
542
- });
543
- });
544
- } else {
545
- printError("\uC785\uB825\uAC12\uC774 \uD544\uC694\uD569\uB2C8\uB2E4. \uC0AC\uC6A9\uBC95:");
546
- console.log(' xgen workflow run <id> "\uC785\uB825 \uD14D\uC2A4\uFFFD\uFFFD\uFFFD"');
547
- console.log(" xgen workflow run -i <id>");
548
- process.exit(1);
506
+ const preset = PRESETS[idx];
507
+ console.log(chalk11.green(`
508
+ \u2713 ${preset.label}
509
+ `));
510
+ let apiKey = "";
511
+ if (preset.needsKey) {
512
+ const envKey = detectEnvKey(preset);
513
+ if (envKey) {
514
+ console.log(chalk11.green(` API Key \uC790\uB3D9 \uAC10\uC9C0 (${preset.envKey})`));
515
+ const useEnv = await ask(chalk11.white(` \uC774 \uD0A4\uB97C \uC0AC\uC6A9\uD560\uAE4C\uC694? (Y/n): `));
516
+ if (useEnv.toLowerCase() !== "n") {
517
+ apiKey = envKey;
518
+ }
519
+ }
520
+ if (!apiKey) {
521
+ console.log(chalk11.gray(` \uBC1C\uAE09: ${preset.keyHint}
522
+ `));
523
+ apiKey = await ask(chalk11.white(" API Key: "));
524
+ if (!apiKey) {
525
+ console.log(chalk11.red(" API Key \uD544\uC694.\n"));
526
+ return null;
527
+ }
549
528
  }
550
529
  }
551
- if (!input) {
552
- printError("\uC785\uB825\uAC12\uC774 \uBE44\uC5B4\uC788\uC2B5\uB2C8\uB2E4");
553
- process.exit(1);
530
+ let baseUrl = preset.baseUrl;
531
+ if (preset.label === "\uAE30\uD0C0 (OpenAI \uD638\uD658 \uC11C\uBC84)") {
532
+ baseUrl = await ask(chalk11.white(" Base URL: "));
533
+ if (!baseUrl) {
534
+ console.log(chalk11.red(" URL \uD544\uC694.\n"));
535
+ return null;
536
+ }
554
537
  }
555
- const interactionId = `cli_${randomUUID().slice(0, 8)}`;
556
- printHeader(`\uC2E4\uD589: ${workflowName}`);
557
- printInfo(`\uC785\uB825: ${input}`);
558
- console.log();
538
+ let model = preset.defaultModel;
539
+ if (preset.models.length > 0) {
540
+ console.log(chalk11.bold("\n \uBAA8\uB378:\n"));
541
+ const defaultIdx = preset.models.indexOf(preset.defaultModel);
542
+ preset.models.forEach((m, i) => {
543
+ const tag = i === defaultIdx ? chalk11.green(" \u2190 \uCD94\uCC9C") : "";
544
+ console.log(` ${chalk11.cyan(`${String(i + 1).padStart(2)}.`)} ${m}${tag}`);
545
+ });
546
+ console.log(` ${chalk11.cyan(`${String(preset.models.length + 1).padStart(2)}.`)} \uC9C1\uC811 \uC785\uB825`);
547
+ console.log();
548
+ const mc = await ask(chalk11.cyan(` \uBC88\uD638 [${defaultIdx + 1}]: `));
549
+ if (!mc || mc === String(defaultIdx + 1)) {
550
+ model = preset.defaultModel;
551
+ } else {
552
+ const mi = parseInt(mc) - 1;
553
+ if (mi >= 0 && mi < preset.models.length) {
554
+ model = preset.models[mi];
555
+ } else if (parseInt(mc) === preset.models.length + 1) {
556
+ model = await ask(chalk11.white(" \uBAA8\uB378\uBA85: ")) || preset.defaultModel;
557
+ }
558
+ }
559
+ } else if (preset.label === "\uAE30\uD0C0 (OpenAI \uD638\uD658 \uC11C\uBC84)") {
560
+ model = await ask(chalk11.white(` \uBAA8\uB378\uBA85 [${preset.defaultModel}]: `)) || preset.defaultModel;
561
+ }
562
+ console.log(chalk11.green(`
563
+ \u2713 ${preset.label} \xB7 ${model}`));
564
+ console.log(chalk11.gray(" \uC5F0\uACB0 \uD14C\uC2A4\uD2B8 \uC911...\n"));
565
+ const provider = {
566
+ id: preset.label.toLowerCase().replace(/[^a-z0-9]/g, "-").replace(/-+/g, "-"),
567
+ name: preset.label,
568
+ type: preset.type,
569
+ baseUrl,
570
+ apiKey,
571
+ model
572
+ };
559
573
  try {
560
- const stream = await executeWorkflowStream({
561
- workflow_id: workflowId,
562
- workflow_name: workflowName,
563
- input_data: input,
564
- interaction_id: interactionId
565
- });
566
- let hasOutput = false;
567
- let fullResponse = "";
568
- await parseSSEStream(
569
- stream,
570
- (event) => {
571
- switch (event.type) {
572
- case "token":
573
- if (event.content) {
574
- if (!hasOutput) {
575
- hasOutput = true;
576
- console.log();
577
- }
578
- process.stdout.write(event.content);
579
- fullResponse += event.content;
580
- }
581
- break;
582
- case "log":
583
- if (opts.logs && event.content) {
584
- process.stderr.write(chalk7.gray(`[LOG] ${event.content}
585
- `));
586
- }
587
- break;
588
- case "node_status":
589
- if (opts.logs) {
590
- const nodeName = event.node_name ?? event.node_id ?? "?";
591
- const status = event.status ?? "?";
592
- process.stderr.write(
593
- chalk7.gray(`[\uB178\uB4DC] ${nodeName}: ${status}
594
- `)
595
- );
596
- }
597
- break;
598
- case "tool":
599
- if (opts.logs) {
600
- process.stderr.write(chalk7.gray(`[\uB3C4\uAD6C] ${JSON.stringify(event.data)}
601
- `));
602
- }
603
- break;
604
- case "complete":
605
- break;
606
- case "error":
607
- console.log();
608
- printError(event.error ?? event.content ?? "\uC54C \uC218 \uC5C6\uB294 \uC624\uB958");
609
- break;
610
- default:
611
- if (event.content) {
612
- if (!hasOutput) {
613
- process.stdout.write(chalk7.green("\uC751\uB2F5: "));
614
- hasOutput = true;
615
- }
616
- process.stdout.write(event.content);
617
- }
618
- }
619
- },
620
- () => {
621
- if (hasOutput) {
622
- console.log();
623
- if (fullResponse.includes("```") || fullResponse.includes("**")) {
624
- console.log(chalk7.gray("\u2500".repeat(40)));
625
- console.log(renderMarkdown(fullResponse));
626
- }
627
- }
628
- console.log();
629
- console.log(chalk7.gray(`\uC138\uC158: ${interactionId}`));
630
- },
631
- (err) => {
632
- console.log();
633
- printError(`\uC2A4\uD2B8\uB9AC\uBC0D \uC624\uB958: ${err.message}`);
634
- }
635
- );
636
- } catch (err) {
637
- const msg = err?.response?.data?.detail ?? err.message;
638
- printError(`\uC2E4\uD589 \uC2E4\uD328: ${msg}`);
639
- process.exit(1);
640
- }
641
- }
642
- var init_run = __esm({
643
- "src/commands/workflow/run.ts"() {
644
- "use strict";
645
- init_store();
646
- init_workflow();
647
- init_sse();
648
- init_format();
649
- init_markdown();
650
- }
651
- });
652
-
653
- // src/commands/chat.ts
654
- import chalk9 from "chalk";
655
- import { createInterface as createInterface2 } from "readline";
656
- import { randomUUID as randomUUID2 } from "crypto";
657
- function printHelp() {
658
- console.log(`
659
- ${chalk9.bold("\uC2AC\uB798\uC2DC \uCEE4\uB9E8\uB4DC")}
660
- ${chalk9.cyan("/workflows")} \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D \uBCF4\uAE30 & \uC804\uD658
661
- ${chalk9.cyan("/switch")} \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBC88\uD638\uB85C \uC804\uD658 (\uC608: /switch 3)
662
- ${chalk9.cyan("/history")} \uD604\uC7AC \uC138\uC158 \uB300\uD654 \uC774\uB825
663
- ${chalk9.cyan("/clear")} \uD654\uBA74 \uC9C0\uC6B0\uAE30
664
- ${chalk9.cyan("/info")} \uD604\uC7AC \uC5F0\uACB0 \uC815\uBCF4
665
- ${chalk9.cyan("/help")} \uC774 \uB3C4\uC6C0\uB9D0
666
- ${chalk9.cyan("/exit")} \uC885\uB8CC (Ctrl+C\uB3C4 \uAC00\uB2A5)
667
- `);
668
- }
669
- async function promptLine(rl, promptStr) {
670
- return new Promise((resolve) => {
671
- rl.question(promptStr, (answer) => resolve(answer));
672
- });
673
- }
674
- async function chat(workflowId) {
675
- const auth = requireAuth();
676
- const server = getServer();
677
- let workflows = [];
678
- try {
679
- workflows = await listWorkflows();
680
- } catch {
681
- printError("\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D\uC744 \uBD88\uB7EC\uC62C \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
682
- process.exit(1);
683
- }
684
- if (workflows.length === 0) {
685
- printError("\uC0AC\uC6A9 \uAC00\uB2A5\uD55C \uC6CC\uD06C\uD50C\uB85C\uC6B0\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4");
686
- process.exit(1);
687
- }
688
- let current;
689
- if (workflowId) {
690
- const found = workflows.find((w) => w.id === workflowId || w.workflow_name === workflowId);
691
- current = found ?? { id: workflowId, workflow_name: workflowId };
692
- } else {
693
- console.log(CHAT_BANNER);
694
- console.log(chalk9.gray(` \uC11C\uBC84: ${server} | \uC0AC\uC6A9\uC790: ${auth.username}
695
- `));
696
- console.log(chalk9.bold(" \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC120\uD0DD:\n"));
697
- workflows.forEach((w, i) => {
698
- console.log(` ${chalk9.cyan(String(i + 1).padStart(3))} ${w.workflow_name}`);
699
- });
700
- console.log();
701
- const rl2 = createInterface2({ input: process.stdin, output: process.stdout });
702
- const answer = await promptLine(rl2, chalk9.cyan(" \uBC88\uD638> "));
703
- rl2.close();
704
- const idx = parseInt(answer.trim()) - 1;
705
- if (isNaN(idx) || idx < 0 || idx >= workflows.length) {
706
- current = workflows[0];
707
- } else {
708
- current = workflows[idx];
709
- }
710
- }
711
- const sessionId = randomUUID2().slice(0, 8);
712
- let turnCount = 0;
713
- const history = [];
714
- console.log();
715
- console.log(chalk9.cyan("\u2500".repeat(42)));
716
- console.log(chalk9.white.bold(` ${current.workflow_name}`));
717
- console.log(chalk9.cyan("\u2500".repeat(42)));
718
- console.log(chalk9.gray(" \uBA54\uC2DC\uC9C0\uB97C \uC785\uB825\uD558\uC138\uC694. /help \uB85C \uB3C4\uC6C0\uB9D0.\n"));
719
- const rl = createInterface2({
720
- input: process.stdin,
721
- output: process.stdout
722
- });
723
- const getPrompt = () => chalk9.cyan("\u276F ");
724
- const processInput = async (line) => {
725
- const input = line.trim();
726
- if (!input) return;
727
- if (input.startsWith("/")) {
728
- const [cmd, ...args] = input.slice(1).split(" ");
729
- switch (cmd.toLowerCase()) {
730
- case "exit":
731
- case "quit":
732
- case "q":
733
- console.log(chalk9.gray("\n \uC885\uB8CC\uD569\uB2C8\uB2E4.\n"));
734
- rl.close();
735
- process.exit(0);
736
- break;
737
- case "help":
738
- case "h":
739
- printHelp();
740
- break;
741
- case "clear":
742
- case "cls":
743
- console.clear();
744
- console.log(chalk9.white.bold(` ${current.workflow_name}`));
745
- console.log(chalk9.cyan("\u2500".repeat(42)));
746
- break;
747
- case "workflows":
748
- case "wf":
749
- console.log();
750
- workflows.forEach((w, i) => {
751
- const marker = w.id === current.id ? chalk9.green("\u25B8") : " ";
752
- console.log(` ${marker} ${chalk9.cyan(String(i + 1).padStart(2))} ${w.workflow_name}`);
753
- });
754
- console.log(chalk9.gray("\n /switch <\uBC88\uD638> \uB85C \uC804\uD658\n"));
755
- break;
756
- case "switch":
757
- case "sw": {
758
- const num = parseInt(args[0]);
759
- if (isNaN(num) || num < 1 || num > workflows.length) {
760
- console.log(chalk9.yellow(` 1~${workflows.length} \uC0AC\uC774 \uBC88\uD638\uB97C \uC785\uB825\uD558\uC138\uC694`));
761
- } else {
762
- current = workflows[num - 1];
763
- turnCount = 0;
764
- history.length = 0;
765
- console.log(chalk9.green(`
766
- \uC804\uD658: ${current.workflow_name}
767
- `));
768
- }
769
- break;
770
- }
771
- case "history":
772
- case "hist":
773
- if (history.length === 0) {
774
- console.log(chalk9.gray(" \uB300\uD654 \uC774\uB825\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.\n"));
775
- } else {
776
- console.log();
777
- for (const h of history) {
778
- const label = h.role === "user" ? chalk9.cyan("\uB098") : chalk9.green("AI");
779
- const text = h.content.length > 80 ? h.content.slice(0, 80) + "..." : h.content;
780
- console.log(` ${label}: ${text}`);
781
- }
782
- console.log();
783
- }
784
- break;
785
- case "info":
786
- console.log(`
787
- ${chalk9.gray("\uC11C\uBC84:")} ${server}
788
- ${chalk9.gray("\uC0AC\uC6A9\uC790:")} ${auth.username}
789
- ${chalk9.gray("\uC6CC\uD06C\uD50C\uB85C\uC6B0:")} ${current.workflow_name}
790
- ${chalk9.gray("\uC138\uC158:")} ${sessionId}
791
- ${chalk9.gray("\uD134:")} ${turnCount}
792
- `);
793
- break;
794
- default:
795
- console.log(chalk9.yellow(` \uC54C \uC218 \uC5C6\uB294 \uCEE4\uB9E8\uB4DC: /${cmd}. /help \uCC38\uACE0`));
796
- }
797
- rl.prompt();
798
- return;
799
- }
800
- turnCount++;
801
- const interactionId = `${sessionId}_t${turnCount}`;
802
- history.push({ role: "user", content: input });
803
- process.stdout.write(chalk9.gray(" thinking..."));
804
- try {
805
- const stream = await executeWorkflowStream({
806
- workflow_id: current.id,
807
- workflow_name: current.workflow_name,
808
- input_data: input,
809
- interaction_id: interactionId
810
- });
811
- process.stdout.write("\r" + " ".repeat(20) + "\r");
812
- let fullResponse = "";
813
- let hasOutput = false;
814
- await parseSSEStream(
815
- stream,
816
- (event) => {
817
- if ((event.type === "token" || !event.type) && event.content) {
818
- if (!hasOutput) {
819
- hasOutput = true;
820
- console.log();
821
- }
822
- process.stdout.write(event.content);
823
- fullResponse += event.content;
824
- } else if (event.type === "error") {
825
- process.stdout.write("\r" + " ".repeat(20) + "\r");
826
- printError(event.error ?? event.content ?? "\uC624\uB958");
827
- }
828
- },
829
- () => {
830
- if (hasOutput) {
831
- console.log();
832
- console.log();
833
- }
834
- if (fullResponse) {
835
- history.push({ role: "assistant", content: fullResponse });
836
- }
837
- },
838
- (err) => {
839
- process.stdout.write("\r" + " ".repeat(20) + "\r");
840
- printError(`\uC2A4\uD2B8\uB9AC\uBC0D \uC624\uB958: ${err.message}`);
841
- }
842
- );
843
- } catch (err) {
844
- process.stdout.write("\r" + " ".repeat(20) + "\r");
845
- const msg = err?.response?.data?.detail ?? err.message;
846
- printError(`\uC2E4\uD589 \uC2E4\uD328: ${msg}`);
847
- }
848
- rl.prompt();
849
- };
850
- rl.setPrompt(getPrompt());
851
- rl.prompt();
852
- rl.on("line", (line) => {
853
- processInput(line).then(() => {
854
- });
855
- });
856
- rl.on("close", () => {
857
- console.log(chalk9.gray("\n \uC885\uB8CC\uD569\uB2C8\uB2E4.\n"));
858
- process.exit(0);
859
- });
860
- process.on("SIGINT", () => {
861
- console.log(chalk9.gray("\n \uC885\uB8CC\uD569\uB2C8\uB2E4.\n"));
862
- process.exit(0);
863
- });
864
- }
865
- function registerChatCommand(program2) {
866
- program2.command("chat [workflow-id]").description("\uC778\uD130\uB799\uD2F0\uBE0C \uB300\uD654 \uBAA8\uB4DC").action((workflowId) => chat(workflowId));
867
- }
868
- var CHAT_BANNER;
869
- var init_chat = __esm({
870
- "src/commands/chat.ts"() {
871
- "use strict";
872
- init_store();
873
- init_workflow();
874
- init_sse();
875
- init_format();
876
- CHAT_BANNER = `
877
- ${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")}
878
- ${chalk9.cyan("\u2502")} ${chalk9.white.bold("XGEN")} ${chalk9.gray("\u2014 \uC6CC\uD06C\uD50C\uB85C\uC6B0 AI \uD130\uBBF8\uB110")} ${chalk9.cyan("\u2502")}
879
- ${chalk9.cyan("\u2502")} ${chalk9.gray("/help \uB3C4\uC6C0\uB9D0 /workflows \uC804\uD658 /exit")} ${chalk9.cyan("\u2502")}
880
- ${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")}`;
881
- }
882
- });
883
-
884
- // src/utils/ui.ts
885
- import chalk10 from "chalk";
886
- import { createInterface as createInterface3 } from "readline";
887
- function box(lines, color = "cyan") {
888
- const c = chalk10[color];
889
- const inner = W - 4;
890
- const top = c(" \u256D" + "\u2500".repeat(inner) + "\u256E");
891
- const bot = c(" \u2570" + "\u2500".repeat(inner) + "\u256F");
892
- const body = lines.map((line) => {
893
- const clean = line.replace(/\x1b\[[0-9;]*m/g, "");
894
- const pad = Math.max(0, inner - clean.length);
895
- return c(" \u2502 ") + line + " ".repeat(pad) + c(" \u2502");
896
- });
897
- return [top, ...body, bot].join("\n");
898
- }
899
- function divider(label) {
900
- if (label) {
901
- const rest = W - label.length - 6;
902
- return chalk10.gray(` \u2500\u2500 ${label} ${"\u2500".repeat(Math.max(0, rest))}`);
903
- }
904
- return chalk10.gray(" " + "\u2500".repeat(W - 2));
905
- }
906
- function statusDot(active, label, detail) {
907
- const dot = active ? chalk10.green("\u25CF") : chalk10.gray("\u25CB");
908
- const d = detail ? chalk10.gray(` ${detail}`) : "";
909
- return ` ${dot} ${label}${d}`;
910
- }
911
- function ask(question) {
912
- return new Promise((resolve) => {
913
- const rl = createInterface3({ input: process.stdin, output: process.stdout });
914
- rl.question(question, (answer) => {
915
- rl.close();
916
- resolve(answer.trim());
917
- });
918
- });
919
- }
920
- function welcome() {
921
- const logo = chalk10.cyan(`
922
- \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588 \u2588\u2588
923
- \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588
924
- \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588
925
- \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588
926
- \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588`) + chalk10.white.bold(`
927
- \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588 \u2588\u2588
928
- \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588
929
- \u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588
930
- \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588
931
- \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588`);
932
- return logo;
933
- }
934
- var W;
935
- var init_ui = __esm({
936
- "src/utils/ui.ts"() {
937
- "use strict";
938
- W = Math.min(process.stdout.columns || 60, 70);
939
- }
940
- });
941
-
942
- // src/commands/provider.ts
943
- import chalk11 from "chalk";
944
- import OpenAI from "openai";
945
- function detectEnvKey(preset) {
946
- if (!preset.envKey) return null;
947
- return process.env[preset.envKey] ?? null;
948
- }
949
- async function guidedProviderSetup() {
950
- console.log();
951
- console.log(box(["OPEN XGEN \u2014 \uD504\uB85C\uBC14\uC774\uB354 \uC124\uC815", "", chalk11.gray("AI \uC5D0\uC774\uC804\uD2B8\uC5D0 \uC0AC\uC6A9\uD560 LLM\uC744 \uC120\uD0DD\uD558\uC138\uC694.")]));
952
- console.log();
953
- console.log(chalk11.bold(" \uD504\uB85C\uBC14\uC774\uB354 \uC120\uD0DD:\n"));
954
- PRESETS.forEach((p, i) => {
955
- const envDetected = detectEnvKey(p);
956
- const envTag = envDetected ? chalk11.green(" [\uD0A4 \uAC10\uC9C0\uB428]") : "";
957
- const free = !p.needsKey ? chalk11.green(" [\uBB34\uB8CC]") : "";
958
- console.log(` ${chalk11.cyan(`${String(i + 1).padStart(2)}.`)} ${p.label}${free}${envTag}`);
959
- console.log(` ${chalk11.gray(p.defaultModel)}`);
960
- });
961
- console.log();
962
- const choice = await ask(chalk11.cyan(" \uBC88\uD638: "));
963
- const idx = parseInt(choice) - 1;
964
- if (isNaN(idx) || idx < 0 || idx >= PRESETS.length) {
965
- console.log(chalk11.red(" \uC798\uBABB\uB41C \uC120\uD0DD.\n"));
966
- return null;
967
- }
968
- const preset = PRESETS[idx];
969
- console.log(chalk11.green(`
970
- \u2713 ${preset.label}
971
- `));
972
- let apiKey = "";
973
- if (preset.needsKey) {
974
- const envKey = detectEnvKey(preset);
975
- if (envKey) {
976
- console.log(chalk11.green(` API Key \uC790\uB3D9 \uAC10\uC9C0 (${preset.envKey})`));
977
- const useEnv = await ask(chalk11.white(` \uC774 \uD0A4\uB97C \uC0AC\uC6A9\uD560\uAE4C\uC694? (Y/n): `));
978
- if (useEnv.toLowerCase() !== "n") {
979
- apiKey = envKey;
980
- }
981
- }
982
- if (!apiKey) {
983
- console.log(chalk11.gray(` \uBC1C\uAE09: ${preset.keyHint}
984
- `));
985
- apiKey = await ask(chalk11.white(" API Key: "));
986
- if (!apiKey) {
987
- console.log(chalk11.red(" API Key \uD544\uC694.\n"));
988
- return null;
989
- }
990
- }
991
- }
992
- let baseUrl = preset.baseUrl;
993
- if (preset.label === "\uAE30\uD0C0 (OpenAI \uD638\uD658 \uC11C\uBC84)") {
994
- baseUrl = await ask(chalk11.white(" Base URL: "));
995
- if (!baseUrl) {
996
- console.log(chalk11.red(" URL \uD544\uC694.\n"));
997
- return null;
998
- }
999
- }
1000
- let model = preset.defaultModel;
1001
- if (preset.models.length > 0) {
1002
- console.log(chalk11.bold("\n \uBAA8\uB378:\n"));
1003
- const defaultIdx = preset.models.indexOf(preset.defaultModel);
1004
- preset.models.forEach((m, i) => {
1005
- const tag = i === defaultIdx ? chalk11.green(" \u2190 \uCD94\uCC9C") : "";
1006
- console.log(` ${chalk11.cyan(`${String(i + 1).padStart(2)}.`)} ${m}${tag}`);
1007
- });
1008
- console.log(` ${chalk11.cyan(`${String(preset.models.length + 1).padStart(2)}.`)} \uC9C1\uC811 \uC785\uB825`);
1009
- console.log();
1010
- const mc = await ask(chalk11.cyan(` \uBC88\uD638 [${defaultIdx + 1}]: `));
1011
- if (!mc || mc === String(defaultIdx + 1)) {
1012
- model = preset.defaultModel;
1013
- } else {
1014
- const mi = parseInt(mc) - 1;
1015
- if (mi >= 0 && mi < preset.models.length) {
1016
- model = preset.models[mi];
1017
- } else if (parseInt(mc) === preset.models.length + 1) {
1018
- model = await ask(chalk11.white(" \uBAA8\uB378\uBA85: ")) || preset.defaultModel;
1019
- }
1020
- }
1021
- } else if (preset.label === "\uAE30\uD0C0 (OpenAI \uD638\uD658 \uC11C\uBC84)") {
1022
- model = await ask(chalk11.white(` \uBAA8\uB378\uBA85 [${preset.defaultModel}]: `)) || preset.defaultModel;
1023
- }
1024
- console.log(chalk11.green(`
1025
- \u2713 ${preset.label} \xB7 ${model}`));
1026
- console.log(chalk11.gray(" \uC5F0\uACB0 \uD14C\uC2A4\uD2B8 \uC911...\n"));
1027
- const provider = {
1028
- id: preset.label.toLowerCase().replace(/[^a-z0-9]/g, "-").replace(/-+/g, "-"),
1029
- name: preset.label,
1030
- type: preset.type,
1031
- baseUrl,
1032
- apiKey,
1033
- model
1034
- };
1035
- try {
1036
- const client2 = new OpenAI({ apiKey: apiKey || "ollama", baseURL: baseUrl });
1037
- await client2.chat.completions.create({
1038
- model,
1039
- messages: [{ role: "user", content: "Hi" }],
1040
- max_tokens: 5
574
+ const client2 = new OpenAI({ apiKey: apiKey || "ollama", baseURL: baseUrl });
575
+ await client2.chat.completions.create({
576
+ model,
577
+ messages: [{ role: "user", content: "Hi" }],
578
+ max_tokens: 5
1041
579
  });
1042
580
  console.log(chalk11.green(" \u2713 \uC5F0\uACB0 \uC131\uACF5!\n"));
1043
581
  } catch (err) {
@@ -1236,1724 +774,1894 @@ var init_provider = __esm({
1236
774
  }
1237
775
  });
1238
776
 
1239
- // src/agent/llm.ts
1240
- import OpenAI2 from "openai";
1241
- function createLLMClient(provider) {
1242
- const opts = {
1243
- apiKey: provider.apiKey || "ollama"
1244
- };
1245
- if (provider.baseUrl) {
1246
- opts.baseURL = provider.baseUrl;
1247
- }
1248
- return new OpenAI2(opts);
1249
- }
1250
- async function streamChat(client2, model, messages, tools2, onDelta) {
1251
- const params = {
1252
- model,
1253
- messages,
1254
- stream: true
1255
- };
1256
- if (tools2 && tools2.length > 0) {
1257
- params.tools = tools2;
1258
- }
1259
- const stream = await client2.chat.completions.create(params);
1260
- let content = "";
1261
- const toolCallMap = /* @__PURE__ */ new Map();
1262
- for await (const chunk of stream) {
1263
- const delta = chunk.choices[0]?.delta;
1264
- if (!delta) continue;
1265
- if (delta.content) {
1266
- content += delta.content;
1267
- onDelta?.(delta.content);
1268
- }
1269
- if (delta.tool_calls) {
1270
- for (const tc of delta.tool_calls) {
1271
- const idx = tc.index;
1272
- if (!toolCallMap.has(idx)) {
1273
- toolCallMap.set(idx, { id: tc.id ?? "", name: tc.function?.name ?? "", arguments: "" });
1274
- }
1275
- const entry = toolCallMap.get(idx);
1276
- if (tc.id) entry.id = tc.id;
1277
- if (tc.function?.name) entry.name = tc.function.name;
1278
- if (tc.function?.arguments) entry.arguments += tc.function.arguments;
1279
- }
1280
- }
1281
- }
1282
- return {
1283
- content,
1284
- toolCalls: [...toolCallMap.values()]
1285
- };
1286
- }
1287
- var init_llm = __esm({
1288
- "src/agent/llm.ts"() {
1289
- "use strict";
1290
- }
1291
- });
1292
-
1293
- // src/agent/tools/file-read.ts
1294
- var file_read_exports = {};
1295
- __export(file_read_exports, {
1296
- definition: () => definition,
1297
- execute: () => execute
777
+ // src/api/document.ts
778
+ var document_exports = {};
779
+ __export(document_exports, {
780
+ getDocumentInfo: () => getDocumentInfo,
781
+ listDocuments: () => listDocuments,
782
+ uploadDocument: () => uploadDocument
1298
783
  });
1299
- import { readFileSync as readFileSync2 } from "fs";
1300
- async function execute(args) {
1301
- const path = args.path;
1302
- const startLine = args.start_line || 1;
1303
- const endLine = args.end_line;
1304
- try {
1305
- const content = readFileSync2(path, "utf-8");
1306
- const lines = content.split("\n");
1307
- const sliced = lines.slice(startLine - 1, endLine ?? lines.length);
1308
- return sliced.map((line, i) => `${startLine + i} ${line}`).join("\n");
1309
- } catch (err) {
1310
- return `Error: ${err.message}`;
1311
- }
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 ?? [];
1312
792
  }
1313
- var definition;
1314
- var init_file_read = __esm({
1315
- "src/agent/tools/file-read.ts"() {
1316
- "use strict";
1317
- definition = {
1318
- type: "function",
1319
- function: {
1320
- name: "file_read",
1321
- description: "\uD30C\uC77C \uB0B4\uC6A9\uC744 \uC77D\uC2B5\uB2C8\uB2E4. \uC904 \uBC88\uD638\uAC00 \uD3EC\uD568\uB429\uB2C8\uB2E4.",
1322
- parameters: {
1323
- type: "object",
1324
- properties: {
1325
- path: { type: "string", description: "\uD30C\uC77C \uACBD\uB85C" },
1326
- start_line: { type: "number", description: "\uC2DC\uC791 \uC904 \uBC88\uD638 (\uC120\uD0DD)" },
1327
- end_line: { type: "number", description: "\uB05D \uC904 \uBC88\uD638 (\uC120\uD0DD)" }
1328
- },
1329
- required: ["path"]
1330
- }
1331
- }
1332
- };
1333
- }
1334
- });
1335
-
1336
- // src/agent/tools/file-write.ts
1337
- var file_write_exports = {};
1338
- __export(file_write_exports, {
1339
- definition: () => definition2,
1340
- execute: () => execute2
1341
- });
1342
- import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
1343
- import { dirname } from "path";
1344
- async function execute2(args) {
1345
- const path = args.path;
1346
- const content = args.content;
1347
- try {
1348
- mkdirSync2(dirname(path), { recursive: true });
1349
- writeFileSync2(path, content, "utf-8");
1350
- return `\uD30C\uC77C \uC791\uC131 \uC644\uB8CC: ${path}`;
1351
- } catch (err) {
1352
- return `Error: ${err.message}`;
1353
- }
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;
808
+ }
809
+ async function getDocumentInfo(docId) {
810
+ const client2 = getClient();
811
+ const res = await client2.get(`/api/documents/${docId}`);
812
+ return res.data;
1354
813
  }
1355
- var definition2;
1356
- var init_file_write = __esm({
1357
- "src/agent/tools/file-write.ts"() {
814
+ var init_document = __esm({
815
+ "src/api/document.ts"() {
1358
816
  "use strict";
1359
- definition2 = {
1360
- type: "function",
1361
- function: {
1362
- name: "file_write",
1363
- description: "\uD30C\uC77C\uC744 \uC0DD\uC131\uD558\uAC70\uB098 \uB36E\uC5B4\uC501\uB2C8\uB2E4.",
1364
- parameters: {
1365
- type: "object",
1366
- properties: {
1367
- path: { type: "string", description: "\uD30C\uC77C \uACBD\uB85C" },
1368
- content: { type: "string", description: "\uD30C\uC77C \uB0B4\uC6A9" }
1369
- },
1370
- required: ["path", "content"]
1371
- }
1372
- }
1373
- };
817
+ init_client();
1374
818
  }
1375
819
  });
1376
820
 
1377
- // src/agent/tools/file-edit.ts
1378
- var file_edit_exports = {};
1379
- __export(file_edit_exports, {
1380
- definition: () => definition3,
1381
- execute: () => execute3
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
1382
828
  });
1383
- import { readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
1384
- async function execute3(args) {
1385
- const path = args.path;
1386
- const oldText = args.old_text;
1387
- const newText = args.new_text;
1388
- try {
1389
- const content = readFileSync3(path, "utf-8");
1390
- if (!content.includes(oldText)) {
1391
- return `Error: \uD14D\uC2A4\uD2B8\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4`;
1392
- }
1393
- const updated = content.replace(oldText, newText);
1394
- writeFileSync3(path, updated, "utf-8");
1395
- return `\uD30C\uC77C \uC218\uC815 \uC644\uB8CC: ${path}`;
1396
- } catch (err) {
1397
- return `Error: ${err.message}`;
1398
- }
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 ?? [];
1399
857
  }
1400
- var definition3;
1401
- var init_file_edit = __esm({
1402
- "src/agent/tools/file-edit.ts"() {
858
+ var init_ontology = __esm({
859
+ "src/api/ontology.ts"() {
1403
860
  "use strict";
1404
- definition3 = {
1405
- type: "function",
1406
- function: {
1407
- name: "file_edit",
1408
- description: "\uD30C\uC77C\uC5D0\uC11C \uD2B9\uC815 \uD14D\uC2A4\uD2B8\uB97C \uCC3E\uC544 \uAD50\uCCB4\uD569\uB2C8\uB2E4.",
1409
- parameters: {
1410
- type: "object",
1411
- properties: {
1412
- path: { type: "string", description: "\uD30C\uC77C \uACBD\uB85C" },
1413
- old_text: { type: "string", description: "\uAD50\uCCB4\uD560 \uAE30\uC874 \uD14D\uC2A4\uD2B8" },
1414
- new_text: { type: "string", description: "\uC0C8 \uD14D\uC2A4\uD2B8" }
1415
- },
1416
- required: ["path", "old_text", "new_text"]
1417
- }
1418
- }
1419
- };
861
+ init_client();
1420
862
  }
1421
863
  });
1422
864
 
1423
- // src/agent/tools/bash.ts
1424
- var bash_exports = {};
1425
- __export(bash_exports, {
1426
- definition: () => definition4,
1427
- execute: () => execute4
1428
- });
1429
- import { execSync } from "child_process";
1430
- async function execute4(args) {
1431
- const command = args.command;
1432
- try {
1433
- const output = execSync(command, {
1434
- encoding: "utf-8",
1435
- timeout: 3e4,
1436
- maxBuffer: 1024 * 1024,
1437
- stdio: ["pipe", "pipe", "pipe"]
865
+ // src/index.ts
866
+ import { Command } from "commander";
867
+ import chalk15 from "chalk";
868
+
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);
910
+ }
911
+ const parsed = key === "streamLogs" ? value === "true" : value;
912
+ setConfig({ [key]: parsed });
913
+ printSuccess(`${key} = ${value}`);
914
+ });
915
+ }
916
+
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
1438
928
  });
1439
- return output || "(no output)";
1440
- } catch (err) {
1441
- const e = err;
1442
- return (e.stdout || "") + (e.stderr || "") || `Error: ${e.message}`;
1443
- }
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
+ });
1444
963
  }
1445
- var definition4;
1446
- var init_bash = __esm({
1447
- "src/agent/tools/bash.ts"() {
1448
- "use strict";
1449
- definition4 = {
1450
- type: "function",
1451
- function: {
1452
- name: "bash",
1453
- description: "\uC178 \uBA85\uB839\uC5B4\uB97C \uC2E4\uD589\uD569\uB2C8\uB2E4. stdout + stderr\uB97C \uBC18\uD658\uD569\uB2C8\uB2E4.",
1454
- parameters: {
1455
- type: "object",
1456
- properties: {
1457
- command: { type: "string", description: "\uC2E4\uD589\uD560 \uBA85\uB839\uC5B4" }
1458
- },
1459
- required: ["command"]
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")}`);
1460
1029
  }
1461
- }
1462
- };
1463
- }
1464
- });
1465
-
1466
- // src/agent/tools/grep.ts
1467
- var grep_exports = {};
1468
- __export(grep_exports, {
1469
- definition: () => definition5,
1470
- execute: () => execute5
1471
- });
1472
- import { execSync as execSync2 } from "child_process";
1473
- async function execute5(args) {
1474
- const pattern = args.pattern;
1475
- const path = args.path || ".";
1476
- const glob = args.glob;
1477
- try {
1478
- let cmd = `grep -rn --color=never "${pattern.replace(/"/g, '\\"')}" "${path}"`;
1479
- if (glob) cmd += ` --include="${glob}"`;
1480
- cmd += " | head -50";
1481
- const output = execSync2(cmd, {
1482
- encoding: "utf-8",
1483
- timeout: 1e4,
1484
- maxBuffer: 512 * 1024,
1485
- stdio: ["pipe", "pipe", "pipe"]
1486
- });
1487
- return output || "\uC77C\uCE58\uD558\uB294 \uACB0\uACFC \uC5C6\uC74C";
1488
- } catch {
1489
- return "\uC77C\uCE58\uD558\uB294 \uACB0\uACFC \uC5C6\uC74C";
1490
- }
1491
- }
1492
- var definition5;
1493
- var init_grep = __esm({
1494
- "src/agent/tools/grep.ts"() {
1495
- "use strict";
1496
- definition5 = {
1497
- type: "function",
1498
- function: {
1499
- name: "grep",
1500
- description: "\uD30C\uC77C\uC5D0\uC11C \uD328\uD134\uC744 \uAC80\uC0C9\uD569\uB2C8\uB2E4 (\uC7AC\uADC0, \uC904 \uBC88\uD638 \uD3EC\uD568).",
1501
- parameters: {
1502
- type: "object",
1503
- properties: {
1504
- pattern: { type: "string", description: "\uAC80\uC0C9 \uD328\uD134 (\uC815\uADDC\uC2DD)" },
1505
- path: { type: "string", description: "\uAC80\uC0C9 \uB514\uB809\uD1A0\uB9AC \uB610\uB294 \uD30C\uC77C (\uAE30\uBCF8: .)" },
1506
- glob: { type: "string", description: "\uD30C\uC77C \uD544\uD130 (\uC608: *.ts)" }
1507
- },
1508
- required: ["pattern"]
1030
+ if (result.user_type) {
1031
+ console.log(` ${chalk3.gray("\uC720\uD615:")} ${result.user_type}`);
1509
1032
  }
1033
+ } else {
1034
+ console.log(` ${chalk3.gray("\uC0C1\uD0DC:")} ${chalk3.red("\uD1A0\uD070 \uB9CC\uB8CC")}`);
1510
1035
  }
1511
- };
1512
- }
1513
- });
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
+ }
1514
1042
 
1515
- // src/agent/tools/list-files.ts
1516
- var list_files_exports = {};
1517
- __export(list_files_exports, {
1518
- definition: () => definition6,
1519
- execute: () => execute6
1520
- });
1521
- import { execSync as execSync3 } from "child_process";
1522
- async function execute6(args) {
1523
- const path = args.path || ".";
1524
- const pattern = args.pattern;
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();
1525
1050
  try {
1526
- let cmd;
1527
- if (pattern) {
1528
- cmd = `find "${path}" -name "${pattern}" -type f | head -100`;
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;
1056
+ }
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
+ );
1529
1069
  } else {
1530
- cmd = `ls -la "${path}"`;
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
+ );
1531
1085
  }
1532
- const output = execSync3(cmd, {
1533
- encoding: "utf-8",
1534
- timeout: 1e4,
1535
- stdio: ["pipe", "pipe", "pipe"]
1536
- });
1537
- return output || "(empty)";
1086
+ console.log();
1538
1087
  } catch (err) {
1539
- return `Error: ${err.message}`;
1088
+ const msg = err.message;
1089
+ printError(`\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D \uC870\uD68C \uC2E4\uD328: ${msg}`);
1090
+ process.exit(1);
1540
1091
  }
1541
1092
  }
1542
- var definition6;
1543
- var init_list_files = __esm({
1544
- "src/agent/tools/list-files.ts"() {
1545
- "use strict";
1546
- definition6 = {
1547
- type: "function",
1548
- function: {
1549
- name: "list_files",
1550
- description: "\uB514\uB809\uD1A0\uB9AC\uC758 \uD30C\uC77C/\uD3F4\uB354 \uBAA9\uB85D\uC744 \uBC18\uD658\uD569\uB2C8\uB2E4. glob \uD328\uD134 \uC9C0\uC6D0.",
1551
- parameters: {
1552
- type: "object",
1553
- properties: {
1554
- path: { type: "string", description: "\uB514\uB809\uD1A0\uB9AC \uACBD\uB85C (\uAE30\uBCF8: .)" },
1555
- pattern: { type: "string", description: "glob \uD328\uD134 (\uC608: **/*.ts)" }
1556
- }
1557
- }
1558
- }
1559
- };
1560
- }
1561
- });
1562
1093
 
1563
- // src/agent/tools/sandbox.ts
1564
- var sandbox_exports = {};
1565
- __export(sandbox_exports, {
1566
- definition: () => definition7,
1567
- execute: () => execute7
1568
- });
1569
- import { execSync as execSync4 } from "child_process";
1570
- import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync4, existsSync as existsSync2, rmSync } from "fs";
1571
- import { join as join2 } from "path";
1572
- import { tmpdir } from "os";
1573
- function ensureSandbox() {
1574
- if (!existsSync2(SANDBOX_DIR)) {
1575
- mkdirSync3(SANDBOX_DIR, { recursive: true });
1576
- }
1577
- return SANDBOX_DIR;
1578
- }
1579
- async function execute7(args) {
1580
- const language = args.language;
1581
- const code = args.code;
1582
- const packages = args.packages ?? [];
1583
- const dir = ensureSandbox();
1584
- const runId = `run_${Date.now()}`;
1585
- const runDir = join2(dir, runId);
1586
- mkdirSync3(runDir, { recursive: true });
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();
1587
1101
  try {
1588
- if (packages.length > 0) {
1589
- if (language === "python") {
1590
- const pkgList = packages.join(" ");
1591
- execSync4(`pip install ${pkgList}`, {
1592
- cwd: runDir,
1593
- encoding: "utf-8",
1594
- timeout: 6e4,
1595
- stdio: ["pipe", "pipe", "pipe"]
1596
- });
1597
- } else {
1598
- execSync4("npm init -y", { cwd: runDir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
1599
- const pkgList = packages.join(" ");
1600
- execSync4(`npm install ${pkgList}`, {
1601
- cwd: runDir,
1602
- encoding: "utf-8",
1603
- timeout: 6e4,
1604
- stdio: ["pipe", "pipe", "pipe"]
1605
- });
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})`)}`);
1606
1115
  }
1607
1116
  }
1608
- let cmd;
1609
- let filename;
1610
- if (language === "python") {
1611
- filename = "script.py";
1612
- writeFileSync4(join2(runDir, filename), code, "utf-8");
1613
- cmd = `python3 ${filename}`;
1614
- } else if (language === "typescript") {
1615
- filename = "script.ts";
1616
- writeFileSync4(join2(runDir, filename), code, "utf-8");
1617
- cmd = `npx tsx ${filename}`;
1618
- } else {
1619
- filename = "script.mjs";
1620
- writeFileSync4(join2(runDir, filename), code, "utf-8");
1621
- cmd = `node ${filename}`;
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
+ }
1622
1123
  }
1623
- const output = execSync4(cmd, {
1624
- cwd: runDir,
1625
- encoding: "utf-8",
1626
- timeout: 3e4,
1627
- maxBuffer: 1024 * 1024,
1628
- stdio: ["pipe", "pipe", "pipe"]
1629
- });
1630
- return output || "(no output)";
1124
+ console.log();
1631
1125
  } catch (err) {
1632
- const e = err;
1633
- return (e.stdout || "") + (e.stderr || "") || `Error: ${e.message}`;
1634
- } finally {
1635
- try {
1636
- rmSync(runDir, { recursive: true, force: true });
1637
- } catch {
1638
- }
1126
+ const msg = err.message;
1127
+ printError(`\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC870\uD68C \uC2E4\uD328: ${msg}`);
1128
+ process.exit(1);
1639
1129
  }
1640
1130
  }
1641
- var SANDBOX_DIR, definition7;
1642
- var init_sandbox = __esm({
1643
- "src/agent/tools/sandbox.ts"() {
1644
- "use strict";
1645
- SANDBOX_DIR = join2(tmpdir(), "xgen-sandbox");
1646
- definition7 = {
1647
- type: "function",
1648
- function: {
1649
- name: "sandbox_run",
1650
- 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.",
1651
- parameters: {
1652
- type: "object",
1653
- properties: {
1654
- language: {
1655
- type: "string",
1656
- enum: ["javascript", "typescript", "python"],
1657
- description: "\uC2E4\uD589\uD560 \uC5B8\uC5B4"
1658
- },
1659
- code: { type: "string", description: "\uC2E4\uD589\uD560 \uCF54\uB4DC" },
1660
- packages: {
1661
- type: "array",
1662
- items: { type: "string" },
1663
- description: "\uC124\uCE58\uD560 \uD328\uD0A4\uC9C0 (npm \uB610\uB294 pip)"
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) });
1664
1175
  }
1665
- },
1666
- required: ["language", "code"]
1176
+ }
1667
1177
  }
1668
1178
  }
1669
- };
1670
- }
1671
- });
1672
-
1673
- // src/agent/tools/index.ts
1674
- function getAllToolDefs() {
1675
- return tools.map((t) => t.definition);
1676
- }
1677
- async function executeTool(name, args) {
1678
- const tool = toolMap.get(name);
1679
- if (!tool) return `Unknown tool: ${name}`;
1680
- return tool.execute(args);
1179
+ onDone?.();
1180
+ resolve();
1181
+ });
1182
+ stream.on("error", (err) => {
1183
+ onError?.(err);
1184
+ reject(err);
1185
+ });
1186
+ });
1681
1187
  }
1682
- function getToolNames() {
1683
- return tools.map((t) => t.definition.function.name);
1188
+
1189
+ // src/commands/workflow/run.ts
1190
+ init_format();
1191
+
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);
1218
+ });
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;
1684
1222
  }
1685
- var tools, toolMap;
1686
- var init_tools = __esm({
1687
- "src/agent/tools/index.ts"() {
1688
- "use strict";
1689
- init_file_read();
1690
- init_file_write();
1691
- init_file_edit();
1692
- init_bash();
1693
- init_grep();
1694
- init_list_files();
1695
- init_sandbox();
1696
- tools = [file_read_exports, file_write_exports, file_edit_exports, bash_exports, grep_exports, list_files_exports, sandbox_exports];
1697
- toolMap = /* @__PURE__ */ new Map();
1698
- for (const t of tools) {
1699
- toolMap.set(t.definition.function.name, t);
1700
- }
1701
- }
1702
- });
1703
1223
 
1704
- // src/mcp/client.ts
1705
- import { spawn } from "child_process";
1706
- import { existsSync as existsSync3, readFileSync as readFileSync4 } from "fs";
1707
- import { join as join3 } from "path";
1708
- import { createInterface as createInterface4 } from "readline";
1709
- function loadMcpConfig(dir) {
1710
- const searchPaths = [
1711
- dir ? join3(dir, ".mcp.json") : null,
1712
- join3(process.cwd(), ".mcp.json"),
1713
- join3(process.env.HOME ?? "", ".mcp.json")
1714
- ].filter(Boolean);
1715
- for (const p of searchPaths) {
1716
- if (existsSync3(p)) {
1717
- try {
1718
- return JSON.parse(readFileSync4(p, "utf-8"));
1719
- } catch {
1720
- continue;
1721
- }
1722
- }
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 {
1723
1232
  }
1724
- return null;
1725
- }
1726
- var McpClient, McpManager;
1727
- var init_client2 = __esm({
1728
- "src/mcp/client.ts"() {
1729
- "use strict";
1730
- McpClient = class {
1731
- process = null;
1732
- requestId = 0;
1733
- pending = /* @__PURE__ */ new Map();
1734
- serverName;
1735
- config;
1736
- tools = [];
1737
- constructor(serverName, config) {
1738
- this.serverName = serverName;
1739
- this.config = config;
1740
- }
1741
- async start() {
1742
- this.process = spawn(this.config.command, this.config.args ?? [], {
1743
- stdio: ["pipe", "pipe", "pipe"],
1744
- env: { ...process.env, ...this.config.env }
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());
1745
1241
  });
1746
- const rl = createInterface4({ input: this.process.stdout });
1747
- rl.on("line", (line) => {
1748
- try {
1749
- const msg = JSON.parse(line);
1750
- if (msg.id !== void 0 && this.pending.has(msg.id)) {
1751
- const p = this.pending.get(msg.id);
1752
- this.pending.delete(msg.id);
1753
- if (msg.error) {
1754
- p.reject(new Error(msg.error.message));
1755
- } else {
1756
- p.resolve(msg.result);
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();
1757
1276
  }
1277
+ process.stdout.write(event.content);
1278
+ fullResponse += event.content;
1758
1279
  }
1759
- } catch {
1760
- }
1761
- });
1762
- this.process.on("error", (err) => {
1763
- console.error(`MCP [${this.serverName}] \uD504\uB85C\uC138\uC2A4 \uC624\uB958:`, err.message);
1764
- });
1765
- await this.send("initialize", {
1766
- protocolVersion: "2024-11-05",
1767
- capabilities: {},
1768
- clientInfo: { name: "open-xgen", version: "0.3.0" }
1769
- });
1770
- await this.send("notifications/initialized", {});
1771
- }
1772
- send(method, params) {
1773
- return new Promise((resolve, reject) => {
1774
- const id = ++this.requestId;
1775
- const request = { jsonrpc: "2.0", id, method, params };
1776
- this.pending.set(id, { resolve, reject });
1777
- const timeout = setTimeout(() => {
1778
- this.pending.delete(id);
1779
- reject(new Error(`MCP \uC694\uCCAD \uD0C0\uC784\uC544\uC6C3: ${method}`));
1780
- }, 15e3);
1781
- this.pending.set(id, {
1782
- resolve: (v) => {
1783
- clearTimeout(timeout);
1784
- resolve(v);
1785
- },
1786
- reject: (e) => {
1787
- clearTimeout(timeout);
1788
- reject(e);
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);
1789
1316
  }
1790
- });
1791
- this.process?.stdin?.write(JSON.stringify(request) + "\n");
1792
- });
1793
- }
1794
- async listTools() {
1795
- const result = await this.send("tools/list", {});
1796
- this.tools = result.tools ?? [];
1797
- return this.tools;
1798
- }
1799
- async callTool(name, args) {
1800
- const result = await this.send("tools/call", { name, arguments: args });
1801
- return result.content?.map((c) => c.text ?? "").join("\n") ?? "";
1802
- }
1803
- getOpenAITools() {
1804
- return this.tools.map((t) => ({
1805
- type: "function",
1806
- function: {
1807
- name: `mcp_${this.serverName}_${t.name}`,
1808
- description: `[MCP:${this.serverName}] ${t.description ?? t.name}`,
1809
- parameters: t.inputSchema ?? { type: "object", properties: {} }
1810
- }
1811
- }));
1812
- }
1813
- stop() {
1814
- this.process?.kill();
1815
- this.process = null;
1816
- }
1817
- };
1818
- McpManager = class {
1819
- clients = /* @__PURE__ */ new Map();
1820
- async startAll(config) {
1821
- for (const [name, serverConfig] of Object.entries(config.mcpServers)) {
1822
- if (serverConfig.type !== "stdio") continue;
1823
- try {
1824
- const client2 = new McpClient(name, serverConfig);
1825
- await client2.start();
1826
- await client2.listTools();
1827
- this.clients.set(name, client2);
1828
- } catch (err) {
1829
- console.error(`MCP [${name}] \uC2DC\uC791 \uC2E4\uD328:`, err.message);
1830
- }
1831
- }
1832
- }
1833
- getAllTools() {
1834
- const tools2 = [];
1835
- for (const client2 of this.clients.values()) {
1836
- tools2.push(...client2.getOpenAITools());
1837
1317
  }
1838
- return tools2;
1839
- }
1840
- async callTool(fullName, args) {
1841
- const parts = fullName.split("_");
1842
- if (parts.length < 3 || parts[0] !== "mcp") return `Unknown MCP tool: ${fullName}`;
1843
- const serverName = parts[1];
1844
- const toolName = parts.slice(2).join("_");
1845
- const client2 = this.clients.get(serverName);
1846
- if (!client2) return `MCP \uC11C\uBC84\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${serverName}`;
1847
- return client2.callTool(toolName, args);
1848
- }
1849
- isMcpTool(name) {
1850
- return name.startsWith("mcp_");
1851
- }
1852
- stopAll() {
1853
- for (const client2 of this.clients.values()) {
1854
- client2.stop();
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
+ }
1855
1326
  }
1856
- this.clients.clear();
1857
- }
1858
- get serverCount() {
1859
- return this.clients.size;
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}`);
1860
1333
  }
1861
- getServerNames() {
1862
- return [...this.clients.keys()];
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
+ }
1341
+
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
+ );
1863
1370
  }
1864
- };
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);
1865
1377
  }
1866
- });
1867
-
1868
- // src/api/document.ts
1869
- var document_exports = {};
1870
- __export(document_exports, {
1871
- getDocumentInfo: () => getDocumentInfo,
1872
- listDocuments: () => listDocuments,
1873
- uploadDocument: () => uploadDocument
1874
- });
1875
- import { createReadStream, statSync } from "fs";
1876
- import { basename } from "path";
1877
- async function listDocuments(collectionId) {
1878
- const client2 = getClient();
1879
- const params = {};
1880
- if (collectionId) params.collection_id = collectionId;
1881
- const res = await client2.get("/api/documents/list", { params });
1882
- return res.data.documents ?? res.data ?? [];
1883
- }
1884
- async function uploadDocument(filePath, collectionId, name) {
1885
- const client2 = getClient();
1886
- const stat = statSync(filePath);
1887
- const fileName = name || basename(filePath);
1888
- const FormData = (await import("buffer")).Blob ? globalThis.FormData : null;
1889
- if (!FormData) throw new Error("FormData not available");
1890
- const form = new FormData();
1891
- const fileBlob = new Blob([createReadStream(filePath)]);
1892
- form.append("file", fileBlob, fileName);
1893
- if (collectionId) form.append("collection_id", collectionId);
1894
- const res = await client2.post("/api/documents/upload", form, {
1895
- headers: { "Content-Type": "multipart/form-data" },
1896
- maxBodyLength: stat.size + 1024 * 1024
1897
- });
1898
- return res.data;
1899
1378
  }
1900
- async function getDocumentInfo(docId) {
1901
- const client2 = getClient();
1902
- const res = await client2.get(`/api/documents/${docId}`);
1903
- return res.data;
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) }));
1904
1387
  }
1905
- var init_document = __esm({
1906
- "src/api/document.ts"() {
1907
- "use strict";
1908
- init_client();
1909
- }
1910
- });
1911
1388
 
1912
- // src/api/ontology.ts
1913
- var ontology_exports = {};
1914
- __export(ontology_exports, {
1915
- getGraphStats: () => getGraphStats,
1916
- listGraphs: () => listGraphs,
1917
- queryGraphRAG: () => queryGraphRAG,
1918
- queryGraphRAGMultiTurn: () => queryGraphRAGMultiTurn
1919
- });
1920
- async function queryGraphRAG(query, graphId, opts) {
1921
- const client2 = getClient();
1922
- const res = await client2.post("/api/graph-rag", {
1923
- query,
1924
- graph_id: graphId,
1925
- use_scs: opts?.scs ?? true
1926
- });
1927
- return res.data;
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
+ `);
1928
1412
  }
1929
- async function queryGraphRAGMultiTurn(query, sessionId, graphId, opts) {
1930
- const client2 = getClient();
1931
- const res = await client2.post("/api/graph-rag/multi-turn", {
1932
- query,
1933
- session_id: sessionId,
1934
- graph_id: graphId,
1935
- max_turns: opts?.maxTurns ?? 5
1413
+ async function promptLine(rl, promptStr) {
1414
+ return new Promise((resolve) => {
1415
+ rl.question(promptStr, (answer) => resolve(answer));
1936
1416
  });
1937
- return res.data;
1938
- }
1939
- async function getGraphStats(graphId) {
1940
- const client2 = getClient();
1941
- const res = await client2.get(`/api/graph/${graphId}/stats`);
1942
- return res.data;
1943
- }
1944
- async function listGraphs() {
1945
- const client2 = getClient();
1946
- const res = await client2.get("/api/graph/list");
1947
- return res.data.graphs ?? res.data ?? [];
1948
1417
  }
1949
- var init_ontology = __esm({
1950
- "src/api/ontology.ts"() {
1951
- "use strict";
1952
- init_client();
1953
- }
1954
- });
1955
-
1956
- // src/commands/home.ts
1957
- var home_exports = {};
1958
- __export(home_exports, {
1959
- homeMenu: () => homeMenu
1960
- });
1961
- import chalk12 from "chalk";
1962
- function showStatus() {
1963
- const provider = getDefaultProvider();
1418
+ async function chat(workflowId) {
1419
+ const auth = requireAuth();
1964
1420
  const server = getServer();
1965
- const auth = getAuth();
1966
- const activeEnv = getActiveEnvironment();
1967
- const envs = getEnvironments();
1968
- console.log(divider("\uC0C1\uD0DC"));
1969
- console.log();
1970
- console.log(provider ? statusDot(true, chalk12.bold("AI \uC5D0\uC774\uC804\uD2B8"), `${provider.name} \xB7 ${provider.model}`) : statusDot(false, "AI \uC5D0\uC774\uC804\uD2B8", "\uBBF8\uC124\uC815"));
1971
- console.log(server && auth ? statusDot(true, chalk12.bold("XGEN \uC11C\uBC84"), `${auth.username} \xB7 ${server.replace("https://", "")}`) : server ? statusDot(false, "XGEN \uC11C\uBC84", `${server.replace("https://", "")} \xB7 \uB85C\uADF8\uC778 \uD544\uC694`) : statusDot(false, "XGEN \uC11C\uBC84", "\uBBF8\uC5F0\uACB0"));
1972
- if (activeEnv) {
1973
- console.log(statusDot(true, chalk12.bold("\uD658\uACBD"), `${activeEnv.name} (${envs.length}\uAC1C \uB4F1\uB85D)`));
1974
- } else if (envs.length > 0) {
1975
- console.log(statusDot(false, "\uD658\uACBD", `${envs.length}\uAC1C \uB4F1\uB85D`));
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);
1976
1427
  }
1977
- console.log();
1978
- }
1979
- async function homeMenu() {
1980
- console.log(welcome());
1981
- console.log(chalk12.gray(" v0.4.1\n"));
1982
- showStatus();
1983
- while (true) {
1984
- const provider = getDefaultProvider();
1985
- const server = getServer();
1986
- const auth = getAuth();
1987
- const hasServer = !!(server && auth);
1988
- const items = [];
1989
- items.push({
1990
- key: "a",
1991
- label: chalk12.bold("AI \uC5D0\uC774\uC804\uD2B8"),
1992
- hint: provider ? `${provider.model} \xB7 \uB300\uD654 \uC2DC\uC791` : "\uD504\uB85C\uBC14\uC774\uB354 \uC124\uC815 \uD6C4 \uC2DC\uC791",
1993
- action: async () => {
1994
- await agentRepl();
1995
- console.log();
1996
- showStatus();
1997
- }
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);
1431
+ }
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}`);
1998
1443
  });
1999
- if (hasServer) {
2000
- items.push({
2001
- key: "c",
2002
- label: chalk12.bold("\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uCC44\uD305"),
2003
- hint: `${auth.username}@${server.replace("https://", "")}`,
2004
- action: async () => {
2005
- await chat();
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];
1453
+ }
1454
+ }
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
1466
+ });
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":
2006
1493
  console.log();
2007
- showStatus();
2008
- }
2009
- });
2010
- items.push({
2011
- key: "w",
2012
- label: "\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uAD00\uB9AC",
2013
- hint: "\uBAA9\uB85D \uC870\uD68C \u2192 \uC120\uD0DD \u2192 \uC2E4\uD589/\uC815\uBCF4",
2014
- action: async () => {
2015
- const { listWorkflows: listWorkflows2 } = await Promise.resolve().then(() => (init_workflow(), workflow_exports));
2016
- const wfs = await listWorkflows2();
2017
- if (!wfs.length) {
2018
- console.log(chalk12.yellow("\n \uC6CC\uD06C\uD50C\uB85C\uC6B0\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.\n"));
2019
- return;
2020
- }
2021
- console.log(chalk12.bold(`
2022
- \uC6CC\uD06C\uD50C\uB85C\uC6B0 (${wfs.length}\uAC1C)
2023
- `));
2024
- wfs.forEach((w, i) => {
2025
- const id = (w.workflow_id ?? w.id ?? "").toString();
2026
- const deployed = w.is_deployed;
2027
- const tag = deployed ? chalk12.green(" [\uBC30\uD3EC]") : "";
2028
- console.log(` ${chalk12.cyan(`${String(i + 1).padStart(3)}.`)} ${w.workflow_name}${tag}`);
2029
- console.log(` ${chalk12.gray(id)}`);
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}`);
2030
1497
  });
2031
- console.log();
2032
- console.log(chalk12.gray(" \uBC88\uD638 \uC785\uB825 \u2192 \uC2E4\uD589 / Enter \u2192 \uB3CC\uC544\uAC00\uAE30"));
2033
- const choice2 = await ask(chalk12.cyan("\n \u276F "));
2034
- if (!choice2) return;
2035
- const wi = parseInt(choice2) - 1;
2036
- if (wi < 0 || wi >= wfs.length) return;
2037
- const selected2 = wfs[wi];
2038
- const wfId = (selected2.workflow_id ?? selected2.id ?? "").toString();
2039
- console.log(chalk12.green(`
2040
- \u2713 ${selected2.workflow_name}
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}
2041
1511
  `));
2042
- const input = await ask(chalk12.white(" \uBA54\uC2DC\uC9C0: "));
2043
- if (!input) return;
2044
- const { workflowRun: workflowRun2 } = await Promise.resolve().then(() => (init_run(), run_exports));
2045
- await workflowRun2(wfId, input, { logs: false, interactive: false });
1512
+ }
1513
+ break;
2046
1514
  }
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}`);
1525
+ }
1526
+ console.log();
1527
+ }
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
2047
1554
  });
2048
- items.push({
2049
- key: "d",
2050
- label: "\uBB38\uC11C \uAD00\uB9AC",
2051
- hint: "\uBB38\uC11C \uBAA9\uB85D \uC870\uD68C",
2052
- action: async () => {
2053
- try {
2054
- const { listDocuments: listDocuments2 } = await Promise.resolve().then(() => (init_document(), document_exports));
2055
- const docs = await listDocuments2();
2056
- if (!docs.length) {
2057
- console.log(chalk12.yellow("\n \uBB38\uC11C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.\n"));
2058
- return;
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();
2059
1565
  }
2060
- console.log(chalk12.bold(`
2061
- \uBB38\uC11C (${docs.length}\uAC1C)
2062
- `));
2063
- docs.forEach((d, i) => {
2064
- console.log(` ${chalk12.cyan(`${i + 1}.`)} ${d.file_name ?? d.name ?? "-"} ${chalk12.gray(d.file_type ?? "")}`);
2065
- });
2066
- console.log();
2067
- } catch (err) {
2068
- console.log(chalk12.red(` \uC624\uB958: ${err.message}
2069
- `));
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");
2070
1571
  }
2071
- }
2072
- });
2073
- items.push({
2074
- key: "o",
2075
- label: "\uC628\uD1A8\uB85C\uC9C0 \uC9C8\uC758",
2076
- hint: "GraphRAG \uC6D0\uC0F7 \uC9C8\uC758",
2077
- action: async () => {
2078
- const question = await ask(chalk12.white("\n \uC9C8\uBB38: "));
2079
- if (!question) return;
2080
- try {
2081
- console.log(chalk12.gray(" \uC9C8\uC758 \uC911...\n"));
2082
- const { queryGraphRAG: queryGraphRAG2 } = await Promise.resolve().then(() => (init_ontology(), ontology_exports));
2083
- const result = await queryGraphRAG2(question);
2084
- if (result.answer) {
2085
- console.log(chalk12.bold(" \uB2F5\uBCC0:"));
2086
- console.log(` ${result.answer}`);
2087
- }
2088
- if (result.sources?.length) {
2089
- console.log(chalk12.bold("\n \uCD9C\uCC98:"));
2090
- result.sources.forEach((s) => console.log(chalk12.gray(` - ${s}`)));
2091
- }
1572
+ },
1573
+ () => {
1574
+ if (hasOutput) {
2092
1575
  console.log();
2093
- } catch (err) {
2094
- console.log(chalk12.red(` \uC624\uB958: ${err.message}
2095
- `));
2096
- }
2097
- }
2098
- });
2099
- items.push({
2100
- key: "h",
2101
- label: "\uC2E4\uD589 \uC774\uB825",
2102
- hint: "\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC2E4\uD589 \uC774\uB825",
2103
- action: async () => {
2104
- try {
2105
- const { getIOLogs: getIOLogs2 } = await Promise.resolve().then(() => (init_workflow(), workflow_exports));
2106
- const logs = await getIOLogs2(void 0, 10);
2107
- if (!logs.length) {
2108
- console.log(chalk12.yellow("\n \uC2E4\uD589 \uC774\uB825\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.\n"));
2109
- return;
2110
- }
2111
- console.log(chalk12.bold(`
2112
- \uCD5C\uADFC \uC2E4\uD589 \uC774\uB825 (${logs.length}\uAC1C)
2113
- `));
2114
- logs.forEach((log, i) => {
2115
- console.log(` ${chalk12.cyan(`${i + 1}.`)} ${chalk12.gray(log.created_at ?? "-")}`);
2116
- console.log(` \uC785\uB825: ${(log.input_data ?? "").slice(0, 50)}`);
2117
- console.log(` \uCD9C\uB825: ${chalk12.gray((log.output_data ?? "").slice(0, 50))}`);
2118
- });
2119
1576
  console.log();
2120
- } catch (err) {
2121
- console.log(chalk12.red(` \uC624\uB958: ${err.message}
2122
- `));
2123
1577
  }
1578
+ if (fullResponse) {
1579
+ history.push({ role: "assistant", content: fullResponse });
1580
+ }
1581
+ },
1582
+ (err) => {
1583
+ process.stdout.write("\r" + " ".repeat(20) + "\r");
1584
+ printError(`\uC2A4\uD2B8\uB9AC\uBC0D \uC624\uB958: ${err.message}`);
2124
1585
  }
2125
- });
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}`);
2126
1591
  }
2127
- items.push({
2128
- key: "s",
2129
- label: hasServer ? "\uC11C\uBC84 \uC7AC\uC124\uC815" : chalk12.bold("XGEN \uC11C\uBC84 \uC5F0\uACB0"),
2130
- hint: hasServer ? "\uC11C\uBC84 \uBCC0\uACBD / \uC7AC\uB85C\uADF8\uC778" : "URL + \uB85C\uADF8\uC778",
2131
- action: async () => {
2132
- await serverSetup();
2133
- showStatus();
2134
- }
2135
- });
2136
- items.push({
2137
- key: "p",
2138
- label: "\uD504\uB85C\uBC14\uC774\uB354 \uAD00\uB9AC",
2139
- hint: `${getProviders().length}\uAC1C \uB4F1\uB85D`,
2140
- action: async () => {
2141
- await providerMenu();
2142
- showStatus();
2143
- }
2144
- });
2145
- items.push({
2146
- key: "e",
2147
- label: "\uD658\uACBD \uAD00\uB9AC",
2148
- hint: `${getEnvironments().length}\uAC1C \uB4F1\uB85D \u2014 \uC11C\uBC84 \uC804\uD658`,
2149
- action: async () => {
2150
- await environmentMenu();
2151
- showStatus();
2152
- }
1592
+ rl.prompt();
1593
+ };
1594
+ rl.setPrompt(getPrompt());
1595
+ rl.prompt();
1596
+ rl.on("line", (line) => {
1597
+ processInput(line).then(() => {
2153
1598
  });
2154
- console.log(divider("\uBA54\uB274"));
2155
- console.log();
2156
- if (hasServer) {
2157
- console.log(chalk12.gray(" AI"));
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();
1615
+
1616
+ // src/commands/agent.ts
1617
+ init_store();
1618
+ import chalk12 from "chalk";
1619
+ import { createInterface as createInterface5 } from "readline";
1620
+
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;
1629
+ }
1630
+ return new OpenAI2(opts);
1631
+ }
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;
1640
+ }
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);
2158
1650
  }
2159
- const aiItem = items.find((i) => i.key === "a");
2160
- console.log(` ${chalk12.cyan.bold(aiItem.key + ".")} ${aiItem.label} ${chalk12.gray("\u2014 " + aiItem.hint)}`);
2161
- if (hasServer) {
2162
- console.log();
2163
- console.log(chalk12.gray(" XGEN \uD50C\uB7AB\uD3FC"));
2164
- for (const item of items.filter((i) => ["c", "w", "r", "d", "o", "h"].includes(i.key))) {
2165
- console.log(` ${chalk12.cyan.bold(item.key + ".")} ${item.label} ${chalk12.gray("\u2014 " + item.hint)}`);
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;
2166
1661
  }
2167
1662
  }
2168
- console.log();
2169
- console.log(chalk12.gray(" \uC124\uC815"));
2170
- for (const item of items.filter((i) => ["s", "p", "e"].includes(i.key))) {
2171
- console.log(` ${chalk12.cyan.bold(item.key + ".")} ${item.label} ${chalk12.gray("\u2014 " + item.hint)}`);
1663
+ }
1664
+ return {
1665
+ content,
1666
+ toolCalls: [...toolCallMap.values()]
1667
+ };
1668
+ }
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"]
2172
1690
  }
2173
- console.log(` ${chalk12.gray("q. \uC885\uB8CC")}`);
2174
- console.log();
2175
- const choice = await ask(chalk12.cyan(" \u276F "));
2176
- if (choice === "q" || choice === "exit") {
2177
- console.log(chalk12.gray("\n \u{1F44B}\n"));
2178
- break;
1691
+ }
1692
+ };
1693
+ async function execute(args) {
1694
+ const path = args.path;
1695
+ const startLine = args.start_line || 1;
1696
+ const endLine = args.end_line;
1697
+ 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");
1702
+ } catch (err) {
1703
+ return `Error: ${err.message}`;
1704
+ }
1705
+ }
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"]
2179
1727
  }
2180
- if (!choice) continue;
2181
- const selected = items.find((i) => i.key === choice);
2182
- if (!selected) {
2183
- console.log(chalk12.red(` "${choice}" \u2014 \uC798\uBABB\uB41C \uC785\uB825
2184
- `));
2185
- continue;
1728
+ }
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}`;
1739
+ }
1740
+ }
1741
+
1742
+ // src/agent/tools/file-edit.ts
1743
+ var file_edit_exports = {};
1744
+ __export(file_edit_exports, {
1745
+ definition: () => definition3,
1746
+ execute: () => execute3
1747
+ });
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"]
2186
1762
  }
2187
- try {
2188
- await selected.action();
2189
- } catch (err) {
2190
- console.log(chalk12.red(`
2191
- \uC624\uB958: ${err.message}
2192
- `));
1763
+ }
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`;
2193
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}`;
2194
1779
  }
2195
1780
  }
2196
- async function serverSetup() {
2197
- console.log();
2198
- console.log(box(["XGEN \uC11C\uBC84 \uC5F0\uACB0"]));
2199
- console.log();
2200
- const currentServer = getServer();
2201
- const urlInput = await ask(
2202
- chalk12.white(` \uC11C\uBC84 URL${currentServer ? chalk12.gray(` [${currentServer}]`) : ""}: `)
2203
- );
2204
- const url = urlInput || currentServer;
2205
- if (!url) {
2206
- console.log(chalk12.red(" URL \uD544\uC694.\n"));
2207
- return;
2208
- }
2209
- const { setServer: setServer2 } = await Promise.resolve().then(() => (init_store(), store_exports));
2210
- setServer2(url);
2211
- console.log(chalk12.green(` \u2713 ${url}
2212
- `));
2213
- const email = await ask(chalk12.white(" \uC774\uBA54\uC77C: "));
2214
- const password = await ask(chalk12.white(" \uBE44\uBC00\uBC88\uD638: "));
2215
- if (!email || !password) {
2216
- console.log(chalk12.red(" \uD544\uC694.\n"));
2217
- return;
1781
+
1782
+ // src/agent/tools/bash.ts
1783
+ var bash_exports = {};
1784
+ __export(bash_exports, {
1785
+ definition: () => definition4,
1786
+ execute: () => execute4
1787
+ });
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
+ }
2218
1801
  }
1802
+ };
1803
+ async function execute4(args) {
1804
+ const command = args.command;
2219
1805
  try {
2220
- const { apiLogin: apiLogin2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
2221
- const { setAuth: setAuth2 } = await Promise.resolve().then(() => (init_store(), store_exports));
2222
- const result = await apiLogin2(email, password);
2223
- if (result.success && result.access_token) {
2224
- setAuth2({
2225
- accessToken: result.access_token,
2226
- refreshToken: result.refresh_token ?? "",
2227
- userId: result.user_id ?? "",
2228
- username: result.username ?? "",
2229
- isAdmin: false,
2230
- expiresAt: null
2231
- });
2232
- console.log(chalk12.green(`
2233
- \u2713 \uB85C\uADF8\uC778 \uC131\uACF5! ${chalk12.bold(result.username ?? email)}
2234
- `));
2235
- } else {
2236
- console.log(chalk12.red(`
2237
- \u2717 ${result.message}
2238
- `));
2239
- }
1806
+ const output = execSync(command, {
1807
+ encoding: "utf-8",
1808
+ timeout: 3e4,
1809
+ maxBuffer: 1024 * 1024,
1810
+ stdio: ["pipe", "pipe", "pipe"]
1811
+ });
1812
+ return output || "(no output)";
2240
1813
  } catch (err) {
2241
- console.log(chalk12.red(`
2242
- \u2717 ${err.message}
2243
- `));
1814
+ const e = err;
1815
+ return (e.stdout || "") + (e.stderr || "") || `Error: ${e.message}`;
2244
1816
  }
2245
1817
  }
2246
- async function providerMenu() {
2247
- const providers = getProviders();
2248
- const defaultP = getDefaultProvider();
2249
- console.log();
2250
- console.log(box(["\uD504\uB85C\uBC14\uC774\uB354 \uAD00\uB9AC"]));
2251
- console.log();
2252
- if (providers.length > 0) {
2253
- for (const p of providers) {
2254
- const mark = p.id === defaultP?.id ? chalk12.green("\u25CF ") : chalk12.gray(" ");
2255
- console.log(` ${mark}${chalk12.bold(p.name)} ${chalk12.gray(`${p.type} \xB7 ${p.model}`)}`);
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"]
2256
1839
  }
2257
- console.log();
2258
- } else {
2259
- console.log(chalk12.gray(" \uC5C6\uC74C\n"));
2260
1840
  }
2261
- const opts = ["\uC0C8\uB85C \uCD94\uAC00"];
2262
- if (providers.length > 1) opts.push("\uAE30\uBCF8 \uBCC0\uACBD");
2263
- if (providers.length > 0) opts.push("\uC0AD\uC81C");
2264
- opts.push("\uB3CC\uC544\uAC00\uAE30");
2265
- opts.forEach((o, i) => console.log(` ${chalk12.cyan(`${i + 1}.`)} ${o}`));
2266
- console.log();
2267
- const c = await ask(chalk12.cyan(" \u276F "));
2268
- const ci = parseInt(c);
2269
- if (ci === 1) {
2270
- await guidedProviderSetup();
2271
- } else if (opts[ci - 1] === "\uAE30\uBCF8 \uBCC0\uACBD") {
2272
- console.log();
2273
- providers.forEach((p, i) => console.log(` ${chalk12.cyan(`${i + 1}.`)} ${p.name} (${p.model})`));
2274
- console.log();
2275
- const pi = parseInt(await ask(chalk12.cyan(" \u276F "))) - 1;
2276
- if (pi >= 0 && pi < providers.length) {
2277
- const { setDefaultProvider: setDefaultProvider2 } = await Promise.resolve().then(() => (init_store(), store_exports));
2278
- setDefaultProvider2(providers[pi].id);
2279
- console.log(chalk12.green(` \u2713 \uAE30\uBCF8: ${providers[pi].name}
2280
- `));
2281
- }
2282
- } else if (opts[ci - 1] === "\uC0AD\uC81C") {
2283
- console.log();
2284
- providers.forEach((p, i) => console.log(` ${chalk12.cyan(`${i + 1}.`)} ${p.name} (${p.model})`));
2285
- console.log();
2286
- const di = parseInt(await ask(chalk12.white(" \uC0AD\uC81C \uBC88\uD638: "))) - 1;
2287
- if (di >= 0 && di < providers.length) {
2288
- const { removeProvider: removeProvider2 } = await Promise.resolve().then(() => (init_store(), store_exports));
2289
- removeProvider2(providers[di].id);
2290
- console.log(chalk12.green(` \u2713 \uC0AD\uC81C: ${providers[di].name}
2291
- `));
2292
- }
1841
+ };
1842
+ async function execute5(args) {
1843
+ const pattern = args.pattern;
1844
+ const path = args.path || ".";
1845
+ const glob = args.glob;
1846
+ 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"]
1855
+ });
1856
+ return output || "\uC77C\uCE58\uD558\uB294 \uACB0\uACFC \uC5C6\uC74C";
1857
+ } catch {
1858
+ return "\uC77C\uCE58\uD558\uB294 \uACB0\uACFC \uC5C6\uC74C";
2293
1859
  }
2294
1860
  }
2295
- async function environmentMenu() {
2296
- const envs = getEnvironments();
2297
- const active = getActiveEnvironment();
2298
- console.log();
2299
- console.log(box(["\uD658\uACBD \uAD00\uB9AC \u2014 XGEN \uC11C\uBC84 \uD504\uB85C\uD544"]));
2300
- console.log();
2301
- if (envs.length > 0) {
2302
- for (const e of envs) {
2303
- const mark = e.id === active?.id ? chalk12.green("\u25CF ") : chalk12.gray(" ");
2304
- console.log(` ${mark}${chalk12.bold(e.name)} ${chalk12.gray(e.url)}`);
2305
- if (e.description) console.log(` ${chalk12.gray(e.description)}`);
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
+ }
2306
1880
  }
2307
- console.log();
2308
- } else {
2309
- console.log(chalk12.gray(" \uB4F1\uB85D\uB41C \uD658\uACBD \uC5C6\uC74C\n"));
2310
1881
  }
2311
- const opts = ["\uC0C8 \uD658\uACBD \uCD94\uAC00", "\uAE30\uBCF8 \uD504\uB9AC\uC14B \uB4F1\uB85D (\uBCF8\uC0AC/\uC81C\uC8FC/\uB86F\uB370\uBAB0)"];
2312
- if (envs.length > 0) opts.push("\uD658\uACBD \uC804\uD658 + \uB85C\uADF8\uC778");
2313
- if (envs.length > 0) opts.push("\uC0AD\uC81C");
2314
- opts.push("\uB3CC\uC544\uAC00\uAE30");
2315
- opts.forEach((o, i) => console.log(` ${chalk12.cyan(`${i + 1}.`)} ${o}`));
2316
- console.log();
2317
- const c = await ask(chalk12.cyan(" \u276F "));
2318
- const ci = parseInt(c);
2319
- if (ci === 1) {
2320
- const name = await ask(chalk12.white(" \uC774\uB984: "));
2321
- const url = await ask(chalk12.white(" URL: "));
2322
- const email = await ask(chalk12.white(" \uC774\uBA54\uC77C (\uC120\uD0DD): "));
2323
- const desc = await ask(chalk12.white(" \uC124\uBA85 (\uC120\uD0DD): "));
2324
- if (name && url) {
2325
- const id = name.toLowerCase().replace(/[^a-z0-9]/g, "-");
2326
- addEnvironment({ id, name, url: url.replace(/\/+$/, ""), email: email || void 0, description: desc || void 0 });
2327
- console.log(chalk12.green(`
2328
- \u2713 ${name} \uCD94\uAC00\uB428
2329
- `));
2330
- }
2331
- } else if (ci === 2) {
2332
- const presets = [
2333
- { id: "hq", name: "\uBCF8\uC0AC (244)", url: "https://xgen.x2bee.com", email: "admin@plateer.com", description: "\uBCF8\uC0AC \uBC30\uD3EC \uD658\uACBD" },
2334
- { id: "jeju", name: "\uC81C\uC8FC (243)", url: "https://jeju-xgen.x2bee.com", email: "admin@plateer.com", description: "\uC81C\uC8FC \uC11C\uBC84" },
2335
- { id: "lotte", name: "\uB86F\uB370\uBAB0 (DGX)", url: "https://lotteimall-xgen.x2bee.com", description: "\uB86F\uB370\uBAB0 DGX Spark" }
2336
- ];
2337
- console.log(chalk12.bold("\n \uAE30\uBCF8 \uD658\uACBD \uD504\uB9AC\uC14B:\n"));
2338
- presets.forEach((p, i) => {
2339
- console.log(` ${chalk12.cyan(`${i + 1}.`)} ${p.name} ${chalk12.gray(p.url)}`);
2340
- });
2341
- console.log(` ${chalk12.cyan(`${presets.length + 1}.`)} \uC804\uBD80 \uB4F1\uB85D`);
2342
- console.log();
2343
- const pc = await ask(chalk12.cyan(" \u276F "));
2344
- const pi = parseInt(pc);
2345
- if (pi === presets.length + 1) {
2346
- for (const p of presets) addEnvironment(p);
2347
- console.log(chalk12.green(` \u2713 ${presets.length}\uAC1C \uD658\uACBD \uB4F1\uB85D\uB428
2348
- `));
2349
- } else if (pi >= 1 && pi <= presets.length) {
2350
- addEnvironment(presets[pi - 1]);
2351
- console.log(chalk12.green(` \u2713 ${presets[pi - 1].name} \uB4F1\uB85D\uB428
2352
- `));
1882
+ };
1883
+ async function execute6(args) {
1884
+ const path = args.path || ".";
1885
+ const pattern = args.pattern;
1886
+ try {
1887
+ let cmd;
1888
+ if (pattern) {
1889
+ cmd = `find "${path}" -name "${pattern}" -type f | head -100`;
1890
+ } else {
1891
+ cmd = `ls -la "${path}"`;
2353
1892
  }
2354
- } else if (opts[ci - 1] === "\uD658\uACBD \uC804\uD658 + \uB85C\uADF8\uC778") {
2355
- console.log();
2356
- envs.forEach((e, i) => {
2357
- const mark = e.id === active?.id ? chalk12.green("\u25CF ") : " ";
2358
- console.log(` ${mark}${chalk12.cyan(`${i + 1}.`)} ${e.name} ${chalk12.gray(e.url)}`);
1893
+ const output = execSync3(cmd, {
1894
+ encoding: "utf-8",
1895
+ timeout: 1e4,
1896
+ stdio: ["pipe", "pipe", "pipe"]
2359
1897
  });
2360
- console.log();
2361
- const ei = parseInt(await ask(chalk12.cyan(" \u276F "))) - 1;
2362
- if (ei >= 0 && ei < envs.length) {
2363
- switchEnvironment(envs[ei].id);
2364
- console.log(chalk12.green(`
2365
- \u2713 ${envs[ei].name} \uC804\uD658\uB428 \u2192 ${envs[ei].url}`));
2366
- if (envs[ei].email) {
2367
- const pw = await ask(chalk12.white(` \uBE44\uBC00\uBC88\uD638 (${envs[ei].email}): `));
2368
- if (pw) {
2369
- try {
2370
- const { apiLogin: apiLogin2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
2371
- const { setAuth: setAuth2 } = await Promise.resolve().then(() => (init_store(), store_exports));
2372
- const result = await apiLogin2(envs[ei].email, pw);
2373
- if (result.success && result.access_token) {
2374
- setAuth2({ accessToken: result.access_token, refreshToken: result.refresh_token ?? "", userId: result.user_id ?? "", username: result.username ?? "", isAdmin: false, expiresAt: null });
2375
- console.log(chalk12.green(` \u2713 \uB85C\uADF8\uC778: ${result.username}
2376
- `));
2377
- } else {
2378
- console.log(chalk12.red(` \u2717 ${result.message}
2379
- `));
2380
- }
2381
- } catch (err) {
2382
- console.log(chalk12.red(` \u2717 ${err.message}
2383
- `));
2384
- }
2385
- }
2386
- }
2387
- console.log();
2388
- }
2389
- } else if (opts[ci - 1] === "\uC0AD\uC81C") {
2390
- console.log();
2391
- envs.forEach((e, i) => console.log(` ${chalk12.cyan(`${i + 1}.`)} ${e.name}`));
2392
- console.log();
2393
- const di = parseInt(await ask(chalk12.white(" \uC0AD\uC81C \uBC88\uD638: "))) - 1;
2394
- if (di >= 0 && di < envs.length) {
2395
- removeEnvironment(envs[di].id);
2396
- console.log(chalk12.green(` \u2713 \uC0AD\uC81C: ${envs[di].name}
2397
- `));
2398
- }
1898
+ return output || "(empty)";
1899
+ } catch (err) {
1900
+ return `Error: ${err.message}`;
2399
1901
  }
2400
1902
  }
2401
- var init_home = __esm({
2402
- "src/commands/home.ts"() {
2403
- "use strict";
2404
- init_store();
2405
- init_ui();
2406
- init_agent();
2407
- init_chat();
2408
- init_provider();
2409
- }
2410
- });
2411
1903
 
2412
- // src/commands/agent.ts
2413
- import chalk13 from "chalk";
2414
- import { createInterface as createInterface5 } from "readline";
2415
- async function agentRepl() {
2416
- let provider = getDefaultProvider();
2417
- if (!provider) {
2418
- provider = await guidedProviderSetup();
2419
- if (!provider) {
2420
- process.exit(1);
2421
- }
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 });
2422
1918
  }
2423
- const client2 = createLLMClient(provider);
2424
- const builtinTools = getAllToolDefs();
2425
- const allTools = [...builtinTools];
2426
- const allToolNames = [...getToolNames()];
2427
- const mcpConfig = loadMcpConfig();
2428
- if (mcpConfig && Object.keys(mcpConfig.mcpServers).length > 0) {
2429
- mcpManager = new McpManager();
2430
- try {
2431
- await mcpManager.startAll(mcpConfig);
2432
- if (mcpManager.serverCount > 0) {
2433
- const mcpTools = mcpManager.getAllTools();
2434
- allTools.push(...mcpTools);
2435
- allToolNames.push(...mcpTools.map((t) => t.function.name));
2436
- }
2437
- } catch {
1919
+ return SANDBOX_DIR;
1920
+ }
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"]
2438
1942
  }
2439
1943
  }
2440
- const messages = [{ role: "system", content: SYSTEM_PROMPT }];
2441
- console.log();
2442
- console.log(box([
2443
- `${chalk13.bold("OPEN XGEN Agent")}`,
2444
- ``,
2445
- `${chalk13.gray("\uD504\uB85C\uBC14\uC774\uB354")} ${provider.name} ${chalk13.gray("\xB7")} ${provider.model}`,
2446
- `${chalk13.gray("\uB3C4\uAD6C")} ${getToolNames().length}\uAC1C \uB0B4\uC7A5${mcpManager && mcpManager.serverCount > 0 ? ` + ${mcpManager.getAllTools().length}\uAC1C MCP` : ""}`,
2447
- ``,
2448
- `${chalk13.gray("\uBB34\uC5C7\uC774\uB4E0 \uBB3C\uC5B4\uBCF4\uC138\uC694. \uD30C\uC77C \uC77D\uAE30/\uC4F0\uAE30, \uCF54\uB4DC \uC2E4\uD589, \uAC80\uC0C9 \uAC00\uB2A5.")}`,
2449
- `${chalk13.gray("/help \uB3C4\uC6C0\uB9D0 \xB7 /home \uD648 \xB7 /exit \uC885\uB8CC")}`
2450
- ]));
2451
- console.log();
2452
- const rl = createInterface5({ input: process.stdin, output: process.stdout });
2453
- const askUser = () => new Promise((resolve) => rl.question(chalk13.cyan.bold(" \u276F "), (a) => resolve(a.trim())));
2454
- process.on("SIGINT", () => {
2455
- console.log(chalk13.gray("\n\uC885\uB8CC\uD569\uB2C8\uB2E4."));
2456
- mcpManager?.stopAll();
2457
- rl.close();
2458
- process.exit(0);
2459
- });
2460
- while (true) {
2461
- const input = await askUser();
2462
- if (!input) continue;
2463
- if (input === "exit" || input === "/exit") {
2464
- console.log(chalk13.gray("\uC885\uB8CC\uD569\uB2C8\uB2E4."));
2465
- mcpManager?.stopAll();
2466
- rl.close();
2467
- break;
2468
- }
2469
- if (input === "/help") {
2470
- console.log();
2471
- console.log(chalk13.bold(" \uC2AC\uB798\uC2DC \uCEE4\uB9E8\uB4DC"));
2472
- console.log(chalk13.gray(" \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"));
2473
- console.log(` ${chalk13.cyan("/tools")} \uC0AC\uC6A9 \uAC00\uB2A5\uD55C \uB3C4\uAD6C \uBAA9\uB85D`);
2474
- console.log(` ${chalk13.cyan("/provider")} \uD604\uC7AC \uD504\uB85C\uBC14\uC774\uB354 \uC815\uBCF4`);
2475
- console.log(` ${chalk13.cyan("/model")} \uB4F1\uB85D\uB41C \uD504\uB85C\uBC14\uC774\uB354 \uBAA9\uB85D`);
2476
- console.log(` ${chalk13.cyan("/mcp")} MCP \uC11C\uBC84 \uC0C1\uD0DC`);
2477
- console.log(` ${chalk13.cyan("/clear")} \uB300\uD654 \uCD08\uAE30\uD654`);
2478
- console.log(` ${chalk13.cyan("/home")} \uD648 \uBA54\uB274\uB85C \uB3CC\uC544\uAC00\uAE30`);
2479
- console.log(` ${chalk13.cyan("/exit")} \uC885\uB8CC`);
2480
- console.log();
2481
- continue;
2482
- }
2483
- if (input === "/clear") {
2484
- messages.length = 1;
2485
- console.log(chalk13.gray(" \uB300\uD654 \uCD08\uAE30\uD654\uB428.\n"));
2486
- continue;
2487
- }
2488
- if (input === "/tools") {
2489
- console.log(chalk13.bold("\n\uB0B4\uC7A5 \uB3C4\uAD6C:"), getToolNames().join(", "));
2490
- if (mcpManager && mcpManager.serverCount > 0) {
2491
- console.log(chalk13.bold("MCP \uB3C4\uAD6C:"), mcpManager.getAllTools().map((t) => t.function.name).join(", "));
2492
- }
2493
- console.log();
2494
- continue;
2495
- }
2496
- if (input === "/provider") {
2497
- console.log(chalk13.gray(`\uD604\uC7AC: ${provider.name} (${provider.model})`));
2498
- console.log(chalk13.gray(`\uBCC0\uACBD: xgen provider add / xgen provider use <id>
2499
- `));
2500
- continue;
2501
- }
2502
- if (input === "/model") {
2503
- const { getProviders: gp } = await Promise.resolve().then(() => (init_store(), store_exports));
2504
- const all = gp();
2505
- if (all.length > 0) {
2506
- console.log(chalk13.bold("\n \uB4F1\uB85D\uB41C \uD504\uB85C\uBC14\uC774\uB354:\n"));
2507
- all.forEach((p, i) => {
2508
- const mark = p.id === provider.id ? chalk13.green("\u25CF ") : " ";
2509
- console.log(` ${mark}${i + 1}) ${p.name} (${p.model})`);
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"]
2510
1962
  });
2511
- console.log(chalk13.gray("\n \uBCC0\uACBD\uD558\uB824\uBA74 exit \uD6C4 xgen provider use <id>\n"));
2512
- }
2513
- continue;
2514
- }
2515
- if (input === "/home" || input === "/menu") {
2516
- console.log(chalk13.gray("\uC5D0\uC774\uC804\uD2B8\uB97C \uC885\uB8CC\uD558\uACE0 \uD648\uC73C\uB85C \uB3CC\uC544\uAC11\uB2C8\uB2E4."));
2517
- mcpManager?.stopAll();
2518
- rl.close();
2519
- const { homeMenu: homeMenu2 } = await Promise.resolve().then(() => (init_home(), home_exports));
2520
- await homeMenu2();
2521
- return;
2522
- }
2523
- if (input === "/mcp") {
2524
- if (mcpManager && mcpManager.serverCount > 0) {
2525
- console.log(chalk13.bold("\nMCP \uC11C\uBC84:"), mcpManager.getServerNames().join(", "));
2526
- console.log(chalk13.gray("\uB3C4\uAD6C:"), mcpManager.getAllTools().map((t) => t.function.name).join(", "));
2527
1963
  } else {
2528
- console.log(chalk13.gray("MCP \uC11C\uBC84 \uC5C6\uC74C. .mcp.json\uC744 \uD504\uB85C\uC81D\uD2B8 \uB8E8\uD2B8\uC5D0 \uCD94\uAC00\uD558\uC138\uC694."));
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
+ });
2529
1972
  }
2530
- console.log();
2531
- continue;
2532
1973
  }
2533
- messages.push({ role: "user", content: input });
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}`;
1984
+ } else {
1985
+ filename = "script.mjs";
1986
+ writeFileSync4(join2(runDir, filename), code, "utf-8");
1987
+ cmd = `node ${filename}`;
1988
+ }
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 {
2534
2001
  try {
2535
- await runAgentLoop(client2, provider.model, messages, allTools);
2536
- } catch (err) {
2537
- console.log(chalk13.red(`
2538
- \uC624\uB958: ${err.message}
2539
- `));
2002
+ rmSync(runDir, { recursive: true, force: true });
2003
+ } catch {
2004
+ }
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);
2024
+ }
2025
+
2026
+ // src/agent/tools/xgen-api.ts
2027
+ 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: {} }
2035
+ }
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
+ }
2540
2052
  }
2541
- }
2542
- }
2543
- async function runAgentLoop(client2, model, messages, tools2) {
2544
- const MAX_ITERATIONS = 20;
2545
- for (let i = 0; i < MAX_ITERATIONS; i++) {
2546
- let first = true;
2547
- const result = await streamChat(client2, model, messages, tools2, (delta) => {
2548
- if (first) {
2549
- process.stdout.write(chalk13.green("\n AI \u203A") + " ");
2550
- first = false;
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"]
2551
2065
  }
2552
- process.stdout.write(delta);
2553
- });
2554
- if (result.content) {
2555
- process.stdout.write("\n\n");
2556
2066
  }
2557
- if (result.toolCalls.length === 0) {
2558
- if (result.content) {
2559
- messages.push({ role: "assistant", content: result.content });
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
+ }
2560
2078
  }
2561
- return;
2562
2079
  }
2563
- messages.push({
2564
- role: "assistant",
2565
- content: result.content || null,
2566
- tool_calls: result.toolCalls.map((tc) => ({
2567
- id: tc.id,
2568
- type: "function",
2569
- function: { name: tc.name, arguments: tc.arguments }
2570
- }))
2571
- });
2572
- for (const tc of result.toolCalls) {
2573
- let args;
2574
- try {
2575
- args = JSON.parse(tc.arguments);
2576
- } catch {
2577
- args = {};
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"]
2578
2093
  }
2579
- console.log(chalk13.gray(` \u2699 `) + chalk13.white.bold(tc.name) + chalk13.gray(` ${summarizeArgs(args)}`));
2580
- let toolResult;
2581
- if (mcpManager?.isMcpTool(tc.name)) {
2582
- toolResult = await mcpManager.callTool(tc.name, args);
2583
- } else {
2584
- toolResult = await executeTool(tc.name, args);
2094
+ }
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: {} }
2102
+ }
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)" }
2113
+ }
2585
2114
  }
2586
- const truncated = toolResult.length > 4e3 ? toolResult.slice(0, 4e3) + "\n...(truncated)" : toolResult;
2587
- messages.push({
2588
- role: "tool",
2589
- tool_call_id: tc.id,
2590
- content: truncated
2591
- });
2592
2115
  }
2593
2116
  }
2594
- console.log(chalk13.yellow("\n\uCD5C\uB300 \uBC18\uBCF5 \uD69F\uC218\uC5D0 \uB3C4\uB2EC\uD588\uC2B5\uB2C8\uB2E4.\n"));
2595
- }
2596
- function summarizeArgs(args) {
2597
- const parts = [];
2598
- for (const [k, v] of Object.entries(args)) {
2599
- const s = String(v);
2600
- parts.push(`${k}: ${s.length > 40 ? s.slice(0, 40) + "..." : s}`);
2601
- }
2602
- return parts.join(", ");
2603
- }
2604
- function registerAgentCommand(program2) {
2605
- program2.command("agent").description("OPEN XGEN AI \uCF54\uB529 \uC5D0\uC774\uC804\uD2B8").action(async () => {
2606
- await agentRepl();
2607
- });
2608
- }
2609
- var SYSTEM_PROMPT, mcpManager;
2610
- var init_agent = __esm({
2611
- "src/commands/agent.ts"() {
2612
- "use strict";
2613
- init_store();
2614
- init_llm();
2615
- init_tools();
2616
- init_client2();
2617
- init_provider();
2618
- init_ui();
2619
- SYSTEM_PROMPT = `You are OPEN XGEN Agent, an AI coding assistant running in the user's terminal.
2620
- You have access to tools for reading/writing files, executing commands, searching code, and running sandboxed code.
2621
- You can also use MCP (Model Context Protocol) tools if available.
2622
- Always respond in the same language as the user.
2623
- When using tools, be concise about what you're doing.
2624
- For file edits, show what you changed briefly.
2625
- For sandbox_run, you can install npm/pip packages and run isolated code.`;
2626
- mcpManager = null;
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.";
2627
2123
  }
2628
- });
2629
-
2630
- // src/index.ts
2631
- import { Command } from "commander";
2632
- import chalk16 from "chalk";
2633
-
2634
- // src/commands/config.ts
2635
- init_store();
2636
- init_client();
2637
- init_format();
2638
- import chalk2 from "chalk";
2639
- function registerConfigCommand(program2) {
2640
- const config = program2.command("config").description("XGEN CLI \uC124\uC815 \uAD00\uB9AC");
2641
- config.command("set-server <url>").description("XGEN \uC11C\uBC84 URL \uC124\uC815").action((url) => {
2642
- if (!url.startsWith("http://") && !url.startsWith("https://")) {
2643
- printError("URL\uC740 http:// \uB610\uB294 https://\uB85C \uC2DC\uC791\uD574\uC57C \uD569\uB2C8\uB2E4");
2644
- process.exit(1);
2645
- }
2646
- setServer(url);
2647
- resetClient();
2648
- printSuccess(`\uC11C\uBC84 \uC124\uC815 \uC644\uB8CC: ${chalk2.underline(url)}`);
2649
- });
2650
- config.command("get-server").description("\uD604\uC7AC \uC124\uC815\uB41C \uC11C\uBC84 URL \uD655\uC778").action(() => {
2651
- const server = getServer();
2652
- if (server) {
2653
- console.log(server);
2654
- } else {
2655
- printError("\uC11C\uBC84\uAC00 \uC124\uC815\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4");
2656
- console.log(" \uC124\uC815: xgen config set-server <url>");
2657
- }
2658
- });
2659
- config.command("list").description("\uC804\uCCB4 \uC124\uC815 \uD655\uC778").action(() => {
2660
- const cfg = getConfig();
2661
- console.log(chalk2.bold("\nXGEN CLI \uC124\uC815"));
2662
- console.log(chalk2.gray("\u2500".repeat(40)));
2663
- printKeyValue("\uC11C\uBC84", cfg.server);
2664
- printKeyValue("\uAE30\uBCF8 \uC6CC\uD06C\uD50C\uB85C\uC6B0", cfg.defaultWorkflow);
2665
- printKeyValue("\uD14C\uB9C8", cfg.theme);
2666
- printKeyValue("\uC2A4\uD2B8\uB9BC \uB85C\uADF8", String(cfg.streamLogs));
2667
- console.log();
2668
- });
2669
- config.command("set <key> <value>").description("\uC124\uC815 \uAC12 \uBCC0\uACBD").action((key, value) => {
2670
- const allowedKeys = ["defaultWorkflow", "theme", "streamLogs"];
2671
- if (!allowedKeys.includes(key)) {
2672
- printError(`\uC54C \uC218 \uC5C6\uB294 \uC124\uC815 \uD0A4: ${key}`);
2673
- console.log(` \uC0AC\uC6A9 \uAC00\uB2A5: ${allowedKeys.join(", ")}`);
2674
- process.exit(1);
2124
+ 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}`;
2675
2142
  }
2676
- const parsed = key === "streamLogs" ? value === "true" : value;
2677
- setConfig({ [key]: parsed });
2678
- printSuccess(`${key} = ${value}`);
2143
+ } catch (err) {
2144
+ return `XGEN API \uC624\uB958: ${err.message}`;
2145
+ }
2146
+ }
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
2679
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");
2680
2223
  }
2681
2224
 
2682
- // src/commands/login.ts
2683
- init_auth();
2684
- init_store();
2685
- init_format();
2686
- import chalk3 from "chalk";
2687
- import { createInterface } from "readline";
2688
- function prompt(question, hidden = false) {
2689
- return new Promise((resolve) => {
2690
- const rl = createInterface({
2691
- input: process.stdin,
2692
- output: process.stdout
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 }
2693
2245
  });
2694
- if (hidden) {
2695
- process.stdout.write(question);
2696
- const stdin = process.stdin;
2697
- const wasRaw = stdin.isRaw;
2698
- if (stdin.isTTY) stdin.setRawMode(true);
2699
- let password = "";
2700
- const onData = (ch) => {
2701
- const c = ch.toString("utf8");
2702
- if (c === "\n" || c === "\r" || c === "") {
2703
- if (stdin.isTTY) stdin.setRawMode(wasRaw ?? false);
2704
- stdin.removeListener("data", onData);
2705
- process.stdout.write("\n");
2706
- rl.close();
2707
- resolve(password);
2708
- } else if (c === "") {
2709
- process.exit(0);
2710
- } else if (c === "\x7F" || c === "\b") {
2711
- if (password.length > 0) {
2712
- password = password.slice(0, -1);
2713
- process.stdout.write("\b \b");
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);
2714
2257
  }
2715
- } else {
2716
- password += c;
2717
- process.stdout.write("*");
2718
2258
  }
2719
- };
2720
- stdin.on("data", onData);
2721
- } else {
2722
- rl.question(question, (answer) => {
2723
- rl.close();
2724
- resolve(answer.trim());
2259
+ } catch {
2260
+ }
2261
+ });
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);
2289
+ }
2725
2290
  });
2291
+ this.process?.stdin?.write(JSON.stringify(request) + "\n");
2292
+ });
2293
+ }
2294
+ async listTools() {
2295
+ const result = await this.send("tools/list", {});
2296
+ this.tools = result.tools ?? [];
2297
+ return this.tools;
2298
+ }
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") ?? "";
2302
+ }
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: {} }
2310
+ }
2311
+ }));
2312
+ }
2313
+ stop() {
2314
+ this.process?.kill();
2315
+ this.process = null;
2316
+ }
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;
2330
+ }
2726
2331
  }
2727
- });
2332
+ }
2333
+ return null;
2728
2334
  }
2729
- function registerLoginCommand(program2) {
2730
- 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) => {
2731
- const server = requireServer();
2732
- printHeader("XGEN Login");
2733
- console.log(chalk3.gray(`\uC11C\uBC84: ${server}
2734
- `));
2735
- let email = opts.email;
2736
- let password = opts.password;
2737
- if (!email) {
2738
- email = await prompt(chalk3.white("\uC774\uBA54\uC77C: "));
2739
- }
2740
- if (!password) {
2741
- password = await prompt(chalk3.white("\uBE44\uBC00\uBC88\uD638: "), true);
2742
- }
2743
- if (!email || !password) {
2744
- printError("\uC774\uBA54\uC77C\uACFC \uBE44\uBC00\uBC88\uD638\uB97C \uBAA8\uB450 \uC785\uB825\uD558\uC138\uC694");
2745
- process.exit(1);
2746
- }
2747
- try {
2748
- const result = await apiLogin(email, password);
2749
- if (result.success && result.access_token) {
2750
- setAuth({
2751
- accessToken: result.access_token,
2752
- refreshToken: result.refresh_token ?? "",
2753
- userId: result.user_id ?? "",
2754
- username: result.username ?? "",
2755
- isAdmin: false,
2756
- expiresAt: null
2757
- });
2758
- console.log();
2759
- printSuccess(`\uB85C\uADF8\uC778 \uC131\uACF5! ${chalk3.bold(result.username ?? email)}`);
2760
- } else {
2761
- printError(result.message || "\uB85C\uADF8\uC778 \uC2E4\uD328");
2762
- process.exit(1);
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);
2763
2347
  }
2764
- } catch (err) {
2765
- const msg = err?.response?.data?.message ?? err?.response?.data?.detail ?? err.message;
2766
- printError(`\uB85C\uADF8\uC778 \uC2E4\uD328: ${msg}`);
2767
- process.exit(1);
2768
2348
  }
2769
- });
2770
- program2.command("logout").description("\uB85C\uADF8\uC544\uC6C3").action(async () => {
2771
- const { clearAuth: clearAuth2 } = await Promise.resolve().then(() => (init_store(), store_exports));
2772
- clearAuth2();
2773
- printSuccess("\uB85C\uADF8\uC544\uC6C3 \uC644\uB8CC");
2774
- });
2775
- program2.command("whoami").description("\uD604\uC7AC \uB85C\uADF8\uC778\uB41C \uC0AC\uC6A9\uC790 \uC815\uBCF4").action(async () => {
2776
- const auth = getAuth();
2777
- if (!auth) {
2778
- printError("\uB85C\uADF8\uC778\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. xgen login \uC2E4\uD589\uD558\uC138\uC694");
2779
- process.exit(1);
2349
+ }
2350
+ getAllTools() {
2351
+ const tools2 = [];
2352
+ for (const client2 of this.clients.values()) {
2353
+ tools2.push(...client2.getOpenAITools());
2780
2354
  }
2781
- const server = requireServer();
2782
- console.log(chalk3.bold("\n\uD604\uC7AC \uC0AC\uC6A9\uC790"));
2783
- console.log(chalk3.gray("\u2500".repeat(30)));
2784
- console.log(` ${chalk3.gray("\uC11C\uBC84:")} ${server}`);
2785
- console.log(` ${chalk3.gray("\uC0AC\uC6A9\uC790:")} ${chalk3.bold(auth.username)}`);
2786
- console.log(` ${chalk3.gray("User ID:")} ${auth.userId}`);
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
+
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 += `
2412
+
2413
+ ## XGEN Server: Not connected
2414
+ Tell the user to run /connect to connect to an XGEN server.`;
2415
+ }
2416
+ return prompt2;
2417
+ }
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();
2787
2431
  try {
2788
- const { apiValidate: apiValidate2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
2789
- const result = await apiValidate2(auth.accessToken);
2790
- if (result.valid) {
2791
- console.log(` ${chalk3.gray("\uC0C1\uD0DC:")} ${chalk3.green("\uD65C\uC131")}`);
2792
- if (result.is_admin) {
2793
- console.log(` ${chalk3.gray("\uAD8C\uD55C:")} ${chalk3.yellow("\uAD00\uB9AC\uC790")}`);
2794
- }
2795
- if (result.user_type) {
2796
- console.log(` ${chalk3.gray("\uC720\uD615:")} ${result.user_type}`);
2797
- }
2798
- } else {
2799
- console.log(` ${chalk3.gray("\uC0C1\uD0DC:")} ${chalk3.red("\uD1A0\uD070 \uB9CC\uB8CC")}`);
2800
- }
2432
+ await mcpManager.startAll(mcpConfig);
2433
+ if (mcpManager.serverCount > 0) allTools.push(...mcpManager.getAllTools());
2801
2434
  } catch {
2802
- console.log(` ${chalk3.gray("\uC0C1\uD0DC:")} ${chalk3.yellow("\uAC80\uC99D \uBD88\uAC00 (\uC11C\uBC84 \uC5F0\uACB0 \uC2E4\uD328)")}`);
2803
2435
  }
2804
- console.log();
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);
2805
2457
  });
2806
- }
2807
-
2808
- // src/commands/workflow/list.ts
2809
- init_store();
2810
- init_workflow();
2811
- init_format();
2812
- import chalk4 from "chalk";
2813
- async function workflowList(opts) {
2814
- requireAuth();
2815
- try {
2816
- if (opts.detail) {
2817
- const workflows = await getWorkflowListDetail();
2818
- if (!workflows || workflows.length === 0) {
2819
- console.log(chalk4.yellow("\n\uC6CC\uD06C\uD50C\uB85C\uC6B0\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.\n"));
2820
- return;
2821
- }
2822
- printHeader(`\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D (${workflows.length}\uAC1C)`);
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();
2823
2491
  console.log();
2824
- printTable(
2825
- ["#", "ID", "\uC774\uB984", "\uBC30\uD3EC", "\uC5C5\uB370\uC774\uD2B8"],
2826
- workflows.map((w, i) => [
2827
- String(i + 1),
2828
- (w.workflow_id ?? w.id ?? "-").slice(0, 12),
2829
- truncate(w.workflow_name ?? "-", 30),
2830
- w.is_deployed ? chalk4.green("\uBC30\uD3EC\uB428") : chalk4.gray("\uBBF8\uBC30\uD3EC"),
2831
- formatDate(w.updated_at)
2832
- ])
2833
- );
2834
- } else {
2835
- const workflows = await listWorkflows();
2836
- if (!workflows || workflows.length === 0) {
2837
- console.log(chalk4.yellow("\n\uC6CC\uD06C\uD50C\uB85C\uC6B0\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.\n"));
2838
- return;
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(", ")}`);
2839
2497
  }
2840
- printHeader(`\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D (${workflows.length}\uAC1C)`);
2841
2498
  console.log();
2842
- printTable(
2843
- ["#", "ID", "\uC774\uB984"],
2844
- workflows.map((w, i) => [
2845
- String(i + 1),
2846
- (w.workflow_id ?? w.id ?? "-").slice(0, 12),
2847
- w.workflow_name ?? "-"
2848
- ])
2849
- );
2499
+ continue;
2850
2500
  }
2851
- console.log();
2852
- } catch (err) {
2853
- const msg = err.message;
2854
- printError(`\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D \uC870\uD68C \uC2E4\uD328: ${msg}`);
2855
- process.exit(1);
2856
- }
2857
- }
2858
-
2859
- // src/commands/workflow/info.ts
2860
- init_store();
2861
- init_workflow();
2862
- init_format();
2863
- import chalk5 from "chalk";
2864
- async function workflowInfo(workflowId) {
2865
- requireAuth();
2866
- try {
2867
- const detail = await getWorkflowDetail(workflowId);
2868
- printHeader(`\uC6CC\uD06C\uD50C\uB85C\uC6B0: ${detail.workflow_name ?? workflowId}`);
2869
- console.log();
2870
- printKeyValue("ID", detail.id);
2871
- printKeyValue("\uC774\uB984", detail.workflow_name);
2872
- printKeyValue("\uC124\uBA85", detail.description ?? "(\uC5C6\uC74C)");
2873
- if (detail.nodes && Array.isArray(detail.nodes)) {
2874
- console.log();
2875
- console.log(chalk5.bold(" \uB178\uB4DC \uAD6C\uC131:"));
2876
- for (const node of detail.nodes) {
2877
- const label = node.data?.label ?? node.id;
2878
- const type = node.data?.type ?? "unknown";
2879
- console.log(` ${chalk5.cyan("\u2022")} ${label} ${chalk5.gray(`(${type})`)}`);
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(", ")}`);
2880
2507
  }
2881
- }
2882
- if (detail.parameters && Object.keys(detail.parameters).length > 0) {
2883
2508
  console.log();
2884
- console.log(chalk5.bold(" \uD30C\uB77C\uBBF8\uD130:"));
2885
- for (const [key, val] of Object.entries(detail.parameters)) {
2886
- console.log(` ${chalk5.gray(key)}: ${JSON.stringify(val)}`);
2887
- }
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
+ `));
2888
2534
  }
2889
- console.log();
2890
- } catch (err) {
2891
- const msg = err.message;
2892
- printError(`\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC870\uD68C \uC2E4\uD328: ${msg}`);
2893
- process.exit(1);
2894
2535
  }
2895
2536
  }
2896
-
2897
- // src/commands/workflow/index.ts
2898
- init_run();
2899
-
2900
- // src/commands/workflow/history.ts
2901
- init_store();
2902
- init_workflow();
2903
- init_format();
2904
- import chalk8 from "chalk";
2905
- async function workflowHistory(workflowId, opts = {}) {
2906
- requireAuth();
2907
- const limit = opts.limit ?? 20;
2908
- try {
2909
- const logs = await getIOLogs(workflowId, limit);
2910
- if (!logs || logs.length === 0) {
2911
- console.log(chalk8.yellow("\n\uC2E4\uD589 \uC774\uB825\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.\n"));
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 });
2912
2550
  return;
2913
2551
  }
2914
- printHeader(`\uC2E4\uD589 \uC774\uB825 (\uCD5C\uADFC ${logs.length}\uAC74)`);
2915
- console.log();
2916
- for (const log of logs) {
2917
- console.log(
2918
- ` ${chalk8.gray(formatDate(log.created_at))} ${chalk8.cyan(log.interaction_id)}`
2919
- );
2920
- console.log(` ${chalk8.white("\uC785\uB825:")} ${truncate(log.input_data, 60)}`);
2921
- console.log(
2922
- ` ${chalk8.green("\uCD9C\uB825:")} ${truncate(log.output_data, 60)}`
2923
- );
2924
- if (log.execution_time) {
2925
- console.log(
2926
- ` ${chalk8.gray("\uC2DC\uAC04:")} ${(log.execution_time / 1e3).toFixed(1)}s`
2927
- );
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 = {};
2928
2567
  }
2929
- console.log();
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
+ }
2584
+ }
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;
2610
+ }
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
2623
+ `));
2624
+ } else {
2625
+ console.log(chalk12.red(` \u2717 ${result.message}
2626
+ `));
2930
2627
  }
2931
2628
  } catch (err) {
2932
- const msg = err.message;
2933
- printError(`\uC774\uB825 \uC870\uD68C \uC2E4\uD328: ${msg}`);
2934
- process.exit(1);
2629
+ console.log(chalk12.red(` \u2717 ${err.message}
2630
+ `));
2935
2631
  }
2936
2632
  }
2937
-
2938
- // src/commands/workflow/index.ts
2939
- function registerWorkflowCommand(program2) {
2940
- const wf = program2.command("workflow").alias("wf").description("\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uAD00\uB9AC \uBC0F \uC2E4\uD589");
2941
- 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));
2942
- wf.command("info <workflow-id>").description("\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC0C1\uC138 \uC815\uBCF4").action((id) => workflowInfo(id));
2943
- 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));
2944
- 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) }));
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
+ }
2640
+ const active = getActiveEnvironment();
2641
+ 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)}`);
2645
+ });
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}
2651
+ `));
2652
+ }
2653
+ }
2654
+ function registerAgentCommand(program2) {
2655
+ program2.command("agent").description("OPEN XGEN AI \uC5D0\uC774\uC804\uD2B8").action(async () => {
2656
+ await agentRepl();
2657
+ });
2945
2658
  }
2946
-
2947
- // src/index.ts
2948
- init_chat();
2949
- init_provider();
2950
- init_agent();
2951
2659
 
2952
2660
  // src/commands/doc.ts
2953
2661
  init_store();
2954
2662
  init_document();
2955
2663
  init_format();
2956
- import chalk14 from "chalk";
2664
+ import chalk13 from "chalk";
2957
2665
  function registerDocCommand(program2) {
2958
2666
  const doc = program2.command("doc").description("\uBB38\uC11C \uAD00\uB9AC");
2959
2667
  doc.command("list").alias("ls").description("\uBB38\uC11C \uBAA9\uB85D \uC870\uD68C").option("-c, --collection <id>", "\uCEEC\uB809\uC158 ID").action(async (opts) => {
@@ -2961,7 +2669,7 @@ function registerDocCommand(program2) {
2961
2669
  try {
2962
2670
  const docs = await listDocuments(opts.collection);
2963
2671
  if (!docs.length) {
2964
- console.log(chalk14.yellow("\n\uBB38\uC11C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.\n"));
2672
+ console.log(chalk13.yellow("\n\uBB38\uC11C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.\n"));
2965
2673
  return;
2966
2674
  }
2967
2675
  printHeader(`\uBB38\uC11C \uBAA9\uB85D (${docs.length}\uAC1C)`);
@@ -2985,10 +2693,10 @@ function registerDocCommand(program2) {
2985
2693
  doc.command("upload <file>").description("\uBB38\uC11C \uC5C5\uB85C\uB4DC").option("-c, --collection <id>", "\uCEEC\uB809\uC158 ID").option("-n, --name <name>", "\uD30C\uC77C\uBA85").action(async (file, opts) => {
2986
2694
  requireAuth();
2987
2695
  try {
2988
- console.log(chalk14.gray(`\uC5C5\uB85C\uB4DC \uC911: ${file}`));
2696
+ console.log(chalk13.gray(`\uC5C5\uB85C\uB4DC \uC911: ${file}`));
2989
2697
  const result = await uploadDocument(file, opts.collection, opts.name);
2990
- console.log(chalk14.green("\u2713 \uC5C5\uB85C\uB4DC \uC644\uB8CC"));
2991
- console.log(chalk14.gray(JSON.stringify(result, null, 2)));
2698
+ console.log(chalk13.green("\u2713 \uC5C5\uB85C\uB4DC \uC644\uB8CC"));
2699
+ console.log(chalk13.gray(JSON.stringify(result, null, 2)));
2992
2700
  } catch (err) {
2993
2701
  printError(`\uC5C5\uB85C\uB4DC \uC2E4\uD328: ${err.message}`);
2994
2702
  }
@@ -2998,7 +2706,7 @@ function registerDocCommand(program2) {
2998
2706
  try {
2999
2707
  const d = await getDocumentInfo(id);
3000
2708
  printHeader("\uBB38\uC11C \uC815\uBCF4");
3001
- console.log(chalk14.gray(JSON.stringify(d, null, 2)));
2709
+ console.log(chalk13.gray(JSON.stringify(d, null, 2)));
3002
2710
  } catch (err) {
3003
2711
  printError(`\uC870\uD68C \uC2E4\uD328: ${err.message}`);
3004
2712
  }
@@ -3009,7 +2717,7 @@ function registerDocCommand(program2) {
3009
2717
  init_store();
3010
2718
  init_ontology();
3011
2719
  init_format();
3012
- import chalk15 from "chalk";
2720
+ import chalk14 from "chalk";
3013
2721
  import { createInterface as createInterface6 } from "readline";
3014
2722
  import { randomUUID as randomUUID3 } from "crypto";
3015
2723
  function registerOntologyCommand(program2) {
@@ -3017,19 +2725,19 @@ function registerOntologyCommand(program2) {
3017
2725
  ont.command("query <question>").alias("q").description("GraphRAG \uC6D0\uC0F7 \uC9C8\uC758").option("-g, --graph <id>", "\uADF8\uB798\uD504 ID").option("--no-scs", "SCS \uCEE8\uD14D\uC2A4\uD2B8 \uBE44\uD65C\uC131\uD654").action(async (question, opts) => {
3018
2726
  requireAuth();
3019
2727
  try {
3020
- console.log(chalk15.gray("\n\uC9C8\uC758 \uC911...\n"));
2728
+ console.log(chalk14.gray("\n\uC9C8\uC758 \uC911...\n"));
3021
2729
  const result = await queryGraphRAG(question, opts.graph, { scs: opts.scs });
3022
2730
  if (result.answer) {
3023
- console.log(chalk15.bold("\uB2F5\uBCC0:"));
2731
+ console.log(chalk14.bold("\uB2F5\uBCC0:"));
3024
2732
  console.log(result.answer);
3025
2733
  }
3026
2734
  if (result.sources?.length) {
3027
- console.log(chalk15.bold("\n\uCD9C\uCC98:"));
3028
- result.sources.forEach((s) => console.log(chalk15.gray(` - ${s}`)));
2735
+ console.log(chalk14.bold("\n\uCD9C\uCC98:"));
2736
+ result.sources.forEach((s) => console.log(chalk14.gray(` - ${s}`)));
3029
2737
  }
3030
2738
  if (result.triples_used?.length) {
3031
- console.log(chalk15.bold("\n\uC0AC\uC6A9\uB41C \uD2B8\uB9AC\uD50C:"));
3032
- result.triples_used.forEach((t) => console.log(chalk15.dim(` ${t}`)));
2739
+ console.log(chalk14.bold("\n\uC0AC\uC6A9\uB41C \uD2B8\uB9AC\uD50C:"));
2740
+ result.triples_used.forEach((t) => console.log(chalk14.dim(` ${t}`)));
3033
2741
  }
3034
2742
  console.log();
3035
2743
  } catch (err) {
@@ -3040,9 +2748,9 @@ function registerOntologyCommand(program2) {
3040
2748
  requireAuth();
3041
2749
  const sessionId = randomUUID3();
3042
2750
  printHeader("Ontology Chat");
3043
- console.log(chalk15.gray("\uBA40\uD2F0\uD134 GraphRAG \uB300\uD654. exit\uB85C \uC885\uB8CC.\n"));
2751
+ console.log(chalk14.gray("\uBA40\uD2F0\uD134 GraphRAG \uB300\uD654. exit\uB85C \uC885\uB8CC.\n"));
3044
2752
  const rl = createInterface6({ input: process.stdin, output: process.stdout });
3045
- const ask2 = () => new Promise((resolve) => rl.question(chalk15.green("\u276F "), (a) => resolve(a.trim())));
2753
+ const ask2 = () => new Promise((resolve) => rl.question(chalk14.green("\u276F "), (a) => resolve(a.trim())));
3046
2754
  while (true) {
3047
2755
  const input = await ask2();
3048
2756
  if (!input) continue;
@@ -3056,7 +2764,7 @@ function registerOntologyCommand(program2) {
3056
2764
  ${result.answer}
3057
2765
  `);
3058
2766
  } catch (err) {
3059
- console.log(chalk15.red(`\uC624\uB958: ${err.message}
2767
+ console.log(chalk14.red(`\uC624\uB958: ${err.message}
3060
2768
  `));
3061
2769
  }
3062
2770
  }
@@ -3066,7 +2774,7 @@ ${result.answer}
3066
2774
  try {
3067
2775
  const stats = await getGraphStats(graphId);
3068
2776
  printHeader("\uADF8\uB798\uD504 \uD1B5\uACC4");
3069
- console.log(chalk15.gray(JSON.stringify(stats, null, 2)));
2777
+ console.log(chalk14.gray(JSON.stringify(stats, null, 2)));
3070
2778
  console.log();
3071
2779
  } catch (err) {
3072
2780
  printError(`\uD1B5\uACC4 \uC870\uD68C \uC2E4\uD328: ${err.message}`);
@@ -3075,44 +2783,43 @@ ${result.answer}
3075
2783
  }
3076
2784
 
3077
2785
  // src/index.ts
3078
- init_home();
3079
2786
  var VERSION = "0.3.0";
3080
- var LOGO = chalk16.cyan(`
2787
+ var LOGO = chalk15.cyan(`
3081
2788
  \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588 \u2588\u2588
3082
2789
  \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588
3083
2790
  \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588
3084
2791
  \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588
3085
2792
  \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588
3086
- `) + chalk16.white.bold(`
2793
+ `) + chalk15.white.bold(`
3087
2794
  \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588 \u2588\u2588
3088
2795
  \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588
3089
2796
  \u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588
3090
2797
  \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588
3091
2798
  \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588
3092
- `) + chalk16.gray(` v${VERSION}
2799
+ `) + chalk15.gray(` v${VERSION}
3093
2800
  `);
3094
2801
  var BANNER = LOGO;
3095
2802
  var program = new Command();
3096
2803
  program.name("xgen").description("OPEN XGEN \u2014 AI Coding Agent + XGEN Platform CLI").version(VERSION).addHelpText("before", BANNER).addHelpText(
3097
2804
  "after",
3098
2805
  `
3099
- ${chalk16.bold("\uC2DC\uC791\uD558\uAE30:")}
3100
- ${chalk16.cyan("xgen provider add")} AI \uD504\uB85C\uBC14\uC774\uB354 \uC124\uC815
3101
- ${chalk16.cyan("xgen agent")} AI \uCF54\uB529 \uC5D0\uC774\uC804\uD2B8
3102
- ${chalk16.cyan("xgen config set-server")} <url> XGEN \uC11C\uBC84 \uC5F0\uACB0
3103
- ${chalk16.cyan("xgen login")} \uC11C\uBC84 \uB85C\uADF8\uC778
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
3104
2811
 
3105
- ${chalk16.bold("AI \uC5D0\uC774\uC804\uD2B8:")}
3106
- ${chalk16.cyan("xgen agent")} \uCF54\uB529 \uC5D0\uC774\uC804\uD2B8 (\uD30C\uC77C, \uD130\uBBF8\uB110, \uAC80\uC0C9)
3107
- ${chalk16.cyan("xgen provider ls")} \uD504\uB85C\uBC14\uC774\uB354 \uBAA9\uB85D
3108
- ${chalk16.cyan("xgen provider add")} \uD504\uB85C\uBC14\uC774\uB354 \uCD94\uAC00
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
3109
2816
 
3110
- ${chalk16.bold("XGEN \uD50C\uB7AB\uD3FC:")}
3111
- ${chalk16.cyan("xgen chat")} \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uB300\uD654
3112
- ${chalk16.cyan("xgen wf ls")} \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D
3113
- ${chalk16.cyan("xgen wf run")} <id> "\uC9C8\uBB38" \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC2E4\uD589
3114
- ${chalk16.cyan("xgen doc ls")} \uBB38\uC11C \uBAA9\uB85D
3115
- ${chalk16.cyan("xgen ont query")} "\uC9C8\uBB38" \uC628\uD1A8\uB85C\uC9C0 \uC9C8\uC758
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
3116
2823
  `
3117
2824
  );
3118
2825
  registerConfigCommand(program);
@@ -3124,8 +2831,8 @@ registerAgentCommand(program);
3124
2831
  registerDocCommand(program);
3125
2832
  registerOntologyCommand(program);
3126
2833
  if (process.argv.length <= 2) {
3127
- homeMenu().catch((err) => {
3128
- console.error(chalk16.red(`\uC624\uB958: ${err.message}`));
2834
+ agentRepl().catch((err) => {
2835
+ console.error(chalk15.red(`\uC624\uB958: ${err.message}`));
3129
2836
  process.exit(1);
3130
2837
  });
3131
2838
  } else {