openxgen 0.3.1 → 0.3.2
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 +1261 -1113
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -419,231 +419,6 @@ var init_list = __esm({
|
|
|
419
419
|
}
|
|
420
420
|
});
|
|
421
421
|
|
|
422
|
-
// src/index.ts
|
|
423
|
-
import { Command } from "commander";
|
|
424
|
-
import chalk15 from "chalk";
|
|
425
|
-
|
|
426
|
-
// src/commands/config.ts
|
|
427
|
-
init_store();
|
|
428
|
-
init_client();
|
|
429
|
-
init_format();
|
|
430
|
-
import chalk2 from "chalk";
|
|
431
|
-
function registerConfigCommand(program2) {
|
|
432
|
-
const config = program2.command("config").description("XGEN CLI \uC124\uC815 \uAD00\uB9AC");
|
|
433
|
-
config.command("set-server <url>").description("XGEN \uC11C\uBC84 URL \uC124\uC815").action((url) => {
|
|
434
|
-
if (!url.startsWith("http://") && !url.startsWith("https://")) {
|
|
435
|
-
printError("URL\uC740 http:// \uB610\uB294 https://\uB85C \uC2DC\uC791\uD574\uC57C \uD569\uB2C8\uB2E4");
|
|
436
|
-
process.exit(1);
|
|
437
|
-
}
|
|
438
|
-
setServer(url);
|
|
439
|
-
resetClient();
|
|
440
|
-
printSuccess(`\uC11C\uBC84 \uC124\uC815 \uC644\uB8CC: ${chalk2.underline(url)}`);
|
|
441
|
-
});
|
|
442
|
-
config.command("get-server").description("\uD604\uC7AC \uC124\uC815\uB41C \uC11C\uBC84 URL \uD655\uC778").action(() => {
|
|
443
|
-
const server = getServer();
|
|
444
|
-
if (server) {
|
|
445
|
-
console.log(server);
|
|
446
|
-
} else {
|
|
447
|
-
printError("\uC11C\uBC84\uAC00 \uC124\uC815\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4");
|
|
448
|
-
console.log(" \uC124\uC815: xgen config set-server <url>");
|
|
449
|
-
}
|
|
450
|
-
});
|
|
451
|
-
config.command("list").description("\uC804\uCCB4 \uC124\uC815 \uD655\uC778").action(() => {
|
|
452
|
-
const cfg = getConfig();
|
|
453
|
-
console.log(chalk2.bold("\nXGEN CLI \uC124\uC815"));
|
|
454
|
-
console.log(chalk2.gray("\u2500".repeat(40)));
|
|
455
|
-
printKeyValue("\uC11C\uBC84", cfg.server);
|
|
456
|
-
printKeyValue("\uAE30\uBCF8 \uC6CC\uD06C\uD50C\uB85C\uC6B0", cfg.defaultWorkflow);
|
|
457
|
-
printKeyValue("\uD14C\uB9C8", cfg.theme);
|
|
458
|
-
printKeyValue("\uC2A4\uD2B8\uB9BC \uB85C\uADF8", String(cfg.streamLogs));
|
|
459
|
-
console.log();
|
|
460
|
-
});
|
|
461
|
-
config.command("set <key> <value>").description("\uC124\uC815 \uAC12 \uBCC0\uACBD").action((key, value) => {
|
|
462
|
-
const allowedKeys = ["defaultWorkflow", "theme", "streamLogs"];
|
|
463
|
-
if (!allowedKeys.includes(key)) {
|
|
464
|
-
printError(`\uC54C \uC218 \uC5C6\uB294 \uC124\uC815 \uD0A4: ${key}`);
|
|
465
|
-
console.log(` \uC0AC\uC6A9 \uAC00\uB2A5: ${allowedKeys.join(", ")}`);
|
|
466
|
-
process.exit(1);
|
|
467
|
-
}
|
|
468
|
-
const parsed = key === "streamLogs" ? value === "true" : value;
|
|
469
|
-
setConfig({ [key]: parsed });
|
|
470
|
-
printSuccess(`${key} = ${value}`);
|
|
471
|
-
});
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
// src/commands/login.ts
|
|
475
|
-
init_auth();
|
|
476
|
-
init_store();
|
|
477
|
-
init_format();
|
|
478
|
-
import chalk3 from "chalk";
|
|
479
|
-
import { createInterface } from "readline";
|
|
480
|
-
function prompt(question, hidden = false) {
|
|
481
|
-
return new Promise((resolve) => {
|
|
482
|
-
const rl = createInterface({
|
|
483
|
-
input: process.stdin,
|
|
484
|
-
output: process.stdout
|
|
485
|
-
});
|
|
486
|
-
if (hidden) {
|
|
487
|
-
process.stdout.write(question);
|
|
488
|
-
const stdin = process.stdin;
|
|
489
|
-
const wasRaw = stdin.isRaw;
|
|
490
|
-
if (stdin.isTTY) stdin.setRawMode(true);
|
|
491
|
-
let password = "";
|
|
492
|
-
const onData = (ch) => {
|
|
493
|
-
const c = ch.toString("utf8");
|
|
494
|
-
if (c === "\n" || c === "\r" || c === "") {
|
|
495
|
-
if (stdin.isTTY) stdin.setRawMode(wasRaw ?? false);
|
|
496
|
-
stdin.removeListener("data", onData);
|
|
497
|
-
process.stdout.write("\n");
|
|
498
|
-
rl.close();
|
|
499
|
-
resolve(password);
|
|
500
|
-
} else if (c === "") {
|
|
501
|
-
process.exit(0);
|
|
502
|
-
} else if (c === "\x7F" || c === "\b") {
|
|
503
|
-
if (password.length > 0) {
|
|
504
|
-
password = password.slice(0, -1);
|
|
505
|
-
process.stdout.write("\b \b");
|
|
506
|
-
}
|
|
507
|
-
} else {
|
|
508
|
-
password += c;
|
|
509
|
-
process.stdout.write("*");
|
|
510
|
-
}
|
|
511
|
-
};
|
|
512
|
-
stdin.on("data", onData);
|
|
513
|
-
} else {
|
|
514
|
-
rl.question(question, (answer) => {
|
|
515
|
-
rl.close();
|
|
516
|
-
resolve(answer.trim());
|
|
517
|
-
});
|
|
518
|
-
}
|
|
519
|
-
});
|
|
520
|
-
}
|
|
521
|
-
function registerLoginCommand(program2) {
|
|
522
|
-
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) => {
|
|
523
|
-
const server = requireServer();
|
|
524
|
-
printHeader("XGEN Login");
|
|
525
|
-
console.log(chalk3.gray(`\uC11C\uBC84: ${server}
|
|
526
|
-
`));
|
|
527
|
-
let email = opts.email;
|
|
528
|
-
let password = opts.password;
|
|
529
|
-
if (!email) {
|
|
530
|
-
email = await prompt(chalk3.white("\uC774\uBA54\uC77C: "));
|
|
531
|
-
}
|
|
532
|
-
if (!password) {
|
|
533
|
-
password = await prompt(chalk3.white("\uBE44\uBC00\uBC88\uD638: "), true);
|
|
534
|
-
}
|
|
535
|
-
if (!email || !password) {
|
|
536
|
-
printError("\uC774\uBA54\uC77C\uACFC \uBE44\uBC00\uBC88\uD638\uB97C \uBAA8\uB450 \uC785\uB825\uD558\uC138\uC694");
|
|
537
|
-
process.exit(1);
|
|
538
|
-
}
|
|
539
|
-
try {
|
|
540
|
-
const result = await apiLogin(email, password);
|
|
541
|
-
if (result.success && result.access_token) {
|
|
542
|
-
setAuth({
|
|
543
|
-
accessToken: result.access_token,
|
|
544
|
-
refreshToken: result.refresh_token ?? "",
|
|
545
|
-
userId: result.user_id ?? "",
|
|
546
|
-
username: result.username ?? "",
|
|
547
|
-
isAdmin: false,
|
|
548
|
-
expiresAt: null
|
|
549
|
-
});
|
|
550
|
-
console.log();
|
|
551
|
-
printSuccess(`\uB85C\uADF8\uC778 \uC131\uACF5! ${chalk3.bold(result.username ?? email)}`);
|
|
552
|
-
} else {
|
|
553
|
-
printError(result.message || "\uB85C\uADF8\uC778 \uC2E4\uD328");
|
|
554
|
-
process.exit(1);
|
|
555
|
-
}
|
|
556
|
-
} catch (err) {
|
|
557
|
-
const msg = err?.response?.data?.message ?? err?.response?.data?.detail ?? err.message;
|
|
558
|
-
printError(`\uB85C\uADF8\uC778 \uC2E4\uD328: ${msg}`);
|
|
559
|
-
process.exit(1);
|
|
560
|
-
}
|
|
561
|
-
});
|
|
562
|
-
program2.command("logout").description("\uB85C\uADF8\uC544\uC6C3").action(async () => {
|
|
563
|
-
const { clearAuth: clearAuth2 } = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
564
|
-
clearAuth2();
|
|
565
|
-
printSuccess("\uB85C\uADF8\uC544\uC6C3 \uC644\uB8CC");
|
|
566
|
-
});
|
|
567
|
-
program2.command("whoami").description("\uD604\uC7AC \uB85C\uADF8\uC778\uB41C \uC0AC\uC6A9\uC790 \uC815\uBCF4").action(async () => {
|
|
568
|
-
const auth = getAuth();
|
|
569
|
-
if (!auth) {
|
|
570
|
-
printError("\uB85C\uADF8\uC778\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. xgen login \uC2E4\uD589\uD558\uC138\uC694");
|
|
571
|
-
process.exit(1);
|
|
572
|
-
}
|
|
573
|
-
const server = requireServer();
|
|
574
|
-
console.log(chalk3.bold("\n\uD604\uC7AC \uC0AC\uC6A9\uC790"));
|
|
575
|
-
console.log(chalk3.gray("\u2500".repeat(30)));
|
|
576
|
-
console.log(` ${chalk3.gray("\uC11C\uBC84:")} ${server}`);
|
|
577
|
-
console.log(` ${chalk3.gray("\uC0AC\uC6A9\uC790:")} ${chalk3.bold(auth.username)}`);
|
|
578
|
-
console.log(` ${chalk3.gray("User ID:")} ${auth.userId}`);
|
|
579
|
-
try {
|
|
580
|
-
const { apiValidate: apiValidate2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
|
|
581
|
-
const result = await apiValidate2(auth.accessToken);
|
|
582
|
-
if (result.valid) {
|
|
583
|
-
console.log(` ${chalk3.gray("\uC0C1\uD0DC:")} ${chalk3.green("\uD65C\uC131")}`);
|
|
584
|
-
if (result.is_admin) {
|
|
585
|
-
console.log(` ${chalk3.gray("\uAD8C\uD55C:")} ${chalk3.yellow("\uAD00\uB9AC\uC790")}`);
|
|
586
|
-
}
|
|
587
|
-
if (result.user_type) {
|
|
588
|
-
console.log(` ${chalk3.gray("\uC720\uD615:")} ${result.user_type}`);
|
|
589
|
-
}
|
|
590
|
-
} else {
|
|
591
|
-
console.log(` ${chalk3.gray("\uC0C1\uD0DC:")} ${chalk3.red("\uD1A0\uD070 \uB9CC\uB8CC")}`);
|
|
592
|
-
}
|
|
593
|
-
} catch {
|
|
594
|
-
console.log(` ${chalk3.gray("\uC0C1\uD0DC:")} ${chalk3.yellow("\uAC80\uC99D \uBD88\uAC00 (\uC11C\uBC84 \uC5F0\uACB0 \uC2E4\uD328)")}`);
|
|
595
|
-
}
|
|
596
|
-
console.log();
|
|
597
|
-
});
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
// src/commands/workflow/index.ts
|
|
601
|
-
init_list();
|
|
602
|
-
|
|
603
|
-
// src/commands/workflow/info.ts
|
|
604
|
-
init_store();
|
|
605
|
-
init_workflow();
|
|
606
|
-
init_format();
|
|
607
|
-
import chalk5 from "chalk";
|
|
608
|
-
async function workflowInfo(workflowId) {
|
|
609
|
-
requireAuth();
|
|
610
|
-
try {
|
|
611
|
-
const detail = await getWorkflowDetail(workflowId);
|
|
612
|
-
printHeader(`\uC6CC\uD06C\uD50C\uB85C\uC6B0: ${detail.workflow_name ?? workflowId}`);
|
|
613
|
-
console.log();
|
|
614
|
-
printKeyValue("ID", detail.id);
|
|
615
|
-
printKeyValue("\uC774\uB984", detail.workflow_name);
|
|
616
|
-
printKeyValue("\uC124\uBA85", detail.description ?? "(\uC5C6\uC74C)");
|
|
617
|
-
if (detail.nodes && Array.isArray(detail.nodes)) {
|
|
618
|
-
console.log();
|
|
619
|
-
console.log(chalk5.bold(" \uB178\uB4DC \uAD6C\uC131:"));
|
|
620
|
-
for (const node of detail.nodes) {
|
|
621
|
-
const label = node.data?.label ?? node.id;
|
|
622
|
-
const type = node.data?.type ?? "unknown";
|
|
623
|
-
console.log(` ${chalk5.cyan("\u2022")} ${label} ${chalk5.gray(`(${type})`)}`);
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
if (detail.parameters && Object.keys(detail.parameters).length > 0) {
|
|
627
|
-
console.log();
|
|
628
|
-
console.log(chalk5.bold(" \uD30C\uB77C\uBBF8\uD130:"));
|
|
629
|
-
for (const [key, val] of Object.entries(detail.parameters)) {
|
|
630
|
-
console.log(` ${chalk5.gray(key)}: ${JSON.stringify(val)}`);
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
console.log();
|
|
634
|
-
} catch (err) {
|
|
635
|
-
const msg = err.message;
|
|
636
|
-
printError(`\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC870\uD68C \uC2E4\uD328: ${msg}`);
|
|
637
|
-
process.exit(1);
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
// src/commands/workflow/run.ts
|
|
642
|
-
init_store();
|
|
643
|
-
init_workflow();
|
|
644
|
-
import chalk7 from "chalk";
|
|
645
|
-
import { randomUUID } from "crypto";
|
|
646
|
-
|
|
647
422
|
// src/utils/sse.ts
|
|
648
423
|
async function parseSSEStream(stream, onEvent, onDone, onError) {
|
|
649
424
|
let buffer = "";
|
|
@@ -694,219 +469,16 @@ async function parseSSEStream(stream, onEvent, onDone, onError) {
|
|
|
694
469
|
});
|
|
695
470
|
});
|
|
696
471
|
}
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
import chalk6 from "chalk";
|
|
703
|
-
var CODE_BLOCK_RE = /```(\w*)\n([\s\S]*?)```/g;
|
|
704
|
-
var INLINE_CODE_RE = /`([^`]+)`/g;
|
|
705
|
-
var BOLD_RE = /\*\*(.+?)\*\*/g;
|
|
706
|
-
var HEADING_RE = /^(#{1,3})\s+(.+)$/gm;
|
|
707
|
-
var LIST_RE = /^(\s*)[-*]\s+(.+)$/gm;
|
|
708
|
-
var LINK_RE = /\[([^\]]+)\]\(([^)]+)\)/g;
|
|
709
|
-
function renderMarkdown(text) {
|
|
710
|
-
let result = text;
|
|
711
|
-
result = result.replace(CODE_BLOCK_RE, (_match, lang, code) => {
|
|
712
|
-
const trimmed = code.trimEnd();
|
|
713
|
-
const header = lang ? chalk6.gray(` \u2500\u2500 ${lang} \u2500\u2500`) : chalk6.gray(" \u2500\u2500 code \u2500\u2500");
|
|
714
|
-
const lines = trimmed.split("\n").map((l) => chalk6.white(` ${l}`)).join("\n");
|
|
715
|
-
return `
|
|
716
|
-
${header}
|
|
717
|
-
${lines}
|
|
718
|
-
${chalk6.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}
|
|
719
|
-
`;
|
|
720
|
-
});
|
|
721
|
-
result = result.replace(INLINE_CODE_RE, (_m, code) => chalk6.cyan(`\`${code}\``));
|
|
722
|
-
result = result.replace(BOLD_RE, (_m, text2) => chalk6.bold(text2));
|
|
723
|
-
result = result.replace(HEADING_RE, (_m, hashes, text2) => {
|
|
724
|
-
if (hashes.length === 1) return chalk6.bold.underline(text2);
|
|
725
|
-
if (hashes.length === 2) return chalk6.bold(text2);
|
|
726
|
-
return chalk6.bold.dim(text2);
|
|
727
|
-
});
|
|
728
|
-
result = result.replace(LIST_RE, (_m, indent, text2) => `${indent}${chalk6.cyan("\u2022")} ${text2}`);
|
|
729
|
-
result = result.replace(LINK_RE, (_m, label, url) => `${chalk6.blue.underline(label)} ${chalk6.gray(`(${url})`)}`);
|
|
730
|
-
return result;
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
// src/commands/workflow/run.ts
|
|
734
|
-
async function workflowRun(workflowId, input, opts) {
|
|
735
|
-
const auth = requireAuth();
|
|
736
|
-
let workflowName = workflowId;
|
|
737
|
-
try {
|
|
738
|
-
const detail = await getWorkflowDetail(workflowId);
|
|
739
|
-
workflowName = detail.workflow_name ?? workflowId;
|
|
740
|
-
} catch {
|
|
741
|
-
}
|
|
742
|
-
if (!input) {
|
|
743
|
-
if (opts.interactive || !process.stdin.isTTY) {
|
|
744
|
-
const { createInterface: createInterface8 } = await import("readline");
|
|
745
|
-
const rl = createInterface8({ input: process.stdin, output: process.stdout });
|
|
746
|
-
input = await new Promise((resolve) => {
|
|
747
|
-
rl.question(chalk7.cyan("\uC785\uB825> "), (answer) => {
|
|
748
|
-
rl.close();
|
|
749
|
-
resolve(answer.trim());
|
|
750
|
-
});
|
|
751
|
-
});
|
|
752
|
-
} else {
|
|
753
|
-
printError("\uC785\uB825\uAC12\uC774 \uD544\uC694\uD569\uB2C8\uB2E4. \uC0AC\uC6A9\uBC95:");
|
|
754
|
-
console.log(' xgen workflow run <id> "\uC785\uB825 \uD14D\uC2A4\uFFFD\uFFFD\uFFFD"');
|
|
755
|
-
console.log(" xgen workflow run -i <id>");
|
|
756
|
-
process.exit(1);
|
|
757
|
-
}
|
|
758
|
-
}
|
|
759
|
-
if (!input) {
|
|
760
|
-
printError("\uC785\uB825\uAC12\uC774 \uBE44\uC5B4\uC788\uC2B5\uB2C8\uB2E4");
|
|
761
|
-
process.exit(1);
|
|
762
|
-
}
|
|
763
|
-
const interactionId = `cli_${randomUUID().slice(0, 8)}`;
|
|
764
|
-
printHeader(`\uC2E4\uD589: ${workflowName}`);
|
|
765
|
-
printInfo(`\uC785\uB825: ${input}`);
|
|
766
|
-
console.log();
|
|
767
|
-
try {
|
|
768
|
-
const stream = await executeWorkflowStream({
|
|
769
|
-
workflow_id: workflowId,
|
|
770
|
-
workflow_name: workflowName,
|
|
771
|
-
input_data: input,
|
|
772
|
-
interaction_id: interactionId
|
|
773
|
-
});
|
|
774
|
-
let hasOutput = false;
|
|
775
|
-
let fullResponse = "";
|
|
776
|
-
await parseSSEStream(
|
|
777
|
-
stream,
|
|
778
|
-
(event) => {
|
|
779
|
-
switch (event.type) {
|
|
780
|
-
case "token":
|
|
781
|
-
if (event.content) {
|
|
782
|
-
if (!hasOutput) {
|
|
783
|
-
hasOutput = true;
|
|
784
|
-
console.log();
|
|
785
|
-
}
|
|
786
|
-
process.stdout.write(event.content);
|
|
787
|
-
fullResponse += event.content;
|
|
788
|
-
}
|
|
789
|
-
break;
|
|
790
|
-
case "log":
|
|
791
|
-
if (opts.logs && event.content) {
|
|
792
|
-
process.stderr.write(chalk7.gray(`[LOG] ${event.content}
|
|
793
|
-
`));
|
|
794
|
-
}
|
|
795
|
-
break;
|
|
796
|
-
case "node_status":
|
|
797
|
-
if (opts.logs) {
|
|
798
|
-
const nodeName = event.node_name ?? event.node_id ?? "?";
|
|
799
|
-
const status = event.status ?? "?";
|
|
800
|
-
process.stderr.write(
|
|
801
|
-
chalk7.gray(`[\uB178\uB4DC] ${nodeName}: ${status}
|
|
802
|
-
`)
|
|
803
|
-
);
|
|
804
|
-
}
|
|
805
|
-
break;
|
|
806
|
-
case "tool":
|
|
807
|
-
if (opts.logs) {
|
|
808
|
-
process.stderr.write(chalk7.gray(`[\uB3C4\uAD6C] ${JSON.stringify(event.data)}
|
|
809
|
-
`));
|
|
810
|
-
}
|
|
811
|
-
break;
|
|
812
|
-
case "complete":
|
|
813
|
-
break;
|
|
814
|
-
case "error":
|
|
815
|
-
console.log();
|
|
816
|
-
printError(event.error ?? event.content ?? "\uC54C \uC218 \uC5C6\uB294 \uC624\uB958");
|
|
817
|
-
break;
|
|
818
|
-
default:
|
|
819
|
-
if (event.content) {
|
|
820
|
-
if (!hasOutput) {
|
|
821
|
-
process.stdout.write(chalk7.green("\uC751\uB2F5: "));
|
|
822
|
-
hasOutput = true;
|
|
823
|
-
}
|
|
824
|
-
process.stdout.write(event.content);
|
|
825
|
-
}
|
|
826
|
-
}
|
|
827
|
-
},
|
|
828
|
-
() => {
|
|
829
|
-
if (hasOutput) {
|
|
830
|
-
console.log();
|
|
831
|
-
if (fullResponse.includes("```") || fullResponse.includes("**")) {
|
|
832
|
-
console.log(chalk7.gray("\u2500".repeat(40)));
|
|
833
|
-
console.log(renderMarkdown(fullResponse));
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
console.log();
|
|
837
|
-
console.log(chalk7.gray(`\uC138\uC158: ${interactionId}`));
|
|
838
|
-
},
|
|
839
|
-
(err) => {
|
|
840
|
-
console.log();
|
|
841
|
-
printError(`\uC2A4\uD2B8\uB9AC\uBC0D \uC624\uB958: ${err.message}`);
|
|
842
|
-
}
|
|
843
|
-
);
|
|
844
|
-
} catch (err) {
|
|
845
|
-
const msg = err?.response?.data?.detail ?? err.message;
|
|
846
|
-
printError(`\uC2E4\uD589 \uC2E4\uD328: ${msg}`);
|
|
847
|
-
process.exit(1);
|
|
848
|
-
}
|
|
849
|
-
}
|
|
850
|
-
|
|
851
|
-
// src/commands/workflow/history.ts
|
|
852
|
-
init_store();
|
|
853
|
-
init_workflow();
|
|
854
|
-
init_format();
|
|
855
|
-
import chalk8 from "chalk";
|
|
856
|
-
async function workflowHistory(workflowId, opts = {}) {
|
|
857
|
-
requireAuth();
|
|
858
|
-
const limit = opts.limit ?? 20;
|
|
859
|
-
try {
|
|
860
|
-
const logs = await getIOLogs(workflowId, limit);
|
|
861
|
-
if (!logs || logs.length === 0) {
|
|
862
|
-
console.log(chalk8.yellow("\n\uC2E4\uD589 \uC774\uB825\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.\n"));
|
|
863
|
-
return;
|
|
864
|
-
}
|
|
865
|
-
printHeader(`\uC2E4\uD589 \uC774\uB825 (\uCD5C\uADFC ${logs.length}\uAC74)`);
|
|
866
|
-
console.log();
|
|
867
|
-
for (const log of logs) {
|
|
868
|
-
console.log(
|
|
869
|
-
` ${chalk8.gray(formatDate(log.created_at))} ${chalk8.cyan(log.interaction_id)}`
|
|
870
|
-
);
|
|
871
|
-
console.log(` ${chalk8.white("\uC785\uB825:")} ${truncate(log.input_data, 60)}`);
|
|
872
|
-
console.log(
|
|
873
|
-
` ${chalk8.green("\uCD9C\uB825:")} ${truncate(log.output_data, 60)}`
|
|
874
|
-
);
|
|
875
|
-
if (log.execution_time) {
|
|
876
|
-
console.log(
|
|
877
|
-
` ${chalk8.gray("\uC2DC\uAC04:")} ${(log.execution_time / 1e3).toFixed(1)}s`
|
|
878
|
-
);
|
|
879
|
-
}
|
|
880
|
-
console.log();
|
|
881
|
-
}
|
|
882
|
-
} catch (err) {
|
|
883
|
-
const msg = err.message;
|
|
884
|
-
printError(`\uC774\uB825 \uC870\uD68C \uC2E4\uD328: ${msg}`);
|
|
885
|
-
process.exit(1);
|
|
886
|
-
}
|
|
887
|
-
}
|
|
888
|
-
|
|
889
|
-
// src/commands/workflow/index.ts
|
|
890
|
-
function registerWorkflowCommand(program2) {
|
|
891
|
-
const wf = program2.command("workflow").alias("wf").description("\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uAD00\uB9AC \uBC0F \uC2E4\uD589");
|
|
892
|
-
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));
|
|
893
|
-
wf.command("info <workflow-id>").description("\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC0C1\uC138 \uC815\uBCF4").action((id) => workflowInfo(id));
|
|
894
|
-
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));
|
|
895
|
-
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) }));
|
|
896
|
-
}
|
|
472
|
+
var init_sse = __esm({
|
|
473
|
+
"src/utils/sse.ts"() {
|
|
474
|
+
"use strict";
|
|
475
|
+
}
|
|
476
|
+
});
|
|
897
477
|
|
|
898
478
|
// src/commands/chat.ts
|
|
899
|
-
init_store();
|
|
900
|
-
init_workflow();
|
|
901
479
|
import chalk9 from "chalk";
|
|
902
480
|
import { createInterface as createInterface2 } from "readline";
|
|
903
481
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
904
|
-
init_format();
|
|
905
|
-
var CHAT_BANNER = `
|
|
906
|
-
${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")}
|
|
907
|
-
${chalk9.cyan("\u2502")} ${chalk9.white.bold("XGEN")} ${chalk9.gray("\u2014 \uC6CC\uD06C\uD50C\uB85C\uC6B0 AI \uD130\uBBF8\uB110")} ${chalk9.cyan("\u2502")}
|
|
908
|
-
${chalk9.cyan("\u2502")} ${chalk9.gray("/help \uB3C4\uC6C0\uB9D0 /workflows \uC804\uD658 /exit")} ${chalk9.cyan("\u2502")}
|
|
909
|
-
${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")}`;
|
|
910
482
|
function printHelp() {
|
|
911
483
|
console.log(`
|
|
912
484
|
${chalk9.bold("\uC2AC\uB798\uC2DC \uCEE4\uB9E8\uB4DC")}
|
|
@@ -1118,10 +690,23 @@ async function chat(workflowId) {
|
|
|
1118
690
|
function registerChatCommand(program2) {
|
|
1119
691
|
program2.command("chat [workflow-id]").description("\uC778\uD130\uB799\uD2F0\uBE0C \uB300\uD654 \uBAA8\uB4DC").action((workflowId) => chat(workflowId));
|
|
1120
692
|
}
|
|
693
|
+
var CHAT_BANNER;
|
|
694
|
+
var init_chat = __esm({
|
|
695
|
+
"src/commands/chat.ts"() {
|
|
696
|
+
"use strict";
|
|
697
|
+
init_store();
|
|
698
|
+
init_workflow();
|
|
699
|
+
init_sse();
|
|
700
|
+
init_format();
|
|
701
|
+
CHAT_BANNER = `
|
|
702
|
+
${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")}
|
|
703
|
+
${chalk9.cyan("\u2502")} ${chalk9.white.bold("XGEN")} ${chalk9.gray("\u2014 \uC6CC\uD06C\uD50C\uB85C\uC6B0 AI \uD130\uBBF8\uB110")} ${chalk9.cyan("\u2502")}
|
|
704
|
+
${chalk9.cyan("\u2502")} ${chalk9.gray("/help \uB3C4\uC6C0\uB9D0 /workflows \uC804\uD658 /exit")} ${chalk9.cyan("\u2502")}
|
|
705
|
+
${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")}`;
|
|
706
|
+
}
|
|
707
|
+
});
|
|
1121
708
|
|
|
1122
709
|
// src/commands/provider.ts
|
|
1123
|
-
init_store();
|
|
1124
|
-
init_format();
|
|
1125
710
|
import chalk10 from "chalk";
|
|
1126
711
|
import { createInterface as createInterface3 } from "readline";
|
|
1127
712
|
import OpenAI from "openai";
|
|
@@ -1134,51 +719,6 @@ function prompt2(question) {
|
|
|
1134
719
|
});
|
|
1135
720
|
});
|
|
1136
721
|
}
|
|
1137
|
-
var PRESETS = [
|
|
1138
|
-
{
|
|
1139
|
-
label: "OpenAI",
|
|
1140
|
-
type: "openai",
|
|
1141
|
-
defaultModel: "gpt-4o-mini",
|
|
1142
|
-
models: ["gpt-4o", "gpt-4o-mini", "gpt-4.1", "gpt-4.1-mini", "o3-mini"],
|
|
1143
|
-
needsKey: true,
|
|
1144
|
-
keyHint: "https://platform.openai.com/api-keys \uC5D0\uC11C \uBC1C\uAE09"
|
|
1145
|
-
},
|
|
1146
|
-
{
|
|
1147
|
-
label: "Google Gemini",
|
|
1148
|
-
type: "gemini",
|
|
1149
|
-
baseUrl: "https://generativelanguage.googleapis.com/v1beta/openai",
|
|
1150
|
-
defaultModel: "gemini-2.0-flash",
|
|
1151
|
-
models: ["gemini-2.0-flash", "gemini-2.5-pro-preview-06-05", "gemini-2.5-flash-preview-05-20"],
|
|
1152
|
-
needsKey: true,
|
|
1153
|
-
keyHint: "https://aistudio.google.com/apikey \uC5D0\uC11C \uBC1C\uAE09"
|
|
1154
|
-
},
|
|
1155
|
-
{
|
|
1156
|
-
label: "Ollama (\uB85C\uCEEC)",
|
|
1157
|
-
type: "ollama",
|
|
1158
|
-
baseUrl: "http://localhost:11434/v1",
|
|
1159
|
-
defaultModel: "llama3.1",
|
|
1160
|
-
models: ["llama3.1", "llama3.2", "codellama", "mistral", "qwen2.5-coder"],
|
|
1161
|
-
needsKey: false,
|
|
1162
|
-
keyHint: "https://ollama.ai \uC5D0\uC11C \uC124\uCE58"
|
|
1163
|
-
},
|
|
1164
|
-
{
|
|
1165
|
-
label: "Anthropic (Claude)",
|
|
1166
|
-
type: "anthropic",
|
|
1167
|
-
baseUrl: "https://api.anthropic.com/v1",
|
|
1168
|
-
defaultModel: "claude-sonnet-4-20250514",
|
|
1169
|
-
models: ["claude-sonnet-4-20250514", "claude-opus-4-20250514", "claude-haiku-4-5-20251001"],
|
|
1170
|
-
needsKey: true,
|
|
1171
|
-
keyHint: "https://console.anthropic.com/settings/keys \uC5D0\uC11C \uBC1C\uAE09"
|
|
1172
|
-
},
|
|
1173
|
-
{
|
|
1174
|
-
label: "Custom (OpenAI \uD638\uD658 \uC11C\uBC84)",
|
|
1175
|
-
type: "custom",
|
|
1176
|
-
defaultModel: "gpt-4o-mini",
|
|
1177
|
-
models: [],
|
|
1178
|
-
needsKey: true,
|
|
1179
|
-
keyHint: "\uC11C\uBC84\uC5D0\uC11C \uBC1C\uAE09\uBC1B\uC740 API Key"
|
|
1180
|
-
}
|
|
1181
|
-
];
|
|
1182
722
|
async function guidedProviderSetup() {
|
|
1183
723
|
console.log(chalk10.cyan.bold("\n \u26A1 OPEN XGEN \u2014 \uD504\uB85C\uBC14\uC774\uB354 \uC124\uC815\n"));
|
|
1184
724
|
console.log(chalk10.gray(" AI \uC5D0\uC774\uC804\uD2B8\uB97C \uC0AC\uC6A9\uD558\uB824\uBA74 \uD504\uB85C\uBC14\uC774\uB354\uB97C \uC124\uC815\uD558\uC138\uC694.\n"));
|
|
@@ -1324,11 +864,59 @@ function registerProviderCommand(program2) {
|
|
|
1324
864
|
}
|
|
1325
865
|
});
|
|
1326
866
|
}
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
867
|
+
var PRESETS;
|
|
868
|
+
var init_provider = __esm({
|
|
869
|
+
"src/commands/provider.ts"() {
|
|
870
|
+
"use strict";
|
|
871
|
+
init_store();
|
|
872
|
+
init_format();
|
|
873
|
+
PRESETS = [
|
|
874
|
+
{
|
|
875
|
+
label: "OpenAI",
|
|
876
|
+
type: "openai",
|
|
877
|
+
defaultModel: "gpt-4o-mini",
|
|
878
|
+
models: ["gpt-4o", "gpt-4o-mini", "gpt-4.1", "gpt-4.1-mini", "o3-mini"],
|
|
879
|
+
needsKey: true,
|
|
880
|
+
keyHint: "https://platform.openai.com/api-keys \uC5D0\uC11C \uBC1C\uAE09"
|
|
881
|
+
},
|
|
882
|
+
{
|
|
883
|
+
label: "Google Gemini",
|
|
884
|
+
type: "gemini",
|
|
885
|
+
baseUrl: "https://generativelanguage.googleapis.com/v1beta/openai",
|
|
886
|
+
defaultModel: "gemini-2.0-flash",
|
|
887
|
+
models: ["gemini-2.0-flash", "gemini-2.5-pro-preview-06-05", "gemini-2.5-flash-preview-05-20"],
|
|
888
|
+
needsKey: true,
|
|
889
|
+
keyHint: "https://aistudio.google.com/apikey \uC5D0\uC11C \uBC1C\uAE09"
|
|
890
|
+
},
|
|
891
|
+
{
|
|
892
|
+
label: "Ollama (\uB85C\uCEEC)",
|
|
893
|
+
type: "ollama",
|
|
894
|
+
baseUrl: "http://localhost:11434/v1",
|
|
895
|
+
defaultModel: "llama3.1",
|
|
896
|
+
models: ["llama3.1", "llama3.2", "codellama", "mistral", "qwen2.5-coder"],
|
|
897
|
+
needsKey: false,
|
|
898
|
+
keyHint: "https://ollama.ai \uC5D0\uC11C \uC124\uCE58"
|
|
899
|
+
},
|
|
900
|
+
{
|
|
901
|
+
label: "Anthropic (Claude)",
|
|
902
|
+
type: "anthropic",
|
|
903
|
+
baseUrl: "https://api.anthropic.com/v1",
|
|
904
|
+
defaultModel: "claude-sonnet-4-20250514",
|
|
905
|
+
models: ["claude-sonnet-4-20250514", "claude-opus-4-20250514", "claude-haiku-4-5-20251001"],
|
|
906
|
+
needsKey: true,
|
|
907
|
+
keyHint: "https://console.anthropic.com/settings/keys \uC5D0\uC11C \uBC1C\uAE09"
|
|
908
|
+
},
|
|
909
|
+
{
|
|
910
|
+
label: "Custom (OpenAI \uD638\uD658 \uC11C\uBC84)",
|
|
911
|
+
type: "custom",
|
|
912
|
+
defaultModel: "gpt-4o-mini",
|
|
913
|
+
models: [],
|
|
914
|
+
needsKey: true,
|
|
915
|
+
keyHint: "\uC11C\uBC84\uC5D0\uC11C \uBC1C\uAE09\uBC1B\uC740 API Key"
|
|
916
|
+
}
|
|
917
|
+
];
|
|
918
|
+
}
|
|
919
|
+
});
|
|
1332
920
|
|
|
1333
921
|
// src/agent/llm.ts
|
|
1334
922
|
import OpenAI2 from "openai";
|
|
@@ -1378,6 +966,11 @@ async function streamChat(client2, model, messages, tools2, onDelta) {
|
|
|
1378
966
|
toolCalls: [...toolCallMap.values()]
|
|
1379
967
|
};
|
|
1380
968
|
}
|
|
969
|
+
var init_llm = __esm({
|
|
970
|
+
"src/agent/llm.ts"() {
|
|
971
|
+
"use strict";
|
|
972
|
+
}
|
|
973
|
+
});
|
|
1381
974
|
|
|
1382
975
|
// src/agent/tools/file-read.ts
|
|
1383
976
|
var file_read_exports = {};
|
|
@@ -1386,22 +979,6 @@ __export(file_read_exports, {
|
|
|
1386
979
|
execute: () => execute
|
|
1387
980
|
});
|
|
1388
981
|
import { readFileSync as readFileSync2 } from "fs";
|
|
1389
|
-
var definition = {
|
|
1390
|
-
type: "function",
|
|
1391
|
-
function: {
|
|
1392
|
-
name: "file_read",
|
|
1393
|
-
description: "\uD30C\uC77C \uB0B4\uC6A9\uC744 \uC77D\uC2B5\uB2C8\uB2E4. \uC904 \uBC88\uD638\uAC00 \uD3EC\uD568\uB429\uB2C8\uB2E4.",
|
|
1394
|
-
parameters: {
|
|
1395
|
-
type: "object",
|
|
1396
|
-
properties: {
|
|
1397
|
-
path: { type: "string", description: "\uD30C\uC77C \uACBD\uB85C" },
|
|
1398
|
-
start_line: { type: "number", description: "\uC2DC\uC791 \uC904 \uBC88\uD638 (\uC120\uD0DD)" },
|
|
1399
|
-
end_line: { type: "number", description: "\uB05D \uC904 \uBC88\uD638 (\uC120\uD0DD)" }
|
|
1400
|
-
},
|
|
1401
|
-
required: ["path"]
|
|
1402
|
-
}
|
|
1403
|
-
}
|
|
1404
|
-
};
|
|
1405
982
|
async function execute(args) {
|
|
1406
983
|
const path = args.path;
|
|
1407
984
|
const startLine = args.start_line || 1;
|
|
@@ -1415,6 +992,28 @@ async function execute(args) {
|
|
|
1415
992
|
return `Error: ${err.message}`;
|
|
1416
993
|
}
|
|
1417
994
|
}
|
|
995
|
+
var definition;
|
|
996
|
+
var init_file_read = __esm({
|
|
997
|
+
"src/agent/tools/file-read.ts"() {
|
|
998
|
+
"use strict";
|
|
999
|
+
definition = {
|
|
1000
|
+
type: "function",
|
|
1001
|
+
function: {
|
|
1002
|
+
name: "file_read",
|
|
1003
|
+
description: "\uD30C\uC77C \uB0B4\uC6A9\uC744 \uC77D\uC2B5\uB2C8\uB2E4. \uC904 \uBC88\uD638\uAC00 \uD3EC\uD568\uB429\uB2C8\uB2E4.",
|
|
1004
|
+
parameters: {
|
|
1005
|
+
type: "object",
|
|
1006
|
+
properties: {
|
|
1007
|
+
path: { type: "string", description: "\uD30C\uC77C \uACBD\uB85C" },
|
|
1008
|
+
start_line: { type: "number", description: "\uC2DC\uC791 \uC904 \uBC88\uD638 (\uC120\uD0DD)" },
|
|
1009
|
+
end_line: { type: "number", description: "\uB05D \uC904 \uBC88\uD638 (\uC120\uD0DD)" }
|
|
1010
|
+
},
|
|
1011
|
+
required: ["path"]
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
};
|
|
1015
|
+
}
|
|
1016
|
+
});
|
|
1418
1017
|
|
|
1419
1018
|
// src/agent/tools/file-write.ts
|
|
1420
1019
|
var file_write_exports = {};
|
|
@@ -1424,21 +1023,6 @@ __export(file_write_exports, {
|
|
|
1424
1023
|
});
|
|
1425
1024
|
import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
|
|
1426
1025
|
import { dirname } from "path";
|
|
1427
|
-
var definition2 = {
|
|
1428
|
-
type: "function",
|
|
1429
|
-
function: {
|
|
1430
|
-
name: "file_write",
|
|
1431
|
-
description: "\uD30C\uC77C\uC744 \uC0DD\uC131\uD558\uAC70\uB098 \uB36E\uC5B4\uC501\uB2C8\uB2E4.",
|
|
1432
|
-
parameters: {
|
|
1433
|
-
type: "object",
|
|
1434
|
-
properties: {
|
|
1435
|
-
path: { type: "string", description: "\uD30C\uC77C \uACBD\uB85C" },
|
|
1436
|
-
content: { type: "string", description: "\uD30C\uC77C \uB0B4\uC6A9" }
|
|
1437
|
-
},
|
|
1438
|
-
required: ["path", "content"]
|
|
1439
|
-
}
|
|
1440
|
-
}
|
|
1441
|
-
};
|
|
1442
1026
|
async function execute2(args) {
|
|
1443
1027
|
const path = args.path;
|
|
1444
1028
|
const content = args.content;
|
|
@@ -1450,6 +1034,27 @@ async function execute2(args) {
|
|
|
1450
1034
|
return `Error: ${err.message}`;
|
|
1451
1035
|
}
|
|
1452
1036
|
}
|
|
1037
|
+
var definition2;
|
|
1038
|
+
var init_file_write = __esm({
|
|
1039
|
+
"src/agent/tools/file-write.ts"() {
|
|
1040
|
+
"use strict";
|
|
1041
|
+
definition2 = {
|
|
1042
|
+
type: "function",
|
|
1043
|
+
function: {
|
|
1044
|
+
name: "file_write",
|
|
1045
|
+
description: "\uD30C\uC77C\uC744 \uC0DD\uC131\uD558\uAC70\uB098 \uB36E\uC5B4\uC501\uB2C8\uB2E4.",
|
|
1046
|
+
parameters: {
|
|
1047
|
+
type: "object",
|
|
1048
|
+
properties: {
|
|
1049
|
+
path: { type: "string", description: "\uD30C\uC77C \uACBD\uB85C" },
|
|
1050
|
+
content: { type: "string", description: "\uD30C\uC77C \uB0B4\uC6A9" }
|
|
1051
|
+
},
|
|
1052
|
+
required: ["path", "content"]
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
};
|
|
1056
|
+
}
|
|
1057
|
+
});
|
|
1453
1058
|
|
|
1454
1059
|
// src/agent/tools/file-edit.ts
|
|
1455
1060
|
var file_edit_exports = {};
|
|
@@ -1458,22 +1063,6 @@ __export(file_edit_exports, {
|
|
|
1458
1063
|
execute: () => execute3
|
|
1459
1064
|
});
|
|
1460
1065
|
import { readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
1461
|
-
var definition3 = {
|
|
1462
|
-
type: "function",
|
|
1463
|
-
function: {
|
|
1464
|
-
name: "file_edit",
|
|
1465
|
-
description: "\uD30C\uC77C\uC5D0\uC11C \uD2B9\uC815 \uD14D\uC2A4\uD2B8\uB97C \uCC3E\uC544 \uAD50\uCCB4\uD569\uB2C8\uB2E4.",
|
|
1466
|
-
parameters: {
|
|
1467
|
-
type: "object",
|
|
1468
|
-
properties: {
|
|
1469
|
-
path: { type: "string", description: "\uD30C\uC77C \uACBD\uB85C" },
|
|
1470
|
-
old_text: { type: "string", description: "\uAD50\uCCB4\uD560 \uAE30\uC874 \uD14D\uC2A4\uD2B8" },
|
|
1471
|
-
new_text: { type: "string", description: "\uC0C8 \uD14D\uC2A4\uD2B8" }
|
|
1472
|
-
},
|
|
1473
|
-
required: ["path", "old_text", "new_text"]
|
|
1474
|
-
}
|
|
1475
|
-
}
|
|
1476
|
-
};
|
|
1477
1066
|
async function execute3(args) {
|
|
1478
1067
|
const path = args.path;
|
|
1479
1068
|
const oldText = args.old_text;
|
|
@@ -1490,6 +1079,28 @@ async function execute3(args) {
|
|
|
1490
1079
|
return `Error: ${err.message}`;
|
|
1491
1080
|
}
|
|
1492
1081
|
}
|
|
1082
|
+
var definition3;
|
|
1083
|
+
var init_file_edit = __esm({
|
|
1084
|
+
"src/agent/tools/file-edit.ts"() {
|
|
1085
|
+
"use strict";
|
|
1086
|
+
definition3 = {
|
|
1087
|
+
type: "function",
|
|
1088
|
+
function: {
|
|
1089
|
+
name: "file_edit",
|
|
1090
|
+
description: "\uD30C\uC77C\uC5D0\uC11C \uD2B9\uC815 \uD14D\uC2A4\uD2B8\uB97C \uCC3E\uC544 \uAD50\uCCB4\uD569\uB2C8\uB2E4.",
|
|
1091
|
+
parameters: {
|
|
1092
|
+
type: "object",
|
|
1093
|
+
properties: {
|
|
1094
|
+
path: { type: "string", description: "\uD30C\uC77C \uACBD\uB85C" },
|
|
1095
|
+
old_text: { type: "string", description: "\uAD50\uCCB4\uD560 \uAE30\uC874 \uD14D\uC2A4\uD2B8" },
|
|
1096
|
+
new_text: { type: "string", description: "\uC0C8 \uD14D\uC2A4\uD2B8" }
|
|
1097
|
+
},
|
|
1098
|
+
required: ["path", "old_text", "new_text"]
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
};
|
|
1102
|
+
}
|
|
1103
|
+
});
|
|
1493
1104
|
|
|
1494
1105
|
// src/agent/tools/bash.ts
|
|
1495
1106
|
var bash_exports = {};
|
|
@@ -1498,20 +1109,6 @@ __export(bash_exports, {
|
|
|
1498
1109
|
execute: () => execute4
|
|
1499
1110
|
});
|
|
1500
1111
|
import { execSync } from "child_process";
|
|
1501
|
-
var definition4 = {
|
|
1502
|
-
type: "function",
|
|
1503
|
-
function: {
|
|
1504
|
-
name: "bash",
|
|
1505
|
-
description: "\uC178 \uBA85\uB839\uC5B4\uB97C \uC2E4\uD589\uD569\uB2C8\uB2E4. stdout + stderr\uB97C \uBC18\uD658\uD569\uB2C8\uB2E4.",
|
|
1506
|
-
parameters: {
|
|
1507
|
-
type: "object",
|
|
1508
|
-
properties: {
|
|
1509
|
-
command: { type: "string", description: "\uC2E4\uD589\uD560 \uBA85\uB839\uC5B4" }
|
|
1510
|
-
},
|
|
1511
|
-
required: ["command"]
|
|
1512
|
-
}
|
|
1513
|
-
}
|
|
1514
|
-
};
|
|
1515
1112
|
async function execute4(args) {
|
|
1516
1113
|
const command = args.command;
|
|
1517
1114
|
try {
|
|
@@ -1527,30 +1124,34 @@ async function execute4(args) {
|
|
|
1527
1124
|
return (e.stdout || "") + (e.stderr || "") || `Error: ${e.message}`;
|
|
1528
1125
|
}
|
|
1529
1126
|
}
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
glob: { type: "string", description: "\uD30C\uC77C \uD544\uD130 (\uC608: *.ts)" }
|
|
1549
|
-
},
|
|
1550
|
-
required: ["pattern"]
|
|
1551
|
-
}
|
|
1127
|
+
var definition4;
|
|
1128
|
+
var init_bash = __esm({
|
|
1129
|
+
"src/agent/tools/bash.ts"() {
|
|
1130
|
+
"use strict";
|
|
1131
|
+
definition4 = {
|
|
1132
|
+
type: "function",
|
|
1133
|
+
function: {
|
|
1134
|
+
name: "bash",
|
|
1135
|
+
description: "\uC178 \uBA85\uB839\uC5B4\uB97C \uC2E4\uD589\uD569\uB2C8\uB2E4. stdout + stderr\uB97C \uBC18\uD658\uD569\uB2C8\uB2E4.",
|
|
1136
|
+
parameters: {
|
|
1137
|
+
type: "object",
|
|
1138
|
+
properties: {
|
|
1139
|
+
command: { type: "string", description: "\uC2E4\uD589\uD560 \uBA85\uB839\uC5B4" }
|
|
1140
|
+
},
|
|
1141
|
+
required: ["command"]
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
};
|
|
1552
1145
|
}
|
|
1553
|
-
};
|
|
1146
|
+
});
|
|
1147
|
+
|
|
1148
|
+
// src/agent/tools/grep.ts
|
|
1149
|
+
var grep_exports = {};
|
|
1150
|
+
__export(grep_exports, {
|
|
1151
|
+
definition: () => definition5,
|
|
1152
|
+
execute: () => execute5
|
|
1153
|
+
});
|
|
1154
|
+
import { execSync as execSync2 } from "child_process";
|
|
1554
1155
|
async function execute5(args) {
|
|
1555
1156
|
const pattern = args.pattern;
|
|
1556
1157
|
const path = args.path || ".";
|
|
@@ -1570,6 +1171,28 @@ async function execute5(args) {
|
|
|
1570
1171
|
return "\uC77C\uCE58\uD558\uB294 \uACB0\uACFC \uC5C6\uC74C";
|
|
1571
1172
|
}
|
|
1572
1173
|
}
|
|
1174
|
+
var definition5;
|
|
1175
|
+
var init_grep = __esm({
|
|
1176
|
+
"src/agent/tools/grep.ts"() {
|
|
1177
|
+
"use strict";
|
|
1178
|
+
definition5 = {
|
|
1179
|
+
type: "function",
|
|
1180
|
+
function: {
|
|
1181
|
+
name: "grep",
|
|
1182
|
+
description: "\uD30C\uC77C\uC5D0\uC11C \uD328\uD134\uC744 \uAC80\uC0C9\uD569\uB2C8\uB2E4 (\uC7AC\uADC0, \uC904 \uBC88\uD638 \uD3EC\uD568).",
|
|
1183
|
+
parameters: {
|
|
1184
|
+
type: "object",
|
|
1185
|
+
properties: {
|
|
1186
|
+
pattern: { type: "string", description: "\uAC80\uC0C9 \uD328\uD134 (\uC815\uADDC\uC2DD)" },
|
|
1187
|
+
path: { type: "string", description: "\uAC80\uC0C9 \uB514\uB809\uD1A0\uB9AC \uB610\uB294 \uD30C\uC77C (\uAE30\uBCF8: .)" },
|
|
1188
|
+
glob: { type: "string", description: "\uD30C\uC77C \uD544\uD130 (\uC608: *.ts)" }
|
|
1189
|
+
},
|
|
1190
|
+
required: ["pattern"]
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
};
|
|
1194
|
+
}
|
|
1195
|
+
});
|
|
1573
1196
|
|
|
1574
1197
|
// src/agent/tools/list-files.ts
|
|
1575
1198
|
var list_files_exports = {};
|
|
@@ -1578,20 +1201,6 @@ __export(list_files_exports, {
|
|
|
1578
1201
|
execute: () => execute6
|
|
1579
1202
|
});
|
|
1580
1203
|
import { execSync as execSync3 } from "child_process";
|
|
1581
|
-
var definition6 = {
|
|
1582
|
-
type: "function",
|
|
1583
|
-
function: {
|
|
1584
|
-
name: "list_files",
|
|
1585
|
-
description: "\uB514\uB809\uD1A0\uB9AC\uC758 \uD30C\uC77C/\uD3F4\uB354 \uBAA9\uB85D\uC744 \uBC18\uD658\uD569\uB2C8\uB2E4. glob \uD328\uD134 \uC9C0\uC6D0.",
|
|
1586
|
-
parameters: {
|
|
1587
|
-
type: "object",
|
|
1588
|
-
properties: {
|
|
1589
|
-
path: { type: "string", description: "\uB514\uB809\uD1A0\uB9AC \uACBD\uB85C (\uAE30\uBCF8: .)" },
|
|
1590
|
-
pattern: { type: "string", description: "glob \uD328\uD134 (\uC608: **/*.ts)" }
|
|
1591
|
-
}
|
|
1592
|
-
}
|
|
1593
|
-
}
|
|
1594
|
-
};
|
|
1595
1204
|
async function execute6(args) {
|
|
1596
1205
|
const path = args.path || ".";
|
|
1597
1206
|
const pattern = args.pattern;
|
|
@@ -1612,6 +1221,26 @@ async function execute6(args) {
|
|
|
1612
1221
|
return `Error: ${err.message}`;
|
|
1613
1222
|
}
|
|
1614
1223
|
}
|
|
1224
|
+
var definition6;
|
|
1225
|
+
var init_list_files = __esm({
|
|
1226
|
+
"src/agent/tools/list-files.ts"() {
|
|
1227
|
+
"use strict";
|
|
1228
|
+
definition6 = {
|
|
1229
|
+
type: "function",
|
|
1230
|
+
function: {
|
|
1231
|
+
name: "list_files",
|
|
1232
|
+
description: "\uB514\uB809\uD1A0\uB9AC\uC758 \uD30C\uC77C/\uD3F4\uB354 \uBAA9\uB85D\uC744 \uBC18\uD658\uD569\uB2C8\uB2E4. glob \uD328\uD134 \uC9C0\uC6D0.",
|
|
1233
|
+
parameters: {
|
|
1234
|
+
type: "object",
|
|
1235
|
+
properties: {
|
|
1236
|
+
path: { type: "string", description: "\uB514\uB809\uD1A0\uB9AC \uACBD\uB85C (\uAE30\uBCF8: .)" },
|
|
1237
|
+
pattern: { type: "string", description: "glob \uD328\uD134 (\uC608: **/*.ts)" }
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
};
|
|
1242
|
+
}
|
|
1243
|
+
});
|
|
1615
1244
|
|
|
1616
1245
|
// src/agent/tools/sandbox.ts
|
|
1617
1246
|
var sandbox_exports = {};
|
|
@@ -1623,37 +1252,12 @@ import { execSync as execSync4 } from "child_process";
|
|
|
1623
1252
|
import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync4, existsSync as existsSync2, rmSync } from "fs";
|
|
1624
1253
|
import { join as join2 } from "path";
|
|
1625
1254
|
import { tmpdir } from "os";
|
|
1626
|
-
var SANDBOX_DIR = join2(tmpdir(), "xgen-sandbox");
|
|
1627
1255
|
function ensureSandbox() {
|
|
1628
1256
|
if (!existsSync2(SANDBOX_DIR)) {
|
|
1629
1257
|
mkdirSync3(SANDBOX_DIR, { recursive: true });
|
|
1630
1258
|
}
|
|
1631
1259
|
return SANDBOX_DIR;
|
|
1632
1260
|
}
|
|
1633
|
-
var definition7 = {
|
|
1634
|
-
type: "function",
|
|
1635
|
-
function: {
|
|
1636
|
-
name: "sandbox_run",
|
|
1637
|
-
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.",
|
|
1638
|
-
parameters: {
|
|
1639
|
-
type: "object",
|
|
1640
|
-
properties: {
|
|
1641
|
-
language: {
|
|
1642
|
-
type: "string",
|
|
1643
|
-
enum: ["javascript", "typescript", "python"],
|
|
1644
|
-
description: "\uC2E4\uD589\uD560 \uC5B8\uC5B4"
|
|
1645
|
-
},
|
|
1646
|
-
code: { type: "string", description: "\uC2E4\uD589\uD560 \uCF54\uB4DC" },
|
|
1647
|
-
packages: {
|
|
1648
|
-
type: "array",
|
|
1649
|
-
items: { type: "string" },
|
|
1650
|
-
description: "\uC124\uCE58\uD560 \uD328\uD0A4\uC9C0 (npm \uB610\uB294 pip)"
|
|
1651
|
-
}
|
|
1652
|
-
},
|
|
1653
|
-
required: ["language", "code"]
|
|
1654
|
-
}
|
|
1655
|
-
}
|
|
1656
|
-
};
|
|
1657
1261
|
async function execute7(args) {
|
|
1658
1262
|
const language = args.language;
|
|
1659
1263
|
const code = args.code;
|
|
@@ -1716,13 +1320,39 @@ async function execute7(args) {
|
|
|
1716
1320
|
}
|
|
1717
1321
|
}
|
|
1718
1322
|
}
|
|
1323
|
+
var SANDBOX_DIR, definition7;
|
|
1324
|
+
var init_sandbox = __esm({
|
|
1325
|
+
"src/agent/tools/sandbox.ts"() {
|
|
1326
|
+
"use strict";
|
|
1327
|
+
SANDBOX_DIR = join2(tmpdir(), "xgen-sandbox");
|
|
1328
|
+
definition7 = {
|
|
1329
|
+
type: "function",
|
|
1330
|
+
function: {
|
|
1331
|
+
name: "sandbox_run",
|
|
1332
|
+
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.",
|
|
1333
|
+
parameters: {
|
|
1334
|
+
type: "object",
|
|
1335
|
+
properties: {
|
|
1336
|
+
language: {
|
|
1337
|
+
type: "string",
|
|
1338
|
+
enum: ["javascript", "typescript", "python"],
|
|
1339
|
+
description: "\uC2E4\uD589\uD560 \uC5B8\uC5B4"
|
|
1340
|
+
},
|
|
1341
|
+
code: { type: "string", description: "\uC2E4\uD589\uD560 \uCF54\uB4DC" },
|
|
1342
|
+
packages: {
|
|
1343
|
+
type: "array",
|
|
1344
|
+
items: { type: "string" },
|
|
1345
|
+
description: "\uC124\uCE58\uD560 \uD328\uD0A4\uC9C0 (npm \uB610\uB294 pip)"
|
|
1346
|
+
}
|
|
1347
|
+
},
|
|
1348
|
+
required: ["language", "code"]
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
};
|
|
1352
|
+
}
|
|
1353
|
+
});
|
|
1719
1354
|
|
|
1720
1355
|
// src/agent/tools/index.ts
|
|
1721
|
-
var tools = [file_read_exports, file_write_exports, file_edit_exports, bash_exports, grep_exports, list_files_exports, sandbox_exports];
|
|
1722
|
-
var toolMap = /* @__PURE__ */ new Map();
|
|
1723
|
-
for (const t of tools) {
|
|
1724
|
-
toolMap.set(t.definition.function.name, t);
|
|
1725
|
-
}
|
|
1726
1356
|
function getAllToolDefs() {
|
|
1727
1357
|
return tools.map((t) => t.definition);
|
|
1728
1358
|
}
|
|
@@ -1734,100 +1364,30 @@ async function executeTool(name, args) {
|
|
|
1734
1364
|
function getToolNames() {
|
|
1735
1365
|
return tools.map((t) => t.definition.function.name);
|
|
1736
1366
|
}
|
|
1367
|
+
var tools, toolMap;
|
|
1368
|
+
var init_tools = __esm({
|
|
1369
|
+
"src/agent/tools/index.ts"() {
|
|
1370
|
+
"use strict";
|
|
1371
|
+
init_file_read();
|
|
1372
|
+
init_file_write();
|
|
1373
|
+
init_file_edit();
|
|
1374
|
+
init_bash();
|
|
1375
|
+
init_grep();
|
|
1376
|
+
init_list_files();
|
|
1377
|
+
init_sandbox();
|
|
1378
|
+
tools = [file_read_exports, file_write_exports, file_edit_exports, bash_exports, grep_exports, list_files_exports, sandbox_exports];
|
|
1379
|
+
toolMap = /* @__PURE__ */ new Map();
|
|
1380
|
+
for (const t of tools) {
|
|
1381
|
+
toolMap.set(t.definition.function.name, t);
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
});
|
|
1737
1385
|
|
|
1738
1386
|
// src/mcp/client.ts
|
|
1739
1387
|
import { spawn } from "child_process";
|
|
1740
1388
|
import { existsSync as existsSync3, readFileSync as readFileSync4 } from "fs";
|
|
1741
1389
|
import { join as join3 } from "path";
|
|
1742
1390
|
import { createInterface as createInterface4 } from "readline";
|
|
1743
|
-
var McpClient = class {
|
|
1744
|
-
process = null;
|
|
1745
|
-
requestId = 0;
|
|
1746
|
-
pending = /* @__PURE__ */ new Map();
|
|
1747
|
-
serverName;
|
|
1748
|
-
config;
|
|
1749
|
-
tools = [];
|
|
1750
|
-
constructor(serverName, config) {
|
|
1751
|
-
this.serverName = serverName;
|
|
1752
|
-
this.config = config;
|
|
1753
|
-
}
|
|
1754
|
-
async start() {
|
|
1755
|
-
this.process = spawn(this.config.command, this.config.args ?? [], {
|
|
1756
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
1757
|
-
env: { ...process.env, ...this.config.env }
|
|
1758
|
-
});
|
|
1759
|
-
const rl = createInterface4({ input: this.process.stdout });
|
|
1760
|
-
rl.on("line", (line) => {
|
|
1761
|
-
try {
|
|
1762
|
-
const msg = JSON.parse(line);
|
|
1763
|
-
if (msg.id !== void 0 && this.pending.has(msg.id)) {
|
|
1764
|
-
const p = this.pending.get(msg.id);
|
|
1765
|
-
this.pending.delete(msg.id);
|
|
1766
|
-
if (msg.error) {
|
|
1767
|
-
p.reject(new Error(msg.error.message));
|
|
1768
|
-
} else {
|
|
1769
|
-
p.resolve(msg.result);
|
|
1770
|
-
}
|
|
1771
|
-
}
|
|
1772
|
-
} catch {
|
|
1773
|
-
}
|
|
1774
|
-
});
|
|
1775
|
-
this.process.on("error", (err) => {
|
|
1776
|
-
console.error(`MCP [${this.serverName}] \uD504\uB85C\uC138\uC2A4 \uC624\uB958:`, err.message);
|
|
1777
|
-
});
|
|
1778
|
-
await this.send("initialize", {
|
|
1779
|
-
protocolVersion: "2024-11-05",
|
|
1780
|
-
capabilities: {},
|
|
1781
|
-
clientInfo: { name: "open-xgen", version: "0.3.0" }
|
|
1782
|
-
});
|
|
1783
|
-
await this.send("notifications/initialized", {});
|
|
1784
|
-
}
|
|
1785
|
-
send(method, params) {
|
|
1786
|
-
return new Promise((resolve, reject) => {
|
|
1787
|
-
const id = ++this.requestId;
|
|
1788
|
-
const request = { jsonrpc: "2.0", id, method, params };
|
|
1789
|
-
this.pending.set(id, { resolve, reject });
|
|
1790
|
-
const timeout = setTimeout(() => {
|
|
1791
|
-
this.pending.delete(id);
|
|
1792
|
-
reject(new Error(`MCP \uC694\uCCAD \uD0C0\uC784\uC544\uC6C3: ${method}`));
|
|
1793
|
-
}, 15e3);
|
|
1794
|
-
this.pending.set(id, {
|
|
1795
|
-
resolve: (v) => {
|
|
1796
|
-
clearTimeout(timeout);
|
|
1797
|
-
resolve(v);
|
|
1798
|
-
},
|
|
1799
|
-
reject: (e) => {
|
|
1800
|
-
clearTimeout(timeout);
|
|
1801
|
-
reject(e);
|
|
1802
|
-
}
|
|
1803
|
-
});
|
|
1804
|
-
this.process?.stdin?.write(JSON.stringify(request) + "\n");
|
|
1805
|
-
});
|
|
1806
|
-
}
|
|
1807
|
-
async listTools() {
|
|
1808
|
-
const result = await this.send("tools/list", {});
|
|
1809
|
-
this.tools = result.tools ?? [];
|
|
1810
|
-
return this.tools;
|
|
1811
|
-
}
|
|
1812
|
-
async callTool(name, args) {
|
|
1813
|
-
const result = await this.send("tools/call", { name, arguments: args });
|
|
1814
|
-
return result.content?.map((c) => c.text ?? "").join("\n") ?? "";
|
|
1815
|
-
}
|
|
1816
|
-
getOpenAITools() {
|
|
1817
|
-
return this.tools.map((t) => ({
|
|
1818
|
-
type: "function",
|
|
1819
|
-
function: {
|
|
1820
|
-
name: `mcp_${this.serverName}_${t.name}`,
|
|
1821
|
-
description: `[MCP:${this.serverName}] ${t.description ?? t.name}`,
|
|
1822
|
-
parameters: t.inputSchema ?? { type: "object", properties: {} }
|
|
1823
|
-
}
|
|
1824
|
-
}));
|
|
1825
|
-
}
|
|
1826
|
-
stop() {
|
|
1827
|
-
this.process?.kill();
|
|
1828
|
-
this.process = null;
|
|
1829
|
-
}
|
|
1830
|
-
};
|
|
1831
1391
|
function loadMcpConfig(dir) {
|
|
1832
1392
|
const searchPaths = [
|
|
1833
1393
|
dir ? join3(dir, ".mcp.json") : null,
|
|
@@ -1845,163 +1405,534 @@ function loadMcpConfig(dir) {
|
|
|
1845
1405
|
}
|
|
1846
1406
|
return null;
|
|
1847
1407
|
}
|
|
1848
|
-
var McpManager
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1408
|
+
var McpClient, McpManager;
|
|
1409
|
+
var init_client2 = __esm({
|
|
1410
|
+
"src/mcp/client.ts"() {
|
|
1411
|
+
"use strict";
|
|
1412
|
+
McpClient = class {
|
|
1413
|
+
process = null;
|
|
1414
|
+
requestId = 0;
|
|
1415
|
+
pending = /* @__PURE__ */ new Map();
|
|
1416
|
+
serverName;
|
|
1417
|
+
config;
|
|
1418
|
+
tools = [];
|
|
1419
|
+
constructor(serverName, config) {
|
|
1420
|
+
this.serverName = serverName;
|
|
1421
|
+
this.config = config;
|
|
1860
1422
|
}
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1423
|
+
async start() {
|
|
1424
|
+
this.process = spawn(this.config.command, this.config.args ?? [], {
|
|
1425
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
1426
|
+
env: { ...process.env, ...this.config.env }
|
|
1427
|
+
});
|
|
1428
|
+
const rl = createInterface4({ input: this.process.stdout });
|
|
1429
|
+
rl.on("line", (line) => {
|
|
1430
|
+
try {
|
|
1431
|
+
const msg = JSON.parse(line);
|
|
1432
|
+
if (msg.id !== void 0 && this.pending.has(msg.id)) {
|
|
1433
|
+
const p = this.pending.get(msg.id);
|
|
1434
|
+
this.pending.delete(msg.id);
|
|
1435
|
+
if (msg.error) {
|
|
1436
|
+
p.reject(new Error(msg.error.message));
|
|
1437
|
+
} else {
|
|
1438
|
+
p.resolve(msg.result);
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
} catch {
|
|
1442
|
+
}
|
|
1443
|
+
});
|
|
1444
|
+
this.process.on("error", (err) => {
|
|
1445
|
+
console.error(`MCP [${this.serverName}] \uD504\uB85C\uC138\uC2A4 \uC624\uB958:`, err.message);
|
|
1446
|
+
});
|
|
1447
|
+
await this.send("initialize", {
|
|
1448
|
+
protocolVersion: "2024-11-05",
|
|
1449
|
+
capabilities: {},
|
|
1450
|
+
clientInfo: { name: "open-xgen", version: "0.3.0" }
|
|
1451
|
+
});
|
|
1452
|
+
await this.send("notifications/initialized", {});
|
|
1453
|
+
}
|
|
1454
|
+
send(method, params) {
|
|
1455
|
+
return new Promise((resolve, reject) => {
|
|
1456
|
+
const id = ++this.requestId;
|
|
1457
|
+
const request = { jsonrpc: "2.0", id, method, params };
|
|
1458
|
+
this.pending.set(id, { resolve, reject });
|
|
1459
|
+
const timeout = setTimeout(() => {
|
|
1460
|
+
this.pending.delete(id);
|
|
1461
|
+
reject(new Error(`MCP \uC694\uCCAD \uD0C0\uC784\uC544\uC6C3: ${method}`));
|
|
1462
|
+
}, 15e3);
|
|
1463
|
+
this.pending.set(id, {
|
|
1464
|
+
resolve: (v) => {
|
|
1465
|
+
clearTimeout(timeout);
|
|
1466
|
+
resolve(v);
|
|
1467
|
+
},
|
|
1468
|
+
reject: (e) => {
|
|
1469
|
+
clearTimeout(timeout);
|
|
1470
|
+
reject(e);
|
|
1471
|
+
}
|
|
1472
|
+
});
|
|
1473
|
+
this.process?.stdin?.write(JSON.stringify(request) + "\n");
|
|
1474
|
+
});
|
|
1475
|
+
}
|
|
1476
|
+
async listTools() {
|
|
1477
|
+
const result = await this.send("tools/list", {});
|
|
1478
|
+
this.tools = result.tools ?? [];
|
|
1479
|
+
return this.tools;
|
|
1480
|
+
}
|
|
1481
|
+
async callTool(name, args) {
|
|
1482
|
+
const result = await this.send("tools/call", { name, arguments: args });
|
|
1483
|
+
return result.content?.map((c) => c.text ?? "").join("\n") ?? "";
|
|
1484
|
+
}
|
|
1485
|
+
getOpenAITools() {
|
|
1486
|
+
return this.tools.map((t) => ({
|
|
1487
|
+
type: "function",
|
|
1488
|
+
function: {
|
|
1489
|
+
name: `mcp_${this.serverName}_${t.name}`,
|
|
1490
|
+
description: `[MCP:${this.serverName}] ${t.description ?? t.name}`,
|
|
1491
|
+
parameters: t.inputSchema ?? { type: "object", properties: {} }
|
|
1492
|
+
}
|
|
1493
|
+
}));
|
|
1494
|
+
}
|
|
1495
|
+
stop() {
|
|
1496
|
+
this.process?.kill();
|
|
1497
|
+
this.process = null;
|
|
1498
|
+
}
|
|
1499
|
+
};
|
|
1500
|
+
McpManager = class {
|
|
1501
|
+
clients = /* @__PURE__ */ new Map();
|
|
1502
|
+
async startAll(config) {
|
|
1503
|
+
for (const [name, serverConfig] of Object.entries(config.mcpServers)) {
|
|
1504
|
+
if (serverConfig.type !== "stdio") continue;
|
|
1505
|
+
try {
|
|
1506
|
+
const client2 = new McpClient(name, serverConfig);
|
|
1507
|
+
await client2.start();
|
|
1508
|
+
await client2.listTools();
|
|
1509
|
+
this.clients.set(name, client2);
|
|
1510
|
+
} catch (err) {
|
|
1511
|
+
console.error(`MCP [${name}] \uC2DC\uC791 \uC2E4\uD328:`, err.message);
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
getAllTools() {
|
|
1516
|
+
const tools2 = [];
|
|
1517
|
+
for (const client2 of this.clients.values()) {
|
|
1518
|
+
tools2.push(...client2.getOpenAITools());
|
|
1519
|
+
}
|
|
1520
|
+
return tools2;
|
|
1521
|
+
}
|
|
1522
|
+
async callTool(fullName, args) {
|
|
1523
|
+
const parts = fullName.split("_");
|
|
1524
|
+
if (parts.length < 3 || parts[0] !== "mcp") return `Unknown MCP tool: ${fullName}`;
|
|
1525
|
+
const serverName = parts[1];
|
|
1526
|
+
const toolName = parts.slice(2).join("_");
|
|
1527
|
+
const client2 = this.clients.get(serverName);
|
|
1528
|
+
if (!client2) return `MCP \uC11C\uBC84\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${serverName}`;
|
|
1529
|
+
return client2.callTool(toolName, args);
|
|
1530
|
+
}
|
|
1531
|
+
isMcpTool(name) {
|
|
1532
|
+
return name.startsWith("mcp_");
|
|
1533
|
+
}
|
|
1534
|
+
stopAll() {
|
|
1535
|
+
for (const client2 of this.clients.values()) {
|
|
1536
|
+
client2.stop();
|
|
1537
|
+
}
|
|
1538
|
+
this.clients.clear();
|
|
1539
|
+
}
|
|
1540
|
+
get serverCount() {
|
|
1541
|
+
return this.clients.size;
|
|
1542
|
+
}
|
|
1543
|
+
getServerNames() {
|
|
1544
|
+
return [...this.clients.keys()];
|
|
1545
|
+
}
|
|
1546
|
+
};
|
|
1893
1547
|
}
|
|
1894
|
-
};
|
|
1548
|
+
});
|
|
1895
1549
|
|
|
1896
|
-
// src/commands/
|
|
1897
|
-
var
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
const
|
|
1914
|
-
const
|
|
1915
|
-
const
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
if (
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
if (mcpManager.serverCount > 0) {
|
|
1923
|
-
const mcpTools = mcpManager.getAllTools();
|
|
1924
|
-
allTools.push(...mcpTools);
|
|
1925
|
-
allToolNames.push(...mcpTools.map((t) => t.function.name));
|
|
1926
|
-
}
|
|
1927
|
-
} catch {
|
|
1928
|
-
}
|
|
1550
|
+
// src/commands/home.ts
|
|
1551
|
+
var home_exports = {};
|
|
1552
|
+
__export(home_exports, {
|
|
1553
|
+
homeMenu: () => homeMenu
|
|
1554
|
+
});
|
|
1555
|
+
import chalk11 from "chalk";
|
|
1556
|
+
import { createInterface as createInterface5 } from "readline";
|
|
1557
|
+
function prompt3(question) {
|
|
1558
|
+
return new Promise((resolve) => {
|
|
1559
|
+
const rl = createInterface5({ input: process.stdin, output: process.stdout });
|
|
1560
|
+
rl.question(question, (answer) => {
|
|
1561
|
+
rl.close();
|
|
1562
|
+
resolve(answer.trim());
|
|
1563
|
+
});
|
|
1564
|
+
});
|
|
1565
|
+
}
|
|
1566
|
+
function showStatus() {
|
|
1567
|
+
const provider = getDefaultProvider();
|
|
1568
|
+
const server = getServer();
|
|
1569
|
+
const auth = getAuth();
|
|
1570
|
+
console.log(chalk11.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\u2500\u2500\u2500\u2500"));
|
|
1571
|
+
console.log(chalk11.gray(" \uC0C1\uD0DC:"));
|
|
1572
|
+
if (provider) {
|
|
1573
|
+
console.log(` AI \uC5D0\uC774\uC804\uD2B8 ${chalk11.green("\u25CF")} ${provider.name} (${provider.model})`);
|
|
1574
|
+
} else {
|
|
1575
|
+
console.log(` AI \uC5D0\uC774\uC804\uD2B8 ${chalk11.red("\u25CB")} \uBBF8\uC124\uC815`);
|
|
1929
1576
|
}
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
console.log(chalk11.gray(` MCP: ${mcpManager.getServerNames().join(", ")} (${mcpManager.getAllTools().length}\uAC1C \uB3C4\uAD6C)`));
|
|
1577
|
+
if (server && auth) {
|
|
1578
|
+
console.log(` XGEN \uC11C\uBC84 ${chalk11.green("\u25CF")} ${server} (${auth.username})`);
|
|
1579
|
+
} else if (server) {
|
|
1580
|
+
console.log(` XGEN \uC11C\uBC84 ${chalk11.yellow("\u25CB")} ${server} (\uB85C\uADF8\uC778 \uD544\uC694)`);
|
|
1581
|
+
} else {
|
|
1582
|
+
console.log(` XGEN \uC11C\uBC84 ${chalk11.red("\u25CB")} \uBBF8\uC124\uC815`);
|
|
1937
1583
|
}
|
|
1938
|
-
console.log(chalk11.gray(
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
const
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
if (input === "/clear") {
|
|
1958
|
-
messages.length = 1;
|
|
1959
|
-
console.log(chalk11.gray("\uB300\uD654 \uCD08\uAE30\uD654\uB428.\n"));
|
|
1960
|
-
continue;
|
|
1961
|
-
}
|
|
1962
|
-
if (input === "/tools") {
|
|
1963
|
-
console.log(chalk11.bold("\n\uB0B4\uC7A5 \uB3C4\uAD6C:"), getToolNames().join(", "));
|
|
1964
|
-
if (mcpManager && mcpManager.serverCount > 0) {
|
|
1965
|
-
console.log(chalk11.bold("MCP \uB3C4\uAD6C:"), mcpManager.getAllTools().map((t) => t.function.name).join(", "));
|
|
1966
|
-
}
|
|
1967
|
-
console.log();
|
|
1968
|
-
continue;
|
|
1969
|
-
}
|
|
1970
|
-
if (input === "/provider") {
|
|
1971
|
-
console.log(chalk11.gray(`\uD604\uC7AC: ${provider.name} (${provider.model})
|
|
1584
|
+
console.log(chalk11.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\u2500\u2500\u2500\u2500\n"));
|
|
1585
|
+
}
|
|
1586
|
+
async function homeMenu() {
|
|
1587
|
+
const provider = getDefaultProvider();
|
|
1588
|
+
const server = getServer();
|
|
1589
|
+
const auth = getAuth();
|
|
1590
|
+
console.log(chalk11.cyan(`
|
|
1591
|
+
\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588 \u2588\u2588
|
|
1592
|
+
\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588
|
|
1593
|
+
\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588
|
|
1594
|
+
\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588
|
|
1595
|
+
\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588`));
|
|
1596
|
+
console.log(chalk11.white.bold(`
|
|
1597
|
+
\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588 \u2588\u2588
|
|
1598
|
+
\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588
|
|
1599
|
+
\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588
|
|
1600
|
+
\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588
|
|
1601
|
+
\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588`));
|
|
1602
|
+
console.log(chalk11.gray(` v0.3.0
|
|
1972
1603
|
`));
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1604
|
+
showStatus();
|
|
1605
|
+
while (true) {
|
|
1606
|
+
const items = [];
|
|
1607
|
+
items.push({
|
|
1608
|
+
key: "1",
|
|
1609
|
+
label: provider ? `AI \uC5D0\uC774\uC804\uD2B8 \uC2DC\uC791 ${chalk11.gray(`(${provider.name})`)}` : `AI \uC5D0\uC774\uC804\uD2B8 \uC124\uC815 + \uC2DC\uC791`,
|
|
1610
|
+
available: true,
|
|
1611
|
+
action: async () => {
|
|
1612
|
+
await agentRepl();
|
|
1981
1613
|
}
|
|
1982
|
-
console.log();
|
|
1983
|
-
continue;
|
|
1984
|
-
}
|
|
1985
|
-
messages.push({ role: "user", content: input });
|
|
1986
|
-
try {
|
|
1987
|
-
await runAgentLoop(client2, provider.model, messages, allTools);
|
|
1988
|
-
} catch (err) {
|
|
1989
|
-
console.log(chalk11.red(`
|
|
1990
|
-
\uC624\uB958: ${err.message}
|
|
1991
|
-
`));
|
|
1992
|
-
}
|
|
1993
|
-
}
|
|
1994
|
-
}
|
|
1995
|
-
async function runAgentLoop(client2, model, messages, tools2) {
|
|
1996
|
-
const MAX_ITERATIONS = 20;
|
|
1997
|
-
for (let i = 0; i < MAX_ITERATIONS; i++) {
|
|
1998
|
-
const result = await streamChat(client2, model, messages, tools2, (delta) => {
|
|
1999
|
-
process.stdout.write(delta);
|
|
2000
1614
|
});
|
|
2001
|
-
if (
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
1615
|
+
if (server && auth) {
|
|
1616
|
+
items.push({
|
|
1617
|
+
key: "2",
|
|
1618
|
+
label: `\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uCC44\uD305 ${chalk11.gray(`(${auth.username}@${server.replace("https://", "")})`)}`,
|
|
1619
|
+
available: true,
|
|
1620
|
+
action: async () => {
|
|
1621
|
+
await chat();
|
|
1622
|
+
}
|
|
1623
|
+
});
|
|
1624
|
+
items.push({
|
|
1625
|
+
key: "3",
|
|
1626
|
+
label: "\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D",
|
|
1627
|
+
available: true,
|
|
1628
|
+
action: async () => {
|
|
1629
|
+
const { workflowList: workflowList2 } = await Promise.resolve().then(() => (init_list(), list_exports));
|
|
1630
|
+
await workflowList2({ detail: false });
|
|
1631
|
+
return;
|
|
1632
|
+
}
|
|
1633
|
+
});
|
|
1634
|
+
} else {
|
|
1635
|
+
items.push({
|
|
1636
|
+
key: "2",
|
|
1637
|
+
label: "XGEN \uC11C\uBC84 \uC5F0\uACB0 + \uB85C\uADF8\uC778",
|
|
1638
|
+
available: true,
|
|
1639
|
+
action: async () => {
|
|
1640
|
+
await serverSetup();
|
|
1641
|
+
}
|
|
1642
|
+
});
|
|
1643
|
+
}
|
|
1644
|
+
items.push({
|
|
1645
|
+
key: String(items.length + 1),
|
|
1646
|
+
label: "\uD504\uB85C\uBC14\uC774\uB354 \uAD00\uB9AC",
|
|
1647
|
+
available: true,
|
|
1648
|
+
action: async () => {
|
|
1649
|
+
await providerMenu();
|
|
1650
|
+
}
|
|
1651
|
+
});
|
|
1652
|
+
items.push({
|
|
1653
|
+
key: String(items.length + 1),
|
|
1654
|
+
label: "\uC124\uC815 \uBCF4\uAE30",
|
|
1655
|
+
available: true,
|
|
1656
|
+
action: async () => {
|
|
1657
|
+
showStatus();
|
|
1658
|
+
const cfg = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
1659
|
+
const config = cfg.getConfig();
|
|
1660
|
+
console.log(chalk11.gray(" \uC124\uC815 \uD30C\uC77C: ~/.xgen/\n"));
|
|
1661
|
+
console.log(chalk11.gray(` \uC11C\uBC84: ${config.server ?? "(\uC5C6\uC74C)"}`));
|
|
1662
|
+
console.log(chalk11.gray(` \uD14C\uB9C8: ${config.theme}`));
|
|
1663
|
+
console.log(chalk11.gray(` \uC2A4\uD2B8\uB9BC \uB85C\uADF8: ${config.streamLogs}
|
|
1664
|
+
`));
|
|
1665
|
+
}
|
|
1666
|
+
});
|
|
1667
|
+
items.push({
|
|
1668
|
+
key: "q",
|
|
1669
|
+
label: "\uC885\uB8CC",
|
|
1670
|
+
available: true,
|
|
1671
|
+
action: async () => {
|
|
1672
|
+
process.exit(0);
|
|
1673
|
+
}
|
|
1674
|
+
});
|
|
1675
|
+
console.log(chalk11.bold(" \uBB58 \uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?\n"));
|
|
1676
|
+
for (const item of items) {
|
|
1677
|
+
console.log(` ${chalk11.cyan(item.key + ")")} ${item.label}`);
|
|
1678
|
+
}
|
|
1679
|
+
console.log();
|
|
1680
|
+
const choice = await prompt3(chalk11.white(" \uC120\uD0DD: "));
|
|
1681
|
+
if (choice === "q" || choice === "exit") {
|
|
1682
|
+
console.log(chalk11.gray("\n \uC548\uB155\uD788.\n"));
|
|
1683
|
+
break;
|
|
1684
|
+
}
|
|
1685
|
+
const selected = items.find((i) => i.key === choice);
|
|
1686
|
+
if (!selected) {
|
|
1687
|
+
console.log(chalk11.red(" \uC798\uBABB\uB41C \uC120\uD0DD\uC785\uB2C8\uB2E4.\n"));
|
|
1688
|
+
continue;
|
|
1689
|
+
}
|
|
1690
|
+
try {
|
|
1691
|
+
await selected.action();
|
|
1692
|
+
} catch (err) {
|
|
1693
|
+
console.log(chalk11.red(`
|
|
1694
|
+
\uC624\uB958: ${err.message}
|
|
1695
|
+
`));
|
|
1696
|
+
}
|
|
1697
|
+
console.log();
|
|
1698
|
+
showStatus();
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
async function serverSetup() {
|
|
1702
|
+
console.log(chalk11.cyan.bold("\n XGEN \uC11C\uBC84 \uC5F0\uACB0\n"));
|
|
1703
|
+
const currentServer = getServer();
|
|
1704
|
+
const urlInput = await prompt3(
|
|
1705
|
+
chalk11.white(` \uC11C\uBC84 URL${currentServer ? ` [${currentServer}]` : ""}: `)
|
|
1706
|
+
);
|
|
1707
|
+
const url = urlInput || currentServer;
|
|
1708
|
+
if (!url) {
|
|
1709
|
+
console.log(chalk11.red(" URL\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.\n"));
|
|
1710
|
+
return;
|
|
1711
|
+
}
|
|
1712
|
+
const { setServer: setServer2 } = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
1713
|
+
setServer2(url);
|
|
1714
|
+
console.log(chalk11.green(` \u2713 \uC11C\uBC84 \uC124\uC815: ${url}
|
|
1715
|
+
`));
|
|
1716
|
+
console.log(chalk11.bold(" \uB85C\uADF8\uC778\n"));
|
|
1717
|
+
const email = await prompt3(chalk11.white(" \uC774\uBA54\uC77C: "));
|
|
1718
|
+
const password = await prompt3(chalk11.white(" \uBE44\uBC00\uBC88\uD638: "));
|
|
1719
|
+
if (!email || !password) {
|
|
1720
|
+
console.log(chalk11.red(" \uC774\uBA54\uC77C\uACFC \uBE44\uBC00\uBC88\uD638\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.\n"));
|
|
1721
|
+
return;
|
|
1722
|
+
}
|
|
1723
|
+
try {
|
|
1724
|
+
const { apiLogin: apiLogin2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
|
|
1725
|
+
const { setAuth: setAuth2 } = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
1726
|
+
const result = await apiLogin2(email, password);
|
|
1727
|
+
if (result.success && result.access_token) {
|
|
1728
|
+
setAuth2({
|
|
1729
|
+
accessToken: result.access_token,
|
|
1730
|
+
refreshToken: result.refresh_token ?? "",
|
|
1731
|
+
userId: result.user_id ?? "",
|
|
1732
|
+
username: result.username ?? "",
|
|
1733
|
+
isAdmin: false,
|
|
1734
|
+
expiresAt: null
|
|
1735
|
+
});
|
|
1736
|
+
console.log(chalk11.green(` \u2713 \uB85C\uADF8\uC778 \uC131\uACF5! ${result.username ?? email}
|
|
1737
|
+
`));
|
|
1738
|
+
} else {
|
|
1739
|
+
console.log(chalk11.red(` \u2717 \uB85C\uADF8\uC778 \uC2E4\uD328: ${result.message}
|
|
1740
|
+
`));
|
|
1741
|
+
}
|
|
1742
|
+
} catch (err) {
|
|
1743
|
+
console.log(chalk11.red(` \u2717 \uB85C\uADF8\uC778 \uC2E4\uD328: ${err.message}
|
|
1744
|
+
`));
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
async function providerMenu() {
|
|
1748
|
+
const { getProviders: getProviders2, getDefaultProvider: getDefault } = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
1749
|
+
const providers = getProviders2();
|
|
1750
|
+
const defaultP = getDefault();
|
|
1751
|
+
console.log(chalk11.cyan.bold("\n \uD504\uB85C\uBC14\uC774\uB354 \uAD00\uB9AC\n"));
|
|
1752
|
+
if (providers.length > 0) {
|
|
1753
|
+
for (const p of providers) {
|
|
1754
|
+
const mark = p.id === defaultP?.id ? chalk11.green("\u25CF ") : chalk11.gray(" ");
|
|
1755
|
+
console.log(` ${mark}${p.name} ${chalk11.gray(`(${p.type} \u2014 ${p.model})`)}`);
|
|
1756
|
+
}
|
|
1757
|
+
console.log();
|
|
1758
|
+
}
|
|
1759
|
+
console.log(` ${chalk11.cyan("1)")} \uC0C8 \uD504\uB85C\uBC14\uC774\uB354 \uCD94\uAC00`);
|
|
1760
|
+
if (providers.length > 1) {
|
|
1761
|
+
console.log(` ${chalk11.cyan("2)")} \uAE30\uBCF8 \uD504\uB85C\uBC14\uC774\uB354 \uBCC0\uACBD`);
|
|
1762
|
+
}
|
|
1763
|
+
if (providers.length > 0) {
|
|
1764
|
+
console.log(` ${chalk11.cyan("3)")} \uD504\uB85C\uBC14\uC774\uB354 \uC0AD\uC81C`);
|
|
1765
|
+
}
|
|
1766
|
+
console.log(` ${chalk11.cyan("b)")} \uB3CC\uC544\uAC00\uAE30`);
|
|
1767
|
+
console.log();
|
|
1768
|
+
const choice = await prompt3(chalk11.white(" \uC120\uD0DD: "));
|
|
1769
|
+
if (choice === "1") {
|
|
1770
|
+
await guidedProviderSetup();
|
|
1771
|
+
} else if (choice === "2" && providers.length > 1) {
|
|
1772
|
+
console.log();
|
|
1773
|
+
providers.forEach((p, i) => {
|
|
1774
|
+
console.log(` ${chalk11.cyan(`${i + 1})`)} ${p.name} (${p.model})`);
|
|
1775
|
+
});
|
|
1776
|
+
console.log();
|
|
1777
|
+
const pc = await prompt3(chalk11.white(" \uBC88\uD638: "));
|
|
1778
|
+
const pi = parseInt(pc) - 1;
|
|
1779
|
+
if (pi >= 0 && pi < providers.length) {
|
|
1780
|
+
const { setDefaultProvider: setDef } = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
1781
|
+
setDef(providers[pi].id);
|
|
1782
|
+
console.log(chalk11.green(` \u2713 \uAE30\uBCF8 \uD504\uB85C\uBC14\uC774\uB354: ${providers[pi].name}
|
|
1783
|
+
`));
|
|
1784
|
+
}
|
|
1785
|
+
} else if (choice === "3" && providers.length > 0) {
|
|
1786
|
+
console.log();
|
|
1787
|
+
providers.forEach((p, i) => {
|
|
1788
|
+
console.log(` ${chalk11.cyan(`${i + 1})`)} ${p.name} (${p.model})`);
|
|
1789
|
+
});
|
|
1790
|
+
console.log();
|
|
1791
|
+
const dc = await prompt3(chalk11.white(" \uC0AD\uC81C\uD560 \uBC88\uD638: "));
|
|
1792
|
+
const di = parseInt(dc) - 1;
|
|
1793
|
+
if (di >= 0 && di < providers.length) {
|
|
1794
|
+
const { removeProvider: rmProv } = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
1795
|
+
rmProv(providers[di].id);
|
|
1796
|
+
console.log(chalk11.green(` \u2713 \uC0AD\uC81C\uB428: ${providers[di].name}
|
|
1797
|
+
`));
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1800
|
+
}
|
|
1801
|
+
var init_home = __esm({
|
|
1802
|
+
"src/commands/home.ts"() {
|
|
1803
|
+
"use strict";
|
|
1804
|
+
init_store();
|
|
1805
|
+
init_agent();
|
|
1806
|
+
init_chat();
|
|
1807
|
+
init_provider();
|
|
1808
|
+
}
|
|
1809
|
+
});
|
|
1810
|
+
|
|
1811
|
+
// src/commands/agent.ts
|
|
1812
|
+
import chalk12 from "chalk";
|
|
1813
|
+
import { createInterface as createInterface6 } from "readline";
|
|
1814
|
+
async function agentRepl() {
|
|
1815
|
+
let provider = getDefaultProvider();
|
|
1816
|
+
if (!provider) {
|
|
1817
|
+
provider = await guidedProviderSetup();
|
|
1818
|
+
if (!provider) {
|
|
1819
|
+
process.exit(1);
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1822
|
+
const client2 = createLLMClient(provider);
|
|
1823
|
+
const builtinTools = getAllToolDefs();
|
|
1824
|
+
const allTools = [...builtinTools];
|
|
1825
|
+
const allToolNames = [...getToolNames()];
|
|
1826
|
+
const mcpConfig = loadMcpConfig();
|
|
1827
|
+
if (mcpConfig && Object.keys(mcpConfig.mcpServers).length > 0) {
|
|
1828
|
+
mcpManager = new McpManager();
|
|
1829
|
+
try {
|
|
1830
|
+
await mcpManager.startAll(mcpConfig);
|
|
1831
|
+
if (mcpManager.serverCount > 0) {
|
|
1832
|
+
const mcpTools = mcpManager.getAllTools();
|
|
1833
|
+
allTools.push(...mcpTools);
|
|
1834
|
+
allToolNames.push(...mcpTools.map((t) => t.function.name));
|
|
1835
|
+
}
|
|
1836
|
+
} catch {
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
const messages = [{ role: "system", content: SYSTEM_PROMPT }];
|
|
1840
|
+
console.log(chalk12.cyan.bold("\n OPEN XGEN Agent"));
|
|
1841
|
+
console.log(chalk12.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"));
|
|
1842
|
+
console.log(chalk12.gray(` \uD504\uB85C\uBC14\uC774\uB354: ${provider.name} (${provider.model})`));
|
|
1843
|
+
console.log(chalk12.gray(` \uB3C4\uAD6C: ${getToolNames().join(", ")}`));
|
|
1844
|
+
if (mcpManager && mcpManager.serverCount > 0) {
|
|
1845
|
+
console.log(chalk12.gray(` MCP: ${mcpManager.getServerNames().join(", ")} (${mcpManager.getAllTools().length}\uAC1C \uB3C4\uAD6C)`));
|
|
1846
|
+
}
|
|
1847
|
+
console.log(chalk12.gray(` \uCEE4\uB9E8\uB4DC: /tools /provider /model /mcp /clear /home /exit`));
|
|
1848
|
+
console.log();
|
|
1849
|
+
const rl = createInterface6({ input: process.stdin, output: process.stdout });
|
|
1850
|
+
const ask = () => new Promise((resolve) => rl.question(chalk12.green("\u276F "), (a) => resolve(a.trim())));
|
|
1851
|
+
process.on("SIGINT", () => {
|
|
1852
|
+
console.log(chalk12.gray("\n\uC885\uB8CC\uD569\uB2C8\uB2E4."));
|
|
1853
|
+
mcpManager?.stopAll();
|
|
1854
|
+
rl.close();
|
|
1855
|
+
process.exit(0);
|
|
1856
|
+
});
|
|
1857
|
+
while (true) {
|
|
1858
|
+
const input = await ask();
|
|
1859
|
+
if (!input) continue;
|
|
1860
|
+
if (input === "exit" || input === "/exit") {
|
|
1861
|
+
console.log(chalk12.gray("\uC885\uB8CC\uD569\uB2C8\uB2E4."));
|
|
1862
|
+
mcpManager?.stopAll();
|
|
1863
|
+
rl.close();
|
|
1864
|
+
break;
|
|
1865
|
+
}
|
|
1866
|
+
if (input === "/clear") {
|
|
1867
|
+
messages.length = 1;
|
|
1868
|
+
console.log(chalk12.gray("\uB300\uD654 \uCD08\uAE30\uD654\uB428.\n"));
|
|
1869
|
+
continue;
|
|
1870
|
+
}
|
|
1871
|
+
if (input === "/tools") {
|
|
1872
|
+
console.log(chalk12.bold("\n\uB0B4\uC7A5 \uB3C4\uAD6C:"), getToolNames().join(", "));
|
|
1873
|
+
if (mcpManager && mcpManager.serverCount > 0) {
|
|
1874
|
+
console.log(chalk12.bold("MCP \uB3C4\uAD6C:"), mcpManager.getAllTools().map((t) => t.function.name).join(", "));
|
|
1875
|
+
}
|
|
1876
|
+
console.log();
|
|
1877
|
+
continue;
|
|
1878
|
+
}
|
|
1879
|
+
if (input === "/provider") {
|
|
1880
|
+
console.log(chalk12.gray(`\uD604\uC7AC: ${provider.name} (${provider.model})`));
|
|
1881
|
+
console.log(chalk12.gray(`\uBCC0\uACBD: xgen provider add / xgen provider use <id>
|
|
1882
|
+
`));
|
|
1883
|
+
continue;
|
|
1884
|
+
}
|
|
1885
|
+
if (input === "/model") {
|
|
1886
|
+
const { getProviders: gp } = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
1887
|
+
const all = gp();
|
|
1888
|
+
if (all.length > 0) {
|
|
1889
|
+
console.log(chalk12.bold("\n \uB4F1\uB85D\uB41C \uD504\uB85C\uBC14\uC774\uB354:\n"));
|
|
1890
|
+
all.forEach((p, i) => {
|
|
1891
|
+
const mark = p.id === provider.id ? chalk12.green("\u25CF ") : " ";
|
|
1892
|
+
console.log(` ${mark}${i + 1}) ${p.name} (${p.model})`);
|
|
1893
|
+
});
|
|
1894
|
+
console.log(chalk12.gray("\n \uBCC0\uACBD\uD558\uB824\uBA74 exit \uD6C4 xgen provider use <id>\n"));
|
|
1895
|
+
}
|
|
1896
|
+
continue;
|
|
1897
|
+
}
|
|
1898
|
+
if (input === "/home" || input === "/menu") {
|
|
1899
|
+
console.log(chalk12.gray("\uC5D0\uC774\uC804\uD2B8\uB97C \uC885\uB8CC\uD558\uACE0 \uD648\uC73C\uB85C \uB3CC\uC544\uAC11\uB2C8\uB2E4."));
|
|
1900
|
+
mcpManager?.stopAll();
|
|
1901
|
+
rl.close();
|
|
1902
|
+
const { homeMenu: homeMenu2 } = await Promise.resolve().then(() => (init_home(), home_exports));
|
|
1903
|
+
await homeMenu2();
|
|
1904
|
+
return;
|
|
1905
|
+
}
|
|
1906
|
+
if (input === "/mcp") {
|
|
1907
|
+
if (mcpManager && mcpManager.serverCount > 0) {
|
|
1908
|
+
console.log(chalk12.bold("\nMCP \uC11C\uBC84:"), mcpManager.getServerNames().join(", "));
|
|
1909
|
+
console.log(chalk12.gray("\uB3C4\uAD6C:"), mcpManager.getAllTools().map((t) => t.function.name).join(", "));
|
|
1910
|
+
} else {
|
|
1911
|
+
console.log(chalk12.gray("MCP \uC11C\uBC84 \uC5C6\uC74C. .mcp.json\uC744 \uD504\uB85C\uC81D\uD2B8 \uB8E8\uD2B8\uC5D0 \uCD94\uAC00\uD558\uC138\uC694."));
|
|
1912
|
+
}
|
|
1913
|
+
console.log();
|
|
1914
|
+
continue;
|
|
1915
|
+
}
|
|
1916
|
+
messages.push({ role: "user", content: input });
|
|
1917
|
+
try {
|
|
1918
|
+
await runAgentLoop(client2, provider.model, messages, allTools);
|
|
1919
|
+
} catch (err) {
|
|
1920
|
+
console.log(chalk12.red(`
|
|
1921
|
+
\uC624\uB958: ${err.message}
|
|
1922
|
+
`));
|
|
1923
|
+
}
|
|
1924
|
+
}
|
|
1925
|
+
}
|
|
1926
|
+
async function runAgentLoop(client2, model, messages, tools2) {
|
|
1927
|
+
const MAX_ITERATIONS = 20;
|
|
1928
|
+
for (let i = 0; i < MAX_ITERATIONS; i++) {
|
|
1929
|
+
const result = await streamChat(client2, model, messages, tools2, (delta) => {
|
|
1930
|
+
process.stdout.write(delta);
|
|
1931
|
+
});
|
|
1932
|
+
if (result.content) {
|
|
1933
|
+
process.stdout.write("\n\n");
|
|
1934
|
+
}
|
|
1935
|
+
if (result.toolCalls.length === 0) {
|
|
2005
1936
|
if (result.content) {
|
|
2006
1937
|
messages.push({ role: "assistant", content: result.content });
|
|
2007
1938
|
}
|
|
@@ -2023,7 +1954,7 @@ async function runAgentLoop(client2, model, messages, tools2) {
|
|
|
2023
1954
|
} catch {
|
|
2024
1955
|
args = {};
|
|
2025
1956
|
}
|
|
2026
|
-
console.log(
|
|
1957
|
+
console.log(chalk12.gray(` \u2699 ${tc.name}(`), chalk12.dim(summarizeArgs(args)), chalk12.gray(")"));
|
|
2027
1958
|
let toolResult;
|
|
2028
1959
|
if (mcpManager?.isMcpTool(tc.name)) {
|
|
2029
1960
|
toolResult = await mcpManager.callTool(tc.name, args);
|
|
@@ -2038,25 +1969,473 @@ async function runAgentLoop(client2, model, messages, tools2) {
|
|
|
2038
1969
|
});
|
|
2039
1970
|
}
|
|
2040
1971
|
}
|
|
2041
|
-
console.log(
|
|
1972
|
+
console.log(chalk12.yellow("\n\uCD5C\uB300 \uBC18\uBCF5 \uD69F\uC218\uC5D0 \uB3C4\uB2EC\uD588\uC2B5\uB2C8\uB2E4.\n"));
|
|
1973
|
+
}
|
|
1974
|
+
function summarizeArgs(args) {
|
|
1975
|
+
const parts = [];
|
|
1976
|
+
for (const [k, v] of Object.entries(args)) {
|
|
1977
|
+
const s = String(v);
|
|
1978
|
+
parts.push(`${k}: ${s.length > 40 ? s.slice(0, 40) + "..." : s}`);
|
|
1979
|
+
}
|
|
1980
|
+
return parts.join(", ");
|
|
1981
|
+
}
|
|
1982
|
+
function registerAgentCommand(program2) {
|
|
1983
|
+
program2.command("agent").description("OPEN XGEN AI \uCF54\uB529 \uC5D0\uC774\uC804\uD2B8").action(async () => {
|
|
1984
|
+
await agentRepl();
|
|
1985
|
+
});
|
|
1986
|
+
}
|
|
1987
|
+
var SYSTEM_PROMPT, mcpManager;
|
|
1988
|
+
var init_agent = __esm({
|
|
1989
|
+
"src/commands/agent.ts"() {
|
|
1990
|
+
"use strict";
|
|
1991
|
+
init_store();
|
|
1992
|
+
init_llm();
|
|
1993
|
+
init_tools();
|
|
1994
|
+
init_client2();
|
|
1995
|
+
init_provider();
|
|
1996
|
+
SYSTEM_PROMPT = `You are OPEN XGEN Agent, an AI coding assistant running in the user's terminal.
|
|
1997
|
+
You have access to tools for reading/writing files, executing commands, searching code, and running sandboxed code.
|
|
1998
|
+
You can also use MCP (Model Context Protocol) tools if available.
|
|
1999
|
+
Always respond in the same language as the user.
|
|
2000
|
+
When using tools, be concise about what you're doing.
|
|
2001
|
+
For file edits, show what you changed briefly.
|
|
2002
|
+
For sandbox_run, you can install npm/pip packages and run isolated code.`;
|
|
2003
|
+
mcpManager = null;
|
|
2004
|
+
}
|
|
2005
|
+
});
|
|
2006
|
+
|
|
2007
|
+
// src/index.ts
|
|
2008
|
+
import { Command } from "commander";
|
|
2009
|
+
import chalk15 from "chalk";
|
|
2010
|
+
|
|
2011
|
+
// src/commands/config.ts
|
|
2012
|
+
init_store();
|
|
2013
|
+
init_client();
|
|
2014
|
+
init_format();
|
|
2015
|
+
import chalk2 from "chalk";
|
|
2016
|
+
function registerConfigCommand(program2) {
|
|
2017
|
+
const config = program2.command("config").description("XGEN CLI \uC124\uC815 \uAD00\uB9AC");
|
|
2018
|
+
config.command("set-server <url>").description("XGEN \uC11C\uBC84 URL \uC124\uC815").action((url) => {
|
|
2019
|
+
if (!url.startsWith("http://") && !url.startsWith("https://")) {
|
|
2020
|
+
printError("URL\uC740 http:// \uB610\uB294 https://\uB85C \uC2DC\uC791\uD574\uC57C \uD569\uB2C8\uB2E4");
|
|
2021
|
+
process.exit(1);
|
|
2022
|
+
}
|
|
2023
|
+
setServer(url);
|
|
2024
|
+
resetClient();
|
|
2025
|
+
printSuccess(`\uC11C\uBC84 \uC124\uC815 \uC644\uB8CC: ${chalk2.underline(url)}`);
|
|
2026
|
+
});
|
|
2027
|
+
config.command("get-server").description("\uD604\uC7AC \uC124\uC815\uB41C \uC11C\uBC84 URL \uD655\uC778").action(() => {
|
|
2028
|
+
const server = getServer();
|
|
2029
|
+
if (server) {
|
|
2030
|
+
console.log(server);
|
|
2031
|
+
} else {
|
|
2032
|
+
printError("\uC11C\uBC84\uAC00 \uC124\uC815\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4");
|
|
2033
|
+
console.log(" \uC124\uC815: xgen config set-server <url>");
|
|
2034
|
+
}
|
|
2035
|
+
});
|
|
2036
|
+
config.command("list").description("\uC804\uCCB4 \uC124\uC815 \uD655\uC778").action(() => {
|
|
2037
|
+
const cfg = getConfig();
|
|
2038
|
+
console.log(chalk2.bold("\nXGEN CLI \uC124\uC815"));
|
|
2039
|
+
console.log(chalk2.gray("\u2500".repeat(40)));
|
|
2040
|
+
printKeyValue("\uC11C\uBC84", cfg.server);
|
|
2041
|
+
printKeyValue("\uAE30\uBCF8 \uC6CC\uD06C\uD50C\uB85C\uC6B0", cfg.defaultWorkflow);
|
|
2042
|
+
printKeyValue("\uD14C\uB9C8", cfg.theme);
|
|
2043
|
+
printKeyValue("\uC2A4\uD2B8\uB9BC \uB85C\uADF8", String(cfg.streamLogs));
|
|
2044
|
+
console.log();
|
|
2045
|
+
});
|
|
2046
|
+
config.command("set <key> <value>").description("\uC124\uC815 \uAC12 \uBCC0\uACBD").action((key, value) => {
|
|
2047
|
+
const allowedKeys = ["defaultWorkflow", "theme", "streamLogs"];
|
|
2048
|
+
if (!allowedKeys.includes(key)) {
|
|
2049
|
+
printError(`\uC54C \uC218 \uC5C6\uB294 \uC124\uC815 \uD0A4: ${key}`);
|
|
2050
|
+
console.log(` \uC0AC\uC6A9 \uAC00\uB2A5: ${allowedKeys.join(", ")}`);
|
|
2051
|
+
process.exit(1);
|
|
2052
|
+
}
|
|
2053
|
+
const parsed = key === "streamLogs" ? value === "true" : value;
|
|
2054
|
+
setConfig({ [key]: parsed });
|
|
2055
|
+
printSuccess(`${key} = ${value}`);
|
|
2056
|
+
});
|
|
2057
|
+
}
|
|
2058
|
+
|
|
2059
|
+
// src/commands/login.ts
|
|
2060
|
+
init_auth();
|
|
2061
|
+
init_store();
|
|
2062
|
+
init_format();
|
|
2063
|
+
import chalk3 from "chalk";
|
|
2064
|
+
import { createInterface } from "readline";
|
|
2065
|
+
function prompt(question, hidden = false) {
|
|
2066
|
+
return new Promise((resolve) => {
|
|
2067
|
+
const rl = createInterface({
|
|
2068
|
+
input: process.stdin,
|
|
2069
|
+
output: process.stdout
|
|
2070
|
+
});
|
|
2071
|
+
if (hidden) {
|
|
2072
|
+
process.stdout.write(question);
|
|
2073
|
+
const stdin = process.stdin;
|
|
2074
|
+
const wasRaw = stdin.isRaw;
|
|
2075
|
+
if (stdin.isTTY) stdin.setRawMode(true);
|
|
2076
|
+
let password = "";
|
|
2077
|
+
const onData = (ch) => {
|
|
2078
|
+
const c = ch.toString("utf8");
|
|
2079
|
+
if (c === "\n" || c === "\r" || c === "") {
|
|
2080
|
+
if (stdin.isTTY) stdin.setRawMode(wasRaw ?? false);
|
|
2081
|
+
stdin.removeListener("data", onData);
|
|
2082
|
+
process.stdout.write("\n");
|
|
2083
|
+
rl.close();
|
|
2084
|
+
resolve(password);
|
|
2085
|
+
} else if (c === "") {
|
|
2086
|
+
process.exit(0);
|
|
2087
|
+
} else if (c === "\x7F" || c === "\b") {
|
|
2088
|
+
if (password.length > 0) {
|
|
2089
|
+
password = password.slice(0, -1);
|
|
2090
|
+
process.stdout.write("\b \b");
|
|
2091
|
+
}
|
|
2092
|
+
} else {
|
|
2093
|
+
password += c;
|
|
2094
|
+
process.stdout.write("*");
|
|
2095
|
+
}
|
|
2096
|
+
};
|
|
2097
|
+
stdin.on("data", onData);
|
|
2098
|
+
} else {
|
|
2099
|
+
rl.question(question, (answer) => {
|
|
2100
|
+
rl.close();
|
|
2101
|
+
resolve(answer.trim());
|
|
2102
|
+
});
|
|
2103
|
+
}
|
|
2104
|
+
});
|
|
2105
|
+
}
|
|
2106
|
+
function registerLoginCommand(program2) {
|
|
2107
|
+
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) => {
|
|
2108
|
+
const server = requireServer();
|
|
2109
|
+
printHeader("XGEN Login");
|
|
2110
|
+
console.log(chalk3.gray(`\uC11C\uBC84: ${server}
|
|
2111
|
+
`));
|
|
2112
|
+
let email = opts.email;
|
|
2113
|
+
let password = opts.password;
|
|
2114
|
+
if (!email) {
|
|
2115
|
+
email = await prompt(chalk3.white("\uC774\uBA54\uC77C: "));
|
|
2116
|
+
}
|
|
2117
|
+
if (!password) {
|
|
2118
|
+
password = await prompt(chalk3.white("\uBE44\uBC00\uBC88\uD638: "), true);
|
|
2119
|
+
}
|
|
2120
|
+
if (!email || !password) {
|
|
2121
|
+
printError("\uC774\uBA54\uC77C\uACFC \uBE44\uBC00\uBC88\uD638\uB97C \uBAA8\uB450 \uC785\uB825\uD558\uC138\uC694");
|
|
2122
|
+
process.exit(1);
|
|
2123
|
+
}
|
|
2124
|
+
try {
|
|
2125
|
+
const result = await apiLogin(email, password);
|
|
2126
|
+
if (result.success && result.access_token) {
|
|
2127
|
+
setAuth({
|
|
2128
|
+
accessToken: result.access_token,
|
|
2129
|
+
refreshToken: result.refresh_token ?? "",
|
|
2130
|
+
userId: result.user_id ?? "",
|
|
2131
|
+
username: result.username ?? "",
|
|
2132
|
+
isAdmin: false,
|
|
2133
|
+
expiresAt: null
|
|
2134
|
+
});
|
|
2135
|
+
console.log();
|
|
2136
|
+
printSuccess(`\uB85C\uADF8\uC778 \uC131\uACF5! ${chalk3.bold(result.username ?? email)}`);
|
|
2137
|
+
} else {
|
|
2138
|
+
printError(result.message || "\uB85C\uADF8\uC778 \uC2E4\uD328");
|
|
2139
|
+
process.exit(1);
|
|
2140
|
+
}
|
|
2141
|
+
} catch (err) {
|
|
2142
|
+
const msg = err?.response?.data?.message ?? err?.response?.data?.detail ?? err.message;
|
|
2143
|
+
printError(`\uB85C\uADF8\uC778 \uC2E4\uD328: ${msg}`);
|
|
2144
|
+
process.exit(1);
|
|
2145
|
+
}
|
|
2146
|
+
});
|
|
2147
|
+
program2.command("logout").description("\uB85C\uADF8\uC544\uC6C3").action(async () => {
|
|
2148
|
+
const { clearAuth: clearAuth2 } = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
2149
|
+
clearAuth2();
|
|
2150
|
+
printSuccess("\uB85C\uADF8\uC544\uC6C3 \uC644\uB8CC");
|
|
2151
|
+
});
|
|
2152
|
+
program2.command("whoami").description("\uD604\uC7AC \uB85C\uADF8\uC778\uB41C \uC0AC\uC6A9\uC790 \uC815\uBCF4").action(async () => {
|
|
2153
|
+
const auth = getAuth();
|
|
2154
|
+
if (!auth) {
|
|
2155
|
+
printError("\uB85C\uADF8\uC778\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. xgen login \uC2E4\uD589\uD558\uC138\uC694");
|
|
2156
|
+
process.exit(1);
|
|
2157
|
+
}
|
|
2158
|
+
const server = requireServer();
|
|
2159
|
+
console.log(chalk3.bold("\n\uD604\uC7AC \uC0AC\uC6A9\uC790"));
|
|
2160
|
+
console.log(chalk3.gray("\u2500".repeat(30)));
|
|
2161
|
+
console.log(` ${chalk3.gray("\uC11C\uBC84:")} ${server}`);
|
|
2162
|
+
console.log(` ${chalk3.gray("\uC0AC\uC6A9\uC790:")} ${chalk3.bold(auth.username)}`);
|
|
2163
|
+
console.log(` ${chalk3.gray("User ID:")} ${auth.userId}`);
|
|
2164
|
+
try {
|
|
2165
|
+
const { apiValidate: apiValidate2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
|
|
2166
|
+
const result = await apiValidate2(auth.accessToken);
|
|
2167
|
+
if (result.valid) {
|
|
2168
|
+
console.log(` ${chalk3.gray("\uC0C1\uD0DC:")} ${chalk3.green("\uD65C\uC131")}`);
|
|
2169
|
+
if (result.is_admin) {
|
|
2170
|
+
console.log(` ${chalk3.gray("\uAD8C\uD55C:")} ${chalk3.yellow("\uAD00\uB9AC\uC790")}`);
|
|
2171
|
+
}
|
|
2172
|
+
if (result.user_type) {
|
|
2173
|
+
console.log(` ${chalk3.gray("\uC720\uD615:")} ${result.user_type}`);
|
|
2174
|
+
}
|
|
2175
|
+
} else {
|
|
2176
|
+
console.log(` ${chalk3.gray("\uC0C1\uD0DC:")} ${chalk3.red("\uD1A0\uD070 \uB9CC\uB8CC")}`);
|
|
2177
|
+
}
|
|
2178
|
+
} catch {
|
|
2179
|
+
console.log(` ${chalk3.gray("\uC0C1\uD0DC:")} ${chalk3.yellow("\uAC80\uC99D \uBD88\uAC00 (\uC11C\uBC84 \uC5F0\uACB0 \uC2E4\uD328)")}`);
|
|
2180
|
+
}
|
|
2181
|
+
console.log();
|
|
2182
|
+
});
|
|
2183
|
+
}
|
|
2184
|
+
|
|
2185
|
+
// src/commands/workflow/index.ts
|
|
2186
|
+
init_list();
|
|
2187
|
+
|
|
2188
|
+
// src/commands/workflow/info.ts
|
|
2189
|
+
init_store();
|
|
2190
|
+
init_workflow();
|
|
2191
|
+
init_format();
|
|
2192
|
+
import chalk5 from "chalk";
|
|
2193
|
+
async function workflowInfo(workflowId) {
|
|
2194
|
+
requireAuth();
|
|
2195
|
+
try {
|
|
2196
|
+
const detail = await getWorkflowDetail(workflowId);
|
|
2197
|
+
printHeader(`\uC6CC\uD06C\uD50C\uB85C\uC6B0: ${detail.workflow_name ?? workflowId}`);
|
|
2198
|
+
console.log();
|
|
2199
|
+
printKeyValue("ID", detail.id);
|
|
2200
|
+
printKeyValue("\uC774\uB984", detail.workflow_name);
|
|
2201
|
+
printKeyValue("\uC124\uBA85", detail.description ?? "(\uC5C6\uC74C)");
|
|
2202
|
+
if (detail.nodes && Array.isArray(detail.nodes)) {
|
|
2203
|
+
console.log();
|
|
2204
|
+
console.log(chalk5.bold(" \uB178\uB4DC \uAD6C\uC131:"));
|
|
2205
|
+
for (const node of detail.nodes) {
|
|
2206
|
+
const label = node.data?.label ?? node.id;
|
|
2207
|
+
const type = node.data?.type ?? "unknown";
|
|
2208
|
+
console.log(` ${chalk5.cyan("\u2022")} ${label} ${chalk5.gray(`(${type})`)}`);
|
|
2209
|
+
}
|
|
2210
|
+
}
|
|
2211
|
+
if (detail.parameters && Object.keys(detail.parameters).length > 0) {
|
|
2212
|
+
console.log();
|
|
2213
|
+
console.log(chalk5.bold(" \uD30C\uB77C\uBBF8\uD130:"));
|
|
2214
|
+
for (const [key, val] of Object.entries(detail.parameters)) {
|
|
2215
|
+
console.log(` ${chalk5.gray(key)}: ${JSON.stringify(val)}`);
|
|
2216
|
+
}
|
|
2217
|
+
}
|
|
2218
|
+
console.log();
|
|
2219
|
+
} catch (err) {
|
|
2220
|
+
const msg = err.message;
|
|
2221
|
+
printError(`\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC870\uD68C \uC2E4\uD328: ${msg}`);
|
|
2222
|
+
process.exit(1);
|
|
2223
|
+
}
|
|
2224
|
+
}
|
|
2225
|
+
|
|
2226
|
+
// src/commands/workflow/run.ts
|
|
2227
|
+
init_store();
|
|
2228
|
+
init_workflow();
|
|
2229
|
+
init_sse();
|
|
2230
|
+
init_format();
|
|
2231
|
+
import chalk7 from "chalk";
|
|
2232
|
+
import { randomUUID } from "crypto";
|
|
2233
|
+
|
|
2234
|
+
// src/utils/markdown.ts
|
|
2235
|
+
import chalk6 from "chalk";
|
|
2236
|
+
var CODE_BLOCK_RE = /```(\w*)\n([\s\S]*?)```/g;
|
|
2237
|
+
var INLINE_CODE_RE = /`([^`]+)`/g;
|
|
2238
|
+
var BOLD_RE = /\*\*(.+?)\*\*/g;
|
|
2239
|
+
var HEADING_RE = /^(#{1,3})\s+(.+)$/gm;
|
|
2240
|
+
var LIST_RE = /^(\s*)[-*]\s+(.+)$/gm;
|
|
2241
|
+
var LINK_RE = /\[([^\]]+)\]\(([^)]+)\)/g;
|
|
2242
|
+
function renderMarkdown(text) {
|
|
2243
|
+
let result = text;
|
|
2244
|
+
result = result.replace(CODE_BLOCK_RE, (_match, lang, code) => {
|
|
2245
|
+
const trimmed = code.trimEnd();
|
|
2246
|
+
const header = lang ? chalk6.gray(` \u2500\u2500 ${lang} \u2500\u2500`) : chalk6.gray(" \u2500\u2500 code \u2500\u2500");
|
|
2247
|
+
const lines = trimmed.split("\n").map((l) => chalk6.white(` ${l}`)).join("\n");
|
|
2248
|
+
return `
|
|
2249
|
+
${header}
|
|
2250
|
+
${lines}
|
|
2251
|
+
${chalk6.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}
|
|
2252
|
+
`;
|
|
2253
|
+
});
|
|
2254
|
+
result = result.replace(INLINE_CODE_RE, (_m, code) => chalk6.cyan(`\`${code}\``));
|
|
2255
|
+
result = result.replace(BOLD_RE, (_m, text2) => chalk6.bold(text2));
|
|
2256
|
+
result = result.replace(HEADING_RE, (_m, hashes, text2) => {
|
|
2257
|
+
if (hashes.length === 1) return chalk6.bold.underline(text2);
|
|
2258
|
+
if (hashes.length === 2) return chalk6.bold(text2);
|
|
2259
|
+
return chalk6.bold.dim(text2);
|
|
2260
|
+
});
|
|
2261
|
+
result = result.replace(LIST_RE, (_m, indent, text2) => `${indent}${chalk6.cyan("\u2022")} ${text2}`);
|
|
2262
|
+
result = result.replace(LINK_RE, (_m, label, url) => `${chalk6.blue.underline(label)} ${chalk6.gray(`(${url})`)}`);
|
|
2263
|
+
return result;
|
|
2264
|
+
}
|
|
2265
|
+
|
|
2266
|
+
// src/commands/workflow/run.ts
|
|
2267
|
+
async function workflowRun(workflowId, input, opts) {
|
|
2268
|
+
const auth = requireAuth();
|
|
2269
|
+
let workflowName = workflowId;
|
|
2270
|
+
try {
|
|
2271
|
+
const detail = await getWorkflowDetail(workflowId);
|
|
2272
|
+
workflowName = detail.workflow_name ?? workflowId;
|
|
2273
|
+
} catch {
|
|
2274
|
+
}
|
|
2275
|
+
if (!input) {
|
|
2276
|
+
if (opts.interactive || !process.stdin.isTTY) {
|
|
2277
|
+
const { createInterface: createInterface8 } = await import("readline");
|
|
2278
|
+
const rl = createInterface8({ input: process.stdin, output: process.stdout });
|
|
2279
|
+
input = await new Promise((resolve) => {
|
|
2280
|
+
rl.question(chalk7.cyan("\uC785\uB825> "), (answer) => {
|
|
2281
|
+
rl.close();
|
|
2282
|
+
resolve(answer.trim());
|
|
2283
|
+
});
|
|
2284
|
+
});
|
|
2285
|
+
} else {
|
|
2286
|
+
printError("\uC785\uB825\uAC12\uC774 \uD544\uC694\uD569\uB2C8\uB2E4. \uC0AC\uC6A9\uBC95:");
|
|
2287
|
+
console.log(' xgen workflow run <id> "\uC785\uB825 \uD14D\uC2A4\uFFFD\uFFFD\uFFFD"');
|
|
2288
|
+
console.log(" xgen workflow run -i <id>");
|
|
2289
|
+
process.exit(1);
|
|
2290
|
+
}
|
|
2291
|
+
}
|
|
2292
|
+
if (!input) {
|
|
2293
|
+
printError("\uC785\uB825\uAC12\uC774 \uBE44\uC5B4\uC788\uC2B5\uB2C8\uB2E4");
|
|
2294
|
+
process.exit(1);
|
|
2295
|
+
}
|
|
2296
|
+
const interactionId = `cli_${randomUUID().slice(0, 8)}`;
|
|
2297
|
+
printHeader(`\uC2E4\uD589: ${workflowName}`);
|
|
2298
|
+
printInfo(`\uC785\uB825: ${input}`);
|
|
2299
|
+
console.log();
|
|
2300
|
+
try {
|
|
2301
|
+
const stream = await executeWorkflowStream({
|
|
2302
|
+
workflow_id: workflowId,
|
|
2303
|
+
workflow_name: workflowName,
|
|
2304
|
+
input_data: input,
|
|
2305
|
+
interaction_id: interactionId
|
|
2306
|
+
});
|
|
2307
|
+
let hasOutput = false;
|
|
2308
|
+
let fullResponse = "";
|
|
2309
|
+
await parseSSEStream(
|
|
2310
|
+
stream,
|
|
2311
|
+
(event) => {
|
|
2312
|
+
switch (event.type) {
|
|
2313
|
+
case "token":
|
|
2314
|
+
if (event.content) {
|
|
2315
|
+
if (!hasOutput) {
|
|
2316
|
+
hasOutput = true;
|
|
2317
|
+
console.log();
|
|
2318
|
+
}
|
|
2319
|
+
process.stdout.write(event.content);
|
|
2320
|
+
fullResponse += event.content;
|
|
2321
|
+
}
|
|
2322
|
+
break;
|
|
2323
|
+
case "log":
|
|
2324
|
+
if (opts.logs && event.content) {
|
|
2325
|
+
process.stderr.write(chalk7.gray(`[LOG] ${event.content}
|
|
2326
|
+
`));
|
|
2327
|
+
}
|
|
2328
|
+
break;
|
|
2329
|
+
case "node_status":
|
|
2330
|
+
if (opts.logs) {
|
|
2331
|
+
const nodeName = event.node_name ?? event.node_id ?? "?";
|
|
2332
|
+
const status = event.status ?? "?";
|
|
2333
|
+
process.stderr.write(
|
|
2334
|
+
chalk7.gray(`[\uB178\uB4DC] ${nodeName}: ${status}
|
|
2335
|
+
`)
|
|
2336
|
+
);
|
|
2337
|
+
}
|
|
2338
|
+
break;
|
|
2339
|
+
case "tool":
|
|
2340
|
+
if (opts.logs) {
|
|
2341
|
+
process.stderr.write(chalk7.gray(`[\uB3C4\uAD6C] ${JSON.stringify(event.data)}
|
|
2342
|
+
`));
|
|
2343
|
+
}
|
|
2344
|
+
break;
|
|
2345
|
+
case "complete":
|
|
2346
|
+
break;
|
|
2347
|
+
case "error":
|
|
2348
|
+
console.log();
|
|
2349
|
+
printError(event.error ?? event.content ?? "\uC54C \uC218 \uC5C6\uB294 \uC624\uB958");
|
|
2350
|
+
break;
|
|
2351
|
+
default:
|
|
2352
|
+
if (event.content) {
|
|
2353
|
+
if (!hasOutput) {
|
|
2354
|
+
process.stdout.write(chalk7.green("\uC751\uB2F5: "));
|
|
2355
|
+
hasOutput = true;
|
|
2356
|
+
}
|
|
2357
|
+
process.stdout.write(event.content);
|
|
2358
|
+
}
|
|
2359
|
+
}
|
|
2360
|
+
},
|
|
2361
|
+
() => {
|
|
2362
|
+
if (hasOutput) {
|
|
2363
|
+
console.log();
|
|
2364
|
+
if (fullResponse.includes("```") || fullResponse.includes("**")) {
|
|
2365
|
+
console.log(chalk7.gray("\u2500".repeat(40)));
|
|
2366
|
+
console.log(renderMarkdown(fullResponse));
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2369
|
+
console.log();
|
|
2370
|
+
console.log(chalk7.gray(`\uC138\uC158: ${interactionId}`));
|
|
2371
|
+
},
|
|
2372
|
+
(err) => {
|
|
2373
|
+
console.log();
|
|
2374
|
+
printError(`\uC2A4\uD2B8\uB9AC\uBC0D \uC624\uB958: ${err.message}`);
|
|
2375
|
+
}
|
|
2376
|
+
);
|
|
2377
|
+
} catch (err) {
|
|
2378
|
+
const msg = err?.response?.data?.detail ?? err.message;
|
|
2379
|
+
printError(`\uC2E4\uD589 \uC2E4\uD328: ${msg}`);
|
|
2380
|
+
process.exit(1);
|
|
2381
|
+
}
|
|
2042
2382
|
}
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2383
|
+
|
|
2384
|
+
// src/commands/workflow/history.ts
|
|
2385
|
+
init_store();
|
|
2386
|
+
init_workflow();
|
|
2387
|
+
init_format();
|
|
2388
|
+
import chalk8 from "chalk";
|
|
2389
|
+
async function workflowHistory(workflowId, opts = {}) {
|
|
2390
|
+
requireAuth();
|
|
2391
|
+
const limit = opts.limit ?? 20;
|
|
2392
|
+
try {
|
|
2393
|
+
const logs = await getIOLogs(workflowId, limit);
|
|
2394
|
+
if (!logs || logs.length === 0) {
|
|
2395
|
+
console.log(chalk8.yellow("\n\uC2E4\uD589 \uC774\uB825\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.\n"));
|
|
2396
|
+
return;
|
|
2397
|
+
}
|
|
2398
|
+
printHeader(`\uC2E4\uD589 \uC774\uB825 (\uCD5C\uADFC ${logs.length}\uAC74)`);
|
|
2399
|
+
console.log();
|
|
2400
|
+
for (const log of logs) {
|
|
2401
|
+
console.log(
|
|
2402
|
+
` ${chalk8.gray(formatDate(log.created_at))} ${chalk8.cyan(log.interaction_id)}`
|
|
2403
|
+
);
|
|
2404
|
+
console.log(` ${chalk8.white("\uC785\uB825:")} ${truncate(log.input_data, 60)}`);
|
|
2405
|
+
console.log(
|
|
2406
|
+
` ${chalk8.green("\uCD9C\uB825:")} ${truncate(log.output_data, 60)}`
|
|
2407
|
+
);
|
|
2408
|
+
if (log.execution_time) {
|
|
2409
|
+
console.log(
|
|
2410
|
+
` ${chalk8.gray("\uC2DC\uAC04:")} ${(log.execution_time / 1e3).toFixed(1)}s`
|
|
2411
|
+
);
|
|
2412
|
+
}
|
|
2413
|
+
console.log();
|
|
2414
|
+
}
|
|
2415
|
+
} catch (err) {
|
|
2416
|
+
const msg = err.message;
|
|
2417
|
+
printError(`\uC774\uB825 \uC870\uD68C \uC2E4\uD328: ${msg}`);
|
|
2418
|
+
process.exit(1);
|
|
2048
2419
|
}
|
|
2049
|
-
return parts.join(", ");
|
|
2050
2420
|
}
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2421
|
+
|
|
2422
|
+
// src/commands/workflow/index.ts
|
|
2423
|
+
function registerWorkflowCommand(program2) {
|
|
2424
|
+
const wf = program2.command("workflow").alias("wf").description("\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uAD00\uB9AC \uBC0F \uC2E4\uD589");
|
|
2425
|
+
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));
|
|
2426
|
+
wf.command("info <workflow-id>").description("\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC0C1\uC138 \uC815\uBCF4").action((id) => workflowInfo(id));
|
|
2427
|
+
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));
|
|
2428
|
+
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) }));
|
|
2055
2429
|
}
|
|
2056
2430
|
|
|
2431
|
+
// src/index.ts
|
|
2432
|
+
init_chat();
|
|
2433
|
+
init_provider();
|
|
2434
|
+
init_agent();
|
|
2435
|
+
|
|
2057
2436
|
// src/commands/doc.ts
|
|
2058
2437
|
init_store();
|
|
2059
|
-
import
|
|
2438
|
+
import chalk13 from "chalk";
|
|
2060
2439
|
|
|
2061
2440
|
// src/api/document.ts
|
|
2062
2441
|
init_client();
|
|
@@ -2100,7 +2479,7 @@ function registerDocCommand(program2) {
|
|
|
2100
2479
|
try {
|
|
2101
2480
|
const docs = await listDocuments(opts.collection);
|
|
2102
2481
|
if (!docs.length) {
|
|
2103
|
-
console.log(
|
|
2482
|
+
console.log(chalk13.yellow("\n\uBB38\uC11C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.\n"));
|
|
2104
2483
|
return;
|
|
2105
2484
|
}
|
|
2106
2485
|
printHeader(`\uBB38\uC11C \uBAA9\uB85D (${docs.length}\uAC1C)`);
|
|
@@ -2124,10 +2503,10 @@ function registerDocCommand(program2) {
|
|
|
2124
2503
|
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) => {
|
|
2125
2504
|
requireAuth();
|
|
2126
2505
|
try {
|
|
2127
|
-
console.log(
|
|
2506
|
+
console.log(chalk13.gray(`\uC5C5\uB85C\uB4DC \uC911: ${file}`));
|
|
2128
2507
|
const result = await uploadDocument(file, opts.collection, opts.name);
|
|
2129
|
-
console.log(
|
|
2130
|
-
console.log(
|
|
2508
|
+
console.log(chalk13.green("\u2713 \uC5C5\uB85C\uB4DC \uC644\uB8CC"));
|
|
2509
|
+
console.log(chalk13.gray(JSON.stringify(result, null, 2)));
|
|
2131
2510
|
} catch (err) {
|
|
2132
2511
|
printError(`\uC5C5\uB85C\uB4DC \uC2E4\uD328: ${err.message}`);
|
|
2133
2512
|
}
|
|
@@ -2137,7 +2516,7 @@ function registerDocCommand(program2) {
|
|
|
2137
2516
|
try {
|
|
2138
2517
|
const d = await getDocumentInfo(id);
|
|
2139
2518
|
printHeader("\uBB38\uC11C \uC815\uBCF4");
|
|
2140
|
-
console.log(
|
|
2519
|
+
console.log(chalk13.gray(JSON.stringify(d, null, 2)));
|
|
2141
2520
|
} catch (err) {
|
|
2142
2521
|
printError(`\uC870\uD68C \uC2E4\uD328: ${err.message}`);
|
|
2143
2522
|
}
|
|
@@ -2146,8 +2525,8 @@ function registerDocCommand(program2) {
|
|
|
2146
2525
|
|
|
2147
2526
|
// src/commands/ontology.ts
|
|
2148
2527
|
init_store();
|
|
2149
|
-
import
|
|
2150
|
-
import { createInterface as
|
|
2528
|
+
import chalk14 from "chalk";
|
|
2529
|
+
import { createInterface as createInterface7 } from "readline";
|
|
2151
2530
|
|
|
2152
2531
|
// src/api/ontology.ts
|
|
2153
2532
|
init_client();
|
|
@@ -2184,19 +2563,19 @@ function registerOntologyCommand(program2) {
|
|
|
2184
2563
|
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) => {
|
|
2185
2564
|
requireAuth();
|
|
2186
2565
|
try {
|
|
2187
|
-
console.log(
|
|
2566
|
+
console.log(chalk14.gray("\n\uC9C8\uC758 \uC911...\n"));
|
|
2188
2567
|
const result = await queryGraphRAG(question, opts.graph, { scs: opts.scs });
|
|
2189
2568
|
if (result.answer) {
|
|
2190
|
-
console.log(
|
|
2569
|
+
console.log(chalk14.bold("\uB2F5\uBCC0:"));
|
|
2191
2570
|
console.log(result.answer);
|
|
2192
2571
|
}
|
|
2193
2572
|
if (result.sources?.length) {
|
|
2194
|
-
console.log(
|
|
2195
|
-
result.sources.forEach((s) => console.log(
|
|
2573
|
+
console.log(chalk14.bold("\n\uCD9C\uCC98:"));
|
|
2574
|
+
result.sources.forEach((s) => console.log(chalk14.gray(` - ${s}`)));
|
|
2196
2575
|
}
|
|
2197
2576
|
if (result.triples_used?.length) {
|
|
2198
|
-
console.log(
|
|
2199
|
-
result.triples_used.forEach((t) => console.log(
|
|
2577
|
+
console.log(chalk14.bold("\n\uC0AC\uC6A9\uB41C \uD2B8\uB9AC\uD50C:"));
|
|
2578
|
+
result.triples_used.forEach((t) => console.log(chalk14.dim(` ${t}`)));
|
|
2200
2579
|
}
|
|
2201
2580
|
console.log();
|
|
2202
2581
|
} catch (err) {
|
|
@@ -2207,9 +2586,9 @@ function registerOntologyCommand(program2) {
|
|
|
2207
2586
|
requireAuth();
|
|
2208
2587
|
const sessionId = randomUUID3();
|
|
2209
2588
|
printHeader("Ontology Chat");
|
|
2210
|
-
console.log(
|
|
2211
|
-
const rl =
|
|
2212
|
-
const ask = () => new Promise((resolve) => rl.question(
|
|
2589
|
+
console.log(chalk14.gray("\uBA40\uD2F0\uD134 GraphRAG \uB300\uD654. exit\uB85C \uC885\uB8CC.\n"));
|
|
2590
|
+
const rl = createInterface7({ input: process.stdin, output: process.stdout });
|
|
2591
|
+
const ask = () => new Promise((resolve) => rl.question(chalk14.green("\u276F "), (a) => resolve(a.trim())));
|
|
2213
2592
|
while (true) {
|
|
2214
2593
|
const input = await ask();
|
|
2215
2594
|
if (!input) continue;
|
|
@@ -2223,7 +2602,7 @@ function registerOntologyCommand(program2) {
|
|
|
2223
2602
|
${result.answer}
|
|
2224
2603
|
`);
|
|
2225
2604
|
} catch (err) {
|
|
2226
|
-
console.log(
|
|
2605
|
+
console.log(chalk14.red(`\uC624\uB958: ${err.message}
|
|
2227
2606
|
`));
|
|
2228
2607
|
}
|
|
2229
2608
|
}
|
|
@@ -2233,7 +2612,7 @@ ${result.answer}
|
|
|
2233
2612
|
try {
|
|
2234
2613
|
const stats = await getGraphStats(graphId);
|
|
2235
2614
|
printHeader("\uADF8\uB798\uD504 \uD1B5\uACC4");
|
|
2236
|
-
console.log(
|
|
2615
|
+
console.log(chalk14.gray(JSON.stringify(stats, null, 2)));
|
|
2237
2616
|
console.log();
|
|
2238
2617
|
} catch (err) {
|
|
2239
2618
|
printError(`\uD1B5\uACC4 \uC870\uD68C \uC2E4\uD328: ${err.message}`);
|
|
@@ -2241,239 +2620,8 @@ ${result.answer}
|
|
|
2241
2620
|
});
|
|
2242
2621
|
}
|
|
2243
2622
|
|
|
2244
|
-
// src/commands/home.ts
|
|
2245
|
-
init_store();
|
|
2246
|
-
import chalk14 from "chalk";
|
|
2247
|
-
import { createInterface as createInterface7 } from "readline";
|
|
2248
|
-
function prompt3(question) {
|
|
2249
|
-
return new Promise((resolve) => {
|
|
2250
|
-
const rl = createInterface7({ input: process.stdin, output: process.stdout });
|
|
2251
|
-
rl.question(question, (answer) => {
|
|
2252
|
-
rl.close();
|
|
2253
|
-
resolve(answer.trim());
|
|
2254
|
-
});
|
|
2255
|
-
});
|
|
2256
|
-
}
|
|
2257
|
-
function showStatus() {
|
|
2258
|
-
const provider = getDefaultProvider();
|
|
2259
|
-
const server = getServer();
|
|
2260
|
-
const auth = getAuth();
|
|
2261
|
-
console.log(chalk14.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\u2500\u2500\u2500\u2500"));
|
|
2262
|
-
console.log(chalk14.gray(" \uC0C1\uD0DC:"));
|
|
2263
|
-
if (provider) {
|
|
2264
|
-
console.log(` AI \uC5D0\uC774\uC804\uD2B8 ${chalk14.green("\u25CF")} ${provider.name} (${provider.model})`);
|
|
2265
|
-
} else {
|
|
2266
|
-
console.log(` AI \uC5D0\uC774\uC804\uD2B8 ${chalk14.red("\u25CB")} \uBBF8\uC124\uC815`);
|
|
2267
|
-
}
|
|
2268
|
-
if (server && auth) {
|
|
2269
|
-
console.log(` XGEN \uC11C\uBC84 ${chalk14.green("\u25CF")} ${server} (${auth.username})`);
|
|
2270
|
-
} else if (server) {
|
|
2271
|
-
console.log(` XGEN \uC11C\uBC84 ${chalk14.yellow("\u25CB")} ${server} (\uB85C\uADF8\uC778 \uD544\uC694)`);
|
|
2272
|
-
} else {
|
|
2273
|
-
console.log(` XGEN \uC11C\uBC84 ${chalk14.red("\u25CB")} \uBBF8\uC124\uC815`);
|
|
2274
|
-
}
|
|
2275
|
-
console.log(chalk14.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\u2500\u2500\u2500\u2500\n"));
|
|
2276
|
-
}
|
|
2277
|
-
async function homeMenu() {
|
|
2278
|
-
const provider = getDefaultProvider();
|
|
2279
|
-
const server = getServer();
|
|
2280
|
-
const auth = getAuth();
|
|
2281
|
-
console.log(chalk14.cyan(`
|
|
2282
|
-
\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588 \u2588\u2588
|
|
2283
|
-
\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588
|
|
2284
|
-
\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588
|
|
2285
|
-
\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588
|
|
2286
|
-
\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588`));
|
|
2287
|
-
console.log(chalk14.white.bold(`
|
|
2288
|
-
\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588 \u2588\u2588
|
|
2289
|
-
\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588
|
|
2290
|
-
\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588
|
|
2291
|
-
\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588
|
|
2292
|
-
\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588`));
|
|
2293
|
-
console.log(chalk14.gray(` v0.3.0
|
|
2294
|
-
`));
|
|
2295
|
-
showStatus();
|
|
2296
|
-
while (true) {
|
|
2297
|
-
const items = [];
|
|
2298
|
-
items.push({
|
|
2299
|
-
key: "1",
|
|
2300
|
-
label: provider ? `AI \uC5D0\uC774\uC804\uD2B8 \uC2DC\uC791 ${chalk14.gray(`(${provider.name})`)}` : `AI \uC5D0\uC774\uC804\uD2B8 \uC124\uC815 + \uC2DC\uC791`,
|
|
2301
|
-
available: true,
|
|
2302
|
-
action: async () => {
|
|
2303
|
-
await agentRepl();
|
|
2304
|
-
}
|
|
2305
|
-
});
|
|
2306
|
-
if (server && auth) {
|
|
2307
|
-
items.push({
|
|
2308
|
-
key: "2",
|
|
2309
|
-
label: `\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uCC44\uD305 ${chalk14.gray(`(${auth.username}@${server.replace("https://", "")})`)}`,
|
|
2310
|
-
available: true,
|
|
2311
|
-
action: async () => {
|
|
2312
|
-
await chat();
|
|
2313
|
-
}
|
|
2314
|
-
});
|
|
2315
|
-
items.push({
|
|
2316
|
-
key: "3",
|
|
2317
|
-
label: "\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D",
|
|
2318
|
-
available: true,
|
|
2319
|
-
action: async () => {
|
|
2320
|
-
const { workflowList: workflowList2 } = await Promise.resolve().then(() => (init_list(), list_exports));
|
|
2321
|
-
await workflowList2({ detail: false });
|
|
2322
|
-
return;
|
|
2323
|
-
}
|
|
2324
|
-
});
|
|
2325
|
-
} else {
|
|
2326
|
-
items.push({
|
|
2327
|
-
key: "2",
|
|
2328
|
-
label: "XGEN \uC11C\uBC84 \uC5F0\uACB0 + \uB85C\uADF8\uC778",
|
|
2329
|
-
available: true,
|
|
2330
|
-
action: async () => {
|
|
2331
|
-
await serverSetup();
|
|
2332
|
-
}
|
|
2333
|
-
});
|
|
2334
|
-
}
|
|
2335
|
-
items.push({
|
|
2336
|
-
key: String(items.length + 1),
|
|
2337
|
-
label: "\uD504\uB85C\uBC14\uC774\uB354 \uAD00\uB9AC",
|
|
2338
|
-
available: true,
|
|
2339
|
-
action: async () => {
|
|
2340
|
-
await providerMenu();
|
|
2341
|
-
}
|
|
2342
|
-
});
|
|
2343
|
-
items.push({
|
|
2344
|
-
key: String(items.length + 1),
|
|
2345
|
-
label: "\uC124\uC815 \uBCF4\uAE30",
|
|
2346
|
-
available: true,
|
|
2347
|
-
action: async () => {
|
|
2348
|
-
showStatus();
|
|
2349
|
-
const cfg = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
2350
|
-
const config = cfg.getConfig();
|
|
2351
|
-
console.log(chalk14.gray(" \uC124\uC815 \uD30C\uC77C: ~/.xgen/\n"));
|
|
2352
|
-
console.log(chalk14.gray(` \uC11C\uBC84: ${config.server ?? "(\uC5C6\uC74C)"}`));
|
|
2353
|
-
console.log(chalk14.gray(` \uD14C\uB9C8: ${config.theme}`));
|
|
2354
|
-
console.log(chalk14.gray(` \uC2A4\uD2B8\uB9BC \uB85C\uADF8: ${config.streamLogs}
|
|
2355
|
-
`));
|
|
2356
|
-
}
|
|
2357
|
-
});
|
|
2358
|
-
items.push({
|
|
2359
|
-
key: "q",
|
|
2360
|
-
label: "\uC885\uB8CC",
|
|
2361
|
-
available: true,
|
|
2362
|
-
action: async () => {
|
|
2363
|
-
process.exit(0);
|
|
2364
|
-
}
|
|
2365
|
-
});
|
|
2366
|
-
console.log(chalk14.bold(" \uBB58 \uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?\n"));
|
|
2367
|
-
for (const item of items) {
|
|
2368
|
-
console.log(` ${chalk14.cyan(item.key + ")")} ${item.label}`);
|
|
2369
|
-
}
|
|
2370
|
-
console.log();
|
|
2371
|
-
const choice = await prompt3(chalk14.white(" \uC120\uD0DD: "));
|
|
2372
|
-
if (choice === "q" || choice === "exit") {
|
|
2373
|
-
console.log(chalk14.gray("\n \uC548\uB155\uD788.\n"));
|
|
2374
|
-
break;
|
|
2375
|
-
}
|
|
2376
|
-
const selected = items.find((i) => i.key === choice);
|
|
2377
|
-
if (!selected) {
|
|
2378
|
-
console.log(chalk14.red(" \uC798\uBABB\uB41C \uC120\uD0DD\uC785\uB2C8\uB2E4.\n"));
|
|
2379
|
-
continue;
|
|
2380
|
-
}
|
|
2381
|
-
try {
|
|
2382
|
-
await selected.action();
|
|
2383
|
-
} catch (err) {
|
|
2384
|
-
console.log(chalk14.red(`
|
|
2385
|
-
\uC624\uB958: ${err.message}
|
|
2386
|
-
`));
|
|
2387
|
-
}
|
|
2388
|
-
console.log();
|
|
2389
|
-
showStatus();
|
|
2390
|
-
}
|
|
2391
|
-
}
|
|
2392
|
-
async function serverSetup() {
|
|
2393
|
-
console.log(chalk14.cyan.bold("\n XGEN \uC11C\uBC84 \uC5F0\uACB0\n"));
|
|
2394
|
-
const currentServer = getServer();
|
|
2395
|
-
const urlInput = await prompt3(
|
|
2396
|
-
chalk14.white(` \uC11C\uBC84 URL${currentServer ? ` [${currentServer}]` : ""}: `)
|
|
2397
|
-
);
|
|
2398
|
-
const url = urlInput || currentServer;
|
|
2399
|
-
if (!url) {
|
|
2400
|
-
console.log(chalk14.red(" URL\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.\n"));
|
|
2401
|
-
return;
|
|
2402
|
-
}
|
|
2403
|
-
const { setServer: setServer2 } = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
2404
|
-
setServer2(url);
|
|
2405
|
-
console.log(chalk14.green(` \u2713 \uC11C\uBC84 \uC124\uC815: ${url}
|
|
2406
|
-
`));
|
|
2407
|
-
console.log(chalk14.bold(" \uB85C\uADF8\uC778\n"));
|
|
2408
|
-
const email = await prompt3(chalk14.white(" \uC774\uBA54\uC77C: "));
|
|
2409
|
-
const password = await prompt3(chalk14.white(" \uBE44\uBC00\uBC88\uD638: "));
|
|
2410
|
-
if (!email || !password) {
|
|
2411
|
-
console.log(chalk14.red(" \uC774\uBA54\uC77C\uACFC \uBE44\uBC00\uBC88\uD638\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.\n"));
|
|
2412
|
-
return;
|
|
2413
|
-
}
|
|
2414
|
-
try {
|
|
2415
|
-
const { apiLogin: apiLogin2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
|
|
2416
|
-
const { setAuth: setAuth2 } = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
2417
|
-
const result = await apiLogin2(email, password);
|
|
2418
|
-
if (result.success && result.access_token) {
|
|
2419
|
-
setAuth2({
|
|
2420
|
-
accessToken: result.access_token,
|
|
2421
|
-
refreshToken: result.refresh_token ?? "",
|
|
2422
|
-
userId: result.user_id ?? "",
|
|
2423
|
-
username: result.username ?? "",
|
|
2424
|
-
isAdmin: false,
|
|
2425
|
-
expiresAt: null
|
|
2426
|
-
});
|
|
2427
|
-
console.log(chalk14.green(` \u2713 \uB85C\uADF8\uC778 \uC131\uACF5! ${result.username ?? email}
|
|
2428
|
-
`));
|
|
2429
|
-
} else {
|
|
2430
|
-
console.log(chalk14.red(` \u2717 \uB85C\uADF8\uC778 \uC2E4\uD328: ${result.message}
|
|
2431
|
-
`));
|
|
2432
|
-
}
|
|
2433
|
-
} catch (err) {
|
|
2434
|
-
console.log(chalk14.red(` \u2717 \uB85C\uADF8\uC778 \uC2E4\uD328: ${err.message}
|
|
2435
|
-
`));
|
|
2436
|
-
}
|
|
2437
|
-
}
|
|
2438
|
-
async function providerMenu() {
|
|
2439
|
-
const { getProviders: getProviders2, getDefaultProvider: getDefault } = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
2440
|
-
const providers = getProviders2();
|
|
2441
|
-
const defaultP = getDefault();
|
|
2442
|
-
console.log(chalk14.cyan.bold("\n \uD504\uB85C\uBC14\uC774\uB354 \uAD00\uB9AC\n"));
|
|
2443
|
-
if (providers.length > 0) {
|
|
2444
|
-
for (const p of providers) {
|
|
2445
|
-
const mark = p.id === defaultP?.id ? chalk14.green("\u25CF ") : chalk14.gray(" ");
|
|
2446
|
-
console.log(` ${mark}${p.name} ${chalk14.gray(`(${p.type} \u2014 ${p.model})`)}`);
|
|
2447
|
-
}
|
|
2448
|
-
console.log();
|
|
2449
|
-
}
|
|
2450
|
-
console.log(` ${chalk14.cyan("1)")} \uC0C8 \uD504\uB85C\uBC14\uC774\uB354 \uCD94\uAC00`);
|
|
2451
|
-
if (providers.length > 1) {
|
|
2452
|
-
console.log(` ${chalk14.cyan("2)")} \uAE30\uBCF8 \uD504\uB85C\uBC14\uC774\uB354 \uBCC0\uACBD`);
|
|
2453
|
-
}
|
|
2454
|
-
console.log(` ${chalk14.cyan("b)")} \uB3CC\uC544\uAC00\uAE30`);
|
|
2455
|
-
console.log();
|
|
2456
|
-
const choice = await prompt3(chalk14.white(" \uC120\uD0DD: "));
|
|
2457
|
-
if (choice === "1") {
|
|
2458
|
-
await guidedProviderSetup();
|
|
2459
|
-
} else if (choice === "2" && providers.length > 1) {
|
|
2460
|
-
console.log();
|
|
2461
|
-
providers.forEach((p, i) => {
|
|
2462
|
-
console.log(` ${chalk14.cyan(`${i + 1})`)} ${p.name} (${p.model})`);
|
|
2463
|
-
});
|
|
2464
|
-
console.log();
|
|
2465
|
-
const pc = await prompt3(chalk14.white(" \uBC88\uD638: "));
|
|
2466
|
-
const pi = parseInt(pc) - 1;
|
|
2467
|
-
if (pi >= 0 && pi < providers.length) {
|
|
2468
|
-
const { setDefaultProvider: setDef } = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
2469
|
-
setDef(providers[pi].id);
|
|
2470
|
-
console.log(chalk14.green(` \u2713 \uAE30\uBCF8 \uD504\uB85C\uBC14\uC774\uB354: ${providers[pi].name}
|
|
2471
|
-
`));
|
|
2472
|
-
}
|
|
2473
|
-
}
|
|
2474
|
-
}
|
|
2475
|
-
|
|
2476
2623
|
// src/index.ts
|
|
2624
|
+
init_home();
|
|
2477
2625
|
var VERSION = "0.3.0";
|
|
2478
2626
|
var LOGO = chalk15.cyan(`
|
|
2479
2627
|
\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588 \u2588\u2588
|