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