openxgen 0.3.0 → 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 CHANGED
@@ -157,60 +157,8 @@ var init_store = __esm({
157
157
  }
158
158
  });
159
159
 
160
- // src/api/auth.ts
161
- var auth_exports = {};
162
- __export(auth_exports, {
163
- apiLogin: () => apiLogin,
164
- apiRefresh: () => apiRefresh,
165
- apiValidate: () => apiValidate
166
- });
167
- import axios2 from "axios";
168
- import { createHash } from "crypto";
169
- async function apiLogin(email, password) {
170
- const server = getServer();
171
- if (!server) throw new Error("\uC11C\uBC84\uAC00 \uC124\uC815\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4");
172
- const hashedPassword = createHash("sha256").update(password).digest("hex");
173
- const res = await axios2.post(`${server}/api/auth/login`, {
174
- email,
175
- password: hashedPassword
176
- });
177
- return res.data;
178
- }
179
- async function apiValidate(accessToken) {
180
- const server = getServer();
181
- if (!server) throw new Error("\uC11C\uBC84\uAC00 \uC124\uC815\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4");
182
- const res = await axios2.get(`${server}/api/auth/validate`, {
183
- headers: { Authorization: `Bearer ${accessToken}` }
184
- });
185
- return res.data;
186
- }
187
- async function apiRefresh(refreshToken) {
188
- const server = getServer();
189
- if (!server) throw new Error("\uC11C\uBC84\uAC00 \uC124\uC815\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4");
190
- const res = await axios2.post(`${server}/api/auth/refresh`, {
191
- refresh_token: refreshToken
192
- });
193
- return res.data;
194
- }
195
- var init_auth = __esm({
196
- "src/api/auth.ts"() {
197
- "use strict";
198
- init_store();
199
- }
200
- });
201
-
202
- // src/index.ts
203
- import { Command } from "commander";
204
- import chalk14 from "chalk";
205
-
206
- // src/commands/config.ts
207
- init_store();
208
- import chalk2 from "chalk";
209
-
210
160
  // src/api/client.ts
211
- init_store();
212
161
  import axios from "axios";
213
- var client = null;
214
162
  function getClient() {
215
163
  if (client) return client;
216
164
  const server = getServer();
@@ -266,6 +214,14 @@ function getClient() {
266
214
  function resetClient() {
267
215
  client = null;
268
216
  }
217
+ var client;
218
+ var init_client = __esm({
219
+ "src/api/client.ts"() {
220
+ "use strict";
221
+ init_store();
222
+ client = null;
223
+ }
224
+ });
269
225
 
270
226
  // src/utils/format.ts
271
227
  import chalk from "chalk";
@@ -313,254 +269,139 @@ function formatDate(dateStr) {
313
269
  return dateStr;
314
270
  }
315
271
  }
272
+ var init_format = __esm({
273
+ "src/utils/format.ts"() {
274
+ "use strict";
275
+ }
276
+ });
316
277
 
317
- // src/commands/config.ts
318
- function registerConfigCommand(program2) {
319
- const config = program2.command("config").description("XGEN CLI \uC124\uC815 \uAD00\uB9AC");
320
- config.command("set-server <url>").description("XGEN \uC11C\uBC84 URL \uC124\uC815").action((url) => {
321
- if (!url.startsWith("http://") && !url.startsWith("https://")) {
322
- printError("URL\uC740 http:// \uB610\uB294 https://\uB85C \uC2DC\uC791\uD574\uC57C \uD569\uB2C8\uB2E4");
323
- process.exit(1);
324
- }
325
- setServer(url);
326
- resetClient();
327
- printSuccess(`\uC11C\uBC84 \uC124\uC815 \uC644\uB8CC: ${chalk2.underline(url)}`);
278
+ // src/api/auth.ts
279
+ var auth_exports = {};
280
+ __export(auth_exports, {
281
+ apiLogin: () => apiLogin,
282
+ apiRefresh: () => apiRefresh,
283
+ apiValidate: () => apiValidate
284
+ });
285
+ import axios2 from "axios";
286
+ import { createHash } from "crypto";
287
+ async function apiLogin(email, password) {
288
+ const server = getServer();
289
+ if (!server) throw new Error("\uC11C\uBC84\uAC00 \uC124\uC815\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4");
290
+ const hashedPassword = createHash("sha256").update(password).digest("hex");
291
+ const res = await axios2.post(`${server}/api/auth/login`, {
292
+ email,
293
+ password: hashedPassword
328
294
  });
329
- config.command("get-server").description("\uD604\uC7AC \uC124\uC815\uB41C \uC11C\uBC84 URL \uD655\uC778").action(() => {
330
- const server = getServer();
331
- if (server) {
332
- console.log(server);
333
- } else {
334
- printError("\uC11C\uBC84\uAC00 \uC124\uC815\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4");
335
- console.log(" \uC124\uC815: xgen config set-server <url>");
336
- }
295
+ return res.data;
296
+ }
297
+ async function apiValidate(accessToken) {
298
+ const server = getServer();
299
+ if (!server) throw new Error("\uC11C\uBC84\uAC00 \uC124\uC815\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4");
300
+ const res = await axios2.get(`${server}/api/auth/validate`, {
301
+ headers: { Authorization: `Bearer ${accessToken}` }
337
302
  });
338
- config.command("list").description("\uC804\uCCB4 \uC124\uC815 \uD655\uC778").action(() => {
339
- const cfg = getConfig();
340
- console.log(chalk2.bold("\nXGEN CLI \uC124\uC815"));
341
- console.log(chalk2.gray("\u2500".repeat(40)));
342
- printKeyValue("\uC11C\uBC84", cfg.server);
343
- printKeyValue("\uAE30\uBCF8 \uC6CC\uD06C\uD50C\uB85C\uC6B0", cfg.defaultWorkflow);
344
- printKeyValue("\uD14C\uB9C8", cfg.theme);
345
- printKeyValue("\uC2A4\uD2B8\uB9BC \uB85C\uADF8", String(cfg.streamLogs));
346
- console.log();
303
+ return res.data;
304
+ }
305
+ async function apiRefresh(refreshToken) {
306
+ const server = getServer();
307
+ if (!server) throw new Error("\uC11C\uBC84\uAC00 \uC124\uC815\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4");
308
+ const res = await axios2.post(`${server}/api/auth/refresh`, {
309
+ refresh_token: refreshToken
347
310
  });
348
- config.command("set <key> <value>").description("\uC124\uC815 \uAC12 \uBCC0\uACBD").action((key, value) => {
349
- const allowedKeys = ["defaultWorkflow", "theme", "streamLogs"];
350
- if (!allowedKeys.includes(key)) {
351
- printError(`\uC54C \uC218 \uC5C6\uB294 \uC124\uC815 \uD0A4: ${key}`);
352
- console.log(` \uC0AC\uC6A9 \uAC00\uB2A5: ${allowedKeys.join(", ")}`);
353
- process.exit(1);
311
+ return res.data;
312
+ }
313
+ var init_auth = __esm({
314
+ "src/api/auth.ts"() {
315
+ "use strict";
316
+ init_store();
317
+ }
318
+ });
319
+
320
+ // src/api/workflow.ts
321
+ async function listWorkflows(userId) {
322
+ const client2 = getClient();
323
+ const params = {};
324
+ if (userId) params.user_id = userId;
325
+ const res = await client2.get("/api/workflow/list", { params });
326
+ return res.data.workflows ?? res.data;
327
+ }
328
+ async function getWorkflowDetail(workflowId) {
329
+ const client2 = getClient();
330
+ const res = await client2.get(`/api/workflow/load/${workflowId}`);
331
+ return res.data;
332
+ }
333
+ async function getWorkflowListDetail() {
334
+ const client2 = getClient();
335
+ const res = await client2.get("/api/workflow/list/detail");
336
+ return res.data;
337
+ }
338
+ async function executeWorkflowStream(request) {
339
+ const client2 = getClient();
340
+ const res = await client2.post("/api/workflow/execute/based_id/stream", request, {
341
+ responseType: "stream",
342
+ headers: {
343
+ Accept: "text/event-stream"
354
344
  }
355
- const parsed = key === "streamLogs" ? value === "true" : value;
356
- setConfig({ [key]: parsed });
357
- printSuccess(`${key} = ${value}`);
358
345
  });
346
+ return res.data;
347
+ }
348
+ async function getIOLogs(workflowId, limit = 20) {
349
+ const client2 = getClient();
350
+ const params = { limit };
351
+ if (workflowId) params.workflow_id = workflowId;
352
+ const res = await client2.get("/api/workflow/io_logs", { params });
353
+ return res.data;
359
354
  }
355
+ var init_workflow = __esm({
356
+ "src/api/workflow.ts"() {
357
+ "use strict";
358
+ init_client();
359
+ }
360
+ });
360
361
 
361
- // src/commands/login.ts
362
- init_auth();
363
- init_store();
364
- import chalk3 from "chalk";
365
- import { createInterface } from "readline";
366
- function prompt(question, hidden = false) {
367
- return new Promise((resolve) => {
368
- const rl = createInterface({
369
- input: process.stdin,
370
- output: process.stdout
371
- });
372
- if (hidden) {
373
- process.stdout.write(question);
374
- const stdin = process.stdin;
375
- const wasRaw = stdin.isRaw;
376
- if (stdin.isTTY) stdin.setRawMode(true);
377
- let password = "";
378
- const onData = (ch) => {
379
- const c = ch.toString("utf8");
380
- if (c === "\n" || c === "\r" || c === "") {
381
- if (stdin.isTTY) stdin.setRawMode(wasRaw ?? false);
382
- stdin.removeListener("data", onData);
383
- process.stdout.write("\n");
384
- rl.close();
385
- resolve(password);
386
- } else if (c === "") {
387
- process.exit(0);
388
- } else if (c === "\x7F" || c === "\b") {
389
- if (password.length > 0) {
390
- password = password.slice(0, -1);
391
- process.stdout.write("\b \b");
392
- }
393
- } else {
394
- password += c;
395
- process.stdout.write("*");
396
- }
397
- };
398
- stdin.on("data", onData);
362
+ // src/commands/workflow/list.ts
363
+ var list_exports = {};
364
+ __export(list_exports, {
365
+ workflowList: () => workflowList
366
+ });
367
+ import chalk4 from "chalk";
368
+ async function workflowList(opts) {
369
+ requireAuth();
370
+ try {
371
+ if (opts.detail) {
372
+ const workflows = await getWorkflowListDetail();
373
+ if (!workflows || workflows.length === 0) {
374
+ console.log(chalk4.yellow("\n\uC6CC\uD06C\uD50C\uB85C\uC6B0\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.\n"));
375
+ return;
376
+ }
377
+ printHeader(`\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D (${workflows.length}\uAC1C)`);
378
+ console.log();
379
+ printTable(
380
+ ["#", "ID", "\uC774\uB984", "\uBC30\uD3EC", "\uC5C5\uB370\uC774\uD2B8"],
381
+ workflows.map((w, i) => [
382
+ String(i + 1),
383
+ (w.workflow_id ?? w.id ?? "-").slice(0, 12),
384
+ truncate(w.workflow_name ?? "-", 30),
385
+ w.deploy_status === "deployed" ? chalk4.green("\uBC30\uD3EC\uB428") : chalk4.gray("\uBBF8\uBC30\uD3EC"),
386
+ formatDate(w.updated_at)
387
+ ])
388
+ );
399
389
  } else {
400
- rl.question(question, (answer) => {
401
- rl.close();
402
- resolve(answer.trim());
403
- });
404
- }
405
- });
406
- }
407
- function registerLoginCommand(program2) {
408
- 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) => {
409
- const server = requireServer();
410
- printHeader("XGEN Login");
411
- console.log(chalk3.gray(`\uC11C\uBC84: ${server}
412
- `));
413
- let email = opts.email;
414
- let password = opts.password;
415
- if (!email) {
416
- email = await prompt(chalk3.white("\uC774\uBA54\uC77C: "));
417
- }
418
- if (!password) {
419
- password = await prompt(chalk3.white("\uBE44\uBC00\uBC88\uD638: "), true);
420
- }
421
- if (!email || !password) {
422
- printError("\uC774\uBA54\uC77C\uACFC \uBE44\uBC00\uBC88\uD638\uB97C \uBAA8\uB450 \uC785\uB825\uD558\uC138\uC694");
423
- process.exit(1);
424
- }
425
- try {
426
- const result = await apiLogin(email, password);
427
- if (result.success && result.access_token) {
428
- setAuth({
429
- accessToken: result.access_token,
430
- refreshToken: result.refresh_token ?? "",
431
- userId: result.user_id ?? "",
432
- username: result.username ?? "",
433
- isAdmin: false,
434
- expiresAt: null
435
- });
436
- console.log();
437
- printSuccess(`\uB85C\uADF8\uC778 \uC131\uACF5! ${chalk3.bold(result.username ?? email)}`);
438
- } else {
439
- printError(result.message || "\uB85C\uADF8\uC778 \uC2E4\uD328");
440
- process.exit(1);
441
- }
442
- } catch (err) {
443
- const msg = err?.response?.data?.message ?? err?.response?.data?.detail ?? err.message;
444
- printError(`\uB85C\uADF8\uC778 \uC2E4\uD328: ${msg}`);
445
- process.exit(1);
446
- }
447
- });
448
- program2.command("logout").description("\uB85C\uADF8\uC544\uC6C3").action(async () => {
449
- const { clearAuth: clearAuth2 } = await Promise.resolve().then(() => (init_store(), store_exports));
450
- clearAuth2();
451
- printSuccess("\uB85C\uADF8\uC544\uC6C3 \uC644\uB8CC");
452
- });
453
- program2.command("whoami").description("\uD604\uC7AC \uB85C\uADF8\uC778\uB41C \uC0AC\uC6A9\uC790 \uC815\uBCF4").action(async () => {
454
- const auth = getAuth();
455
- if (!auth) {
456
- printError("\uB85C\uADF8\uC778\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. xgen login \uC2E4\uD589\uD558\uC138\uC694");
457
- process.exit(1);
458
- }
459
- const server = requireServer();
460
- console.log(chalk3.bold("\n\uD604\uC7AC \uC0AC\uC6A9\uC790"));
461
- console.log(chalk3.gray("\u2500".repeat(30)));
462
- console.log(` ${chalk3.gray("\uC11C\uBC84:")} ${server}`);
463
- console.log(` ${chalk3.gray("\uC0AC\uC6A9\uC790:")} ${chalk3.bold(auth.username)}`);
464
- console.log(` ${chalk3.gray("User ID:")} ${auth.userId}`);
465
- try {
466
- const { apiValidate: apiValidate2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
467
- const result = await apiValidate2(auth.accessToken);
468
- if (result.valid) {
469
- console.log(` ${chalk3.gray("\uC0C1\uD0DC:")} ${chalk3.green("\uD65C\uC131")}`);
470
- if (result.is_admin) {
471
- console.log(` ${chalk3.gray("\uAD8C\uD55C:")} ${chalk3.yellow("\uAD00\uB9AC\uC790")}`);
472
- }
473
- if (result.user_type) {
474
- console.log(` ${chalk3.gray("\uC720\uD615:")} ${result.user_type}`);
475
- }
476
- } else {
477
- console.log(` ${chalk3.gray("\uC0C1\uD0DC:")} ${chalk3.red("\uD1A0\uD070 \uB9CC\uB8CC")}`);
478
- }
479
- } catch {
480
- console.log(` ${chalk3.gray("\uC0C1\uD0DC:")} ${chalk3.yellow("\uAC80\uC99D \uBD88\uAC00 (\uC11C\uBC84 \uC5F0\uACB0 \uC2E4\uD328)")}`);
481
- }
482
- console.log();
483
- });
484
- }
485
-
486
- // src/commands/workflow/list.ts
487
- init_store();
488
- import chalk4 from "chalk";
489
-
490
- // src/api/workflow.ts
491
- async function listWorkflows(userId) {
492
- const client2 = getClient();
493
- const params = {};
494
- if (userId) params.user_id = userId;
495
- const res = await client2.get("/api/workflow/list", { params });
496
- return res.data.workflows ?? res.data;
497
- }
498
- async function getWorkflowDetail(workflowId) {
499
- const client2 = getClient();
500
- const res = await client2.get(`/api/workflow/load/${workflowId}`);
501
- return res.data;
502
- }
503
- async function getWorkflowListDetail() {
504
- const client2 = getClient();
505
- const res = await client2.get("/api/workflow/list/detail");
506
- return res.data;
507
- }
508
- async function executeWorkflowStream(request) {
509
- const client2 = getClient();
510
- const res = await client2.post("/api/workflow/execute/based_id/stream", request, {
511
- responseType: "stream",
512
- headers: {
513
- Accept: "text/event-stream"
514
- }
515
- });
516
- return res.data;
517
- }
518
- async function getIOLogs(workflowId, limit = 20) {
519
- const client2 = getClient();
520
- const params = { limit };
521
- if (workflowId) params.workflow_id = workflowId;
522
- const res = await client2.get("/api/workflow/io_logs", { params });
523
- return res.data;
524
- }
525
-
526
- // src/commands/workflow/list.ts
527
- async function workflowList(opts) {
528
- requireAuth();
529
- try {
530
- if (opts.detail) {
531
- const workflows = await getWorkflowListDetail();
532
- if (!workflows || workflows.length === 0) {
533
- console.log(chalk4.yellow("\n\uC6CC\uD06C\uD50C\uB85C\uC6B0\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.\n"));
534
- return;
535
- }
536
- printHeader(`\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D (${workflows.length}\uAC1C)`);
537
- console.log();
538
- printTable(
539
- ["#", "ID", "\uC774\uB984", "\uBC30\uD3EC", "\uC5C5\uB370\uC774\uD2B8"],
540
- workflows.map((w, i) => [
541
- String(i + 1),
542
- (w.workflow_id ?? w.id ?? "-").slice(0, 12),
543
- truncate(w.workflow_name ?? "-", 30),
544
- w.deploy_status === "deployed" ? chalk4.green("\uBC30\uD3EC\uB428") : chalk4.gray("\uBBF8\uBC30\uD3EC"),
545
- formatDate(w.updated_at)
546
- ])
547
- );
548
- } else {
549
- const workflows = await listWorkflows();
550
- if (!workflows || workflows.length === 0) {
551
- console.log(chalk4.yellow("\n\uC6CC\uD06C\uD50C\uB85C\uC6B0\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.\n"));
552
- return;
553
- }
554
- printHeader(`\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D (${workflows.length}\uAC1C)`);
555
- console.log();
556
- printTable(
557
- ["#", "ID", "\uC774\uB984"],
558
- workflows.map((w, i) => [
559
- String(i + 1),
560
- (w.workflow_id ?? w.id ?? "-").slice(0, 12),
561
- w.workflow_name ?? "-"
562
- ])
563
- );
390
+ const workflows = await listWorkflows();
391
+ if (!workflows || workflows.length === 0) {
392
+ console.log(chalk4.yellow("\n\uC6CC\uD06C\uD50C\uB85C\uC6B0\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.\n"));
393
+ return;
394
+ }
395
+ printHeader(`\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D (${workflows.length}\uAC1C)`);
396
+ console.log();
397
+ printTable(
398
+ ["#", "ID", "\uC774\uB984"],
399
+ workflows.map((w, i) => [
400
+ String(i + 1),
401
+ (w.workflow_id ?? w.id ?? "-").slice(0, 12),
402
+ w.workflow_name ?? "-"
403
+ ])
404
+ );
564
405
  }
565
406
  console.log();
566
407
  } catch (err) {
@@ -569,47 +410,14 @@ async function workflowList(opts) {
569
410
  process.exit(1);
570
411
  }
571
412
  }
572
-
573
- // src/commands/workflow/info.ts
574
- init_store();
575
- import chalk5 from "chalk";
576
- async function workflowInfo(workflowId) {
577
- requireAuth();
578
- try {
579
- const detail = await getWorkflowDetail(workflowId);
580
- printHeader(`\uC6CC\uD06C\uD50C\uB85C\uC6B0: ${detail.workflow_name ?? workflowId}`);
581
- console.log();
582
- printKeyValue("ID", detail.id);
583
- printKeyValue("\uC774\uB984", detail.workflow_name);
584
- printKeyValue("\uC124\uBA85", detail.description ?? "(\uC5C6\uC74C)");
585
- if (detail.nodes && Array.isArray(detail.nodes)) {
586
- console.log();
587
- console.log(chalk5.bold(" \uB178\uB4DC \uAD6C\uC131:"));
588
- for (const node of detail.nodes) {
589
- const label = node.data?.label ?? node.id;
590
- const type = node.data?.type ?? "unknown";
591
- console.log(` ${chalk5.cyan("\u2022")} ${label} ${chalk5.gray(`(${type})`)}`);
592
- }
593
- }
594
- if (detail.parameters && Object.keys(detail.parameters).length > 0) {
595
- console.log();
596
- console.log(chalk5.bold(" \uD30C\uB77C\uBBF8\uD130:"));
597
- for (const [key, val] of Object.entries(detail.parameters)) {
598
- console.log(` ${chalk5.gray(key)}: ${JSON.stringify(val)}`);
599
- }
600
- }
601
- console.log();
602
- } catch (err) {
603
- const msg = err.message;
604
- printError(`\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC870\uD68C \uC2E4\uD328: ${msg}`);
605
- process.exit(1);
413
+ var init_list = __esm({
414
+ "src/commands/workflow/list.ts"() {
415
+ "use strict";
416
+ init_store();
417
+ init_workflow();
418
+ init_format();
606
419
  }
607
- }
608
-
609
- // src/commands/workflow/run.ts
610
- init_store();
611
- import chalk7 from "chalk";
612
- import { randomUUID } from "crypto";
420
+ });
613
421
 
614
422
  // src/utils/sse.ts
615
423
  async function parseSSEStream(stream, onEvent, onDone, onError) {
@@ -661,233 +469,37 @@ async function parseSSEStream(stream, onEvent, onDone, onError) {
661
469
  });
662
470
  });
663
471
  }
472
+ var init_sse = __esm({
473
+ "src/utils/sse.ts"() {
474
+ "use strict";
475
+ }
476
+ });
664
477
 
665
- // src/utils/markdown.ts
666
- import chalk6 from "chalk";
667
- var CODE_BLOCK_RE = /```(\w*)\n([\s\S]*?)```/g;
668
- var INLINE_CODE_RE = /`([^`]+)`/g;
669
- var BOLD_RE = /\*\*(.+?)\*\*/g;
670
- var HEADING_RE = /^(#{1,3})\s+(.+)$/gm;
671
- var LIST_RE = /^(\s*)[-*]\s+(.+)$/gm;
672
- var LINK_RE = /\[([^\]]+)\]\(([^)]+)\)/g;
673
- function renderMarkdown(text) {
674
- let result = text;
675
- result = result.replace(CODE_BLOCK_RE, (_match, lang, code) => {
676
- const trimmed = code.trimEnd();
677
- const header = lang ? chalk6.gray(` \u2500\u2500 ${lang} \u2500\u2500`) : chalk6.gray(" \u2500\u2500 code \u2500\u2500");
678
- const lines = trimmed.split("\n").map((l) => chalk6.white(` ${l}`)).join("\n");
679
- return `
680
- ${header}
681
- ${lines}
682
- ${chalk6.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}
683
- `;
684
- });
685
- result = result.replace(INLINE_CODE_RE, (_m, code) => chalk6.cyan(`\`${code}\``));
686
- result = result.replace(BOLD_RE, (_m, text2) => chalk6.bold(text2));
687
- result = result.replace(HEADING_RE, (_m, hashes, text2) => {
688
- if (hashes.length === 1) return chalk6.bold.underline(text2);
689
- if (hashes.length === 2) return chalk6.bold(text2);
690
- return chalk6.bold.dim(text2);
478
+ // src/commands/chat.ts
479
+ import chalk9 from "chalk";
480
+ import { createInterface as createInterface2 } from "readline";
481
+ import { randomUUID as randomUUID2 } from "crypto";
482
+ function printHelp() {
483
+ console.log(`
484
+ ${chalk9.bold("\uC2AC\uB798\uC2DC \uCEE4\uB9E8\uB4DC")}
485
+ ${chalk9.cyan("/workflows")} \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D \uBCF4\uAE30 & \uC804\uD658
486
+ ${chalk9.cyan("/switch")} \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBC88\uD638\uB85C \uC804\uD658 (\uC608: /switch 3)
487
+ ${chalk9.cyan("/history")} \uD604\uC7AC \uC138\uC158 \uB300\uD654 \uC774\uB825
488
+ ${chalk9.cyan("/clear")} \uD654\uBA74 \uC9C0\uC6B0\uAE30
489
+ ${chalk9.cyan("/info")} \uD604\uC7AC \uC5F0\uACB0 \uC815\uBCF4
490
+ ${chalk9.cyan("/help")} \uC774 \uB3C4\uC6C0\uB9D0
491
+ ${chalk9.cyan("/exit")} \uC885\uB8CC (Ctrl+C\uB3C4 \uAC00\uB2A5)
492
+ `);
493
+ }
494
+ async function promptLine(rl, promptStr) {
495
+ return new Promise((resolve) => {
496
+ rl.question(promptStr, (answer) => resolve(answer));
691
497
  });
692
- result = result.replace(LIST_RE, (_m, indent, text2) => `${indent}${chalk6.cyan("\u2022")} ${text2}`);
693
- result = result.replace(LINK_RE, (_m, label, url) => `${chalk6.blue.underline(label)} ${chalk6.gray(`(${url})`)}`);
694
- return result;
695
498
  }
696
-
697
- // src/commands/workflow/run.ts
698
- async function workflowRun(workflowId, input, opts) {
499
+ async function chat(workflowId) {
699
500
  const auth = requireAuth();
700
- let workflowName = workflowId;
701
- try {
702
- const detail = await getWorkflowDetail(workflowId);
703
- workflowName = detail.workflow_name ?? workflowId;
704
- } catch {
705
- }
706
- if (!input) {
707
- if (opts.interactive || !process.stdin.isTTY) {
708
- const { createInterface: createInterface7 } = await import("readline");
709
- const rl = createInterface7({ input: process.stdin, output: process.stdout });
710
- input = await new Promise((resolve) => {
711
- rl.question(chalk7.cyan("\uC785\uB825> "), (answer) => {
712
- rl.close();
713
- resolve(answer.trim());
714
- });
715
- });
716
- } else {
717
- printError("\uC785\uB825\uAC12\uC774 \uD544\uC694\uD569\uB2C8\uB2E4. \uC0AC\uC6A9\uBC95:");
718
- console.log(' xgen workflow run <id> "\uC785\uB825 \uD14D\uC2A4\uFFFD\uFFFD\uFFFD"');
719
- console.log(" xgen workflow run -i <id>");
720
- process.exit(1);
721
- }
722
- }
723
- if (!input) {
724
- printError("\uC785\uB825\uAC12\uC774 \uBE44\uC5B4\uC788\uC2B5\uB2C8\uB2E4");
725
- process.exit(1);
726
- }
727
- const interactionId = `cli_${randomUUID().slice(0, 8)}`;
728
- printHeader(`\uC2E4\uD589: ${workflowName}`);
729
- printInfo(`\uC785\uB825: ${input}`);
730
- console.log();
731
- try {
732
- const stream = await executeWorkflowStream({
733
- workflow_id: workflowId,
734
- workflow_name: workflowName,
735
- input_data: input,
736
- interaction_id: interactionId
737
- });
738
- let hasOutput = false;
739
- let fullResponse = "";
740
- await parseSSEStream(
741
- stream,
742
- (event) => {
743
- switch (event.type) {
744
- case "token":
745
- if (event.content) {
746
- if (!hasOutput) {
747
- hasOutput = true;
748
- console.log();
749
- }
750
- process.stdout.write(event.content);
751
- fullResponse += event.content;
752
- }
753
- break;
754
- case "log":
755
- if (opts.logs && event.content) {
756
- process.stderr.write(chalk7.gray(`[LOG] ${event.content}
757
- `));
758
- }
759
- break;
760
- case "node_status":
761
- if (opts.logs) {
762
- const nodeName = event.node_name ?? event.node_id ?? "?";
763
- const status = event.status ?? "?";
764
- process.stderr.write(
765
- chalk7.gray(`[\uB178\uB4DC] ${nodeName}: ${status}
766
- `)
767
- );
768
- }
769
- break;
770
- case "tool":
771
- if (opts.logs) {
772
- process.stderr.write(chalk7.gray(`[\uB3C4\uAD6C] ${JSON.stringify(event.data)}
773
- `));
774
- }
775
- break;
776
- case "complete":
777
- break;
778
- case "error":
779
- console.log();
780
- printError(event.error ?? event.content ?? "\uC54C \uC218 \uC5C6\uB294 \uC624\uB958");
781
- break;
782
- default:
783
- if (event.content) {
784
- if (!hasOutput) {
785
- process.stdout.write(chalk7.green("\uC751\uB2F5: "));
786
- hasOutput = true;
787
- }
788
- process.stdout.write(event.content);
789
- }
790
- }
791
- },
792
- () => {
793
- if (hasOutput) {
794
- console.log();
795
- if (fullResponse.includes("```") || fullResponse.includes("**")) {
796
- console.log(chalk7.gray("\u2500".repeat(40)));
797
- console.log(renderMarkdown(fullResponse));
798
- }
799
- }
800
- console.log();
801
- console.log(chalk7.gray(`\uC138\uC158: ${interactionId}`));
802
- },
803
- (err) => {
804
- console.log();
805
- printError(`\uC2A4\uD2B8\uB9AC\uBC0D \uC624\uB958: ${err.message}`);
806
- }
807
- );
808
- } catch (err) {
809
- const msg = err?.response?.data?.detail ?? err.message;
810
- printError(`\uC2E4\uD589 \uC2E4\uD328: ${msg}`);
811
- process.exit(1);
812
- }
813
- }
814
-
815
- // src/commands/workflow/history.ts
816
- init_store();
817
- import chalk8 from "chalk";
818
- async function workflowHistory(workflowId, opts = {}) {
819
- requireAuth();
820
- const limit = opts.limit ?? 20;
821
- try {
822
- const logs = await getIOLogs(workflowId, limit);
823
- if (!logs || logs.length === 0) {
824
- console.log(chalk8.yellow("\n\uC2E4\uD589 \uC774\uB825\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.\n"));
825
- return;
826
- }
827
- printHeader(`\uC2E4\uD589 \uC774\uB825 (\uCD5C\uADFC ${logs.length}\uAC74)`);
828
- console.log();
829
- for (const log of logs) {
830
- console.log(
831
- ` ${chalk8.gray(formatDate(log.created_at))} ${chalk8.cyan(log.interaction_id)}`
832
- );
833
- console.log(` ${chalk8.white("\uC785\uB825:")} ${truncate(log.input_data, 60)}`);
834
- console.log(
835
- ` ${chalk8.green("\uCD9C\uB825:")} ${truncate(log.output_data, 60)}`
836
- );
837
- if (log.execution_time) {
838
- console.log(
839
- ` ${chalk8.gray("\uC2DC\uAC04:")} ${(log.execution_time / 1e3).toFixed(1)}s`
840
- );
841
- }
842
- console.log();
843
- }
844
- } catch (err) {
845
- const msg = err.message;
846
- printError(`\uC774\uB825 \uC870\uD68C \uC2E4\uD328: ${msg}`);
847
- process.exit(1);
848
- }
849
- }
850
-
851
- // src/commands/workflow/index.ts
852
- function registerWorkflowCommand(program2) {
853
- const wf = program2.command("workflow").alias("wf").description("\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uAD00\uB9AC \uBC0F \uC2E4\uD589");
854
- 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));
855
- wf.command("info <workflow-id>").description("\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC0C1\uC138 \uC815\uBCF4").action((id) => workflowInfo(id));
856
- 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));
857
- 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) }));
858
- }
859
-
860
- // src/commands/chat.ts
861
- init_store();
862
- import chalk9 from "chalk";
863
- import { createInterface as createInterface2 } from "readline";
864
- import { randomUUID as randomUUID2 } from "crypto";
865
- var CHAT_BANNER = `
866
- ${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")}
867
- ${chalk9.cyan("\u2502")} ${chalk9.white.bold("XGEN")} ${chalk9.gray("\u2014 \uC6CC\uD06C\uD50C\uB85C\uC6B0 AI \uD130\uBBF8\uB110")} ${chalk9.cyan("\u2502")}
868
- ${chalk9.cyan("\u2502")} ${chalk9.gray("/help \uB3C4\uC6C0\uB9D0 /workflows \uC804\uD658 /exit")} ${chalk9.cyan("\u2502")}
869
- ${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")}`;
870
- function printHelp() {
871
- console.log(`
872
- ${chalk9.bold("\uC2AC\uB798\uC2DC \uCEE4\uB9E8\uB4DC")}
873
- ${chalk9.cyan("/workflows")} \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D \uBCF4\uAE30 & \uC804\uD658
874
- ${chalk9.cyan("/switch")} \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBC88\uD638\uB85C \uC804\uD658 (\uC608: /switch 3)
875
- ${chalk9.cyan("/history")} \uD604\uC7AC \uC138\uC158 \uB300\uD654 \uC774\uB825
876
- ${chalk9.cyan("/clear")} \uD654\uBA74 \uC9C0\uC6B0\uAE30
877
- ${chalk9.cyan("/info")} \uD604\uC7AC \uC5F0\uACB0 \uC815\uBCF4
878
- ${chalk9.cyan("/help")} \uC774 \uB3C4\uC6C0\uB9D0
879
- ${chalk9.cyan("/exit")} \uC885\uB8CC (Ctrl+C\uB3C4 \uAC00\uB2A5)
880
- `);
881
- }
882
- async function promptLine(rl, promptStr) {
883
- return new Promise((resolve) => {
884
- rl.question(promptStr, (answer) => resolve(answer));
885
- });
886
- }
887
- async function chat(workflowId) {
888
- const auth = requireAuth();
889
- const server = getServer();
890
- let workflows = [];
501
+ const server = getServer();
502
+ let workflows = [];
891
503
  try {
892
504
  workflows = await listWorkflows();
893
505
  } catch {
@@ -1078,11 +690,26 @@ async function chat(workflowId) {
1078
690
  function registerChatCommand(program2) {
1079
691
  program2.command("chat [workflow-id]").description("\uC778\uD130\uB799\uD2F0\uBE0C \uB300\uD654 \uBAA8\uB4DC").action((workflowId) => chat(workflowId));
1080
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
+ });
1081
708
 
1082
709
  // src/commands/provider.ts
1083
- init_store();
1084
710
  import chalk10 from "chalk";
1085
711
  import { createInterface as createInterface3 } from "readline";
712
+ import OpenAI from "openai";
1086
713
  function prompt2(question) {
1087
714
  return new Promise((resolve) => {
1088
715
  const rl = createInterface3({ input: process.stdin, output: process.stdout });
@@ -1092,56 +719,124 @@ function prompt2(question) {
1092
719
  });
1093
720
  });
1094
721
  }
1095
- var PROVIDER_PRESETS = {
1096
- openai: { defaultModel: "gpt-4o-mini" },
1097
- gemini: { baseUrl: "https://generativelanguage.googleapis.com/v1beta/openai", defaultModel: "gemini-2.0-flash" },
1098
- ollama: { baseUrl: "http://localhost:11434/v1", defaultModel: "llama3.1" },
1099
- anthropic: { baseUrl: "https://api.anthropic.com/v1", defaultModel: "claude-sonnet-4-20250514" },
1100
- custom: { defaultModel: "gpt-4o-mini" }
1101
- };
1102
- function registerProviderCommand(program2) {
1103
- const prov = program2.command("provider").description("AI \uD504\uB85C\uBC14\uC774\uB354 \uAD00\uB9AC");
1104
- prov.command("add").description("\uD504\uB85C\uBC14\uC774\uB354 \uCD94\uAC00 (\uB300\uD654\uD615)").action(async () => {
1105
- printHeader("\uD504\uB85C\uBC14\uC774\uB354 \uCD94\uAC00");
1106
- console.log();
1107
- const types = Object.keys(PROVIDER_PRESETS);
1108
- console.log(chalk10.gray("\uC9C0\uC6D0 \uD0C0\uC785:"), types.join(", "));
1109
- const type = await prompt2(chalk10.white("\uD0C0\uC785: "));
1110
- if (!types.includes(type)) {
1111
- printError(`\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uD0C0\uC785: ${type}`);
1112
- process.exit(1);
722
+ async function guidedProviderSetup() {
723
+ console.log(chalk10.cyan.bold("\n \u26A1 OPEN XGEN \u2014 \uD504\uB85C\uBC14\uC774\uB354 \uC124\uC815\n"));
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"));
725
+ console.log(chalk10.bold(" \uD504\uB85C\uBC14\uC774\uB354 \uC120\uD0DD:\n"));
726
+ PRESETS.forEach((p, i) => {
727
+ console.log(` ${chalk10.cyan(`${i + 1})`)} ${p.label} ${chalk10.gray(`\u2014 ${p.defaultModel}`)}`);
728
+ });
729
+ console.log();
730
+ const choice = await prompt2(chalk10.white(" \uBC88\uD638 \uC120\uD0DD: "));
731
+ const idx = parseInt(choice) - 1;
732
+ if (isNaN(idx) || idx < 0 || idx >= PRESETS.length) {
733
+ printError("\uC798\uBABB\uB41C \uC120\uD0DD\uC785\uB2C8\uB2E4.");
734
+ return null;
735
+ }
736
+ const preset = PRESETS[idx];
737
+ console.log(chalk10.green(`
738
+ \u2713 ${preset.label} \uC120\uD0DD\uB428
739
+ `));
740
+ let apiKey = "";
741
+ if (preset.needsKey) {
742
+ console.log(chalk10.gray(` ${preset.keyHint}
743
+ `));
744
+ apiKey = await prompt2(chalk10.white(" API Key: "));
745
+ if (!apiKey) {
746
+ printError("API Key\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.");
747
+ return null;
1113
748
  }
1114
- const preset = PROVIDER_PRESETS[type];
1115
- const name = await prompt2(chalk10.white("\uC774\uB984 (\uD45C\uC2DC\uC6A9): ")) || type;
1116
- const id = name.toLowerCase().replace(/[^a-z0-9]/g, "-");
1117
- let baseUrl = preset.baseUrl;
1118
- if (type === "custom" || type === "ollama") {
1119
- const input = await prompt2(chalk10.white(`Base URL [${preset.baseUrl ?? ""}]: `));
1120
- if (input) baseUrl = input;
1121
- }
1122
- let apiKey = "";
1123
- if (type !== "ollama") {
1124
- apiKey = await prompt2(chalk10.white("API Key: "));
1125
- if (!apiKey) {
1126
- printError("API Key\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4");
1127
- process.exit(1);
1128
- }
749
+ }
750
+ let baseUrl = preset.baseUrl;
751
+ if (preset.type === "custom") {
752
+ const url = await prompt2(chalk10.white(" Base URL: "));
753
+ if (!url) {
754
+ printError("Base URL\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.");
755
+ return null;
1129
756
  }
1130
- const model = await prompt2(chalk10.white(`\uBAA8\uB378 [${preset.defaultModel}]: `)) || preset.defaultModel;
1131
- const provider = { id, name, type, baseUrl, apiKey, model };
1132
- addProvider(provider);
757
+ baseUrl = url;
758
+ } else if (preset.type === "ollama") {
759
+ const url = await prompt2(chalk10.white(` Base URL [${preset.baseUrl}]: `));
760
+ if (url) baseUrl = url;
761
+ }
762
+ let model = preset.defaultModel;
763
+ if (preset.models.length > 0) {
764
+ console.log(chalk10.bold("\n \uBAA8\uB378 \uC120\uD0DD:\n"));
765
+ preset.models.forEach((m, i) => {
766
+ const isDefault = m === preset.defaultModel ? chalk10.gray(" (\uAE30\uBCF8)") : "";
767
+ console.log(` ${chalk10.cyan(`${i + 1})`)} ${m}${isDefault}`);
768
+ });
769
+ console.log(` ${chalk10.cyan(`${preset.models.length + 1})`)} \uC9C1\uC811 \uC785\uB825`);
1133
770
  console.log();
1134
- printSuccess(`\uD504\uB85C\uBC14\uC774\uB354 \uCD94\uAC00 \uC644\uB8CC: ${chalk10.bold(name)} (${model})`);
771
+ const defaultIdx = preset.models.indexOf(preset.defaultModel);
772
+ const mc = await prompt2(chalk10.white(` \uBC88\uD638 \uC120\uD0DD [${defaultIdx + 1}]: `));
773
+ if (!mc) {
774
+ model = preset.defaultModel;
775
+ } else {
776
+ const mi = parseInt(mc) - 1;
777
+ if (!isNaN(mi) && mi >= 0 && mi < preset.models.length) {
778
+ model = preset.models[mi];
779
+ } else if (parseInt(mc) === preset.models.length + 1) {
780
+ model = await prompt2(chalk10.white(" \uBAA8\uB378 \uC774\uB984: ")) || preset.defaultModel;
781
+ } else {
782
+ model = preset.defaultModel;
783
+ }
784
+ }
785
+ } else {
786
+ model = await prompt2(chalk10.white(` \uBAA8\uB378 \uC774\uB984 [${preset.defaultModel}]: `)) || preset.defaultModel;
787
+ }
788
+ console.log(chalk10.green(`
789
+ \u2713 \uBAA8\uB378: ${model}`));
790
+ console.log(chalk10.gray("\n \uC5F0\uACB0 \uD14C\uC2A4\uD2B8 \uC911..."));
791
+ const provider = {
792
+ id: preset.type,
793
+ name: preset.label,
794
+ type: preset.type,
795
+ baseUrl,
796
+ apiKey,
797
+ model
798
+ };
799
+ try {
800
+ const client2 = new OpenAI({
801
+ apiKey: apiKey || "ollama",
802
+ baseURL: baseUrl
803
+ });
804
+ const res = await client2.chat.completions.create({
805
+ model,
806
+ messages: [{ role: "user", content: "Hi" }],
807
+ max_tokens: 5
808
+ });
809
+ if (res.choices[0]) {
810
+ console.log(chalk10.green(" \u2713 \uC5F0\uACB0 \uC131\uACF5!\n"));
811
+ }
812
+ } catch (err) {
813
+ console.log(chalk10.yellow(` \u26A0 \uC5F0\uACB0 \uD14C\uC2A4\uD2B8 \uC2E4\uD328: ${err.message}`));
814
+ console.log(chalk10.gray(" \uC124\uC815\uC740 \uC800\uC7A5\uB429\uB2C8\uB2E4. \uB098\uC911\uC5D0 \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC138\uC694.\n"));
815
+ }
816
+ addProvider(provider);
817
+ console.log(chalk10.green.bold(` \u2713 ${preset.label} (${model}) \uC124\uC815 \uC644\uB8CC!
818
+ `));
819
+ console.log(chalk10.gray(` \uC774\uC81C ${chalk10.cyan("xgen agent")} \uB610\uB294 ${chalk10.cyan("xgen")} \uC73C\uB85C \uC2DC\uC791\uD558\uC138\uC694.
820
+ `));
821
+ return provider;
822
+ }
823
+ function registerProviderCommand(program2) {
824
+ const prov = program2.command("provider").description("AI \uD504\uB85C\uBC14\uC774\uB354 \uAD00\uB9AC");
825
+ prov.command("add").description("\uD504\uB85C\uBC14\uC774\uB354 \uCD94\uAC00 (\uAC00\uC774\uB4DC \uC124\uC815)").action(async () => {
826
+ await guidedProviderSetup();
1135
827
  });
1136
828
  prov.command("list").alias("ls").description("\uD504\uB85C\uBC14\uC774\uB354 \uBAA9\uB85D").action(() => {
1137
829
  const providers = getProviders();
1138
830
  const defaultP = getDefaultProvider();
1139
831
  if (providers.length === 0) {
1140
- console.log(chalk10.yellow("\n\uD504\uB85C\uBC14\uC774\uB354\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. xgen provider add \uB85C \uCD94\uAC00\uD558\uC138\uC694.\n"));
832
+ console.log(chalk10.yellow("\n \uD504\uB85C\uBC14\uC774\uB354\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."));
833
+ console.log(` ${chalk10.cyan("xgen provider add")} \uB85C \uCD94\uAC00\uD558\uC138\uC694.
834
+ `);
1141
835
  return;
1142
836
  }
1143
- printHeader(`\uD504\uB85C\uBC14\uC774\uB354 (${providers.length}\uAC1C)`);
1144
- console.log();
837
+ console.log(chalk10.cyan.bold(`
838
+ \uD504\uB85C\uBC14\uC774\uB354 (${providers.length}\uAC1C)
839
+ `));
1145
840
  printTable(
1146
841
  ["", "ID", "\uC774\uB984", "\uD0C0\uC785", "\uBAA8\uB378"],
1147
842
  providers.map((p) => [
@@ -1169,14 +864,62 @@ function registerProviderCommand(program2) {
1169
864
  }
1170
865
  });
1171
866
  }
1172
-
1173
- // src/commands/agent.ts
1174
- init_store();
1175
- import chalk11 from "chalk";
1176
- import { createInterface as createInterface5 } from "readline";
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
+ });
1177
920
 
1178
921
  // src/agent/llm.ts
1179
- import OpenAI from "openai";
922
+ import OpenAI2 from "openai";
1180
923
  function createLLMClient(provider) {
1181
924
  const opts = {
1182
925
  apiKey: provider.apiKey || "ollama"
@@ -1184,7 +927,7 @@ function createLLMClient(provider) {
1184
927
  if (provider.baseUrl) {
1185
928
  opts.baseURL = provider.baseUrl;
1186
929
  }
1187
- return new OpenAI(opts);
930
+ return new OpenAI2(opts);
1188
931
  }
1189
932
  async function streamChat(client2, model, messages, tools2, onDelta) {
1190
933
  const params = {
@@ -1223,6 +966,11 @@ async function streamChat(client2, model, messages, tools2, onDelta) {
1223
966
  toolCalls: [...toolCallMap.values()]
1224
967
  };
1225
968
  }
969
+ var init_llm = __esm({
970
+ "src/agent/llm.ts"() {
971
+ "use strict";
972
+ }
973
+ });
1226
974
 
1227
975
  // src/agent/tools/file-read.ts
1228
976
  var file_read_exports = {};
@@ -1231,22 +979,6 @@ __export(file_read_exports, {
1231
979
  execute: () => execute
1232
980
  });
1233
981
  import { readFileSync as readFileSync2 } from "fs";
1234
- var definition = {
1235
- type: "function",
1236
- function: {
1237
- name: "file_read",
1238
- description: "\uD30C\uC77C \uB0B4\uC6A9\uC744 \uC77D\uC2B5\uB2C8\uB2E4. \uC904 \uBC88\uD638\uAC00 \uD3EC\uD568\uB429\uB2C8\uB2E4.",
1239
- parameters: {
1240
- type: "object",
1241
- properties: {
1242
- path: { type: "string", description: "\uD30C\uC77C \uACBD\uB85C" },
1243
- start_line: { type: "number", description: "\uC2DC\uC791 \uC904 \uBC88\uD638 (\uC120\uD0DD)" },
1244
- end_line: { type: "number", description: "\uB05D \uC904 \uBC88\uD638 (\uC120\uD0DD)" }
1245
- },
1246
- required: ["path"]
1247
- }
1248
- }
1249
- };
1250
982
  async function execute(args) {
1251
983
  const path = args.path;
1252
984
  const startLine = args.start_line || 1;
@@ -1260,8 +992,30 @@ async function execute(args) {
1260
992
  return `Error: ${err.message}`;
1261
993
  }
1262
994
  }
1263
-
1264
- // src/agent/tools/file-write.ts
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
+ });
1017
+
1018
+ // src/agent/tools/file-write.ts
1265
1019
  var file_write_exports = {};
1266
1020
  __export(file_write_exports, {
1267
1021
  definition: () => definition2,
@@ -1269,21 +1023,6 @@ __export(file_write_exports, {
1269
1023
  });
1270
1024
  import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
1271
1025
  import { dirname } from "path";
1272
- var definition2 = {
1273
- type: "function",
1274
- function: {
1275
- name: "file_write",
1276
- description: "\uD30C\uC77C\uC744 \uC0DD\uC131\uD558\uAC70\uB098 \uB36E\uC5B4\uC501\uB2C8\uB2E4.",
1277
- parameters: {
1278
- type: "object",
1279
- properties: {
1280
- path: { type: "string", description: "\uD30C\uC77C \uACBD\uB85C" },
1281
- content: { type: "string", description: "\uD30C\uC77C \uB0B4\uC6A9" }
1282
- },
1283
- required: ["path", "content"]
1284
- }
1285
- }
1286
- };
1287
1026
  async function execute2(args) {
1288
1027
  const path = args.path;
1289
1028
  const content = args.content;
@@ -1295,6 +1034,27 @@ async function execute2(args) {
1295
1034
  return `Error: ${err.message}`;
1296
1035
  }
1297
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
+ });
1298
1058
 
1299
1059
  // src/agent/tools/file-edit.ts
1300
1060
  var file_edit_exports = {};
@@ -1303,22 +1063,6 @@ __export(file_edit_exports, {
1303
1063
  execute: () => execute3
1304
1064
  });
1305
1065
  import { readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
1306
- var definition3 = {
1307
- type: "function",
1308
- function: {
1309
- name: "file_edit",
1310
- description: "\uD30C\uC77C\uC5D0\uC11C \uD2B9\uC815 \uD14D\uC2A4\uD2B8\uB97C \uCC3E\uC544 \uAD50\uCCB4\uD569\uB2C8\uB2E4.",
1311
- parameters: {
1312
- type: "object",
1313
- properties: {
1314
- path: { type: "string", description: "\uD30C\uC77C \uACBD\uB85C" },
1315
- old_text: { type: "string", description: "\uAD50\uCCB4\uD560 \uAE30\uC874 \uD14D\uC2A4\uD2B8" },
1316
- new_text: { type: "string", description: "\uC0C8 \uD14D\uC2A4\uD2B8" }
1317
- },
1318
- required: ["path", "old_text", "new_text"]
1319
- }
1320
- }
1321
- };
1322
1066
  async function execute3(args) {
1323
1067
  const path = args.path;
1324
1068
  const oldText = args.old_text;
@@ -1335,6 +1079,28 @@ async function execute3(args) {
1335
1079
  return `Error: ${err.message}`;
1336
1080
  }
1337
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
+ });
1338
1104
 
1339
1105
  // src/agent/tools/bash.ts
1340
1106
  var bash_exports = {};
@@ -1343,20 +1109,6 @@ __export(bash_exports, {
1343
1109
  execute: () => execute4
1344
1110
  });
1345
1111
  import { execSync } from "child_process";
1346
- var definition4 = {
1347
- type: "function",
1348
- function: {
1349
- name: "bash",
1350
- description: "\uC178 \uBA85\uB839\uC5B4\uB97C \uC2E4\uD589\uD569\uB2C8\uB2E4. stdout + stderr\uB97C \uBC18\uD658\uD569\uB2C8\uB2E4.",
1351
- parameters: {
1352
- type: "object",
1353
- properties: {
1354
- command: { type: "string", description: "\uC2E4\uD589\uD560 \uBA85\uB839\uC5B4" }
1355
- },
1356
- required: ["command"]
1357
- }
1358
- }
1359
- };
1360
1112
  async function execute4(args) {
1361
1113
  const command = args.command;
1362
1114
  try {
@@ -1372,6 +1124,26 @@ async function execute4(args) {
1372
1124
  return (e.stdout || "") + (e.stderr || "") || `Error: ${e.message}`;
1373
1125
  }
1374
1126
  }
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
+ };
1145
+ }
1146
+ });
1375
1147
 
1376
1148
  // src/agent/tools/grep.ts
1377
1149
  var grep_exports = {};
@@ -1380,22 +1152,6 @@ __export(grep_exports, {
1380
1152
  execute: () => execute5
1381
1153
  });
1382
1154
  import { execSync as execSync2 } from "child_process";
1383
- var definition5 = {
1384
- type: "function",
1385
- function: {
1386
- name: "grep",
1387
- description: "\uD30C\uC77C\uC5D0\uC11C \uD328\uD134\uC744 \uAC80\uC0C9\uD569\uB2C8\uB2E4 (\uC7AC\uADC0, \uC904 \uBC88\uD638 \uD3EC\uD568).",
1388
- parameters: {
1389
- type: "object",
1390
- properties: {
1391
- pattern: { type: "string", description: "\uAC80\uC0C9 \uD328\uD134 (\uC815\uADDC\uC2DD)" },
1392
- path: { type: "string", description: "\uAC80\uC0C9 \uB514\uB809\uD1A0\uB9AC \uB610\uB294 \uD30C\uC77C (\uAE30\uBCF8: .)" },
1393
- glob: { type: "string", description: "\uD30C\uC77C \uD544\uD130 (\uC608: *.ts)" }
1394
- },
1395
- required: ["pattern"]
1396
- }
1397
- }
1398
- };
1399
1155
  async function execute5(args) {
1400
1156
  const pattern = args.pattern;
1401
1157
  const path = args.path || ".";
@@ -1415,6 +1171,28 @@ async function execute5(args) {
1415
1171
  return "\uC77C\uCE58\uD558\uB294 \uACB0\uACFC \uC5C6\uC74C";
1416
1172
  }
1417
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
+ });
1418
1196
 
1419
1197
  // src/agent/tools/list-files.ts
1420
1198
  var list_files_exports = {};
@@ -1423,20 +1201,6 @@ __export(list_files_exports, {
1423
1201
  execute: () => execute6
1424
1202
  });
1425
1203
  import { execSync as execSync3 } from "child_process";
1426
- var definition6 = {
1427
- type: "function",
1428
- function: {
1429
- name: "list_files",
1430
- description: "\uB514\uB809\uD1A0\uB9AC\uC758 \uD30C\uC77C/\uD3F4\uB354 \uBAA9\uB85D\uC744 \uBC18\uD658\uD569\uB2C8\uB2E4. glob \uD328\uD134 \uC9C0\uC6D0.",
1431
- parameters: {
1432
- type: "object",
1433
- properties: {
1434
- path: { type: "string", description: "\uB514\uB809\uD1A0\uB9AC \uACBD\uB85C (\uAE30\uBCF8: .)" },
1435
- pattern: { type: "string", description: "glob \uD328\uD134 (\uC608: **/*.ts)" }
1436
- }
1437
- }
1438
- }
1439
- };
1440
1204
  async function execute6(args) {
1441
1205
  const path = args.path || ".";
1442
1206
  const pattern = args.pattern;
@@ -1457,6 +1221,26 @@ async function execute6(args) {
1457
1221
  return `Error: ${err.message}`;
1458
1222
  }
1459
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
+ });
1460
1244
 
1461
1245
  // src/agent/tools/sandbox.ts
1462
1246
  var sandbox_exports = {};
@@ -1468,37 +1252,12 @@ import { execSync as execSync4 } from "child_process";
1468
1252
  import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync4, existsSync as existsSync2, rmSync } from "fs";
1469
1253
  import { join as join2 } from "path";
1470
1254
  import { tmpdir } from "os";
1471
- var SANDBOX_DIR = join2(tmpdir(), "xgen-sandbox");
1472
1255
  function ensureSandbox() {
1473
1256
  if (!existsSync2(SANDBOX_DIR)) {
1474
1257
  mkdirSync3(SANDBOX_DIR, { recursive: true });
1475
1258
  }
1476
1259
  return SANDBOX_DIR;
1477
1260
  }
1478
- var definition7 = {
1479
- type: "function",
1480
- function: {
1481
- name: "sandbox_run",
1482
- description: "\uACA9\uB9AC\uB41C \uC0CC\uB4DC\uBC15\uC2A4\uC5D0\uC11C \uCF54\uB4DC\uB97C \uC2E4\uD589\uD569\uB2C8\uB2E4. Node.js \uB610\uB294 Python \uCF54\uB4DC\uB97C \uC548\uC804\uD558\uAC8C \uC2E4\uD589\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4. npm \uD328\uD0A4\uC9C0 \uC124\uCE58\uB3C4 \uAC00\uB2A5\uD569\uB2C8\uB2E4.",
1483
- parameters: {
1484
- type: "object",
1485
- properties: {
1486
- language: {
1487
- type: "string",
1488
- enum: ["javascript", "typescript", "python"],
1489
- description: "\uC2E4\uD589\uD560 \uC5B8\uC5B4"
1490
- },
1491
- code: { type: "string", description: "\uC2E4\uD589\uD560 \uCF54\uB4DC" },
1492
- packages: {
1493
- type: "array",
1494
- items: { type: "string" },
1495
- description: "\uC124\uCE58\uD560 \uD328\uD0A4\uC9C0 (npm \uB610\uB294 pip)"
1496
- }
1497
- },
1498
- required: ["language", "code"]
1499
- }
1500
- }
1501
- };
1502
1261
  async function execute7(args) {
1503
1262
  const language = args.language;
1504
1263
  const code = args.code;
@@ -1561,13 +1320,39 @@ async function execute7(args) {
1561
1320
  }
1562
1321
  }
1563
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
+ });
1564
1354
 
1565
1355
  // src/agent/tools/index.ts
1566
- var tools = [file_read_exports, file_write_exports, file_edit_exports, bash_exports, grep_exports, list_files_exports, sandbox_exports];
1567
- var toolMap = /* @__PURE__ */ new Map();
1568
- for (const t of tools) {
1569
- toolMap.set(t.definition.function.name, t);
1570
- }
1571
1356
  function getAllToolDefs() {
1572
1357
  return tools.map((t) => t.definition);
1573
1358
  }
@@ -1579,100 +1364,30 @@ async function executeTool(name, args) {
1579
1364
  function getToolNames() {
1580
1365
  return tools.map((t) => t.definition.function.name);
1581
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
+ });
1582
1385
 
1583
1386
  // src/mcp/client.ts
1584
1387
  import { spawn } from "child_process";
1585
1388
  import { existsSync as existsSync3, readFileSync as readFileSync4 } from "fs";
1586
1389
  import { join as join3 } from "path";
1587
1390
  import { createInterface as createInterface4 } from "readline";
1588
- var McpClient = class {
1589
- process = null;
1590
- requestId = 0;
1591
- pending = /* @__PURE__ */ new Map();
1592
- serverName;
1593
- config;
1594
- tools = [];
1595
- constructor(serverName, config) {
1596
- this.serverName = serverName;
1597
- this.config = config;
1598
- }
1599
- async start() {
1600
- this.process = spawn(this.config.command, this.config.args ?? [], {
1601
- stdio: ["pipe", "pipe", "pipe"],
1602
- env: { ...process.env, ...this.config.env }
1603
- });
1604
- const rl = createInterface4({ input: this.process.stdout });
1605
- rl.on("line", (line) => {
1606
- try {
1607
- const msg = JSON.parse(line);
1608
- if (msg.id !== void 0 && this.pending.has(msg.id)) {
1609
- const p = this.pending.get(msg.id);
1610
- this.pending.delete(msg.id);
1611
- if (msg.error) {
1612
- p.reject(new Error(msg.error.message));
1613
- } else {
1614
- p.resolve(msg.result);
1615
- }
1616
- }
1617
- } catch {
1618
- }
1619
- });
1620
- this.process.on("error", (err) => {
1621
- console.error(`MCP [${this.serverName}] \uD504\uB85C\uC138\uC2A4 \uC624\uB958:`, err.message);
1622
- });
1623
- await this.send("initialize", {
1624
- protocolVersion: "2024-11-05",
1625
- capabilities: {},
1626
- clientInfo: { name: "open-xgen", version: "0.3.0" }
1627
- });
1628
- await this.send("notifications/initialized", {});
1629
- }
1630
- send(method, params) {
1631
- return new Promise((resolve, reject) => {
1632
- const id = ++this.requestId;
1633
- const request = { jsonrpc: "2.0", id, method, params };
1634
- this.pending.set(id, { resolve, reject });
1635
- const timeout = setTimeout(() => {
1636
- this.pending.delete(id);
1637
- reject(new Error(`MCP \uC694\uCCAD \uD0C0\uC784\uC544\uC6C3: ${method}`));
1638
- }, 15e3);
1639
- this.pending.set(id, {
1640
- resolve: (v) => {
1641
- clearTimeout(timeout);
1642
- resolve(v);
1643
- },
1644
- reject: (e) => {
1645
- clearTimeout(timeout);
1646
- reject(e);
1647
- }
1648
- });
1649
- this.process?.stdin?.write(JSON.stringify(request) + "\n");
1650
- });
1651
- }
1652
- async listTools() {
1653
- const result = await this.send("tools/list", {});
1654
- this.tools = result.tools ?? [];
1655
- return this.tools;
1656
- }
1657
- async callTool(name, args) {
1658
- const result = await this.send("tools/call", { name, arguments: args });
1659
- return result.content?.map((c) => c.text ?? "").join("\n") ?? "";
1660
- }
1661
- getOpenAITools() {
1662
- return this.tools.map((t) => ({
1663
- type: "function",
1664
- function: {
1665
- name: `mcp_${this.serverName}_${t.name}`,
1666
- description: `[MCP:${this.serverName}] ${t.description ?? t.name}`,
1667
- parameters: t.inputSchema ?? { type: "object", properties: {} }
1668
- }
1669
- }));
1670
- }
1671
- stop() {
1672
- this.process?.kill();
1673
- this.process = null;
1674
- }
1675
- };
1676
1391
  function loadMcpConfig(dir) {
1677
1392
  const searchPaths = [
1678
1393
  dir ? join3(dir, ".mcp.json") : null,
@@ -1690,69 +1405,419 @@ function loadMcpConfig(dir) {
1690
1405
  }
1691
1406
  return null;
1692
1407
  }
1693
- var McpManager = class {
1694
- clients = /* @__PURE__ */ new Map();
1695
- async startAll(config) {
1696
- for (const [name, serverConfig] of Object.entries(config.mcpServers)) {
1697
- if (serverConfig.type !== "stdio") continue;
1698
- try {
1699
- const client2 = new McpClient(name, serverConfig);
1700
- await client2.start();
1701
- await client2.listTools();
1702
- this.clients.set(name, client2);
1703
- } catch (err) {
1704
- console.error(`MCP [${name}] \uC2DC\uC791 \uC2E4\uD328:`, err.message);
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;
1705
1422
  }
1706
- }
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
+ };
1547
+ }
1548
+ });
1549
+
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`);
1576
+ }
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`);
1707
1583
  }
1708
- getAllTools() {
1709
- const tools2 = [];
1710
- for (const client2 of this.clients.values()) {
1711
- tools2.push(...client2.getOpenAITools());
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
1603
+ `));
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();
1613
+ }
1614
+ });
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
+ `));
1712
1696
  }
1713
- return tools2;
1697
+ console.log();
1698
+ showStatus();
1714
1699
  }
1715
- async callTool(fullName, args) {
1716
- const parts = fullName.split("_");
1717
- if (parts.length < 3 || parts[0] !== "mcp") return `Unknown MCP tool: ${fullName}`;
1718
- const serverName = parts[1];
1719
- const toolName = parts.slice(2).join("_");
1720
- const client2 = this.clients.get(serverName);
1721
- if (!client2) return `MCP \uC11C\uBC84\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${serverName}`;
1722
- return client2.callTool(toolName, args);
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;
1723
1711
  }
1724
- isMcpTool(name) {
1725
- return name.startsWith("mcp_");
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;
1726
1722
  }
1727
- stopAll() {
1728
- for (const client2 of this.clients.values()) {
1729
- client2.stop();
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
+ `));
1730
1741
  }
1731
- this.clients.clear();
1742
+ } catch (err) {
1743
+ console.log(chalk11.red(` \u2717 \uB85C\uADF8\uC778 \uC2E4\uD328: ${err.message}
1744
+ `));
1732
1745
  }
1733
- get serverCount() {
1734
- return this.clients.size;
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();
1735
1758
  }
1736
- getServerNames() {
1737
- return [...this.clients.keys()];
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`);
1738
1762
  }
1739
- };
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
+ });
1740
1810
 
1741
1811
  // src/commands/agent.ts
1742
- var SYSTEM_PROMPT = `You are OPEN XGEN Agent, an AI coding assistant running in the user's terminal.
1743
- You have access to tools for reading/writing files, executing commands, searching code, and running sandboxed code.
1744
- You can also use MCP (Model Context Protocol) tools if available.
1745
- Always respond in the same language as the user.
1746
- When using tools, be concise about what you're doing.
1747
- For file edits, show what you changed briefly.
1748
- For sandbox_run, you can install npm/pip packages and run isolated code.`;
1749
- var mcpManager = null;
1812
+ import chalk12 from "chalk";
1813
+ import { createInterface as createInterface6 } from "readline";
1750
1814
  async function agentRepl() {
1751
- const provider = getDefaultProvider();
1815
+ let provider = getDefaultProvider();
1752
1816
  if (!provider) {
1753
- printError("\uD504\uB85C\uBC14\uC774\uB354\uAC00 \uC124\uC815\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.");
1754
- console.log(` ${chalk11.cyan("xgen provider add")} \uD504\uB85C\uBC14\uC774\uB354 \uCD94\uAC00`);
1755
- process.exit(1);
1817
+ provider = await guidedProviderSetup();
1818
+ if (!provider) {
1819
+ process.exit(1);
1820
+ }
1756
1821
  }
1757
1822
  const client2 = createLLMClient(provider);
1758
1823
  const builtinTools = getAllToolDefs();
@@ -1771,138 +1836,609 @@ async function agentRepl() {
1771
1836
  } catch {
1772
1837
  }
1773
1838
  }
1774
- const messages = [{ role: "system", content: SYSTEM_PROMPT }];
1775
- console.log(chalk11.cyan.bold("\n OPEN XGEN Agent"));
1776
- 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"));
1777
- console.log(chalk11.gray(` \uD504\uB85C\uBC14\uC774\uB354: ${provider.name} (${provider.model})`));
1778
- console.log(chalk11.gray(` \uB3C4\uAD6C: ${getToolNames().join(", ")}`));
1779
- if (mcpManager && mcpManager.serverCount > 0) {
1780
- console.log(chalk11.gray(` MCP: ${mcpManager.getServerNames().join(", ")} (${mcpManager.getAllTools().length}\uAC1C \uB3C4\uAD6C)`));
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) {
1936
+ if (result.content) {
1937
+ messages.push({ role: "assistant", content: result.content });
1938
+ }
1939
+ return;
1940
+ }
1941
+ messages.push({
1942
+ role: "assistant",
1943
+ content: result.content || null,
1944
+ tool_calls: result.toolCalls.map((tc) => ({
1945
+ id: tc.id,
1946
+ type: "function",
1947
+ function: { name: tc.name, arguments: tc.arguments }
1948
+ }))
1949
+ });
1950
+ for (const tc of result.toolCalls) {
1951
+ let args;
1952
+ try {
1953
+ args = JSON.parse(tc.arguments);
1954
+ } catch {
1955
+ args = {};
1956
+ }
1957
+ console.log(chalk12.gray(` \u2699 ${tc.name}(`), chalk12.dim(summarizeArgs(args)), chalk12.gray(")"));
1958
+ let toolResult;
1959
+ if (mcpManager?.isMcpTool(tc.name)) {
1960
+ toolResult = await mcpManager.callTool(tc.name, args);
1961
+ } else {
1962
+ toolResult = await executeTool(tc.name, args);
1963
+ }
1964
+ const truncated = toolResult.length > 4e3 ? toolResult.slice(0, 4e3) + "\n...(truncated)" : toolResult;
1965
+ messages.push({
1966
+ role: "tool",
1967
+ tool_call_id: tc.id,
1968
+ content: truncated
1969
+ });
1970
+ }
1971
+ }
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);
1781
2295
  }
1782
- console.log(chalk11.gray(` \uC885\uB8CC: exit | Ctrl+C`));
2296
+ const interactionId = `cli_${randomUUID().slice(0, 8)}`;
2297
+ printHeader(`\uC2E4\uD589: ${workflowName}`);
2298
+ printInfo(`\uC785\uB825: ${input}`);
1783
2299
  console.log();
1784
- const rl = createInterface5({ input: process.stdin, output: process.stdout });
1785
- const ask = () => new Promise((resolve) => rl.question(chalk11.green("\u276F "), (a) => resolve(a.trim())));
1786
- process.on("SIGINT", () => {
1787
- console.log(chalk11.gray("\n\uC885\uB8CC\uD569\uB2C8\uB2E4."));
1788
- mcpManager?.stopAll();
1789
- rl.close();
1790
- process.exit(0);
1791
- });
1792
- while (true) {
1793
- const input = await ask();
1794
- if (!input) continue;
1795
- if (input === "exit" || input === "/exit") {
1796
- console.log(chalk11.gray("\uC885\uB8CC\uD569\uB2C8\uB2E4."));
1797
- mcpManager?.stopAll();
1798
- rl.close();
1799
- break;
1800
- }
1801
- if (input === "/clear") {
1802
- messages.length = 1;
1803
- console.log(chalk11.gray("\uB300\uD654 \uCD08\uAE30\uD654\uB428.\n"));
1804
- continue;
1805
- }
1806
- if (input === "/tools") {
1807
- console.log(chalk11.bold("\n\uB0B4\uC7A5 \uB3C4\uAD6C:"), getToolNames().join(", "));
1808
- if (mcpManager && mcpManager.serverCount > 0) {
1809
- console.log(chalk11.bold("MCP \uB3C4\uAD6C:"), mcpManager.getAllTools().map((t) => t.function.name).join(", "));
1810
- }
1811
- console.log();
1812
- continue;
1813
- }
1814
- if (input === "/provider") {
1815
- console.log(chalk11.gray(`\uD604\uC7AC: ${provider.name} (${provider.model})
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}
1816
2326
  `));
1817
- continue;
1818
- }
1819
- if (input === "/mcp") {
1820
- if (mcpManager && mcpManager.serverCount > 0) {
1821
- console.log(chalk11.bold("\nMCP \uC11C\uBC84:"), mcpManager.getServerNames().join(", "));
1822
- console.log(chalk11.gray("\uB3C4\uAD6C:"), mcpManager.getAllTools().map((t) => t.function.name).join(", "));
1823
- } else {
1824
- console.log(chalk11.gray("MCP \uC11C\uBC84 \uC5C6\uC74C. .mcp.json\uC744 \uD504\uB85C\uC81D\uD2B8 \uB8E8\uD2B8\uC5D0 \uCD94\uAC00\uD558\uC138\uC694."));
1825
- }
1826
- console.log();
1827
- continue;
1828
- }
1829
- messages.push({ role: "user", content: input });
1830
- try {
1831
- await runAgentLoop(client2, provider.model, messages, allTools);
1832
- } catch (err) {
1833
- console.log(chalk11.red(`
1834
- \uC624\uB958: ${err.message}
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)}
1835
2342
  `));
1836
- }
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);
1837
2381
  }
1838
2382
  }
1839
- async function runAgentLoop(client2, model, messages, tools2) {
1840
- const MAX_ITERATIONS = 20;
1841
- for (let i = 0; i < MAX_ITERATIONS; i++) {
1842
- const result = await streamChat(client2, model, messages, tools2, (delta) => {
1843
- process.stdout.write(delta);
1844
- });
1845
- if (result.content) {
1846
- process.stdout.write("\n\n");
1847
- }
1848
- if (result.toolCalls.length === 0) {
1849
- if (result.content) {
1850
- messages.push({ role: "assistant", content: result.content });
1851
- }
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"));
1852
2396
  return;
1853
2397
  }
1854
- messages.push({
1855
- role: "assistant",
1856
- content: result.content || null,
1857
- tool_calls: result.toolCalls.map((tc) => ({
1858
- id: tc.id,
1859
- type: "function",
1860
- function: { name: tc.name, arguments: tc.arguments }
1861
- }))
1862
- });
1863
- for (const tc of result.toolCalls) {
1864
- let args;
1865
- try {
1866
- args = JSON.parse(tc.arguments);
1867
- } catch {
1868
- args = {};
1869
- }
1870
- console.log(chalk11.gray(` \u2699 ${tc.name}(`), chalk11.dim(summarizeArgs(args)), chalk11.gray(")"));
1871
- let toolResult;
1872
- if (mcpManager?.isMcpTool(tc.name)) {
1873
- toolResult = await mcpManager.callTool(tc.name, args);
1874
- } else {
1875
- toolResult = await executeTool(tc.name, args);
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
+ );
1876
2412
  }
1877
- const truncated = toolResult.length > 4e3 ? toolResult.slice(0, 4e3) + "\n...(truncated)" : toolResult;
1878
- messages.push({
1879
- role: "tool",
1880
- tool_call_id: tc.id,
1881
- content: truncated
1882
- });
2413
+ console.log();
1883
2414
  }
2415
+ } catch (err) {
2416
+ const msg = err.message;
2417
+ printError(`\uC774\uB825 \uC870\uD68C \uC2E4\uD328: ${msg}`);
2418
+ process.exit(1);
1884
2419
  }
1885
- console.log(chalk11.yellow("\n\uCD5C\uB300 \uBC18\uBCF5 \uD69F\uC218\uC5D0 \uB3C4\uB2EC\uD588\uC2B5\uB2C8\uB2E4.\n"));
1886
- }
1887
- function summarizeArgs(args) {
1888
- const parts = [];
1889
- for (const [k, v] of Object.entries(args)) {
1890
- const s = String(v);
1891
- parts.push(`${k}: ${s.length > 40 ? s.slice(0, 40) + "..." : s}`);
1892
- }
1893
- return parts.join(", ");
1894
2420
  }
1895
- function registerAgentCommand(program2) {
1896
- program2.command("agent").description("OPEN XGEN AI \uCF54\uB529 \uC5D0\uC774\uC804\uD2B8").action(async () => {
1897
- await agentRepl();
1898
- });
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) }));
1899
2429
  }
1900
2430
 
2431
+ // src/index.ts
2432
+ init_chat();
2433
+ init_provider();
2434
+ init_agent();
2435
+
1901
2436
  // src/commands/doc.ts
1902
2437
  init_store();
1903
- import chalk12 from "chalk";
2438
+ import chalk13 from "chalk";
1904
2439
 
1905
2440
  // src/api/document.ts
2441
+ init_client();
1906
2442
  import { createReadStream, statSync } from "fs";
1907
2443
  import { basename } from "path";
1908
2444
  async function listDocuments(collectionId) {
@@ -1935,6 +2471,7 @@ async function getDocumentInfo(docId) {
1935
2471
  }
1936
2472
 
1937
2473
  // src/commands/doc.ts
2474
+ init_format();
1938
2475
  function registerDocCommand(program2) {
1939
2476
  const doc = program2.command("doc").description("\uBB38\uC11C \uAD00\uB9AC");
1940
2477
  doc.command("list").alias("ls").description("\uBB38\uC11C \uBAA9\uB85D \uC870\uD68C").option("-c, --collection <id>", "\uCEEC\uB809\uC158 ID").action(async (opts) => {
@@ -1942,7 +2479,7 @@ function registerDocCommand(program2) {
1942
2479
  try {
1943
2480
  const docs = await listDocuments(opts.collection);
1944
2481
  if (!docs.length) {
1945
- console.log(chalk12.yellow("\n\uBB38\uC11C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.\n"));
2482
+ console.log(chalk13.yellow("\n\uBB38\uC11C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.\n"));
1946
2483
  return;
1947
2484
  }
1948
2485
  printHeader(`\uBB38\uC11C \uBAA9\uB85D (${docs.length}\uAC1C)`);
@@ -1966,10 +2503,10 @@ function registerDocCommand(program2) {
1966
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) => {
1967
2504
  requireAuth();
1968
2505
  try {
1969
- console.log(chalk12.gray(`\uC5C5\uB85C\uB4DC \uC911: ${file}`));
2506
+ console.log(chalk13.gray(`\uC5C5\uB85C\uB4DC \uC911: ${file}`));
1970
2507
  const result = await uploadDocument(file, opts.collection, opts.name);
1971
- console.log(chalk12.green("\u2713 \uC5C5\uB85C\uB4DC \uC644\uB8CC"));
1972
- console.log(chalk12.gray(JSON.stringify(result, null, 2)));
2508
+ console.log(chalk13.green("\u2713 \uC5C5\uB85C\uB4DC \uC644\uB8CC"));
2509
+ console.log(chalk13.gray(JSON.stringify(result, null, 2)));
1973
2510
  } catch (err) {
1974
2511
  printError(`\uC5C5\uB85C\uB4DC \uC2E4\uD328: ${err.message}`);
1975
2512
  }
@@ -1979,7 +2516,7 @@ function registerDocCommand(program2) {
1979
2516
  try {
1980
2517
  const d = await getDocumentInfo(id);
1981
2518
  printHeader("\uBB38\uC11C \uC815\uBCF4");
1982
- console.log(chalk12.gray(JSON.stringify(d, null, 2)));
2519
+ console.log(chalk13.gray(JSON.stringify(d, null, 2)));
1983
2520
  } catch (err) {
1984
2521
  printError(`\uC870\uD68C \uC2E4\uD328: ${err.message}`);
1985
2522
  }
@@ -1988,10 +2525,11 @@ function registerDocCommand(program2) {
1988
2525
 
1989
2526
  // src/commands/ontology.ts
1990
2527
  init_store();
1991
- import chalk13 from "chalk";
1992
- import { createInterface as createInterface6 } from "readline";
2528
+ import chalk14 from "chalk";
2529
+ import { createInterface as createInterface7 } from "readline";
1993
2530
 
1994
2531
  // src/api/ontology.ts
2532
+ init_client();
1995
2533
  async function queryGraphRAG(query, graphId, opts) {
1996
2534
  const client2 = getClient();
1997
2535
  const res = await client2.post("/api/graph-rag", {
@@ -2018,25 +2556,26 @@ async function getGraphStats(graphId) {
2018
2556
  }
2019
2557
 
2020
2558
  // src/commands/ontology.ts
2559
+ init_format();
2021
2560
  import { randomUUID as randomUUID3 } from "crypto";
2022
2561
  function registerOntologyCommand(program2) {
2023
2562
  const ont = program2.command("ontology").alias("ont").description("\uC628\uD1A8\uB85C\uC9C0 GraphRAG \uC9C8\uC758");
2024
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) => {
2025
2564
  requireAuth();
2026
2565
  try {
2027
- console.log(chalk13.gray("\n\uC9C8\uC758 \uC911...\n"));
2566
+ console.log(chalk14.gray("\n\uC9C8\uC758 \uC911...\n"));
2028
2567
  const result = await queryGraphRAG(question, opts.graph, { scs: opts.scs });
2029
2568
  if (result.answer) {
2030
- console.log(chalk13.bold("\uB2F5\uBCC0:"));
2569
+ console.log(chalk14.bold("\uB2F5\uBCC0:"));
2031
2570
  console.log(result.answer);
2032
2571
  }
2033
2572
  if (result.sources?.length) {
2034
- console.log(chalk13.bold("\n\uCD9C\uCC98:"));
2035
- result.sources.forEach((s) => console.log(chalk13.gray(` - ${s}`)));
2573
+ console.log(chalk14.bold("\n\uCD9C\uCC98:"));
2574
+ result.sources.forEach((s) => console.log(chalk14.gray(` - ${s}`)));
2036
2575
  }
2037
2576
  if (result.triples_used?.length) {
2038
- console.log(chalk13.bold("\n\uC0AC\uC6A9\uB41C \uD2B8\uB9AC\uD50C:"));
2039
- result.triples_used.forEach((t) => console.log(chalk13.dim(` ${t}`)));
2577
+ console.log(chalk14.bold("\n\uC0AC\uC6A9\uB41C \uD2B8\uB9AC\uD50C:"));
2578
+ result.triples_used.forEach((t) => console.log(chalk14.dim(` ${t}`)));
2040
2579
  }
2041
2580
  console.log();
2042
2581
  } catch (err) {
@@ -2047,9 +2586,9 @@ function registerOntologyCommand(program2) {
2047
2586
  requireAuth();
2048
2587
  const sessionId = randomUUID3();
2049
2588
  printHeader("Ontology Chat");
2050
- console.log(chalk13.gray("\uBA40\uD2F0\uD134 GraphRAG \uB300\uD654. exit\uB85C \uC885\uB8CC.\n"));
2051
- const rl = createInterface6({ input: process.stdin, output: process.stdout });
2052
- const ask = () => new Promise((resolve) => rl.question(chalk13.green("\u276F "), (a) => resolve(a.trim())));
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())));
2053
2592
  while (true) {
2054
2593
  const input = await ask();
2055
2594
  if (!input) continue;
@@ -2063,7 +2602,7 @@ function registerOntologyCommand(program2) {
2063
2602
  ${result.answer}
2064
2603
  `);
2065
2604
  } catch (err) {
2066
- console.log(chalk13.red(`\uC624\uB958: ${err.message}
2605
+ console.log(chalk14.red(`\uC624\uB958: ${err.message}
2067
2606
  `));
2068
2607
  }
2069
2608
  }
@@ -2073,7 +2612,7 @@ ${result.answer}
2073
2612
  try {
2074
2613
  const stats = await getGraphStats(graphId);
2075
2614
  printHeader("\uADF8\uB798\uD504 \uD1B5\uACC4");
2076
- console.log(chalk13.gray(JSON.stringify(stats, null, 2)));
2615
+ console.log(chalk14.gray(JSON.stringify(stats, null, 2)));
2077
2616
  console.log();
2078
2617
  } catch (err) {
2079
2618
  printError(`\uD1B5\uACC4 \uC870\uD68C \uC2E4\uD328: ${err.message}`);
@@ -2082,44 +2621,44 @@ ${result.answer}
2082
2621
  }
2083
2622
 
2084
2623
  // src/index.ts
2085
- init_store();
2624
+ init_home();
2086
2625
  var VERSION = "0.3.0";
2087
- var LOGO = chalk14.cyan(`
2626
+ var LOGO = chalk15.cyan(`
2088
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
2089
2628
  \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588
2090
2629
  \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588
2091
2630
  \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588
2092
2631
  \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588
2093
- `) + chalk14.white.bold(`
2632
+ `) + chalk15.white.bold(`
2094
2633
  \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588 \u2588\u2588
2095
2634
  \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588
2096
2635
  \u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588
2097
2636
  \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588
2098
2637
  \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588
2099
- `) + chalk14.gray(` v${VERSION}
2638
+ `) + chalk15.gray(` v${VERSION}
2100
2639
  `);
2101
2640
  var BANNER = LOGO;
2102
2641
  var program = new Command();
2103
2642
  program.name("xgen").description("OPEN XGEN \u2014 AI Coding Agent + XGEN Platform CLI").version(VERSION).addHelpText("before", BANNER).addHelpText(
2104
2643
  "after",
2105
2644
  `
2106
- ${chalk14.bold("\uC2DC\uC791\uD558\uAE30:")}
2107
- ${chalk14.cyan("xgen provider add")} AI \uD504\uB85C\uBC14\uC774\uB354 \uC124\uC815
2108
- ${chalk14.cyan("xgen agent")} AI \uCF54\uB529 \uC5D0\uC774\uC804\uD2B8
2109
- ${chalk14.cyan("xgen config set-server")} <url> XGEN \uC11C\uBC84 \uC5F0\uACB0
2110
- ${chalk14.cyan("xgen login")} \uC11C\uBC84 \uB85C\uADF8\uC778
2645
+ ${chalk15.bold("\uC2DC\uC791\uD558\uAE30:")}
2646
+ ${chalk15.cyan("xgen provider add")} AI \uD504\uB85C\uBC14\uC774\uB354 \uC124\uC815
2647
+ ${chalk15.cyan("xgen agent")} AI \uCF54\uB529 \uC5D0\uC774\uC804\uD2B8
2648
+ ${chalk15.cyan("xgen config set-server")} <url> XGEN \uC11C\uBC84 \uC5F0\uACB0
2649
+ ${chalk15.cyan("xgen login")} \uC11C\uBC84 \uB85C\uADF8\uC778
2111
2650
 
2112
- ${chalk14.bold("AI \uC5D0\uC774\uC804\uD2B8:")}
2113
- ${chalk14.cyan("xgen agent")} \uCF54\uB529 \uC5D0\uC774\uC804\uD2B8 (\uD30C\uC77C, \uD130\uBBF8\uB110, \uAC80\uC0C9)
2114
- ${chalk14.cyan("xgen provider ls")} \uD504\uB85C\uBC14\uC774\uB354 \uBAA9\uB85D
2115
- ${chalk14.cyan("xgen provider add")} \uD504\uB85C\uBC14\uC774\uB354 \uCD94\uAC00
2651
+ ${chalk15.bold("AI \uC5D0\uC774\uC804\uD2B8:")}
2652
+ ${chalk15.cyan("xgen agent")} \uCF54\uB529 \uC5D0\uC774\uC804\uD2B8 (\uD30C\uC77C, \uD130\uBBF8\uB110, \uAC80\uC0C9)
2653
+ ${chalk15.cyan("xgen provider ls")} \uD504\uB85C\uBC14\uC774\uB354 \uBAA9\uB85D
2654
+ ${chalk15.cyan("xgen provider add")} \uD504\uB85C\uBC14\uC774\uB354 \uCD94\uAC00
2116
2655
 
2117
- ${chalk14.bold("XGEN \uD50C\uB7AB\uD3FC:")}
2118
- ${chalk14.cyan("xgen chat")} \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uB300\uD654
2119
- ${chalk14.cyan("xgen wf ls")} \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D
2120
- ${chalk14.cyan("xgen wf run")} <id> "\uC9C8\uBB38" \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC2E4\uD589
2121
- ${chalk14.cyan("xgen doc ls")} \uBB38\uC11C \uBAA9\uB85D
2122
- ${chalk14.cyan("xgen ont query")} "\uC9C8\uBB38" \uC628\uD1A8\uB85C\uC9C0 \uC9C8\uC758
2656
+ ${chalk15.bold("XGEN \uD50C\uB7AB\uD3FC:")}
2657
+ ${chalk15.cyan("xgen chat")} \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uB300\uD654
2658
+ ${chalk15.cyan("xgen wf ls")} \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D
2659
+ ${chalk15.cyan("xgen wf run")} <id> "\uC9C8\uBB38" \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC2E4\uD589
2660
+ ${chalk15.cyan("xgen doc ls")} \uBB38\uC11C \uBAA9\uB85D
2661
+ ${chalk15.cyan("xgen ont query")} "\uC9C8\uBB38" \uC628\uD1A8\uB85C\uC9C0 \uC9C8\uC758
2123
2662
  `
2124
2663
  );
2125
2664
  registerConfigCommand(program);
@@ -2131,30 +2670,10 @@ registerAgentCommand(program);
2131
2670
  registerDocCommand(program);
2132
2671
  registerOntologyCommand(program);
2133
2672
  if (process.argv.length <= 2) {
2134
- const auth = getAuth();
2135
- const server = getServer();
2136
- const provider = getDefaultProvider();
2137
- if (provider) {
2138
- agentRepl().catch((err) => {
2139
- console.error(chalk14.red(`\uC624\uB958: ${err.message}`));
2140
- process.exit(1);
2141
- });
2142
- } else if (auth && server) {
2143
- chat().catch((err) => {
2144
- console.error(chalk14.red(`\uC624\uB958: ${err.message}`));
2145
- process.exit(1);
2146
- });
2147
- } else {
2148
- console.log(BANNER);
2149
- console.log(chalk14.yellow(" \uC124\uC815\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.\n"));
2150
- console.log(chalk14.bold(" AI \uC5D0\uC774\uC804\uD2B8:"));
2151
- console.log(` ${chalk14.cyan("xgen provider add")} \uD504\uB85C\uBC14\uC774\uB354 \uCD94\uAC00
2152
- `);
2153
- console.log(chalk14.bold(" XGEN \uD50C\uB7AB\uD3FC:"));
2154
- console.log(` ${chalk14.cyan("xgen config set-server")} <url> \uC11C\uBC84 \uC124\uC815`);
2155
- console.log(` ${chalk14.cyan("xgen login")} \uB85C\uADF8\uC778
2156
- `);
2157
- }
2673
+ homeMenu().catch((err) => {
2674
+ console.error(chalk15.red(`\uC624\uB958: ${err.message}`));
2675
+ process.exit(1);
2676
+ });
2158
2677
  } else {
2159
2678
  program.parse();
2160
2679
  }