sales-frontend-gemini-cli 0.4.3 โ†’ 0.4.4

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.
Files changed (41) hide show
  1. package/dist/common/helper.cjs +119 -3
  2. package/dist/common/helper.cjs.map +1 -1
  3. package/dist/common/helper.d.cts +30 -1
  4. package/dist/common/helper.d.ts +30 -1
  5. package/dist/common/helper.js +118 -4
  6. package/dist/common/helper.js.map +1 -1
  7. package/dist/pr-review/claude/claude-commander.cjs +10 -3
  8. package/dist/pr-review/claude/claude-commander.cjs.map +1 -1
  9. package/dist/pr-review/claude/claude-commander.js +10 -3
  10. package/dist/pr-review/claude/claude-commander.js.map +1 -1
  11. package/dist/pr-review/claude/installation-claude.cjs +1 -1
  12. package/dist/pr-review/claude/installation-claude.cjs.map +1 -1
  13. package/dist/pr-review/claude/installation-claude.js +1 -1
  14. package/dist/pr-review/claude/installation-claude.js.map +1 -1
  15. package/dist/pr-review/codex/codex-commander.cjs +14 -4
  16. package/dist/pr-review/codex/codex-commander.cjs.map +1 -1
  17. package/dist/pr-review/codex/codex-commander.d.cts +1 -1
  18. package/dist/pr-review/codex/codex-commander.d.ts +1 -1
  19. package/dist/pr-review/codex/codex-commander.js +14 -4
  20. package/dist/pr-review/codex/codex-commander.js.map +1 -1
  21. package/dist/pr-review/codex/installation-codex.cjs +1 -1
  22. package/dist/pr-review/codex/installation-codex.cjs.map +1 -1
  23. package/dist/pr-review/codex/installation-codex.js +1 -1
  24. package/dist/pr-review/codex/installation-codex.js.map +1 -1
  25. package/dist/pr-review/gemini/gemini-commander.cjs +12 -12
  26. package/dist/pr-review/gemini/gemini-commander.cjs.map +1 -1
  27. package/dist/pr-review/gemini/gemini-commander.js +12 -12
  28. package/dist/pr-review/gemini/gemini-commander.js.map +1 -1
  29. package/dist/pr-review/gemini/installation-gemini.cjs +1 -1
  30. package/dist/pr-review/gemini/installation-gemini.cjs.map +1 -1
  31. package/dist/pr-review/gemini/installation-gemini.js +1 -1
  32. package/dist/pr-review/gemini/installation-gemini.js.map +1 -1
  33. package/dist/pr-review/review-one-by-one.cjs +223 -24
  34. package/dist/pr-review/review-one-by-one.cjs.map +1 -1
  35. package/dist/pr-review/review-one-by-one.js +223 -24
  36. package/dist/pr-review/review-one-by-one.js.map +1 -1
  37. package/dist/pr-review/review.cjs +220 -26
  38. package/dist/pr-review/review.cjs.map +1 -1
  39. package/dist/pr-review/review.js +220 -26
  40. package/dist/pr-review/review.js.map +1 -1
  41. package/package.json +1 -1
@@ -80,6 +80,9 @@ var ignoreList = [
80
80
  function isTestMode(args = process.argv.slice(2)) {
81
81
  return args.includes("--test");
82
82
  }
83
+ function shouldStreamAIOutput(args = process.argv.slice(2)) {
84
+ return args.includes("--stream-output");
85
+ }
83
86
  function clearTraceMessages() {
84
87
  traceMessages.length = 0;
85
88
  }
@@ -249,11 +252,41 @@ async function executeShellCommandWithProgress(command, options = {}) {
249
252
  return;
250
253
  }
251
254
  const exitSummary = signal ? `signal=${signal}` : `code=${String(code ?? "unknown")}`;
252
- reject(new Error(`\uC258 \uBA85\uB839 \uC2E4\uD589 \uC2E4\uD328 (${exitSummary})${stderr.trim() ? `
253
- ${stderr.trim()}` : ""}`));
255
+ const failureDetails = {
256
+ code,
257
+ command,
258
+ signal,
259
+ stderr,
260
+ stdout
261
+ };
262
+ reject(createShellCommandExecutionError(failureDetails, exitSummary));
254
263
  });
255
264
  });
256
265
  }
266
+ function getShellCommandFailurePreview(failureDetails) {
267
+ const stderrText = failureDetails.stderr.trim();
268
+ const stdoutText = failureDetails.stdout.trim();
269
+ const combinedOutput = stderrText || stdoutText;
270
+ if (!combinedOutput) {
271
+ return "";
272
+ }
273
+ const MAX_PREVIEW_LENGTH = 4e3;
274
+ if (combinedOutput.length <= MAX_PREVIEW_LENGTH) {
275
+ return combinedOutput;
276
+ }
277
+ return combinedOutput.slice(-4e3);
278
+ }
279
+ function createShellCommandExecutionError(failureDetails, exitSummary) {
280
+ const failurePreview = getShellCommandFailurePreview(failureDetails);
281
+ const error = new Error(`\uC258 \uBA85\uB839 \uC2E4\uD589 \uC2E4\uD328 (${exitSummary})${failurePreview ? `
282
+ ${failurePreview}` : ""}`);
283
+ error.code = failureDetails.code;
284
+ error.signal = failureDetails.signal;
285
+ error.stdout = failureDetails.stdout;
286
+ error.stderr = failureDetails.stderr;
287
+ error.command = failureDetails.command;
288
+ return error;
289
+ }
257
290
  function formatReviewTargetFiles(files, visibleCount = 5) {
258
291
  if (files.length === 0) {
259
292
  return "(\uC5C6\uC74C)";
@@ -326,7 +359,7 @@ function serializeError(error) {
326
359
  }
327
360
  if (error && typeof error === "object") {
328
361
  const errorLike = error;
329
- const extraKeys = ["code", "errno", "syscall", "path", "cmd", "status", "signal", "spawnargs"];
362
+ const extraKeys = ["code", "errno", "syscall", "path", "cmd", "status", "signal", "spawnargs", "command"];
330
363
  extraKeys.forEach((key) => {
331
364
  if (errorLike[key] !== void 0) {
332
365
  serialized[key] = errorLike[key];
@@ -432,6 +465,87 @@ ${section.markdown}`).join("\n")}
432
465
  return "";
433
466
  }
434
467
  }
468
+ function getExecutionLogSummary(status, title) {
469
+ if (title) {
470
+ return title;
471
+ }
472
+ switch (status) {
473
+ case "success":
474
+ return "\uB9AC\uBDF0 \uC2E4\uD589\uC774 \uC131\uACF5\uC801\uC73C\uB85C \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.";
475
+ case "failed":
476
+ return "\uB9AC\uBDF0 \uC2E4\uD589 \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.";
477
+ case "partial_failure":
478
+ return "\uB9AC\uBDF0 \uC2E4\uD589\uC740 \uC644\uB8CC\uB418\uC5C8\uC9C0\uB9CC \uC77C\uBD80 \uB2E8\uACC4\uC5D0\uC11C \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.";
479
+ default:
480
+ return "\uB9AC\uBDF0 \uC2E4\uD589\uC774 \uCDE8\uC18C\uB418\uC5C8\uAC70\uB098 \uB9AC\uBDF0 \uB300\uC0C1\uC774 \uC5C6\uC5B4 \uC885\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.";
481
+ }
482
+ }
483
+ function formatExecutionDuration(startedAt, finishedAt) {
484
+ const durationMs = Math.max(0, finishedAt.getTime() - startedAt.getTime());
485
+ if (durationMs < 1e3) {
486
+ return `${durationMs}ms`;
487
+ }
488
+ const durationSeconds = durationMs / 1e3;
489
+ if (durationSeconds < 60) {
490
+ return `${durationSeconds.toFixed(1)}s`;
491
+ }
492
+ const minutes = Math.floor(durationSeconds / 60);
493
+ const seconds = Math.round(durationSeconds % 60);
494
+ return `${minutes}m ${seconds}s`;
495
+ }
496
+ function writeExecutionLog(options = {}) {
497
+ try {
498
+ const startedAt = options.startedAt ?? /* @__PURE__ */ new Date();
499
+ const finishedAt = options.finishedAt ?? /* @__PURE__ */ new Date();
500
+ const status = options.status ?? "success";
501
+ helperTrace("execution-log:write:start", options.scope || "unknown");
502
+ createReportDirectory();
503
+ const reportPath = getAvailableFilePath(REPORT_DIR, `${getNowString(finishedAt)}-execution-log`, ".md");
504
+ const traceSnapshot = options.traceMessages ?? getTraceMessages();
505
+ const extraSections = options.extraSections || [];
506
+ const serializedError = options.error ? serializeError(options.error) : null;
507
+ const report = `# Execution Log
508
+
509
+ - \uC2DC\uC791 \uC2DC\uAC01: ${getHumanReadableNowString(startedAt)}
510
+ - \uC885\uB8CC \uC2DC\uAC01: ${getHumanReadableNowString(finishedAt)}
511
+ - \uC2E4\uD589 \uC2DC\uAC04: ${formatExecutionDuration(startedAt, finishedAt)}
512
+ - \uC0C1\uD0DC: \`${status}\`
513
+ - Scope: \`${options.scope || "unknown"}\`
514
+ - \uC791\uC5C5 \uACBD\uB85C: \`${process.cwd()}\`
515
+ - \uC2E4\uD589 \uC778\uC790: \`${JSON.stringify(options.args ?? process.argv.slice(2))}\`
516
+ - \uC2E4\uD589 \uD658\uACBD: \`${process.platform} ${process.arch} / Node ${process.version}\`
517
+
518
+ ## Summary
519
+
520
+ ${getExecutionLogSummary(status, options.title)}
521
+ ${serializedError ? `
522
+
523
+ ## Error
524
+
525
+ \`\`\`json
526
+ ${JSON.stringify(serializedError, null, 2)}
527
+ \`\`\`` : ""}
528
+
529
+ ## Trace
530
+
531
+ \`\`\`json
532
+ ${JSON.stringify(traceSnapshot, null, 2)}
533
+ \`\`\`${extraSections.length ? `
534
+ ${extraSections.map((section) => `
535
+ ## ${section.heading}
536
+
537
+ ${section.markdown}`).join("\n")}
538
+ ` : "\n"}
539
+ `;
540
+ fs__default.default.writeFileSync(reportPath, report);
541
+ helperTrace("execution-log:write:done", reportPath);
542
+ return reportPath;
543
+ } catch (writeError) {
544
+ console.error("\u26A0\uFE0F \uC2E4\uD589 \uB85C\uADF8 \uD30C\uC77C \uC0DD\uC131\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.");
545
+ console.error(writeError);
546
+ return "";
547
+ }
548
+ }
435
549
  function exitWithError(message, options = {}) {
436
550
  const reportPath = writeErrorReport(options.error || new Error(message), {
437
551
  ...options,
@@ -882,9 +996,11 @@ exports.reviewFormPath = reviewFormPath;
882
996
  exports.rulesPath = rulesPath;
883
997
  exports.selectAIService = selectAIService;
884
998
  exports.selectReviewCommits = selectReviewCommits;
999
+ exports.shouldStreamAIOutput = shouldStreamAIOutput;
885
1000
  exports.showMultiSelect = showMultiSelect;
886
1001
  exports.showSelectionAIService = showSelectionAIService;
887
1002
  exports.tempDiffPath = tempDiffPath;
888
1003
  exports.writeErrorReport = writeErrorReport;
1004
+ exports.writeExecutionLog = writeExecutionLog;
889
1005
  //# sourceMappingURL=helper.cjs.map
890
1006
  //# sourceMappingURL=helper.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/common/helper.ts"],"names":["__dirname","path","fileURLToPath","fs","execFileSync","inspect","execSync","readline"],"mappings":"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","file":"helper.cjs","sourcesContent":["import { execFileSync, execSync } from 'child_process';\nimport fs from 'fs';\nimport path from 'path';\nimport readline from 'readline';\nimport { fileURLToPath } from 'url';\nimport { inspect } from 'util';\n\nimport { AIServiceType, CommitOption, MultiSelectOption } from './types';\n\ntype ErrorReportSection = {\n heading: string;\n markdown: string;\n};\n\ntype WriteErrorReportOptions = {\n title?: string;\n scope?: string;\n args?: string[];\n traceMessages?: string[];\n extraSections?: ErrorReportSection[];\n};\n\ntype GitCommandOptions = {\n allowFailure?: boolean;\n trimOutput?: boolean;\n};\n\ntype ShellCommandProgressOptions = {\n progressIntervalMs?: number;\n progressMessage?: string;\n streamOutput?: boolean;\n};\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst traceMessages: string[] = [];\nconst GEMINI_CLI_PACKAGE_NAME = 'sales-frontend-gemini-cli';\nlet cachedPackageRootPath = '';\n\n/**\n * @description\n * ํ˜„์žฌ ๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ gemini-cli ํŒจํ‚ค์ง€ ๋ฃจํŠธ์ธ์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.\n * ๋ฒˆ๋“ค ๊ฒฐ๊ณผ๋ฌผ์—์„œ helper ์ฝ”๋“œ๊ฐ€ ๊ฐ ์—”ํŠธ๋ฆฌ ํŒŒ์ผ๋กœ ์ธ๋ผ์ธ๋˜๋ฉด `__dirname` ๊ธฐ์ค€์ ์ด ๋‹ฌ๋ผ์ง€๋ฏ€๋กœ,\n * package.json ์ด๋ฆ„์œผ๋กœ ์‹ค์ œ ํŒจํ‚ค์ง€ ๋ฃจํŠธ๋ฅผ ์‹๋ณ„ํ•ด์•ผ ๊ทœ์น™/์–‘์‹ ํŒŒ์ผ ๊ฒฝ๋กœ๊ฐ€ ๊นจ์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค.\n * @param directory ๊ฒ€์‚ฌํ•  ๋””๋ ‰ํ„ฐ๋ฆฌ ๊ฒฝ๋กœ\n * @returns ํ˜„์žฌ ๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ gemini-cli ํŒจํ‚ค์ง€ ๋ฃจํŠธ์ด๋ฉด true\n */\nfunction isGeminiCliPackageRoot(directory: string) {\n const packageJsonPath = path.join(directory, 'package.json');\n\n if (!fs.existsSync(packageJsonPath)) {\n return false;\n }\n\n try {\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')) as { name?: string };\n\n return packageJson.name === GEMINI_CLI_PACKAGE_NAME;\n } catch {\n return false;\n }\n}\n\n/**\n * @description\n * ํ˜„์žฌ ์‹คํ–‰ ์ค‘์ธ ๋ฒˆ๋“ค ์—”ํŠธ๋ฆฌ ๊ธฐ์ค€์œผ๋กœ gemini-cli ํŒจํ‚ค์ง€ ๋ฃจํŠธ๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค.\n * `dist/pr-review/review.js`, `dist/pr-review/gemini/gemini-commander.js`์ฒ˜๋Ÿผ\n * ์—”ํŠธ๋ฆฌ ์œ„์น˜๊ฐ€ ๋‹ฌ๋ผ๋„ ์ƒ์œ„ ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ์ˆœํšŒํ•˜๋ฉฐ package root๋ฅผ ์ฐพ๋„๋ก ์„ค๊ณ„ํ•ฉ๋‹ˆ๋‹ค.\n * @param startDirectory ํŒจํ‚ค์ง€ ๋ฃจํŠธ ํƒ์ƒ‰์„ ์‹œ์ž‘ํ•  ๋””๋ ‰ํ„ฐ๋ฆฌ\n * @returns ๊ทœ์น™/์–‘์‹ ํŒŒ์ผ์ด ์กด์žฌํ•˜๋Š” gemini-cli ํŒจํ‚ค์ง€ ๋ฃจํŠธ ๊ฒฝ๋กœ\n */\nfunction resolveGeminiCliPackageRoot(startDirectory: string = __dirname) {\n if (cachedPackageRootPath) {\n return cachedPackageRootPath;\n }\n\n let currentDirectory = startDirectory;\n\n while (true) {\n if (isGeminiCliPackageRoot(currentDirectory)) {\n cachedPackageRootPath = currentDirectory;\n\n return cachedPackageRootPath;\n }\n\n const parentDirectory = path.dirname(currentDirectory);\n\n if (parentDirectory === currentDirectory) {\n break;\n }\n\n currentDirectory = parentDirectory;\n }\n\n /**\n * @description\n * package.json ํƒ์ƒ‰์ด ์‹คํŒจํ•ด๋„ ๊ธฐ์กด ์„ค์น˜ ๊ตฌ์กฐ(dist/common -> package root)๋ฅผ ์šฐ์„  fallback์œผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.\n * ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋ฐฐํฌ ํ™˜๊ฒฝ์—์„œ๋„ ์ตœ๋Œ€ํ•œ ๊ธฐ์กด ๋™์ž‘์„ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•œ ๋ณด์ˆ˜์  ์•ˆ์ „์žฅ์น˜์ž…๋‹ˆ๋‹ค.\n */\n cachedPackageRootPath = path.resolve(startDirectory, '../..');\n\n return cachedPackageRootPath;\n}\n\n/**\n * @description\n * gemini-cli ํŒจํ‚ค์ง€ ๋ฃจํŠธ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ •์  asset ํŒŒ์ผ์˜ ์ ˆ๋Œ€ ๊ฒฝ๋กœ๋ฅผ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค.\n * ๋ฒˆ๋“ค ๊ณผ์ •์—์„œ helper ์ฝ”๋“œ๊ฐ€ ๋‹ค๋ฅธ ์—”ํŠธ๋ฆฌ์— ์ธ๋ผ์ธ๋˜์–ด๋„ ํ•ญ์ƒ ๊ฐ™์€ ์‹ค์ œ ํŒŒ์ผ์„ ๊ฐ€๋ฆฌํ‚ค๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.\n * @param relativeFilePath ํŒจํ‚ค์ง€ ๋ฃจํŠธ ๊ธฐ์ค€ ์ƒ๋Œ€ ๊ฒฝ๋กœ\n * @returns asset ํŒŒ์ผ์˜ ์ ˆ๋Œ€ ๊ฒฝ๋กœ\n */\nfunction resolvePackageAssetPath(relativeFilePath: string) {\n return path.resolve(resolveGeminiCliPackageRoot(), relativeFilePath);\n}\n\nexport const rulesPath = resolvePackageAssetPath('src/common/rules/review-rules.md');\nexport const namingRulesPath = resolvePackageAssetPath('src/common/rules/naming-rule.md');\nexport const codingConventionRulesPath = resolvePackageAssetPath('src/common/rules/coding-convention.md');\nexport const reviewFormPath = resolvePackageAssetPath('src/common/form/review-form.md');\nexport const reviewFormOneByOnePath = resolvePackageAssetPath('src/common/form/review-form-one-by-one.md');\nexport const REPORT_DIR = '.review-report';\nexport const tempDiffPath = 'temp_diff.txt';\nexport const AIServices: AIServiceType[] = ['gemini', 'claude', 'codex'];\nexport const COMMIT_FETCH_LIMIT = 20;\nexport const COMMIT_SELECTION_WINDOW = 8;\nexport const ignoreList = [\n 'package.json',\n '*.yml',\n '*.md',\n '*.lock',\n 'dist/',\n 'node_modules/',\n 'assets/',\n 'public/',\n '*.json',\n '*.yaml',\n '.review-report/' // ์ƒ์„ฑ๋˜๋Š” ๋ฆฌํฌํŠธ ํด๋”๋„ ์ œ์™ธ\n];\n\nexport function isTestMode(args: string[] = process.argv.slice(2)) {\n return args.includes('--test');\n}\n\nexport function clearTraceMessages() {\n traceMessages.length = 0;\n}\n\nexport function getTraceMessages() {\n return [...traceMessages];\n}\n\n/**\n * @description\n * ํ„ฐ๋ฏธ๋„ ์„ ํƒ UI์—์„œ ๋™์ผํ•œ ์ƒ‰์ƒ ํ† ํฐ์„ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ANSI escape code๋ฅผ ์ƒ์ˆ˜ํ™”ํ•ฉ๋‹ˆ๋‹ค.\n * ์„œ๋น„์Šค ์„ ํƒ๊ณผ ์ปค๋ฐ‹ ์„ ํƒ์ด ๊ฐ™์€ ์‹œ๊ฐ ์–ธ์–ด๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก helper ๋‚ด๋ถ€์—์„œ๋งŒ ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค.\n */\nconst ANSI = {\n bold: '\\u001b[1m',\n cyan: '\\u001b[36m',\n dim: '\\u001b[2m',\n green: '\\u001b[32m',\n reset: '\\u001b[0m',\n yellow: '\\u001b[33m'\n} as const;\nconst ANSI_PATTERN = new RegExp(`${String.fromCharCode(27)}\\\\[[0-9;]*m`, 'g');\nconst COMBINING_MARK_PATTERN = /\\p{Mark}/u;\nconst GRAPHEME_SEGMENTER =\n typeof Intl !== 'undefined' && 'Segmenter' in Intl ? new Intl.Segmenter('ko', { granularity: 'grapheme' }) : null;\n\ntype VisibleToken = {\n value: string;\n visibleWidth: number;\n};\n\n/**\n * @description\n * ๋ฆฌ๋ทฐ ๋Œ€์ƒ ํŒŒ์ผ ํ•„ํ„ฐ๋ฅผ pathspec ๋ฐฐ์—ด ํ˜•ํƒœ๋กœ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.\n * ๋ฌธ์ž์—ด ์ปค๋งจ๋“œ์™€ argv ๊ธฐ๋ฐ˜ git ์‹คํ–‰์ด ๋ชจ๋‘ ๊ฐ™์€ ๊ธฐ์ค€์„ ๊ณต์œ ํ•˜๋„๋ก ์›๋ณธ ํŒจํ„ด์€ ๋ฐฐ์—ด๋กœ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.\n */\nfunction getGitDiffPathspecs() {\n return {\n excludePatterns: ignoreList.map((item) => `:(exclude)${item}`),\n includePatterns: ['*.ts', '*.tsx', '*.js', '*.jsx']\n };\n}\n\nfunction segmentGraphemes(value: string) {\n if (!GRAPHEME_SEGMENTER) {\n return [...value];\n }\n\n return [...GRAPHEME_SEGMENTER.segment(value)].map(({ segment }) => segment);\n}\n\nfunction isWideCodePoint(codePoint: number) {\n return (\n codePoint >= 0x1100 &&\n (codePoint <= 0x115f ||\n codePoint === 0x2329 ||\n codePoint === 0x232a ||\n (codePoint >= 0x2e80 && codePoint <= 0x3247 && codePoint !== 0x303f) ||\n (codePoint >= 0x3250 && codePoint <= 0x4dbf) ||\n (codePoint >= 0x4e00 && codePoint <= 0xa4c6) ||\n (codePoint >= 0xa960 && codePoint <= 0xa97c) ||\n (codePoint >= 0xac00 && codePoint <= 0xd7a3) ||\n (codePoint >= 0xf900 && codePoint <= 0xfaff) ||\n (codePoint >= 0xfe10 && codePoint <= 0xfe19) ||\n (codePoint >= 0xfe30 && codePoint <= 0xfe6b) ||\n (codePoint >= 0xff01 && codePoint <= 0xff60) ||\n (codePoint >= 0xffe0 && codePoint <= 0xffe6) ||\n (codePoint >= 0x1f200 && codePoint <= 0x1f251) ||\n (codePoint >= 0x20000 && codePoint <= 0x3fffd))\n );\n}\n\nfunction isEmojiCodePoint(codePoint: number) {\n return (\n (codePoint >= 0x1f1e6 && codePoint <= 0x1f1ff) ||\n (codePoint >= 0x1f300 && codePoint <= 0x1faff) ||\n (codePoint >= 0x2600 && codePoint <= 0x27bf)\n );\n}\n\nfunction getGraphemeWidth(grapheme: string) {\n let width = 0;\n\n for (const character of grapheme) {\n const codePoint = character.codePointAt(0);\n\n if (!codePoint || COMBINING_MARK_PATTERN.test(character) || codePoint === 0x200d) {\n continue;\n }\n\n if ((codePoint >= 0xfe00 && codePoint <= 0xfe0f) || (codePoint >= 0xe0100 && codePoint <= 0xe01ef)) {\n continue;\n }\n\n if (isWideCodePoint(codePoint) || isEmojiCodePoint(codePoint)) {\n width = Math.max(width, 2);\n\n continue;\n }\n\n width = Math.max(width, 1);\n }\n\n return width;\n}\n\nfunction tokenizePlainText(value: string) {\n return segmentGraphemes(value).map((segment) => ({\n value: segment,\n visibleWidth: getGraphemeWidth(segment)\n }));\n}\n\nfunction tokenizeVisibleText(value: string) {\n const tokens: VisibleToken[] = [];\n let lastIndex = 0;\n\n for (const match of value.matchAll(ANSI_PATTERN)) {\n const index = match.index ?? 0;\n\n if (index > lastIndex) {\n tokens.push(...tokenizePlainText(value.slice(lastIndex, index)));\n }\n\n tokens.push({\n value: match[0],\n visibleWidth: 0\n });\n lastIndex = index + match[0].length;\n }\n\n if (lastIndex < value.length) {\n tokens.push(...tokenizePlainText(value.slice(lastIndex)));\n }\n\n return tokens;\n}\n\n/**\n * @description\n * ๋ชจ๋‹ฌ ๊ฐ ์ค„์ด ํ„ฐ๋ฏธ๋„ ์‹ค์ œ ํญ์„ ๋„˜์ง€ ์•Š๋„๋ก ANSI ์ฝ”๋“œ๋ฅผ ๋ณด์กดํ•œ ์ฑ„ ์ž˜๋ผ๋ƒ…๋‹ˆ๋‹ค.\n * ์ค„๋ฐ”๊ฟˆ์ด ๋ฐœ์ƒํ•˜๋ฉด ๋ Œ๋” ์ค„ ์ˆ˜ ๊ณ„์‚ฐ์ด ์–ด๊ธ‹๋‚˜๋ฏ€๋กœ, ๋ชจ๋“  ์„ ํƒ ์ค„์„ 1 physical line๋กœ ๊ฐ•์ œํ•ฉ๋‹ˆ๋‹ค.\n * @param value ๋ Œ๋”ํ•  ๋ฌธ์ž์—ด\n * @param maxWidth ํ—ˆ์šฉ ์ตœ๋Œ€ ํ‘œ์‹œ ํญ\n * @returns ํ„ฐ๋ฏธ๋„ ํญ ์•ˆ์œผ๋กœ ์ •๋ฆฌ๋œ ๋ฌธ์ž์—ด\n */\nfunction truncateLineForTerminal(value: string, maxWidth: number) {\n if (maxWidth <= 0) {\n return '';\n }\n\n const tokens = tokenizeVisibleText(value);\n const totalWidth = tokens.reduce((sum, token) => sum + token.visibleWidth, 0);\n\n if (totalWidth <= maxWidth) {\n return value;\n }\n\n const ellipsis = '...';\n const ellipsisWidth = 3;\n const targetWidth = Math.max(0, maxWidth - ellipsisWidth);\n let usedWidth = 0;\n let result = '';\n\n for (const token of tokens) {\n if (token.visibleWidth === 0) {\n result += token.value;\n\n continue;\n }\n\n if (usedWidth + token.visibleWidth > targetWidth) {\n break;\n }\n\n result += token.value;\n usedWidth += token.visibleWidth;\n }\n\n return `${result}${ellipsis}${ANSI.reset}`;\n}\n\nfunction fitLinesToTerminal(lines: string[]) {\n const maxWidth = Math.max(20, (process.stdout.columns || 120) - 1);\n\n return lines.map((line) => truncateLineForTerminal(line, maxWidth));\n}\n\n/**\n * @description\n * git ์„œ๋ธŒํ”„๋กœ์„ธ์Šค๋ฅผ argv ๋ฐฐ์—ด ๊ธฐ๋ฐ˜์œผ๋กœ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.\n * ์ปค๋ฐ‹ ํ•ด์‹œ๋‚˜ ํŒŒ์ผ ๊ฒฝ๋กœ์— ๊ณต๋ฐฑ์ด ์„ž์—ฌ๋„ shell quoting ๋ฌธ์ œ ์—†์ด ๋™์ผํ•œ ๋™์ž‘์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด ๊ณตํ†ต helper๋กœ ๋ถ„๋ฆฌํ•ฉ๋‹ˆ๋‹ค.\n * @param args git ์ธ์ž ๋ฐฐ์—ด\n * @param options ์‹คํŒจ ํ—ˆ์šฉ ์—ฌ๋ถ€์™€ ์ถœ๋ ฅ trim ์—ฌ๋ถ€\n * @returns git ํ‘œ์ค€์ถœ๋ ฅ ๋ฌธ์ž์—ด\n */\nfunction runGitCommand(args: string[], options: GitCommandOptions = {}) {\n const { allowFailure = false, trimOutput = true } = options;\n\n try {\n const output = execFileSync('git', args, {\n encoding: 'utf8',\n maxBuffer: 1024 * 1024 * 20,\n stdio: ['ignore', 'pipe', 'pipe']\n });\n\n return trimOutput ? output.trim() : output;\n } catch (error) {\n helperTrace('git-command:failed', `${args.join(' ')} | ${getErrorSummary(error)}`);\n\n if (allowFailure) {\n return '';\n }\n\n throw error;\n }\n}\n\n/**\n * @description\n * shell ๋ช…๋ น์„ ๋น„๋™๊ธฐ๋กœ ์‹คํ–‰ํ•˜๋ฉด์„œ stdout/stderr๋ฅผ ๊ทธ๋Œ€๋กœ ํ˜๋ ค๋ณด๋‚ด๊ณ , ์žฅ์‹œ๊ฐ„ ์ž‘์—…์—๋Š” ๊ฒฝ๊ณผ ์‹œ๊ฐ„์„ ์ฃผ๊ธฐ์ ์œผ๋กœ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.\n * review ์‹คํ–‰์ฒ˜๋Ÿผ ์‘๋‹ต ์ƒ์„ฑ๊นŒ์ง€ ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” CLI๋ฅผ ๋ฒ„ํผ๋ง ์—†์ด ๊ธฐ๋‹ค๋ฆฌ๊ฒŒ ํ•ด ์‚ฌ์šฉ์ž๊ฐ€ ๋ฉˆ์ถค์œผ๋กœ ์˜คํ•ดํ•˜์ง€ ์•Š๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.\n * @param command ์‹คํ–‰ํ•  shell command ๋ฌธ์ž์—ด\n * @param options ์ง„ํ–‰ ๋ฉ”์‹œ์ง€์™€ ์ถœ๋ ฅ ์ฃผ๊ธฐ ์˜ต์…˜\n * @returns ์ตœ์ข… stdout/stderr ์บก์ฒ˜ ๊ฒฐ๊ณผ\n */\nexport async function executeShellCommandWithProgress(command: string, options: ShellCommandProgressOptions = {}) {\n const { progressIntervalMs = 10000, progressMessage = 'โณ ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๋Š” ์ค‘์ž…๋‹ˆ๋‹ค...', streamOutput = false } = options;\n const { spawn } = await import('child_process');\n\n return new Promise<{ stderr: string; stdout: string }>((resolve, reject) => {\n let stdout = '';\n let stderr = '';\n const startedAt = Date.now();\n console.log(progressMessage);\n\n const child = spawn('/bin/zsh', ['-lc', command], {\n stdio: ['ignore', 'pipe', 'pipe']\n });\n\n const progressTimer = setInterval(() => {\n const elapsedSeconds = Math.max(1, Math.floor((Date.now() - startedAt) / 1000));\n console.log(`${progressMessage} (${elapsedSeconds}s ๊ฒฝ๊ณผ)`);\n }, progressIntervalMs);\n\n child.stdout.on('data', (chunk: Buffer | string) => {\n const text = chunk.toString();\n stdout += text;\n\n if (streamOutput) {\n process.stdout.write(text);\n }\n });\n\n child.stderr.on('data', (chunk: Buffer | string) => {\n const text = chunk.toString();\n stderr += text;\n\n if (streamOutput) {\n process.stderr.write(text);\n }\n });\n\n child.on('error', (error) => {\n clearInterval(progressTimer);\n reject(error);\n });\n\n child.on('close', (code, signal) => {\n clearInterval(progressTimer);\n\n if (code === 0) {\n resolve({\n stderr,\n stdout\n });\n\n return;\n }\n\n const exitSummary = signal ? `signal=${signal}` : `code=${String(code ?? 'unknown')}`;\n reject(new Error(`์‰˜ ๋ช…๋ น ์‹คํ–‰ ์‹คํŒจ (${exitSummary})${stderr.trim() ? `\\n${stderr.trim()}` : ''}`));\n });\n });\n}\n\n/**\n * @description\n * ๋ฆฌ๋ทฐ ๋Œ€์ƒ ํŒŒ์ผ ๋ชฉ๋ก์„ ํ•œ ์ค„ ์š”์•ฝ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.\n * ํŒŒ์ผ์ด ๋งŽ์„ ๋•Œ๋Š” ์ผ๋ถ€๋งŒ ๋…ธ์ถœํ•˜๊ณ  ๋‚˜๋จธ์ง€๋Š” ๊ฐœ์ˆ˜๋กœ ์ถ•์•ฝํ•ด ํ„ฐ๋ฏธ๋„ ์ถœ๋ ฅ์ด ๊ณผ๋„ํ•˜๊ฒŒ ๊ธธ์–ด์ง€์ง€ ์•Š๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.\n * @param files ๋ฆฌ๋ทฐ ๋Œ€์ƒ ํŒŒ์ผ ๋ชฉ๋ก\n * @param visibleCount ํ„ฐ๋ฏธ๋„์— ์ง์ ‘ ๋ณด์—ฌ์ค„ ์ตœ๋Œ€ ํŒŒ์ผ ์ˆ˜\n * @returns ํ™”๋ฉด ํ‘œ์‹œ์šฉ ์š”์•ฝ ๋ฌธ์ž์—ด\n */\nexport function formatReviewTargetFiles(files: string[], visibleCount = 5) {\n if (files.length === 0) {\n return '(์—†์Œ)';\n }\n\n const visibleFiles = files.slice(0, visibleCount);\n const hiddenCount = Math.max(0, files.length - visibleFiles.length);\n\n if (hiddenCount === 0) {\n return visibleFiles.join(', ');\n }\n\n return `${visibleFiles.join(', ')} ์™ธ ${hiddenCount}๊ฐœ`;\n}\n\nexport function createTraceLogger(scope: string, args: string[] = process.argv.slice(2)) {\n const enabled = isTestMode(args);\n\n return (step: string, detail?: string) => {\n const timestamp = new Date().toISOString();\n const message = `[${timestamp}][TRACE][${scope}] ${step}${detail ? ` | ${detail}` : ''}`;\n traceMessages.push(message);\n\n if (!enabled) {\n return;\n }\n\n console.log(message);\n };\n}\n\nconst helperTrace = createTraceLogger('helper');\n\nfunction getTimestampParts(now = new Date()) {\n return {\n YYYY: now.getFullYear(),\n MM: String(now.getMonth() + 1).padStart(2, '0'),\n DD: String(now.getDate()).padStart(2, '0'),\n HH: String(now.getHours()).padStart(2, '0'),\n mm: String(now.getMinutes()).padStart(2, '0'),\n ss: String(now.getSeconds()).padStart(2, '0')\n };\n}\n\nfunction getHumanReadableNowString(now = new Date()) {\n const { YYYY, MM, DD, HH, mm, ss } = getTimestampParts(now);\n\n return `${YYYY}-${MM}-${DD} ${HH}:${mm}:${ss}`;\n}\n\nfunction stringifyUnknown(value: unknown) {\n if (value === undefined || value === null) {\n return '';\n }\n\n if (typeof value === 'string') {\n return value;\n }\n\n if (Buffer.isBuffer(value)) {\n return value.toString();\n }\n\n if (value instanceof Error) {\n return value.stack || value.message;\n }\n\n return inspect(value, { depth: 5, breakLength: 120 });\n}\n\nexport function getErrorSummary(error: unknown) {\n if (error instanceof Error) {\n return `${error.name}: ${error.message}`;\n }\n\n return stringifyUnknown(error) || 'Unknown error';\n}\n\nfunction serializeError(error: unknown) {\n const serialized: Record<string, unknown> = {\n summary: getErrorSummary(error)\n };\n\n if (error instanceof Error) {\n serialized.name = error.name;\n serialized.message = error.message;\n serialized.stack = error.stack;\n } else {\n serialized.value = stringifyUnknown(error);\n }\n\n if (error && typeof error === 'object') {\n const errorLike = error as Record<string, unknown>;\n const extraKeys = ['code', 'errno', 'syscall', 'path', 'cmd', 'status', 'signal', 'spawnargs'];\n\n extraKeys.forEach((key) => {\n if (errorLike[key] !== undefined) {\n serialized[key] = errorLike[key];\n }\n });\n\n const stdout = stringifyUnknown(errorLike.stdout);\n if (stdout) {\n serialized.stdout = stdout;\n }\n\n const stderr = stringifyUnknown(errorLike.stderr);\n if (stderr) {\n serialized.stderr = stderr;\n }\n\n const cause = stringifyUnknown(errorLike.cause);\n if (cause) {\n serialized.cause = cause;\n }\n }\n\n return serialized;\n}\n\nexport function getNextFilePath(dir: string, baseName: string, extension: string) {\n let counter = 1;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const filePath = path.join(dir, `${baseName}-${counter}${extension}`);\n if (!fs.existsSync(filePath)) {\n return filePath;\n }\n counter++;\n }\n}\n\nexport function getAvailableFilePath(dir: string, baseName: string, extension: string) {\n const firstFilePath = path.join(dir, `${baseName}${extension}`);\n if (!fs.existsSync(firstFilePath)) {\n return firstFilePath;\n }\n\n return getNextFilePath(dir, baseName, extension);\n}\n\nexport function deleteFile(filePath: string) {\n if (fs.existsSync(filePath)) {\n fs.unlinkSync(filePath);\n }\n}\n\n/**\n * ์ž„์‹œํŒŒ์ผ ์‚ญ์ œ\n */\nexport function deleteTempDiff() {\n deleteFile(tempDiffPath);\n}\n\n/**\n * ๋ฆฌ๋ทฐ ๊ฒฐ๊ณผ ํด๋” ์ƒ์„ฑ\n */\nexport function createReportDirectory() {\n if (!fs.existsSync(REPORT_DIR)) {\n fs.mkdirSync(REPORT_DIR, { recursive: true });\n }\n}\n\n/**\n * ํ˜„์žฌ ์‹œ๊ฐ„ ๋ฌธ์ž์—ด ์ƒ์„ฑ\n */\nexport function getNowString(now = new Date()) {\n const { YYYY, MM, DD, HH, mm, ss } = getTimestampParts(now);\n\n return `${YYYY}-${MM}-${DD}_${HH}-${mm}-${ss}`;\n}\n\nexport function getErrorLogTimestamp(now = new Date()) {\n const { YYYY, MM, DD, HH, mm, ss } = getTimestampParts(now);\n\n return `${YYYY}-${MM}-${DD}-${HH}์‹œ-${mm}๋ถ„-${ss}์ดˆ`;\n}\n\nexport function writeErrorReport(error: unknown, options: WriteErrorReportOptions = {}) {\n try {\n const now = new Date();\n helperTrace('error-report:write:start', options.scope || 'unknown');\n createReportDirectory();\n\n const reportPath = getAvailableFilePath(REPORT_DIR, `error-log-${getErrorLogTimestamp(now)}`, '.md');\n const serializedError = serializeError(error);\n const traceSnapshot = options.traceMessages ?? getTraceMessages();\n const extraSections = options.extraSections || [];\n\n const report = `# Error Log\n\n- ๋ฐœ์ƒ ์‹œ๊ฐ: ${getHumanReadableNowString(now)}\n- Scope: \\`${options.scope || 'unknown'}\\`\n- ์ž‘์—… ๊ฒฝ๋กœ: \\`${process.cwd()}\\`\n- ์‹คํ–‰ ์ธ์ž: \\`${JSON.stringify(options.args ?? process.argv.slice(2))}\\`\n- ์‹คํ–‰ ํ™˜๊ฒฝ: \\`${process.platform} ${process.arch} / Node ${process.version}\\`\n\n## Summary\n\n${options.title || serializedError.summary || 'Unknown error'}\n\n## Error\n\n\\`\\`\\`json\n${JSON.stringify(serializedError, null, 2)}\n\\`\\`\\`\n\n## Trace\n\n\\`\\`\\`json\n${JSON.stringify(traceSnapshot, null, 2)}\n\\`\\`\\`${extraSections.length ? `\\n${extraSections.map((section) => `\\n## ${section.heading}\\n\\n${section.markdown}`).join('\\n')}\\n` : '\\n'}\n`;\n\n fs.writeFileSync(reportPath, report);\n helperTrace('error-report:write:done', reportPath);\n\n return reportPath;\n } catch (writeError) {\n console.error('โš ๏ธ ์—๋Ÿฌ ๋กœ๊ทธ ํŒŒ์ผ ์ƒ์„ฑ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.');\n console.error(writeError);\n\n return '';\n }\n}\n\nexport function exitWithError(\n message: string,\n options: Omit<WriteErrorReportOptions, 'title'> & { error?: unknown } = {}\n): never {\n const reportPath = writeErrorReport(options.error || new Error(message), {\n ...options,\n title: message\n });\n\n console.error(message);\n\n if (options.error) {\n console.error(options.error);\n }\n\n if (reportPath) {\n console.error(`๐Ÿ“„ ์—๋Ÿฌ ๋กœ๊ทธ ์ €์žฅ ์œ„์น˜: ${reportPath}`);\n }\n\n process.exit(1);\n}\n\nfunction parseServiceFromArgs(args: string[] = process.argv.slice(2)): AIServiceType | '' {\n helperTrace('parse-service:start', `args=${JSON.stringify(args)}`);\n const serviceIndex = args.indexOf('--service');\n const rawService = serviceIndex !== -1 ? args[serviceIndex + 1] : '';\n\n if (!rawService) {\n helperTrace('parse-service:empty');\n\n return '';\n }\n\n const normalizedService = rawService.toLowerCase();\n\n if (AIServices.includes(normalizedService as AIServiceType)) {\n helperTrace('parse-service:resolved', normalizedService);\n\n return normalizedService as AIServiceType;\n }\n\n helperTrace('parse-service:invalid', rawService);\n exitWithError(\n `โŒ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค: ${rawService}. ์‚ฌ์šฉ ๊ฐ€๋Šฅ ๊ฐ’: ${AIServices.join(', ')} (์˜ˆ: --service codex)`,\n {\n scope: 'helper:parseServiceFromArgs',\n args,\n extraSections: [\n {\n heading: 'Allowed Services',\n markdown: `\\`\\`\\`json\\n${JSON.stringify(AIServices, null, 2)}\\n\\`\\`\\``\n }\n ]\n }\n );\n}\n\nexport function getGitDiffFilter() {\n const { includePatterns, excludePatterns } = getGitDiffPathspecs();\n const quote = (pattern: string) => `\"${pattern}\"`;\n const includeParams = includePatterns.map(quote).join(' ');\n const excludeParams = excludePatterns.map(quote).join(' ');\n\n return { includeParams, excludeParams };\n}\n\n/**\n * @description\n * ์ปค๋ฐ‹ ์„ ํƒ ๋ชฉ๋ก์—์„œ subject๊ฐ€ ๊ณผํ•˜๊ฒŒ ๊ธธ์–ด์ง€๋Š” ๊ฒƒ์„ ๋ง‰๊ธฐ ์œ„ํ•ด ํ‘œ์‹œ ๊ธธ์ด๋ฅผ ์ œํ•œํ•ฉ๋‹ˆ๋‹ค.\n * commit hash์™€ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋Š” ๋ณ„๋„ ํ•„๋“œ๋กœ ์œ ์ง€ํ•˜๋ฏ€๋กœ UI ๊ฐ€๋…์„ฑ์— ํ•„์š”ํ•œ subject๋งŒ ์ž๋ฆ…๋‹ˆ๋‹ค.\n * @param subject ์›๋ณธ ์ปค๋ฐ‹ ์ œ๋ชฉ\n * @returns ํ™”๋ฉด ํ‘œ์‹œ์šฉ ์ œ๋ชฉ\n */\nfunction truncateCommitSubject(subject: string) {\n if (subject.length <= 72) {\n return subject;\n }\n\n return `${subject.slice(0, 69)}...`;\n}\n\n/**\n * @description\n * ์ตœ๊ทผ ์ปค๋ฐ‹ ๋ชฉ๋ก์„ ๋ฆฌ๋ทฐ ์„ ํƒ UI์—์„œ ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.\n * git log ํฌ๋งท์„ ํ•œ ๊ณณ์—์„œ ๊ด€๋ฆฌํ•ด main review์™€ one-by-one review๊ฐ€ ๊ฐ™์€ ์ปค๋ฐ‹ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.\n * @returns ์ตœ๊ทผ ์ปค๋ฐ‹ ์˜ต์…˜ ๋ชฉ๋ก\n */\nexport function getRecentCommitOptions(): CommitOption[] {\n const output = runGitCommand(\n ['log', `-${COMMIT_FETCH_LIMIT}`, '--date=relative', '--pretty=format:%h%x09%an%x09%ar%x09%s'],\n { allowFailure: true }\n );\n\n if (!output) {\n return [];\n }\n\n return output.split('\\n').map((line) => {\n const [hash = '', author = '', relativeDate = '', ...subjectParts] = line.split('\\t');\n const subject = subjectParts.join('\\t').trim();\n\n return {\n author,\n description: `${author} | ${relativeDate}`,\n hash,\n label: `${hash} | ${truncateCommitSubject(subject)}`,\n relativeDate,\n subject\n };\n });\n}\n\n/**\n * @description\n * ์„ ํƒ๋œ ์ปค๋ฐ‹ ๋ชฉ๋ก์„ ๋ฆฌํฌํŠธ ๋ฐ diff ํ—ค๋”์— ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” markdown bullet ๋ฌธ์ž์—ด๋กœ ์ •๋ฆฌํ•ฉ๋‹ˆ๋‹ค.\n * @param commits ์‚ฌ์šฉ์ž๊ฐ€ ๊ณ ๋ฅธ ์ปค๋ฐ‹ ๋ชฉ๋ก\n * @returns ์ปค๋ฐ‹ ์š”์•ฝ markdown\n */\nexport function buildSelectedCommitSummary(commits: CommitOption[]) {\n return commits.map((commit) => `- ${commit.hash} | ${commit.subject} | ${commit.author} | ${commit.relativeDate}`).join('\\n');\n}\n\n/**\n * @description\n * ๋ฆฌ๋ทฐ ๋Œ€์ƒ pathspec ๋ฐฐ์—ด์„ git argv์— ๋ฐ”๋กœ ๋ถ™์ผ ์ˆ˜ ์žˆ๊ฒŒ ํ‰ํƒ„ํ™”ํ•ฉ๋‹ˆ๋‹ค.\n * ๋ฌธ์ž์—ด ์ปค๋งจ๋“œ์™€ ๋‹ค๋ฅธ ๊ฒฝ๋กœ ๊ธฐ๋ฐ˜ helper๋„ ๊ฐ™์€ ํ•„ํ„ฐ๋ฅผ ๊ณต์œ ํ•˜๋„๋ก helper ํ•จ์ˆ˜๋กœ ๋ถ„๋ฆฌํ•ฉ๋‹ˆ๋‹ค.\n * @returns include/exclude pathspec ๋ฐฐ์—ด\n */\nfunction getReviewPathspecArgs() {\n const { includePatterns, excludePatterns } = getGitDiffPathspecs();\n\n return [...includePatterns, ...excludePatterns];\n}\n\n/**\n * @description\n * ์„ ํƒ๋œ ์—ฌ๋Ÿฌ ์ปค๋ฐ‹์˜ ์ „์ฒด diff๋ฅผ ํ•œ ํŒŒ์ผ์— ํ•ฉ์นฉ๋‹ˆ๋‹ค.\n * ๊ฐ ์ปค๋ฐ‹์„ ๋ณ„๋„ ์„น์…˜์œผ๋กœ ๊ฐ์‹ธ AI๊ฐ€ ์ปค๋ฐ‹ ๊ฒฝ๊ณ„๋ฅผ ์žƒ์ง€ ์•Š๋„๋ก ํ•˜๋ฉฐ, ๊ธฐ์กด ๋ฆฌ๋ทฐ ๋Œ€์ƒ ํ™•์žฅ์ž ํ•„ํ„ฐ๋„ ๊ทธ๋Œ€๋กœ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.\n * @param commits ์‚ฌ์šฉ์ž๊ฐ€ ๊ณ ๋ฅธ ์ปค๋ฐ‹ ๋ชฉ๋ก\n * @returns ๋ฆฌ๋ทฐ์šฉ ํ†ตํ•ฉ diff ํ…์ŠคํŠธ\n */\nexport function buildSelectedCommitDiff(commits: CommitOption[]) {\n const reviewPathspecArgs = getReviewPathspecArgs();\n const sections = commits\n .map((commit) => {\n const diff = runGitCommand(['show', '--stat', '--patch', '--format=', commit.hash, '--', ...reviewPathspecArgs], {\n allowFailure: true,\n trimOutput: false\n }).trim();\n\n if (!diff) {\n return '';\n }\n\n return [`## ${commit.hash} ${commit.subject}`, diff].join('\\n\\n');\n })\n .filter(Boolean)\n .join('\\n\\n');\n\n if (!sections) {\n return '';\n }\n\n return ['# ์„ ํƒํ•œ ์ปค๋ฐ‹', buildSelectedCommitSummary(commits), '', '# ๋ฆฌ๋ทฐ ๋Œ€์ƒ diff', sections].join('\\n');\n}\n\n/**\n * @description\n * ์„ ํƒ๋œ ์ปค๋ฐ‹์—์„œ ์‹ค์ œ ๋ฆฌ๋ทฐ ๋Œ€์ƒ ํŒŒ์ผ ๋ชฉ๋ก๋งŒ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค.\n * one-by-one ๋ฆฌ๋ทฐ๊ฐ€ ํ˜„์žฌ ์„ ํƒ๋œ ์ปค๋ฐ‹ ์ง‘ํ•ฉ์—๋งŒ ๋ฐ˜์‘ํ•˜๋„๋ก commit๋ณ„ name-only ๊ฒฐ๊ณผ๋ฅผ ํ•ฉ์ง‘ํ•ฉ์œผ๋กœ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค.\n * @param commits ์‚ฌ์šฉ์ž๊ฐ€ ๊ณ ๋ฅธ ์ปค๋ฐ‹ ๋ชฉ๋ก\n * @returns ์ค‘๋ณต ์ œ๊ฑฐ๋œ ํŒŒ์ผ ๋ชฉ๋ก\n */\nexport function getSelectedCommitFiles(commits: CommitOption[]) {\n const reviewPathspecArgs = getReviewPathspecArgs();\n const files = new Set<string>();\n\n commits.forEach((commit) => {\n const output = runGitCommand(['show', '--pretty=format:', '--name-only', commit.hash, '--', ...reviewPathspecArgs], {\n allowFailure: true\n });\n\n output\n .split('\\n')\n .map((line) => line.trim())\n .filter(Boolean)\n .forEach((filePath) => files.add(filePath));\n });\n\n return [...files];\n}\n\n/**\n * @description\n * ํŠน์ • ํŒŒ์ผ์— ๋Œ€ํ•œ ์„ ํƒ ์ปค๋ฐ‹๋“ค์˜ diff๋งŒ ๋ชจ์•„์„œ one-by-one ๋ฆฌ๋ทฐ ์ž…๋ ฅ์œผ๋กœ ๋งŒ๋“ญ๋‹ˆ๋‹ค.\n * ๋™์ผ ํŒŒ์ผ์ด ์—ฌ๋Ÿฌ ์ปค๋ฐ‹์—์„œ ๋ฐ”๋€ ๊ฒฝ์šฐ commit section์„ ๋‚˜๋ˆ  ๋ณด์—ฌ์ค˜ ํŒŒ์ผ ๋ฆฌ๋ทฐ ์‘๋‹ต์ด ์–ด๋А ๋ณ€๊ฒฝ์„ ๋‹ค๋ฃจ๋Š”์ง€ ์ถ”์  ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.\n * @param commits ์‚ฌ์šฉ์ž๊ฐ€ ๊ณ ๋ฅธ ์ปค๋ฐ‹ ๋ชฉ๋ก\n * @param filePath ๋ฆฌ๋ทฐํ•  ํŒŒ์ผ ๊ฒฝ๋กœ\n * @returns ๋‹จ์ผ ํŒŒ์ผ ๋ฆฌ๋ทฐ์šฉ diff ํ…์ŠคํŠธ\n */\nexport function buildSelectedFileDiff(commits: CommitOption[], filePath: string) {\n const sections = commits\n .map((commit) => {\n const diff = runGitCommand(['show', '--stat', '--patch', '--format=', commit.hash, '--', filePath], {\n allowFailure: true,\n trimOutput: false\n }).trim();\n\n if (!diff) {\n return '';\n }\n\n return [`## ${commit.hash} ${commit.subject}`, diff].join('\\n\\n');\n })\n .filter(Boolean)\n .join('\\n\\n');\n\n if (!sections) {\n return '';\n }\n\n return ['# ์„ ํƒํ•œ ์ปค๋ฐ‹', buildSelectedCommitSummary(commits), '', `# ํŒŒ์ผ: ${filePath}`, sections].join('\\n\\n');\n}\n\n/**\n * openReport๋ฅผ OS๋ณ„๋กœ ๋™์ž‘ํ•˜๋„๋ก ๋ณ€๊ฒฝ\n * ์šฐ์„ ์ˆœ์œ„:\n * 1. Chrome ์‹œ๋„\n * - macOS: open -a \"Google Chrome\" \"<path>\"\n * - Ubuntu/Linux: google-chrome \"<path>\"\n * 2. ์‹คํŒจ ์‹œ ๊ธฐ๋ณธ ๋ธŒ๋ผ์šฐ์ €๋กœ ํด๋ฐฑ\n * - macOS: open \"<path>\"\n * - Ubuntu/Linux: xdg-open \"<path>\"\n * 3. ๋‘˜ ๋‹ค ์‹คํŒจํ•˜๋ฉด ์—๋Ÿฌ ์ถœ๋ ฅ\n * 4. ๋ฏธ์ง€์› ํ”Œ๋žซํผ์ด๋ฉด ํ”Œ๋žซํผ ๊ฒฝ๊ณ  ์ถœ๋ ฅ\n */\nexport function openReport(reportPath: string) {\n const resolvedPath = path.resolve(reportPath);\n const { platform } = process;\n helperTrace('open-report:start', resolvedPath);\n\n const openWithChrome = () => {\n if (platform === 'darwin') {\n execSync(`open -a \"Google Chrome\" \"${resolvedPath}\"`, { stdio: 'ignore' });\n\n return true;\n }\n\n if (platform === 'linux') {\n execSync(`google-chrome \"${resolvedPath}\"`, { stdio: 'ignore' });\n\n return true;\n }\n\n return false;\n };\n\n const openWithDefaultBrowser = () => {\n if (platform === 'darwin') {\n execSync(`open \"${resolvedPath}\"`, { stdio: 'ignore' });\n\n return true;\n }\n\n if (platform === 'linux') {\n execSync(`xdg-open \"${resolvedPath}\"`, { stdio: 'ignore' });\n\n return true;\n }\n\n return false;\n };\n\n try {\n if (openWithChrome()) {\n helperTrace('open-report:chrome:success', platform);\n console.log('๐Ÿš€ Google Chrome์—์„œ ๋ฆฌํฌํŠธ๋ฅผ ์—ด์—ˆ์Šต๋‹ˆ๋‹ค.');\n\n return;\n }\n } catch (error) {\n helperTrace('open-report:chrome:failed', getErrorSummary(error));\n // Chrome ์‹คํ–‰ ์‹คํŒจ ์‹œ ๊ธฐ๋ณธ ๋ธŒ๋ผ์šฐ์ €๋กœ ํด๋ฐฑ\n }\n\n try {\n if (openWithDefaultBrowser()) {\n helperTrace('open-report:default-browser:success', platform);\n console.log('๐Ÿš€ ๊ธฐ๋ณธ ๋ธŒ๋ผ์šฐ์ €์—์„œ ๋ฆฌํฌํŠธ๋ฅผ ์—ด์—ˆ์Šต๋‹ˆ๋‹ค.');\n\n return;\n }\n } catch (error) {\n helperTrace('open-report:default-browser:failed', getErrorSummary(error));\n console.error('โš ๏ธ ๋ธŒ๋ผ์šฐ์ € ์—ด๊ธฐ ์‹คํŒจ:', error);\n\n return;\n }\n\n helperTrace('open-report:unsupported-platform', platform);\n console.error(`โš ๏ธ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ํ”Œ๋žซํผ์ž…๋‹ˆ๋‹ค: ${platform}`);\n}\n\n/**\n * @description\n * raw mode ๊ธฐ๋ฐ˜ ์„ ํƒ UI๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ์—ด ์ˆ˜ ์žˆ๋Š” TTY ํ™˜๊ฒฝ์ธ์ง€ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.\n * CI๋‚˜ pipe ํ™˜๊ฒฝ์—์„œ๋Š” ์ปค์„œ๋ฅผ ์ œ์–ดํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ์ฆ‰์‹œ ์—๋Ÿฌ ๋ฆฌํฌํŠธ๋ฅผ ๋‚จ๊ธฐ๊ณ  ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.\n * @param scope ์—๋Ÿฌ ๋ฆฌํฌํŠธ ๊ตฌ๋ถ„์šฉ scope\n * @param message ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ค„ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€\n */\nfunction ensureInteractiveSelectionAvailable(scope: string, message: string) {\n if (process.stdin.isTTY && process.stdout.isTTY && typeof process.stdin.setRawMode === 'function') {\n return;\n }\n\n helperTrace(`${scope}:tty-missing`);\n exitWithError(message, {\n scope: `helper:${scope}`\n });\n}\n\n/**\n * @description\n * ์„ ํƒ ๋ชจ๋‹ฌ์„ ํ˜„์žฌ ์œ„์น˜์—์„œ ๋‹ค์‹œ ๊ทธ๋ฆฝ๋‹ˆ๋‹ค.\n * ๊ฐ ์ค„์€ ๋ฏธ๋ฆฌ ํ„ฐ๋ฏธ๋„ ํญ ์•ˆ์œผ๋กœ ์ž˜๋ผ physical line์ด 1์ค„๋กœ ์œ ์ง€๋˜๋ฏ€๋กœ,\n * ์ง์ „ ๋ Œ๋” ์ค„ ์ˆ˜๋งŒํผ ์œ„๋กœ ์ด๋™ํ•œ ๋’ค clearScreenDown ํ•ด๋„ ์ค‘๋ณต ์—†์ด ์•ˆ์ •์ ์œผ๋กœ ๊ฐฑ์‹ ๋ฉ๋‹ˆ๋‹ค.\n * @param lines ์ƒˆ๋กœ ๋ Œ๋”ํ•  ๋ฌธ์ž์—ด ์ค„ ๋ชฉ๋ก\n * @param previousLineCount ์ง์ „ ๋ Œ๋” ์ค„ ์ˆ˜\n * @returns ํ˜„์žฌ ๋ Œ๋” ์ค„ ์ˆ˜\n */\nfunction renderSelectionBlock(lines: string[], previousLineCount: number) {\n if (previousLineCount > 0) {\n readline.moveCursor(process.stdout, 0, -previousLineCount);\n readline.clearScreenDown(process.stdout);\n }\n\n const fittedLines = fitLinesToTerminal(lines);\n process.stdout.write(`${fittedLines.join('\\n')}\\n`);\n\n return fittedLines.length;\n}\n\n/**\n * @description\n * ํ˜„์žฌ ์ปค์„œ ๊ธฐ์ค€ visible window๋ฅผ ๊ณ„์‚ฐํ•ด ๊ธด ์ปค๋ฐ‹ ๋ชฉ๋ก๋„ ๊ณ ์ • ๋†’์ด๋กœ ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.\n * @param optionCount ์ „์ฒด ์˜ต์…˜ ๊ฐœ์ˆ˜\n * @param selectedIndex ํ˜„์žฌ ํฌ์ปค์Šค ์ธ๋ฑ์Šค\n * @param windowSize ๋™์‹œ์— ๋ณด์—ฌ์ค„ ์ตœ๋Œ€ ์˜ต์…˜ ๊ฐœ์ˆ˜\n * @returns ์‹œ์ž‘/๋ ์ธ๋ฑ์Šค\n */\nfunction getSelectionWindowRange(optionCount: number, selectedIndex: number, windowSize: number) {\n if (optionCount <= windowSize) {\n return {\n end: optionCount,\n start: 0\n };\n }\n\n const halfWindow = Math.floor(windowSize / 2);\n const maxStart = optionCount - windowSize;\n const start = Math.max(0, Math.min(selectedIndex - halfWindow, maxStart));\n\n return {\n end: Math.min(optionCount, start + windowSize),\n start\n };\n}\n\n/**\n * @description\n * ๊ณตํ†ต multi-select UI ๋ Œ๋”๋ง์— ํ•„์š”ํ•œ ๋ฌธ์ž์—ด ๋ชฉ๋ก์„ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.\n * ์„ค๋ช… ํ…์ŠคํŠธ๋Š” dim ์ฒ˜๋ฆฌํ•ด subject์™€ author/date๊ฐ€ ํ•œ ์ค„์—์„œ ๊ตฌ๋ถ„๋˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.\n * @param question ์งˆ๋ฌธ ํ—ค๋”\n * @param options ํ‘œ์‹œํ•  ์˜ต์…˜ ๋ชฉ๋ก\n * @param selectedIndex ํ˜„์žฌ ํฌ์ปค์Šค ์ธ๋ฑ์Šค\n * @param toggled ์„ ํƒ๋œ ์ธ๋ฑ์Šค Set\n * @param windowSize ๋™์‹œ์— ๋ณด์—ฌ์ค„ ์ตœ๋Œ€ ์˜ต์…˜ ๊ฐœ์ˆ˜\n * @returns ์ถœ๋ ฅ ์ค„ ๋ชฉ๋ก\n */\nfunction buildMultiSelectLines<T>(\n question: string,\n options: MultiSelectOption<T>[],\n selectedIndex: number,\n toggled: Set<number>,\n windowSize: number\n) {\n const { start, end } = getSelectionWindowRange(options.length, selectedIndex, windowSize);\n const lines = [\n `${ANSI.bold}${question}${ANSI.reset}`,\n `${ANSI.dim}โ†‘โ†“ ์ด๋™ | Space ์„ ํƒ/ํ•ด์ œ | Enter ์™„๋ฃŒ | Esc ์ทจ์†Œ${ANSI.reset}`,\n `${ANSI.dim}์„ ํƒ๋จ: ${toggled.size}๊ฐœ / ์ „์ฒด: ${options.length}๊ฐœ${ANSI.reset}`\n ];\n\n for (let index = start; index < end; index += 1) {\n const option = options[index];\n\n if (!option) {\n continue;\n }\n\n const cursor = index === selectedIndex ? `${ANSI.cyan}>${ANSI.reset}` : ' ';\n const checked = toggled.has(index) ? `${ANSI.green}โ˜‘${ANSI.reset}` : 'โ˜';\n const description = option.description ? ` ${ANSI.dim}${option.description}${ANSI.reset}` : '';\n lines.push(`${cursor} ${checked} ${option.label}${description}`);\n }\n\n if (options.length > windowSize) {\n lines.push(`${ANSI.dim}ํ‘œ์‹œ ๋ฒ”์œ„: ${start + 1}-${end} / ${options.length}${ANSI.reset}`);\n }\n\n return lines;\n}\n\n/**\n * @description\n * ์ปค๋ฐ‹ ์„ ํƒ์ฒ˜๋Ÿผ ๋ณต์ˆ˜ ์„ ํƒ์ด ํ•„์š”ํ•œ ํ„ฐ๋ฏธ๋„ ๋ชจ๋‹ฌ์„ ๊ณตํ†ต์œผ๋กœ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.\n * raw mode๋ฅผ ์ง์ ‘ ์ œ์–ดํ•ด ๋ฐฉํ–ฅํ‚ค, Space, Enter, Esc๋ฅผ ์ฝ๊ณ  ์„ ํƒ๋œ value ๋ชฉ๋ก๋งŒ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.\n * @param question ์‚ฌ์šฉ์ž ์•ˆ๋‚ด ๋ฌธ๊ตฌ\n * @param options ์„ ํƒ ์˜ต์…˜ ๋ชฉ๋ก\n * @param windowSize ๋™์‹œ์— ๋ณด์—ฌ์ค„ ์ตœ๋Œ€ ์˜ต์…˜ ๊ฐœ์ˆ˜\n * @returns ์‚ฌ์šฉ์ž๊ฐ€ ํ™•์ •ํ•œ ์„ ํƒ ๊ฐ’ ๋ฐฐ์—ด\n */\nexport async function showMultiSelect<T>(question: string, options: MultiSelectOption<T>[], windowSize = COMMIT_SELECTION_WINDOW) {\n ensureInteractiveSelectionAvailable('showMultiSelect', 'โŒ ์ปค๋ฐ‹ ์„ ํƒ ๋ชจ๋‹ฌ์€ TTY ํ™˜๊ฒฝ์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.');\n let selectedIndex = 0;\n let renderedLineCount = 0;\n const toggled = new Set<number>();\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n terminal: true\n });\n\n process.stdout.write('\\u001b[?25l');\n\n const cleanup = () => {\n if (renderedLineCount > 0) {\n readline.moveCursor(process.stdout, 0, -renderedLineCount);\n readline.clearScreenDown(process.stdout);\n renderedLineCount = 0;\n }\n process.stdin.removeListener('data', onData);\n process.stdin.setRawMode(false);\n process.stdin.pause();\n rl.close();\n process.stdout.write('\\u001b[?25h');\n };\n\n const render = () => {\n const lines = buildMultiSelectLines(question, options, selectedIndex, toggled, windowSize);\n renderedLineCount = renderSelectionBlock(lines, renderedLineCount);\n };\n\n const confirmSelection = (resolve: (value: T[]) => void) => {\n const values = [...toggled]\n .sort((left, right) => left - right)\n .map((index) => options[index]?.value)\n .filter((value): value is T => value !== undefined);\n\n cleanup();\n resolve(values);\n };\n\n const cancelSelection = (resolve: (value: T[]) => void) => {\n cleanup();\n resolve([]);\n };\n\n let onData = (_data: Buffer) => {\n // ์‹ค์ œ ๊ตฌํ˜„์€ Promise ์ƒ์„ฑ ์‹œ์ ์— ๋ฐ”์ธ๋”ฉํ•ฉ๋‹ˆ๋‹ค.\n };\n\n render();\n\n return new Promise<T[]>((resolve) => {\n onData = (data: Buffer) => {\n const key = data.toString();\n\n if (key === '\\u0003') {\n cleanup();\n process.exit(0);\n }\n\n if (key === '\\u001b') {\n cancelSelection(resolve);\n\n return;\n }\n\n if (key === '\\x1b[A') {\n selectedIndex = (selectedIndex - 1 + options.length) % options.length;\n render();\n\n return;\n }\n\n if (key === '\\x1b[B') {\n selectedIndex = (selectedIndex + 1) % options.length;\n render();\n\n return;\n }\n\n if (key === ' ') {\n if (toggled.has(selectedIndex)) {\n toggled.delete(selectedIndex);\n } else {\n toggled.add(selectedIndex);\n }\n render();\n\n return;\n }\n\n if (key === '\\r' || key === '\\n') {\n confirmSelection(resolve);\n }\n };\n\n process.stdin.setRawMode(true);\n process.stdin.resume();\n process.stdin.on('data', onData);\n });\n}\n\n/**\n * @description\n * ์ตœ๊ทผ ์ปค๋ฐ‹ ๋ชฉ๋ก์„ modal UI๋กœ ์„ ํƒ๋ฐ›์•„ review ์—”ํŠธ๋ฆฌํฌ์ธํŠธ์—์„œ ๋ฐ”๋กœ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.\n * @returns ์‚ฌ์šฉ์ž๊ฐ€ ๊ณ ๋ฅธ ์ปค๋ฐ‹ ๋ชฉ๋ก\n */\nexport async function selectReviewCommits() {\n const commits = getRecentCommitOptions();\n\n if (commits.length === 0) {\n console.log('โ„น๏ธ ๋ฆฌ๋ทฐํ•  ์ตœ๊ทผ ์ปค๋ฐ‹์ด ์—†์Šต๋‹ˆ๋‹ค.');\n\n return [];\n }\n\n return showMultiSelect<CommitOption>(\n '๋ฆฌ๋ทฐํ•  ์ปค๋ฐ‹์„ ์„ ํƒํ•ด์ฃผ์„ธ์š”.',\n commits.map((commit) => ({\n description: commit.description,\n label: commit.label,\n value: commit\n })),\n COMMIT_SELECTION_WINDOW\n );\n}\n\n/**\n * AI ์„œ๋น„์Šค ์„ ํƒ\n */\nexport function selectAIService() {\n const service = parseServiceFromArgs();\n\n if (!service) {\n helperTrace('select-service:missing');\n exitWithError('โŒ ์„œ๋น„์Šค๊ฐ€ ์„ ํƒ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.', {\n scope: 'helper:selectAIService'\n });\n }\n\n helperTrace('select-service:done', service);\n\n return service;\n}\n\n/**\n * ํ„ฐ๋ฏธ๋„์—์„œ ๋ผ๋””์˜ค ๋ฒ„ํŠผ ํ˜•ํƒœ๋กœ AI ์„œ๋น„์Šค๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.\n */\nexport async function showSelectionAIService(): Promise<AIServiceType> {\n const selectedServiceFromArgs = parseServiceFromArgs();\n\n if (selectedServiceFromArgs) {\n helperTrace('show-selection:from-args', selectedServiceFromArgs);\n console.log(`\\nโœ… ${ANSI.green}${selectedServiceFromArgs}${ANSI.reset} ์„œ๋น„์Šค๊ฐ€ ์„ ํƒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. (--service)\\n`);\n\n return selectedServiceFromArgs;\n }\n\n ensureInteractiveSelectionAvailable('showSelectionAIService', 'โŒ AI ์„œ๋น„์Šค ์„ ํƒ UI๋Š” TTY ํ™˜๊ฒฝ์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.');\n helperTrace('show-selection:interactive:start');\n let selectedIndex = 0;\n\n // Use readline to handle keypresses\n // ํ‚ค ์ž…๋ ฅ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด readline ์ธํ„ฐํŽ˜์ด์Šค ์‚ฌ์šฉ\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n terminal: true\n });\n\n let firstRender = true;\n\n // Hide cursor\n process.stdout.write('\\u001b[?25l');\n\n const render = () => {\n if (!firstRender) {\n // Move cursor back to the starting line of the selection UI\n // We print (1 question line + services.length lines)\n // ์„ ํƒ UI์˜ ์‹œ์ž‘ ๋ผ์ธ์œผ๋กœ ์ปค์„œ ์ด๋™ (์งˆ๋ฌธ 1์ค„ + ์„œ๋น„์Šค ๋ชฉ๋ก N์ค„)\n readline.moveCursor(process.stdout, 0, -(AIServices.length + 1));\n }\n firstRender = false;\n helperTrace('show-selection:interactive:render', AIServices[selectedIndex] || 'unknown');\n\n // Clear everything from cursor down to avoid ghosting/overlaps\n // ์ž”์ƒ์ด๋‚˜ ๊ฒน์นจ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์ปค์„œ ์œ„์น˜๋ถ€ํ„ฐ ์•„๋ž˜์ชฝ ๋ชจ๋‘ ์ง€์›€\n readline.clearScreenDown(process.stdout);\n\n process.stdout.write(\n `๐Ÿค– AI ์„œ๋น„์Šค๋ฅผ ์„ ํƒํ•ด์ฃผ์„ธ์š” (${ANSI.yellow}โ†‘โ†“ ๋ฐฉํ–ฅํ‚ค${ANSI.reset} ์ด๋™, ${ANSI.yellow}Enter${ANSI.reset} ์„ ํƒ):\\n`\n );\n AIServices.forEach((service, index) => {\n if (index === selectedIndex) {\n process.stdout.write(` ${ANSI.cyan}>${ANSI.reset} ${ANSI.cyan}โ—‰${ANSI.reset} ${ANSI.bold}${service}${ANSI.reset}\\n`);\n } else {\n process.stdout.write(` โ—ฏ ${service}\\n`);\n }\n });\n };\n\n render();\n\n return new Promise((resolve) => {\n const onData = (data: Buffer) => {\n const key = data.toString();\n if (key === '\\u0003') {\n // Ctrl+C\n helperTrace('show-selection:interactive:ctrl-c');\n process.stdout.write('\\u001b[?25h'); // Show cursor\n process.exit(0);\n }\n if (key === '\\x1b[A') {\n // Up arrow\n selectedIndex = (selectedIndex - 1 + AIServices.length) % AIServices.length;\n render();\n } else if (key === '\\x1b[B') {\n // Down arrow\n selectedIndex = (selectedIndex + 1) % AIServices.length;\n render();\n } else if (key === '\\r' || key === '\\n') {\n // Enter\n process.stdin.removeListener('data', onData);\n process.stdin.setRawMode(false);\n process.stdin.pause();\n rl.close();\n\n // Show cursor\n process.stdout.write('\\u001b[?25h');\n\n console.log(`\\nโœ… ${ANSI.green}${AIServices[selectedIndex]}${ANSI.reset} ์„œ๋น„์Šค๊ฐ€ ์„ ํƒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.\\n`);\n const result = AIServices[selectedIndex];\n if (result) {\n helperTrace('show-selection:interactive:confirmed', result);\n resolve(result);\n }\n }\n };\n\n process.stdin.setRawMode(true);\n process.stdin.resume();\n process.stdin.on('data', onData);\n });\n}\n"]}
1
+ {"version":3,"sources":["../../src/common/helper.ts"],"names":["__dirname","path","fileURLToPath","fs","execFileSync","inspect","execSync","readline"],"mappings":";;;;;;;;;;;;;;;;;AAuDA,IAAMA,cAAYC,qBAAK,CAAA,OAAA,CAAQC,iBAAc,CAAA,4PAAe,CAAC,CAAA;AAC7D,IAAM,gBAA0B,EAAC;AACjC,IAAM,uBAA0B,GAAA,2BAAA;AAChC,IAAI,qBAAwB,GAAA,EAAA;AAU5B,SAAS,uBAAuB,SAAmB,EAAA;AACjD,EAAA,MAAM,eAAkB,GAAAD,qBAAA,CAAK,IAAK,CAAA,SAAA,EAAW,cAAc,CAAA;AAE3D,EAAA,IAAI,CAACE,mBAAA,CAAG,UAAW,CAAA,eAAe,CAAG,EAAA;AACnC,IAAO,OAAA,KAAA;AAAA;AAGT,EAAI,IAAA;AACF,IAAA,MAAM,cAAc,IAAK,CAAA,KAAA,CAAMA,oBAAG,YAAa,CAAA,eAAA,EAAiB,MAAM,CAAC,CAAA;AAEvE,IAAA,OAAO,YAAY,IAAS,KAAA,uBAAA;AAAA,GACtB,CAAA,MAAA;AACN,IAAO,OAAA,KAAA;AAAA;AAEX;AAUA,SAAS,2BAAA,CAA4B,iBAAyBH,WAAW,EAAA;AACvE,EAAA,IAAI,qBAAuB,EAAA;AACzB,IAAO,OAAA,qBAAA;AAAA;AAGT,EAAA,IAAI,gBAAmB,GAAA,cAAA;AAEvB,EAAA,OAAO,IAAM,EAAA;AACX,IAAI,IAAA,sBAAA,CAAuB,gBAAgB,CAAG,EAAA;AAC5C,MAAwB,qBAAA,GAAA,gBAAA;AAExB,MAAO,OAAA,qBAAA;AAAA;AAGT,IAAM,MAAA,eAAA,GAAkBC,qBAAK,CAAA,OAAA,CAAQ,gBAAgB,CAAA;AAErD,IAAA,IAAI,oBAAoB,gBAAkB,EAAA;AACxC,MAAA;AAAA;AAGF,IAAmB,gBAAA,GAAA,eAAA;AAAA;AAQrB,EAAwB,qBAAA,GAAAA,qBAAA,CAAK,OAAQ,CAAA,cAAA,EAAgB,OAAO,CAAA;AAE5D,EAAO,OAAA,qBAAA;AACT;AASA,SAAS,wBAAwB,gBAA0B,EAAA;AACzD,EAAA,OAAOA,qBAAK,CAAA,OAAA,CAAQ,2BAA4B,EAAA,EAAG,gBAAgB,CAAA;AACrE;AAEa,IAAA,SAAA,GAAY,wBAAwB,kCAAkC;AACtE,IAAA,eAAA,GAAkB,wBAAwB,iCAAiC;AAC3E,IAAA,yBAAA,GAA4B,wBAAwB,uCAAuC;AAC3F,IAAA,cAAA,GAAiB,wBAAwB,gCAAgC;AACzE,IAAA,sBAAA,GAAyB,wBAAwB,2CAA2C;AAClG,IAAM,UAAa,GAAA;AACnB,IAAM,YAAe,GAAA;AACrB,IAAM,UAA8B,GAAA,CAAC,QAAU,EAAA,QAAA,EAAU,OAAO;AAChE,IAAM,kBAAqB,GAAA;AAC3B,IAAM,uBAA0B,GAAA;AAChC,IAAM,UAAa,GAAA;AAAA,EACxB,cAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,eAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA;AAAA;AACF;AAEO,SAAS,WAAW,IAAiB,GAAA,OAAA,CAAQ,IAAK,CAAA,KAAA,CAAM,CAAC,CAAG,EAAA;AACjE,EAAO,OAAA,IAAA,CAAK,SAAS,QAAQ,CAAA;AAC/B;AAUO,SAAS,qBAAqB,IAAiB,GAAA,OAAA,CAAQ,IAAK,CAAA,KAAA,CAAM,CAAC,CAAG,EAAA;AAC3E,EAAO,OAAA,IAAA,CAAK,SAAS,iBAAiB,CAAA;AACxC;AAEO,SAAS,kBAAqB,GAAA;AACnC,EAAA,aAAA,CAAc,MAAS,GAAA,CAAA;AACzB;AAEO,SAAS,gBAAmB,GAAA;AACjC,EAAO,OAAA,CAAC,GAAG,aAAa,CAAA;AAC1B;AAOA,IAAM,IAAO,GAAA;AAAA,EACX,IAAM,EAAA,SAAA;AAAA,EACN,IAAM,EAAA,UAAA;AAAA,EACN,GAAK,EAAA,SAAA;AAAA,EACL,KAAO,EAAA,UAAA;AAAA,EACP,KAAO,EAAA,SAAA;AAAA,EACP,MAAQ,EAAA;AACV,CAAA;AACA,IAAM,YAAA,GAAe,IAAI,MAAO,CAAA,CAAA,EAAG,OAAO,YAAa,CAAA,EAAE,CAAC,CAAA,WAAA,CAAA,EAAe,GAAG,CAAA;AAC5E,IAAM,sBAAyB,GAAA,WAAA;AAC/B,IAAM,kBACJ,GAAA,OAAO,IAAS,KAAA,WAAA,IAAe,eAAe,IAAO,GAAA,IAAI,IAAK,CAAA,SAAA,CAAU,IAAM,EAAA,EAAE,WAAa,EAAA,UAAA,EAAY,CAAI,GAAA,IAAA;AAY/G,SAAS,mBAAsB,GAAA;AAC7B,EAAO,OAAA;AAAA,IACL,iBAAiB,UAAW,CAAA,GAAA,CAAI,CAAC,IAAS,KAAA,CAAA,UAAA,EAAa,IAAI,CAAE,CAAA,CAAA;AAAA,IAC7D,eAAiB,EAAA,CAAC,MAAQ,EAAA,OAAA,EAAS,QAAQ,OAAO;AAAA,GACpD;AACF;AAEA,SAAS,iBAAiB,KAAe,EAAA;AACvC,EAAA,IAAI,CAAC,kBAAoB,EAAA;AACvB,IAAO,OAAA,CAAC,GAAG,KAAK,CAAA;AAAA;AAGlB,EAAA,OAAO,CAAC,GAAG,kBAAmB,CAAA,OAAA,CAAQ,KAAK,CAAC,CAAE,CAAA,GAAA,CAAI,CAAC,EAAE,OAAQ,EAAA,KAAM,OAAO,CAAA;AAC5E;AAEA,SAAS,gBAAgB,SAAmB,EAAA;AAC1C,EACE,OAAA,SAAA,IAAa,IACZ,KAAA,SAAA,IAAa,IACZ,IAAA,SAAA,KAAc,IACd,IAAA,SAAA,KAAc,IACb,IAAA,SAAA,IAAa,KAAU,IAAA,SAAA,IAAa,KAAU,IAAA,SAAA,KAAc,SAC5D,SAAa,IAAA,KAAA,IAAU,SAAa,IAAA,KAAA,IACpC,SAAa,IAAA,KAAA,IAAU,SAAa,IAAA,KAAA,IACpC,SAAa,IAAA,KAAA,IAAU,SAAa,IAAA,KAAA,IACpC,SAAa,IAAA,KAAA,IAAU,aAAa,KACpC,IAAA,SAAA,IAAa,KAAU,IAAA,SAAA,IAAa,KACpC,IAAA,SAAA,IAAa,KAAU,IAAA,SAAA,IAAa,KACpC,IAAA,SAAA,IAAa,KAAU,IAAA,SAAA,IAAa,KACpC,IAAA,SAAA,IAAa,SAAU,SAAa,IAAA,KAAA,IACpC,SAAa,IAAA,KAAA,IAAU,SAAa,IAAA,KAAA,IACpC,SAAa,IAAA,MAAA,IAAW,SAAa,IAAA,MAAA,IACrC,SAAa,IAAA,MAAA,IAAW,SAAa,IAAA,MAAA,CAAA;AAE5C;AAEA,SAAS,iBAAiB,SAAmB,EAAA;AAC3C,EACG,OAAA,SAAA,IAAa,MAAW,IAAA,SAAA,IAAa,MACrC,IAAA,SAAA,IAAa,UAAW,SAAa,IAAA,MAAA,IACrC,SAAa,IAAA,IAAA,IAAU,SAAa,IAAA,KAAA;AAEzC;AAEA,SAAS,iBAAiB,QAAkB,EAAA;AAC1C,EAAA,IAAI,KAAQ,GAAA,CAAA;AAEZ,EAAA,KAAA,MAAW,aAAa,QAAU,EAAA;AAChC,IAAM,MAAA,SAAA,GAAY,SAAU,CAAA,WAAA,CAAY,CAAC,CAAA;AAEzC,IAAA,IAAI,CAAC,SAAa,IAAA,sBAAA,CAAuB,KAAK,SAAS,CAAA,IAAK,cAAc,IAAQ,EAAA;AAChF,MAAA;AAAA;AAGF,IAAA,IAAK,aAAa,KAAU,IAAA,SAAA,IAAa,SAAY,SAAa,IAAA,MAAA,IAAW,aAAa,MAAU,EAAA;AAClG,MAAA;AAAA;AAGF,IAAA,IAAI,eAAgB,CAAA,SAAS,CAAK,IAAA,gBAAA,CAAiB,SAAS,CAAG,EAAA;AAC7D,MAAQ,KAAA,GAAA,IAAA,CAAK,GAAI,CAAA,KAAA,EAAO,CAAC,CAAA;AAEzB,MAAA;AAAA;AAGF,IAAQ,KAAA,GAAA,IAAA,CAAK,GAAI,CAAA,KAAA,EAAO,CAAC,CAAA;AAAA;AAG3B,EAAO,OAAA,KAAA;AACT;AAEA,SAAS,kBAAkB,KAAe,EAAA;AACxC,EAAA,OAAO,gBAAiB,CAAA,KAAK,CAAE,CAAA,GAAA,CAAI,CAAC,OAAa,MAAA;AAAA,IAC/C,KAAO,EAAA,OAAA;AAAA,IACP,YAAA,EAAc,iBAAiB,OAAO;AAAA,GACtC,CAAA,CAAA;AACJ;AAEA,SAAS,oBAAoB,KAAe,EAAA;AAC1C,EAAA,MAAM,SAAyB,EAAC;AAChC,EAAA,IAAI,SAAY,GAAA,CAAA;AAEhB,EAAA,KAAA,MAAW,KAAS,IAAA,KAAA,CAAM,QAAS,CAAA,YAAY,CAAG,EAAA;AAChD,IAAM,MAAA,KAAA,GAAQ,MAAM,KAAS,IAAA,CAAA;AAE7B,IAAA,IAAI,QAAQ,SAAW,EAAA;AACrB,MAAO,MAAA,CAAA,IAAA,CAAK,GAAG,iBAAkB,CAAA,KAAA,CAAM,MAAM,SAAW,EAAA,KAAK,CAAC,CAAC,CAAA;AAAA;AAGjE,IAAA,MAAA,CAAO,IAAK,CAAA;AAAA,MACV,KAAA,EAAO,MAAM,CAAC,CAAA;AAAA,MACd,YAAc,EAAA;AAAA,KACf,CAAA;AACD,IAAY,SAAA,GAAA,KAAA,GAAQ,KAAM,CAAA,CAAC,CAAE,CAAA,MAAA;AAAA;AAG/B,EAAI,IAAA,SAAA,GAAY,MAAM,MAAQ,EAAA;AAC5B,IAAA,MAAA,CAAO,KAAK,GAAG,iBAAA,CAAkB,MAAM,KAAM,CAAA,SAAS,CAAC,CAAC,CAAA;AAAA;AAG1D,EAAO,OAAA,MAAA;AACT;AAUA,SAAS,uBAAA,CAAwB,OAAe,QAAkB,EAAA;AAChE,EAAA,IAAI,YAAY,CAAG,EAAA;AACjB,IAAO,OAAA,EAAA;AAAA;AAGT,EAAM,MAAA,MAAA,GAAS,oBAAoB,KAAK,CAAA;AACxC,EAAM,MAAA,UAAA,GAAa,OAAO,MAAO,CAAA,CAAC,KAAK,KAAU,KAAA,GAAA,GAAM,KAAM,CAAA,YAAA,EAAc,CAAC,CAAA;AAE5E,EAAA,IAAI,cAAc,QAAU,EAAA;AAC1B,IAAO,OAAA,KAAA;AAAA;AAGT,EAAA,MAAM,QAAW,GAAA,KAAA;AACjB,EAAA,MAAM,aAAgB,GAAA,CAAA;AACtB,EAAA,MAAM,WAAc,GAAA,IAAA,CAAK,GAAI,CAAA,CAAA,EAAG,WAAW,aAAa,CAAA;AACxD,EAAA,IAAI,SAAY,GAAA,CAAA;AAChB,EAAA,IAAI,MAAS,GAAA,EAAA;AAEb,EAAA,KAAA,MAAW,SAAS,MAAQ,EAAA;AAC1B,IAAI,IAAA,KAAA,CAAM,iBAAiB,CAAG,EAAA;AAC5B,MAAA,MAAA,IAAU,KAAM,CAAA,KAAA;AAEhB,MAAA;AAAA;AAGF,IAAI,IAAA,SAAA,GAAY,KAAM,CAAA,YAAA,GAAe,WAAa,EAAA;AAChD,MAAA;AAAA;AAGF,IAAA,MAAA,IAAU,KAAM,CAAA,KAAA;AAChB,IAAA,SAAA,IAAa,KAAM,CAAA,YAAA;AAAA;AAGrB,EAAA,OAAO,GAAG,MAAM,CAAA,EAAG,QAAQ,CAAA,EAAG,KAAK,KAAK,CAAA,CAAA;AAC1C;AAEA,SAAS,mBAAmB,KAAiB,EAAA;AAC3C,EAAM,MAAA,QAAA,GAAW,KAAK,GAAI,CAAA,EAAA,EAAA,CAAK,QAAQ,MAAO,CAAA,OAAA,IAAW,OAAO,CAAC,CAAA;AAEjE,EAAA,OAAO,MAAM,GAAI,CAAA,CAAC,SAAS,uBAAwB,CAAA,IAAA,EAAM,QAAQ,CAAC,CAAA;AACpE;AAUA,SAAS,aAAc,CAAA,IAAA,EAAgB,OAA6B,GAAA,EAAI,EAAA;AACtE,EAAA,MAAM,EAAE,YAAA,GAAe,KAAO,EAAA,UAAA,GAAa,MAAS,GAAA,OAAA;AAEpD,EAAI,IAAA;AACF,IAAM,MAAA,MAAA,GAASG,0BAAa,CAAA,KAAA,EAAO,IAAM,EAAA;AAAA,MACvC,QAAU,EAAA,MAAA;AAAA,MACV,SAAA,EAAW,OAAO,IAAO,GAAA,EAAA;AAAA,MACzB,KAAO,EAAA,CAAC,QAAU,EAAA,MAAA,EAAQ,MAAM;AAAA,KACjC,CAAA;AAED,IAAO,OAAA,UAAA,GAAa,MAAO,CAAA,IAAA,EAAS,GAAA,MAAA;AAAA,WAC7B,KAAO,EAAA;AACd,IAAY,WAAA,CAAA,oBAAA,EAAsB,CAAG,EAAA,IAAA,CAAK,IAAK,CAAA,GAAG,CAAC,CAAM,GAAA,EAAA,eAAA,CAAgB,KAAK,CAAC,CAAE,CAAA,CAAA;AAEjF,IAAA,IAAI,YAAc,EAAA;AAChB,MAAO,OAAA,EAAA;AAAA;AAGT,IAAM,MAAA,KAAA;AAAA;AAEV;AAUA,eAAsB,+BAAgC,CAAA,OAAA,EAAiB,OAAuC,GAAA,EAAI,EAAA;AAChH,EAAA,MAAM,EAAE,kBAAqB,GAAA,GAAA,EAAO,kBAAkB,gFAAsB,EAAA,YAAA,GAAe,OAAU,GAAA,OAAA;AACrG,EAAA,MAAM,EAAE,KAAA,EAAU,GAAA,MAAM,OAAO,eAAe,CAAA;AAE9C,EAAA,OAAO,IAAI,OAAA,CAA4C,CAAC,OAAA,EAAS,MAAW,KAAA;AAC1E,IAAA,IAAI,MAAS,GAAA,EAAA;AACb,IAAA,IAAI,MAAS,GAAA,EAAA;AACb,IAAM,MAAA,SAAA,GAAY,KAAK,GAAI,EAAA;AAC3B,IAAA,OAAA,CAAQ,IAAI,eAAe,CAAA;AAE3B,IAAA,MAAM,QAAQ,KAAM,CAAA,UAAA,EAAY,CAAC,KAAA,EAAO,OAAO,CAAG,EAAA;AAAA,MAChD,KAAO,EAAA,CAAC,QAAU,EAAA,MAAA,EAAQ,MAAM;AAAA,KACjC,CAAA;AAED,IAAM,MAAA,aAAA,GAAgB,YAAY,MAAM;AACtC,MAAM,MAAA,cAAA,GAAiB,IAAK,CAAA,GAAA,CAAI,CAAG,EAAA,IAAA,CAAK,KAAO,CAAA,CAAA,IAAA,CAAK,GAAI,EAAA,GAAI,SAAa,IAAA,GAAI,CAAC,CAAA;AAC9E,MAAA,OAAA,CAAQ,GAAI,CAAA,CAAA,EAAG,eAAe,CAAA,EAAA,EAAK,cAAc,CAAO,eAAA,CAAA,CAAA;AAAA,OACvD,kBAAkB,CAAA;AAErB,IAAA,KAAA,CAAM,MAAO,CAAA,EAAA,CAAG,MAAQ,EAAA,CAAC,KAA2B,KAAA;AAClD,MAAM,MAAA,IAAA,GAAO,MAAM,QAAS,EAAA;AAC5B,MAAU,MAAA,IAAA,IAAA;AAEV,MAAA,IAAI,YAAc,EAAA;AAChB,QAAQ,OAAA,CAAA,MAAA,CAAO,MAAM,IAAI,CAAA;AAAA;AAC3B,KACD,CAAA;AAED,IAAA,KAAA,CAAM,MAAO,CAAA,EAAA,CAAG,MAAQ,EAAA,CAAC,KAA2B,KAAA;AAClD,MAAM,MAAA,IAAA,GAAO,MAAM,QAAS,EAAA;AAC5B,MAAU,MAAA,IAAA,IAAA;AAEV,MAAA,IAAI,YAAc,EAAA;AAChB,QAAQ,OAAA,CAAA,MAAA,CAAO,MAAM,IAAI,CAAA;AAAA;AAC3B,KACD,CAAA;AAED,IAAM,KAAA,CAAA,EAAA,CAAG,OAAS,EAAA,CAAC,KAAU,KAAA;AAC3B,MAAA,aAAA,CAAc,aAAa,CAAA;AAC3B,MAAA,MAAA,CAAO,KAAK,CAAA;AAAA,KACb,CAAA;AAED,IAAA,KAAA,CAAM,EAAG,CAAA,OAAA,EAAS,CAAC,IAAA,EAAM,MAAW,KAAA;AAClC,MAAA,aAAA,CAAc,aAAa,CAAA;AAE3B,MAAA,IAAI,SAAS,CAAG,EAAA;AACd,QAAQ,OAAA,CAAA;AAAA,UACN,MAAA;AAAA,UACA;AAAA,SACD,CAAA;AAED,QAAA;AAAA;AAGF,MAAM,MAAA,WAAA,GAAc,SAAS,CAAU,OAAA,EAAA,MAAM,KAAK,CAAQ,KAAA,EAAA,MAAA,CAAO,IAAQ,IAAA,SAAS,CAAC,CAAA,CAAA;AACnF,MAAA,MAAM,cAA6C,GAAA;AAAA,QACjD,IAAA;AAAA,QACA,OAAA;AAAA,QACA,MAAA;AAAA,QACA,MAAA;AAAA,QACA;AAAA,OACF;AAEA,MAAO,MAAA,CAAA,gCAAA,CAAiC,cAAgB,EAAA,WAAW,CAAC,CAAA;AAAA,KACrE,CAAA;AAAA,GACF,CAAA;AACH;AAUA,SAAS,8BAA8B,cAA4C,EAAA;AACjF,EAAM,MAAA,UAAA,GAAa,cAAe,CAAA,MAAA,CAAO,IAAK,EAAA;AAC9C,EAAM,MAAA,UAAA,GAAa,cAAe,CAAA,MAAA,CAAO,IAAK,EAAA;AAC9C,EAAA,MAAM,iBAAiB,UAAc,IAAA,UAAA;AAErC,EAAA,IAAI,CAAC,cAAgB,EAAA;AACnB,IAAO,OAAA,EAAA;AAAA;AAGT,EAAA,MAAM,kBAAqB,GAAA,GAAA;AAE3B,EAAI,IAAA,cAAA,CAAe,UAAU,kBAAoB,EAAA;AAC/C,IAAO,OAAA,cAAA;AAAA;AAGT,EAAO,OAAA,cAAA,CAAe,KAAM,CAAA,IAAmB,CAAA;AACjD;AAWA,SAAS,gCAAA,CAAiC,gBAA4C,WAAqB,EAAA;AACzG,EAAM,MAAA,cAAA,GAAiB,8BAA8B,cAAc,CAAA;AACnE,EAAA,MAAM,QAAQ,IAAI,KAAA,CAAM,CAAe,+CAAA,EAAA,WAAW,IAAI,cAAiB,GAAA;AAAA,EAAK,cAAc,CAAK,CAAA,GAAA,EAAE,CAAE,CAAA,CAAA;AAGnG,EAAA,KAAA,CAAM,OAAO,cAAe,CAAA,IAAA;AAC5B,EAAA,KAAA,CAAM,SAAS,cAAe,CAAA,MAAA;AAC9B,EAAA,KAAA,CAAM,SAAS,cAAe,CAAA,MAAA;AAC9B,EAAA,KAAA,CAAM,SAAS,cAAe,CAAA,MAAA;AAC9B,EAAA,KAAA,CAAM,UAAU,cAAe,CAAA,OAAA;AAE/B,EAAO,OAAA,KAAA;AACT;AAUO,SAAS,uBAAA,CAAwB,KAAiB,EAAA,YAAA,GAAe,CAAG,EAAA;AACzE,EAAI,IAAA,KAAA,CAAM,WAAW,CAAG,EAAA;AACtB,IAAO,OAAA,gBAAA;AAAA;AAGT,EAAA,MAAM,YAAe,GAAA,KAAA,CAAM,KAAM,CAAA,CAAA,EAAG,YAAY,CAAA;AAChD,EAAA,MAAM,cAAc,IAAK,CAAA,GAAA,CAAI,GAAG,KAAM,CAAA,MAAA,GAAS,aAAa,MAAM,CAAA;AAElE,EAAA,IAAI,gBAAgB,CAAG,EAAA;AACrB,IAAO,OAAA,YAAA,CAAa,KAAK,IAAI,CAAA;AAAA;AAG/B,EAAA,OAAO,GAAG,YAAa,CAAA,IAAA,CAAK,IAAI,CAAC,WAAM,WAAW,CAAA,MAAA,CAAA;AACpD;AAEO,SAAS,kBAAkB,KAAe,EAAA,IAAA,GAAiB,QAAQ,IAAK,CAAA,KAAA,CAAM,CAAC,CAAG,EAAA;AACvF,EAAM,MAAA,OAAA,GAAU,WAAW,IAAI,CAAA;AAE/B,EAAO,OAAA,CAAC,MAAc,MAAoB,KAAA;AACxC,IAAA,MAAM,SAAY,GAAA,iBAAA,IAAI,IAAK,EAAA,EAAE,WAAY,EAAA;AACzC,IAAA,MAAM,OAAU,GAAA,CAAA,CAAA,EAAI,SAAS,CAAA,SAAA,EAAY,KAAK,CAAA,EAAA,EAAK,IAAI,CAAA,EAAG,MAAS,GAAA,CAAA,GAAA,EAAM,MAAM,CAAA,CAAA,GAAK,EAAE,CAAA,CAAA;AACtF,IAAA,aAAA,CAAc,KAAK,OAAO,CAAA;AAE1B,IAAA,IAAI,CAAC,OAAS,EAAA;AACZ,MAAA;AAAA;AAGF,IAAA,OAAA,CAAQ,IAAI,OAAO,CAAA;AAAA,GACrB;AACF;AAEA,IAAM,WAAA,GAAc,kBAAkB,QAAQ,CAAA;AAE9C,SAAS,iBAAkB,CAAA,GAAA,mBAAU,IAAA,IAAA,EAAQ,EAAA;AAC3C,EAAO,OAAA;AAAA,IACL,IAAA,EAAM,IAAI,WAAY,EAAA;AAAA,IACtB,EAAA,EAAI,OAAO,GAAI,CAAA,QAAA,KAAa,CAAC,CAAA,CAAE,QAAS,CAAA,CAAA,EAAG,GAAG,CAAA;AAAA,IAC9C,EAAA,EAAI,OAAO,GAAI,CAAA,OAAA,EAAS,CAAE,CAAA,QAAA,CAAS,GAAG,GAAG,CAAA;AAAA,IACzC,EAAA,EAAI,OAAO,GAAI,CAAA,QAAA,EAAU,CAAE,CAAA,QAAA,CAAS,GAAG,GAAG,CAAA;AAAA,IAC1C,EAAA,EAAI,OAAO,GAAI,CAAA,UAAA,EAAY,CAAE,CAAA,QAAA,CAAS,GAAG,GAAG,CAAA;AAAA,IAC5C,EAAA,EAAI,OAAO,GAAI,CAAA,UAAA,EAAY,CAAE,CAAA,QAAA,CAAS,GAAG,GAAG;AAAA,GAC9C;AACF;AAEA,SAAS,yBAA0B,CAAA,GAAA,mBAAU,IAAA,IAAA,EAAQ,EAAA;AACnD,EAAM,MAAA,EAAE,MAAM,EAAI,EAAA,EAAA,EAAI,IAAI,EAAI,EAAA,EAAA,EAAO,GAAA,iBAAA,CAAkB,GAAG,CAAA;AAE1D,EAAO,OAAA,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA;AAC9C;AAEA,SAAS,iBAAiB,KAAgB,EAAA;AACxC,EAAI,IAAA,KAAA,KAAU,MAAa,IAAA,KAAA,KAAU,IAAM,EAAA;AACzC,IAAO,OAAA,EAAA;AAAA;AAGT,EAAI,IAAA,OAAO,UAAU,QAAU,EAAA;AAC7B,IAAO,OAAA,KAAA;AAAA;AAGT,EAAI,IAAA,MAAA,CAAO,QAAS,CAAA,KAAK,CAAG,EAAA;AAC1B,IAAA,OAAO,MAAM,QAAS,EAAA;AAAA;AAGxB,EAAA,IAAI,iBAAiB,KAAO,EAAA;AAC1B,IAAO,OAAA,KAAA,CAAM,SAAS,KAAM,CAAA,OAAA;AAAA;AAG9B,EAAA,OAAOC,aAAQ,KAAO,EAAA,EAAE,OAAO,CAAG,EAAA,WAAA,EAAa,KAAK,CAAA;AACtD;AAEO,SAAS,gBAAgB,KAAgB,EAAA;AAC9C,EAAA,IAAI,iBAAiB,KAAO,EAAA;AAC1B,IAAA,OAAO,CAAG,EAAA,KAAA,CAAM,IAAI,CAAA,EAAA,EAAK,MAAM,OAAO,CAAA,CAAA;AAAA;AAGxC,EAAO,OAAA,gBAAA,CAAiB,KAAK,CAAK,IAAA,eAAA;AACpC;AAEA,SAAS,eAAe,KAAgB,EAAA;AACtC,EAAA,MAAM,UAAsC,GAAA;AAAA,IAC1C,OAAA,EAAS,gBAAgB,KAAK;AAAA,GAChC;AAEA,EAAA,IAAI,iBAAiB,KAAO,EAAA;AAC1B,IAAA,UAAA,CAAW,OAAO,KAAM,CAAA,IAAA;AACxB,IAAA,UAAA,CAAW,UAAU,KAAM,CAAA,OAAA;AAC3B,IAAA,UAAA,CAAW,QAAQ,KAAM,CAAA,KAAA;AAAA,GACpB,MAAA;AACL,IAAW,UAAA,CAAA,KAAA,GAAQ,iBAAiB,KAAK,CAAA;AAAA;AAG3C,EAAI,IAAA,KAAA,IAAS,OAAO,KAAA,KAAU,QAAU,EAAA;AACtC,IAAA,MAAM,SAAY,GAAA,KAAA;AAClB,IAAM,MAAA,SAAA,GAAY,CAAC,MAAA,EAAQ,OAAS,EAAA,SAAA,EAAW,QAAQ,KAAO,EAAA,QAAA,EAAU,QAAU,EAAA,WAAA,EAAa,SAAS,CAAA;AAExG,IAAU,SAAA,CAAA,OAAA,CAAQ,CAAC,GAAQ,KAAA;AACzB,MAAI,IAAA,SAAA,CAAU,GAAG,CAAA,KAAM,MAAW,EAAA;AAChC,QAAW,UAAA,CAAA,GAAG,CAAI,GAAA,SAAA,CAAU,GAAG,CAAA;AAAA;AACjC,KACD,CAAA;AAED,IAAM,MAAA,MAAA,GAAS,gBAAiB,CAAA,SAAA,CAAU,MAAM,CAAA;AAChD,IAAA,IAAI,MAAQ,EAAA;AACV,MAAA,UAAA,CAAW,MAAS,GAAA,MAAA;AAAA;AAGtB,IAAM,MAAA,MAAA,GAAS,gBAAiB,CAAA,SAAA,CAAU,MAAM,CAAA;AAChD,IAAA,IAAI,MAAQ,EAAA;AACV,MAAA,UAAA,CAAW,MAAS,GAAA,MAAA;AAAA;AAGtB,IAAM,MAAA,KAAA,GAAQ,gBAAiB,CAAA,SAAA,CAAU,KAAK,CAAA;AAC9C,IAAA,IAAI,KAAO,EAAA;AACT,MAAA,UAAA,CAAW,KAAQ,GAAA,KAAA;AAAA;AACrB;AAGF,EAAO,OAAA,UAAA;AACT;AAEO,SAAS,eAAA,CAAgB,GAAa,EAAA,QAAA,EAAkB,SAAmB,EAAA;AAChF,EAAA,IAAI,OAAU,GAAA,CAAA;AAEd,EAAA,OAAO,IAAM,EAAA;AACX,IAAM,MAAA,QAAA,GAAWJ,qBAAK,CAAA,IAAA,CAAK,GAAK,EAAA,CAAA,EAAG,QAAQ,CAAI,CAAA,EAAA,OAAO,CAAG,EAAA,SAAS,CAAE,CAAA,CAAA;AACpE,IAAA,IAAI,CAACE,mBAAA,CAAG,UAAW,CAAA,QAAQ,CAAG,EAAA;AAC5B,MAAO,OAAA,QAAA;AAAA;AAET,IAAA,OAAA,EAAA;AAAA;AAEJ;AAEO,SAAS,oBAAA,CAAqB,GAAa,EAAA,QAAA,EAAkB,SAAmB,EAAA;AACrF,EAAM,MAAA,aAAA,GAAgBF,sBAAK,IAAK,CAAA,GAAA,EAAK,GAAG,QAAQ,CAAA,EAAG,SAAS,CAAE,CAAA,CAAA;AAC9D,EAAA,IAAI,CAACE,mBAAA,CAAG,UAAW,CAAA,aAAa,CAAG,EAAA;AACjC,IAAO,OAAA,aAAA;AAAA;AAGT,EAAO,OAAA,eAAA,CAAgB,GAAK,EAAA,QAAA,EAAU,SAAS,CAAA;AACjD;AAEO,SAAS,WAAW,QAAkB,EAAA;AAC3C,EAAI,IAAAA,mBAAA,CAAG,UAAW,CAAA,QAAQ,CAAG,EAAA;AAC3B,IAAAA,mBAAA,CAAG,WAAW,QAAQ,CAAA;AAAA;AAE1B;AAKO,SAAS,cAAiB,GAAA;AAC/B,EAAA,UAAA,CAAW,YAAY,CAAA;AACzB;AAKO,SAAS,qBAAwB,GAAA;AACtC,EAAA,IAAI,CAACA,mBAAA,CAAG,UAAW,CAAA,UAAU,CAAG,EAAA;AAC9B,IAAAA,mBAAA,CAAG,SAAU,CAAA,UAAA,EAAY,EAAE,SAAA,EAAW,MAAM,CAAA;AAAA;AAEhD;AAKO,SAAS,YAAa,CAAA,GAAA,mBAAU,IAAA,IAAA,EAAQ,EAAA;AAC7C,EAAM,MAAA,EAAE,MAAM,EAAI,EAAA,EAAA,EAAI,IAAI,EAAI,EAAA,EAAA,EAAO,GAAA,iBAAA,CAAkB,GAAG,CAAA;AAE1D,EAAO,OAAA,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA;AAC9C;AAEO,SAAS,oBAAqB,CAAA,GAAA,mBAAU,IAAA,IAAA,EAAQ,EAAA;AACrD,EAAM,MAAA,EAAE,MAAM,EAAI,EAAA,EAAA,EAAI,IAAI,EAAI,EAAA,EAAA,EAAO,GAAA,iBAAA,CAAkB,GAAG,CAAA;AAE1D,EAAO,OAAA,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA,EAAI,EAAE,CAAA,OAAA,EAAK,EAAE,CAAA,OAAA,EAAK,EAAE,CAAA,MAAA,CAAA;AAChD;AAEO,SAAS,gBAAiB,CAAA,KAAA,EAAgB,OAAmC,GAAA,EAAI,EAAA;AACtF,EAAI,IAAA;AACF,IAAM,MAAA,GAAA,uBAAU,IAAK,EAAA;AACrB,IAAY,WAAA,CAAA,0BAAA,EAA4B,OAAQ,CAAA,KAAA,IAAS,SAAS,CAAA;AAClE,IAAsB,qBAAA,EAAA;AAEtB,IAAM,MAAA,UAAA,GAAa,qBAAqB,UAAY,EAAA,CAAA,UAAA,EAAa,qBAAqB,GAAG,CAAC,IAAI,KAAK,CAAA;AACnG,IAAM,MAAA,eAAA,GAAkB,eAAe,KAAK,CAAA;AAC5C,IAAM,MAAA,aAAA,GAAgB,OAAQ,CAAA,aAAA,IAAiB,gBAAiB,EAAA;AAChE,IAAM,MAAA,aAAA,GAAgB,OAAQ,CAAA,aAAA,IAAiB,EAAC;AAEhD,IAAA,MAAM,MAAS,GAAA,CAAA;;AAAA,6BAER,EAAA,yBAAA,CAA0B,GAAG,CAAC;AAAA,WAC5B,EAAA,OAAA,CAAQ,SAAS,SAAS,CAAA;AAAA,+BAC1B,EAAA,OAAA,CAAQ,KAAK,CAAA;AAAA,+BACb,EAAA,IAAA,CAAK,UAAU,OAAQ,CAAA,IAAA,IAAQ,QAAQ,IAAK,CAAA,KAAA,CAAM,CAAC,CAAC,CAAC,CAAA;AAAA,+BAAA,EACrD,QAAQ,QAAQ,CAAA,CAAA,EAAI,QAAQ,IAAI,CAAA,QAAA,EAAW,QAAQ,OAAO,CAAA;;AAAA;;AAAA,EAIrE,OAAQ,CAAA,KAAA,IAAS,eAAgB,CAAA,OAAA,IAAW,eAAe;;AAAA;;AAAA;AAAA,EAK3D,IAAK,CAAA,SAAA,CAAU,eAAiB,EAAA,IAAA,EAAM,CAAC,CAAC;AAAA;;AAAA;;AAAA;AAAA,EAMxC,IAAK,CAAA,SAAA,CAAU,aAAe,EAAA,IAAA,EAAM,CAAC,CAAC;AAAA,MAAA,EAChC,cAAc,MAAS,GAAA;AAAA,EAAK,aAAA,CAAc,GAAI,CAAA,CAAC,OAAY,KAAA;AAAA,GAAA,EAAQ,QAAQ,OAAO;;AAAA,EAAO,QAAQ,QAAQ,CAAA,CAAE,CAAE,CAAA,IAAA,CAAK,IAAI,CAAC;AAAA,CAAA,GAAO,IAAI;AAAA,CAAA;AAGtI,IAAGA,mBAAA,CAAA,aAAA,CAAc,YAAY,MAAM,CAAA;AACnC,IAAA,WAAA,CAAY,2BAA2B,UAAU,CAAA;AAEjD,IAAO,OAAA,UAAA;AAAA,WACA,UAAY,EAAA;AACnB,IAAA,OAAA,CAAQ,MAAM,8GAAyB,CAAA;AACvC,IAAA,OAAA,CAAQ,MAAM,UAAU,CAAA;AAExB,IAAO,OAAA,EAAA;AAAA;AAEX;AAEA,SAAS,sBAAA,CAAuB,QAA4B,KAAgB,EAAA;AAC1E,EAAA,IAAI,KAAO,EAAA;AACT,IAAO,OAAA,KAAA;AAAA;AAGT,EAAA,QAAQ,MAAQ;AAAA,IACd,KAAK,SAAA;AACH,MAAO,OAAA,4GAAA;AAAA,IACT,KAAK,QAAA;AACH,MAAO,OAAA,2FAAA;AAAA,IACT,KAAK,iBAAA;AACH,MAAO,OAAA,qKAAA;AAAA,IACT;AACE,MAAO,OAAA,+JAAA;AAAA;AAEb;AAEA,SAAS,uBAAA,CAAwB,WAAiB,UAAkB,EAAA;AAClE,EAAM,MAAA,UAAA,GAAa,KAAK,GAAI,CAAA,CAAA,EAAG,WAAW,OAAQ,EAAA,GAAI,SAAU,CAAA,OAAA,EAAS,CAAA;AAEzE,EAAA,IAAI,aAAa,GAAM,EAAA;AACrB,IAAA,OAAO,GAAG,UAAU,CAAA,EAAA,CAAA;AAAA;AAGtB,EAAA,MAAM,kBAAkB,UAAa,GAAA,GAAA;AAErC,EAAA,IAAI,kBAAkB,EAAI,EAAA;AACxB,IAAA,OAAO,CAAG,EAAA,eAAA,CAAgB,OAAQ,CAAA,CAAC,CAAC,CAAA,CAAA,CAAA;AAAA;AAGtC,EAAA,MAAM,OAAU,GAAA,IAAA,CAAK,KAAM,CAAA,eAAA,GAAkB,EAAE,CAAA;AAC/C,EAAA,MAAM,OAAU,GAAA,IAAA,CAAK,KAAM,CAAA,eAAA,GAAkB,EAAE,CAAA;AAE/C,EAAO,OAAA,CAAA,EAAG,OAAO,CAAA,EAAA,EAAK,OAAO,CAAA,CAAA,CAAA;AAC/B;AASO,SAAS,iBAAA,CAAkB,OAAoC,GAAA,EAAI,EAAA;AACxE,EAAI,IAAA;AACF,IAAA,MAAM,SAAY,GAAA,OAAA,CAAQ,SAAa,oBAAA,IAAI,IAAK,EAAA;AAChD,IAAA,MAAM,UAAa,GAAA,OAAA,CAAQ,UAAc,oBAAA,IAAI,IAAK,EAAA;AAClD,IAAM,MAAA,MAAA,GAAS,QAAQ,MAAU,IAAA,SAAA;AACjC,IAAY,WAAA,CAAA,2BAAA,EAA6B,OAAQ,CAAA,KAAA,IAAS,SAAS,CAAA;AACnE,IAAsB,qBAAA,EAAA;AAEtB,IAAM,MAAA,UAAA,GAAa,qBAAqB,UAAY,EAAA,CAAA,EAAG,aAAa,UAAU,CAAC,kBAAkB,KAAK,CAAA;AACtG,IAAM,MAAA,aAAA,GAAgB,OAAQ,CAAA,aAAA,IAAiB,gBAAiB,EAAA;AAChE,IAAM,MAAA,aAAA,GAAgB,OAAQ,CAAA,aAAA,IAAiB,EAAC;AAChD,IAAA,MAAM,kBAAkB,OAAQ,CAAA,KAAA,GAAQ,cAAe,CAAA,OAAA,CAAQ,KAAK,CAAI,GAAA,IAAA;AAExE,IAAA,MAAM,MAAS,GAAA,CAAA;;AAAA,6BAER,EAAA,yBAAA,CAA0B,SAAS,CAAC;AAAA,6BACpC,EAAA,yBAAA,CAA0B,UAAU,CAAC;AAAA,6BACrC,EAAA,uBAAA,CAAwB,SAAW,EAAA,UAAU,CAAC;AAAA,kBAAA,EAC/C,MAAM,CAAA;AAAA,WACH,EAAA,OAAA,CAAQ,SAAS,SAAS,CAAA;AAAA,+BAC1B,EAAA,OAAA,CAAQ,KAAK,CAAA;AAAA,+BACb,EAAA,IAAA,CAAK,UAAU,OAAQ,CAAA,IAAA,IAAQ,QAAQ,IAAK,CAAA,KAAA,CAAM,CAAC,CAAC,CAAC,CAAA;AAAA,+BAAA,EACrD,QAAQ,QAAQ,CAAA,CAAA,EAAI,QAAQ,IAAI,CAAA,QAAA,EAAW,QAAQ,OAAO,CAAA;;AAAA;;AAAA,EAIrE,sBAAuB,CAAA,MAAA,EAAQ,OAAQ,CAAA,KAAK,CAAC;AAAA,EAC7C,eAAkB,GAAA;;AAAA;;AAAA;AAAA,EAA+B,IAAK,CAAA,SAAA,CAAU,eAAiB,EAAA,IAAA,EAAM,CAAC,CAAC;AAAA,MAAA,CAAA,GAAa,EAAE;;AAAA;;AAAA;AAAA,EAKxG,IAAK,CAAA,SAAA,CAAU,aAAe,EAAA,IAAA,EAAM,CAAC,CAAC;AAAA,MAAA,EAChC,cAAc,MAAS,GAAA;AAAA,EAAK,aAAA,CAAc,GAAI,CAAA,CAAC,OAAY,KAAA;AAAA,GAAA,EAAQ,QAAQ,OAAO;;AAAA,EAAO,QAAQ,QAAQ,CAAA,CAAE,CAAE,CAAA,IAAA,CAAK,IAAI,CAAC;AAAA,CAAA,GAAO,IAAI;AAAA,CAAA;AAGtI,IAAGA,mBAAA,CAAA,aAAA,CAAc,YAAY,MAAM,CAAA;AACnC,IAAA,WAAA,CAAY,4BAA4B,UAAU,CAAA;AAElD,IAAO,OAAA,UAAA;AAAA,WACA,UAAY,EAAA;AACnB,IAAA,OAAA,CAAQ,MAAM,8GAAyB,CAAA;AACvC,IAAA,OAAA,CAAQ,MAAM,UAAU,CAAA;AAExB,IAAO,OAAA,EAAA;AAAA;AAEX;AAEO,SAAS,aACd,CAAA,OAAA,EACA,OAAwE,GAAA,EACjE,EAAA;AACP,EAAA,MAAM,aAAa,gBAAiB,CAAA,OAAA,CAAQ,SAAS,IAAI,KAAA,CAAM,OAAO,CAAG,EAAA;AAAA,IACvE,GAAG,OAAA;AAAA,IACH,KAAO,EAAA;AAAA,GACR,CAAA;AAED,EAAA,OAAA,CAAQ,MAAM,OAAO,CAAA;AAErB,EAAA,IAAI,QAAQ,KAAO,EAAA;AACjB,IAAQ,OAAA,CAAA,KAAA,CAAM,QAAQ,KAAK,CAAA;AAAA;AAG7B,EAAA,IAAI,UAAY,EAAA;AACd,IAAQ,OAAA,CAAA,KAAA,CAAM,CAAmB,+DAAA,EAAA,UAAU,CAAE,CAAA,CAAA;AAAA;AAG/C,EAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAChB;AAEA,SAAS,qBAAqB,IAAiB,GAAA,OAAA,CAAQ,IAAK,CAAA,KAAA,CAAM,CAAC,CAAuB,EAAA;AACxF,EAAA,WAAA,CAAY,uBAAuB,CAAQ,KAAA,EAAA,IAAA,CAAK,SAAU,CAAA,IAAI,CAAC,CAAE,CAAA,CAAA;AACjE,EAAM,MAAA,YAAA,GAAe,IAAK,CAAA,OAAA,CAAQ,WAAW,CAAA;AAC7C,EAAA,MAAM,aAAa,YAAiB,KAAA,EAAA,GAAK,IAAK,CAAA,YAAA,GAAe,CAAC,CAAI,GAAA,EAAA;AAElE,EAAA,IAAI,CAAC,UAAY,EAAA;AACf,IAAA,WAAA,CAAY,qBAAqB,CAAA;AAEjC,IAAO,OAAA,EAAA;AAAA;AAGT,EAAM,MAAA,iBAAA,GAAoB,WAAW,WAAY,EAAA;AAEjD,EAAI,IAAA,UAAA,CAAW,QAAS,CAAA,iBAAkC,CAAG,EAAA;AAC3D,IAAA,WAAA,CAAY,0BAA0B,iBAAiB,CAAA;AAEvD,IAAO,OAAA,iBAAA;AAAA;AAGT,EAAA,WAAA,CAAY,yBAAyB,UAAU,CAAA;AAC/C,EAAA,aAAA;AAAA,IACE,sFAAqB,UAAU,CAAA,oCAAA,EAAc,UAAW,CAAA,IAAA,CAAK,IAAI,CAAC,CAAA,0BAAA,CAAA;AAAA,IAClE;AAAA,MACE,KAAO,EAAA,6BAAA;AAAA,MACP,IAAA;AAAA,MACA,aAAe,EAAA;AAAA,QACb;AAAA,UACE,OAAS,EAAA,kBAAA;AAAA,UACT,QAAU,EAAA,CAAA;AAAA,EAAe,IAAK,CAAA,SAAA,CAAU,UAAY,EAAA,IAAA,EAAM,CAAC,CAAC;AAAA,MAAA;AAAA;AAC9D;AACF;AACF,GACF;AACF;AAEO,SAAS,gBAAmB,GAAA;AACjC,EAAA,MAAM,EAAE,eAAA,EAAiB,eAAgB,EAAA,GAAI,mBAAoB,EAAA;AACjE,EAAA,MAAM,KAAQ,GAAA,CAAC,OAAoB,KAAA,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA,CAAA;AAC9C,EAAA,MAAM,gBAAgB,eAAgB,CAAA,GAAA,CAAI,KAAK,CAAA,CAAE,KAAK,GAAG,CAAA;AACzD,EAAA,MAAM,gBAAgB,eAAgB,CAAA,GAAA,CAAI,KAAK,CAAA,CAAE,KAAK,GAAG,CAAA;AAEzD,EAAO,OAAA,EAAE,eAAe,aAAc,EAAA;AACxC;AASA,SAAS,sBAAsB,OAAiB,EAAA;AAC9C,EAAI,IAAA,OAAA,CAAQ,UAAU,EAAI,EAAA;AACxB,IAAO,OAAA,OAAA;AAAA;AAGT,EAAA,OAAO,CAAG,EAAA,OAAA,CAAQ,KAAM,CAAA,CAAA,EAAG,EAAE,CAAC,CAAA,GAAA,CAAA;AAChC;AAQO,SAAS,sBAAyC,GAAA;AACvD,EAAA,MAAM,MAAS,GAAA,aAAA;AAAA,IACb,CAAC,KAAO,EAAA,CAAA,CAAA,EAAI,kBAAkB,CAAA,CAAA,EAAI,mBAAmB,wCAAwC,CAAA;AAAA,IAC7F,EAAE,cAAc,IAAK;AAAA,GACvB;AAEA,EAAA,IAAI,CAAC,MAAQ,EAAA;AACX,IAAA,OAAO,EAAC;AAAA;AAGV,EAAA,OAAO,OAAO,KAAM,CAAA,IAAI,CAAE,CAAA,GAAA,CAAI,CAAC,IAAS,KAAA;AACtC,IAAA,MAAM,CAAC,IAAA,GAAO,EAAI,EAAA,MAAA,GAAS,EAAI,EAAA,YAAA,GAAe,EAAI,EAAA,GAAG,YAAY,CAAA,GAAI,IAAK,CAAA,KAAA,CAAM,GAAI,CAAA;AACpF,IAAA,MAAM,OAAU,GAAA,YAAA,CAAa,IAAK,CAAA,GAAI,EAAE,IAAK,EAAA;AAE7C,IAAO,OAAA;AAAA,MACL,MAAA;AAAA,MACA,WAAa,EAAA,CAAA,EAAG,MAAM,CAAA,GAAA,EAAM,YAAY,CAAA,CAAA;AAAA,MACxC,IAAA;AAAA,MACA,OAAO,CAAG,EAAA,IAAI,CAAM,GAAA,EAAA,qBAAA,CAAsB,OAAO,CAAC,CAAA,CAAA;AAAA,MAClD,YAAA;AAAA,MACA;AAAA,KACF;AAAA,GACD,CAAA;AACH;AAQO,SAAS,2BAA2B,OAAyB,EAAA;AAClE,EAAA,OAAO,QAAQ,GAAI,CAAA,CAAC,WAAW,CAAK,EAAA,EAAA,MAAA,CAAO,IAAI,CAAM,GAAA,EAAA,MAAA,CAAO,OAAO,CAAM,GAAA,EAAA,MAAA,CAAO,MAAM,CAAM,GAAA,EAAA,MAAA,CAAO,YAAY,CAAE,CAAA,CAAA,CAAE,KAAK,IAAI,CAAA;AAC9H;AAQA,SAAS,qBAAwB,GAAA;AAC/B,EAAA,MAAM,EAAE,eAAA,EAAiB,eAAgB,EAAA,GAAI,mBAAoB,EAAA;AAEjE,EAAA,OAAO,CAAC,GAAG,eAAiB,EAAA,GAAG,eAAe,CAAA;AAChD;AASO,SAAS,wBAAwB,OAAyB,EAAA;AAC/D,EAAA,MAAM,qBAAqB,qBAAsB,EAAA;AACjD,EAAA,MAAM,QAAW,GAAA,OAAA,CACd,GAAI,CAAA,CAAC,MAAW,KAAA;AACf,IAAA,MAAM,IAAO,GAAA,aAAA,CAAc,CAAC,MAAA,EAAQ,QAAU,EAAA,SAAA,EAAW,WAAa,EAAA,MAAA,CAAO,IAAM,EAAA,IAAA,EAAM,GAAG,kBAAkB,CAAG,EAAA;AAAA,MAC/G,YAAc,EAAA,IAAA;AAAA,MACd,UAAY,EAAA;AAAA,KACb,EAAE,IAAK,EAAA;AAER,IAAA,IAAI,CAAC,IAAM,EAAA;AACT,MAAO,OAAA,EAAA;AAAA;AAGT,IAAO,OAAA,CAAC,CAAM,GAAA,EAAA,MAAA,CAAO,IAAI,CAAA,CAAA,EAAI,MAAO,CAAA,OAAO,CAAI,CAAA,EAAA,IAAI,CAAE,CAAA,IAAA,CAAK,MAAM,CAAA;AAAA,GACjE,CACA,CAAA,MAAA,CAAO,OAAO,CAAA,CACd,KAAK,MAAM,CAAA;AAEd,EAAA,IAAI,CAAC,QAAU,EAAA;AACb,IAAO,OAAA,EAAA;AAAA;AAGT,EAAO,OAAA,CAAC,mCAAY,EAAA,0BAAA,CAA2B,OAAO,CAAA,EAAG,IAAI,kCAAgB,EAAA,QAAQ,CAAE,CAAA,IAAA,CAAK,IAAI,CAAA;AAClG;AASO,SAAS,uBAAuB,OAAyB,EAAA;AAC9D,EAAA,MAAM,qBAAqB,qBAAsB,EAAA;AACjD,EAAM,MAAA,KAAA,uBAAY,GAAY,EAAA;AAE9B,EAAQ,OAAA,CAAA,OAAA,CAAQ,CAAC,MAAW,KAAA;AAC1B,IAAM,MAAA,MAAA,GAAS,aAAc,CAAA,CAAC,MAAQ,EAAA,kBAAA,EAAoB,aAAe,EAAA,MAAA,CAAO,IAAM,EAAA,IAAA,EAAM,GAAG,kBAAkB,CAAG,EAAA;AAAA,MAClH,YAAc,EAAA;AAAA,KACf,CAAA;AAED,IAAA,MAAA,CACG,MAAM,IAAI,CAAA,CACV,IAAI,CAAC,IAAA,KAAS,KAAK,IAAK,EAAC,EACzB,MAAO,CAAA,OAAO,EACd,OAAQ,CAAA,CAAC,aAAa,KAAM,CAAA,GAAA,CAAI,QAAQ,CAAC,CAAA;AAAA,GAC7C,CAAA;AAED,EAAO,OAAA,CAAC,GAAG,KAAK,CAAA;AAClB;AAUO,SAAS,qBAAA,CAAsB,SAAyB,QAAkB,EAAA;AAC/E,EAAA,MAAM,QAAW,GAAA,OAAA,CACd,GAAI,CAAA,CAAC,MAAW,KAAA;AACf,IAAM,MAAA,IAAA,GAAO,aAAc,CAAA,CAAC,MAAQ,EAAA,QAAA,EAAU,SAAW,EAAA,WAAA,EAAa,MAAO,CAAA,IAAA,EAAM,IAAM,EAAA,QAAQ,CAAG,EAAA;AAAA,MAClG,YAAc,EAAA,IAAA;AAAA,MACd,UAAY,EAAA;AAAA,KACb,EAAE,IAAK,EAAA;AAER,IAAA,IAAI,CAAC,IAAM,EAAA;AACT,MAAO,OAAA,EAAA;AAAA;AAGT,IAAO,OAAA,CAAC,CAAM,GAAA,EAAA,MAAA,CAAO,IAAI,CAAA,CAAA,EAAI,MAAO,CAAA,OAAO,CAAI,CAAA,EAAA,IAAI,CAAE,CAAA,IAAA,CAAK,MAAM,CAAA;AAAA,GACjE,CACA,CAAA,MAAA,CAAO,OAAO,CAAA,CACd,KAAK,MAAM,CAAA;AAEd,EAAA,IAAI,CAAC,QAAU,EAAA;AACb,IAAO,OAAA,EAAA;AAAA;AAGT,EAAA,OAAO,CAAC,mCAAA,EAAY,0BAA2B,CAAA,OAAO,CAAG,EAAA,EAAA,EAAI,CAAS,gBAAA,EAAA,QAAQ,CAAI,CAAA,EAAA,QAAQ,CAAE,CAAA,IAAA,CAAK,MAAM,CAAA;AACzG;AAcO,SAAS,WAAW,UAAoB,EAAA;AAC7C,EAAM,MAAA,YAAA,GAAeF,qBAAK,CAAA,OAAA,CAAQ,UAAU,CAAA;AAC5C,EAAM,MAAA,EAAE,UAAa,GAAA,OAAA;AACrB,EAAA,WAAA,CAAY,qBAAqB,YAAY,CAAA;AAE7C,EAAA,MAAM,iBAAiB,MAAM;AAC3B,IAAA,IAAI,aAAa,QAAU,EAAA;AACzB,MAAAK,sBAAA,CAAS,4BAA4B,YAAY,CAAA,CAAA,CAAA,EAAK,EAAE,KAAA,EAAO,UAAU,CAAA;AAEzE,MAAO,OAAA,IAAA;AAAA;AAGT,IAAA,IAAI,aAAa,OAAS,EAAA;AACxB,MAAAA,sBAAA,CAAS,kBAAkB,YAAY,CAAA,CAAA,CAAA,EAAK,EAAE,KAAA,EAAO,UAAU,CAAA;AAE/D,MAAO,OAAA,IAAA;AAAA;AAGT,IAAO,OAAA,KAAA;AAAA,GACT;AAEA,EAAA,MAAM,yBAAyB,MAAM;AACnC,IAAA,IAAI,aAAa,QAAU,EAAA;AACzB,MAAAA,sBAAA,CAAS,SAAS,YAAY,CAAA,CAAA,CAAA,EAAK,EAAE,KAAA,EAAO,UAAU,CAAA;AAEtD,MAAO,OAAA,IAAA;AAAA;AAGT,IAAA,IAAI,aAAa,OAAS,EAAA;AACxB,MAAAA,sBAAA,CAAS,aAAa,YAAY,CAAA,CAAA,CAAA,EAAK,EAAE,KAAA,EAAO,UAAU,CAAA;AAE1D,MAAO,OAAA,IAAA;AAAA;AAGT,IAAO,OAAA,KAAA;AAAA,GACT;AAEA,EAAI,IAAA;AACF,IAAA,IAAI,gBAAkB,EAAA;AACpB,MAAA,WAAA,CAAY,8BAA8B,QAAQ,CAAA;AAClD,MAAA,OAAA,CAAQ,IAAI,8FAAgC,CAAA;AAE5C,MAAA;AAAA;AACF,WACO,KAAO,EAAA;AACd,IAAY,WAAA,CAAA,2BAAA,EAA6B,eAAgB,CAAA,KAAK,CAAC,CAAA;AAAA;AAIjE,EAAI,IAAA;AACF,IAAA,IAAI,wBAA0B,EAAA;AAC5B,MAAA,WAAA,CAAY,uCAAuC,QAAQ,CAAA;AAC3D,MAAA,OAAA,CAAQ,IAAI,sHAA0B,CAAA;AAEtC,MAAA;AAAA;AACF,WACO,KAAO,EAAA;AACd,IAAY,WAAA,CAAA,oCAAA,EAAsC,eAAgB,CAAA,KAAK,CAAC,CAAA;AACxE,IAAQ,OAAA,CAAA,KAAA,CAAM,oEAAkB,KAAK,CAAA;AAErC,IAAA;AAAA;AAGF,EAAA,WAAA,CAAY,oCAAoC,QAAQ,CAAA;AACxD,EAAQ,OAAA,CAAA,KAAA,CAAM,CAAsB,yFAAA,EAAA,QAAQ,CAAE,CAAA,CAAA;AAChD;AASA,SAAS,mCAAA,CAAoC,OAAe,OAAiB,EAAA;AAC3E,EAAI,IAAA,OAAA,CAAQ,KAAM,CAAA,KAAA,IAAS,OAAQ,CAAA,MAAA,CAAO,SAAS,OAAO,OAAA,CAAQ,KAAM,CAAA,UAAA,KAAe,UAAY,EAAA;AACjG,IAAA;AAAA;AAGF,EAAY,WAAA,CAAA,CAAA,EAAG,KAAK,CAAc,YAAA,CAAA,CAAA;AAClC,EAAA,aAAA,CAAc,OAAS,EAAA;AAAA,IACrB,KAAA,EAAO,UAAU,KAAK,CAAA;AAAA,GACvB,CAAA;AACH;AAWA,SAAS,oBAAA,CAAqB,OAAiB,iBAA2B,EAAA;AACxE,EAAA,IAAI,oBAAoB,CAAG,EAAA;AACzB,IAAAC,yBAAA,CAAS,UAAW,CAAA,OAAA,CAAQ,MAAQ,EAAA,CAAA,EAAG,CAAC,iBAAiB,CAAA;AACzD,IAASA,yBAAA,CAAA,eAAA,CAAgB,QAAQ,MAAM,CAAA;AAAA;AAGzC,EAAM,MAAA,WAAA,GAAc,mBAAmB,KAAK,CAAA;AAC5C,EAAA,OAAA,CAAQ,OAAO,KAAM,CAAA,CAAA,EAAG,WAAY,CAAA,IAAA,CAAK,IAAI,CAAC;AAAA,CAAI,CAAA;AAElD,EAAA,OAAO,WAAY,CAAA,MAAA;AACrB;AAUA,SAAS,uBAAA,CAAwB,WAAqB,EAAA,aAAA,EAAuB,UAAoB,EAAA;AAC/F,EAAA,IAAI,eAAe,UAAY,EAAA;AAC7B,IAAO,OAAA;AAAA,MACL,GAAK,EAAA,WAAA;AAAA,MACL,KAAO,EAAA;AAAA,KACT;AAAA;AAGF,EAAA,MAAM,UAAa,GAAA,IAAA,CAAK,KAAM,CAAA,UAAA,GAAa,CAAC,CAAA;AAC5C,EAAA,MAAM,WAAW,WAAc,GAAA,UAAA;AAC/B,EAAM,MAAA,KAAA,GAAQ,KAAK,GAAI,CAAA,CAAA,EAAG,KAAK,GAAI,CAAA,aAAA,GAAgB,UAAY,EAAA,QAAQ,CAAC,CAAA;AAExE,EAAO,OAAA;AAAA,IACL,GAAK,EAAA,IAAA,CAAK,GAAI,CAAA,WAAA,EAAa,QAAQ,UAAU,CAAA;AAAA,IAC7C;AAAA,GACF;AACF;AAaA,SAAS,qBACP,CAAA,QAAA,EACA,OACA,EAAA,aAAA,EACA,SACA,UACA,EAAA;AACA,EAAM,MAAA,EAAE,OAAO,GAAI,EAAA,GAAI,wBAAwB,OAAQ,CAAA,MAAA,EAAQ,eAAe,UAAU,CAAA;AACxF,EAAA,MAAM,KAAQ,GAAA;AAAA,IACZ,GAAG,IAAK,CAAA,IAAI,GAAG,QAAQ,CAAA,EAAG,KAAK,KAAK,CAAA,CAAA;AAAA,IACpC,CAAG,EAAA,IAAA,CAAK,GAAG,CAAA,mGAAA,EAA0C,KAAK,KAAK,CAAA,CAAA;AAAA,IAC/D,CAAA,EAAG,IAAK,CAAA,GAAG,CAAQ,oBAAA,EAAA,OAAA,CAAQ,IAAI,CAAA,uBAAA,EAAW,OAAQ,CAAA,MAAM,CAAI,MAAA,EAAA,IAAA,CAAK,KAAK,CAAA;AAAA,GACxE;AAEA,EAAA,KAAA,IAAS,KAAQ,GAAA,KAAA,EAAO,KAAQ,GAAA,GAAA,EAAK,SAAS,CAAG,EAAA;AAC/C,IAAM,MAAA,MAAA,GAAS,QAAQ,KAAK,CAAA;AAE5B,IAAA,IAAI,CAAC,MAAQ,EAAA;AACX,MAAA;AAAA;AAGF,IAAM,MAAA,MAAA,GAAS,UAAU,aAAgB,GAAA,CAAA,EAAG,KAAK,IAAI,CAAA,CAAA,EAAI,IAAK,CAAA,KAAK,CAAK,CAAA,GAAA,GAAA;AACxE,IAAM,MAAA,OAAA,GAAU,OAAQ,CAAA,GAAA,CAAI,KAAK,CAAA,GAAI,CAAG,EAAA,IAAA,CAAK,KAAK,CAAA,MAAA,EAAI,IAAK,CAAA,KAAK,CAAK,CAAA,GAAA,QAAA;AACrE,IAAA,MAAM,WAAc,GAAA,MAAA,CAAO,WAAc,GAAA,CAAA,CAAA,EAAI,IAAK,CAAA,GAAG,CAAG,EAAA,MAAA,CAAO,WAAW,CAAA,EAAG,IAAK,CAAA,KAAK,CAAK,CAAA,GAAA,EAAA;AAC5F,IAAM,KAAA,CAAA,IAAA,CAAK,CAAG,EAAA,MAAM,CAAI,CAAA,EAAA,OAAO,IAAI,MAAO,CAAA,KAAK,CAAG,EAAA,WAAW,CAAE,CAAA,CAAA;AAAA;AAGjE,EAAI,IAAA,OAAA,CAAQ,SAAS,UAAY,EAAA;AAC/B,IAAA,KAAA,CAAM,IAAK,CAAA,CAAA,EAAG,IAAK,CAAA,GAAG,8BAAU,KAAQ,GAAA,CAAC,CAAI,CAAA,EAAA,GAAG,MAAM,OAAQ,CAAA,MAAM,CAAG,EAAA,IAAA,CAAK,KAAK,CAAE,CAAA,CAAA;AAAA;AAGrF,EAAO,OAAA,KAAA;AACT;AAWA,eAAsB,eAAmB,CAAA,QAAA,EAAkB,OAAiC,EAAA,UAAA,GAAa,uBAAyB,EAAA;AAChI,EAAA,mCAAA,CAAoC,mBAAmB,4IAAmC,CAAA;AAC1F,EAAA,IAAI,aAAgB,GAAA,CAAA;AACpB,EAAA,IAAI,iBAAoB,GAAA,CAAA;AACxB,EAAM,MAAA,OAAA,uBAAc,GAAY,EAAA;AAChC,EAAM,MAAA,EAAA,GAAKA,0BAAS,eAAgB,CAAA;AAAA,IAClC,OAAO,OAAQ,CAAA,KAAA;AAAA,IACf,QAAQ,OAAQ,CAAA,MAAA;AAAA,IAChB,QAAU,EAAA;AAAA,GACX,CAAA;AAED,EAAQ,OAAA,CAAA,MAAA,CAAO,MAAM,WAAa,CAAA;AAElC,EAAA,MAAM,UAAU,MAAM;AACpB,IAAA,IAAI,oBAAoB,CAAG,EAAA;AACzB,MAAAA,yBAAA,CAAS,UAAW,CAAA,OAAA,CAAQ,MAAQ,EAAA,CAAA,EAAG,CAAC,iBAAiB,CAAA;AACzD,MAASA,yBAAA,CAAA,eAAA,CAAgB,QAAQ,MAAM,CAAA;AACvC,MAAoB,iBAAA,GAAA,CAAA;AAAA;AAEtB,IAAQ,OAAA,CAAA,KAAA,CAAM,cAAe,CAAA,MAAA,EAAQ,MAAM,CAAA;AAC3C,IAAQ,OAAA,CAAA,KAAA,CAAM,WAAW,KAAK,CAAA;AAC9B,IAAA,OAAA,CAAQ,MAAM,KAAM,EAAA;AACpB,IAAA,EAAA,CAAG,KAAM,EAAA;AACT,IAAQ,OAAA,CAAA,MAAA,CAAO,MAAM,WAAa,CAAA;AAAA,GACpC;AAEA,EAAA,MAAM,SAAS,MAAM;AACnB,IAAA,MAAM,QAAQ,qBAAsB,CAAA,QAAA,EAAU,OAAS,EAAA,aAAA,EAAe,SAAS,UAAU,CAAA;AACzF,IAAoB,iBAAA,GAAA,oBAAA,CAAqB,OAAO,iBAAiB,CAAA;AAAA,GACnE;AAEA,EAAM,MAAA,gBAAA,GAAmB,CAAC,OAAkC,KAAA;AAC1D,IAAM,MAAA,MAAA,GAAS,CAAC,GAAG,OAAO,CAAA,CACvB,KAAK,CAAC,IAAA,EAAM,KAAU,KAAA,IAAA,GAAO,KAAK,CAAA,CAClC,IAAI,CAAC,KAAA,KAAU,OAAQ,CAAA,KAAK,CAAG,EAAA,KAAK,EACpC,MAAO,CAAA,CAAC,KAAsB,KAAA,KAAA,KAAU,MAAS,CAAA;AAEpD,IAAQ,OAAA,EAAA;AACR,IAAA,OAAA,CAAQ,MAAM,CAAA;AAAA,GAChB;AAEA,EAAM,MAAA,eAAA,GAAkB,CAAC,OAAkC,KAAA;AACzD,IAAQ,OAAA,EAAA;AACR,IAAA,OAAA,CAAQ,EAAE,CAAA;AAAA,GACZ;AAEA,EAAI,IAAA,MAAA,GAAS,CAAC,KAAkB,KAAA;AAAA,GAEhC;AAEA,EAAO,MAAA,EAAA;AAEP,EAAO,OAAA,IAAI,OAAa,CAAA,CAAC,OAAY,KAAA;AACnC,IAAA,MAAA,GAAS,CAAC,IAAiB,KAAA;AACzB,MAAM,MAAA,GAAA,GAAM,KAAK,QAAS,EAAA;AAE1B,MAAA,IAAI,QAAQ,GAAU,EAAA;AACpB,QAAQ,OAAA,EAAA;AACR,QAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA;AAGhB,MAAA,IAAI,QAAQ,MAAU,EAAA;AACpB,QAAA,eAAA,CAAgB,OAAO,CAAA;AAEvB,QAAA;AAAA;AAGF,MAAA,IAAI,QAAQ,QAAU,EAAA;AACpB,QAAA,aAAA,GAAA,CAAiB,aAAgB,GAAA,CAAA,GAAI,OAAQ,CAAA,MAAA,IAAU,OAAQ,CAAA,MAAA;AAC/D,QAAO,MAAA,EAAA;AAEP,QAAA;AAAA;AAGF,MAAA,IAAI,QAAQ,QAAU,EAAA;AACpB,QAAiB,aAAA,GAAA,CAAA,aAAA,GAAgB,KAAK,OAAQ,CAAA,MAAA;AAC9C,QAAO,MAAA,EAAA;AAEP,QAAA;AAAA;AAGF,MAAA,IAAI,QAAQ,GAAK,EAAA;AACf,QAAI,IAAA,OAAA,CAAQ,GAAI,CAAA,aAAa,CAAG,EAAA;AAC9B,UAAA,OAAA,CAAQ,OAAO,aAAa,CAAA;AAAA,SACvB,MAAA;AACL,UAAA,OAAA,CAAQ,IAAI,aAAa,CAAA;AAAA;AAE3B,QAAO,MAAA,EAAA;AAEP,QAAA;AAAA;AAGF,MAAI,IAAA,GAAA,KAAQ,IAAQ,IAAA,GAAA,KAAQ,IAAM,EAAA;AAChC,QAAA,gBAAA,CAAiB,OAAO,CAAA;AAAA;AAC1B,KACF;AAEA,IAAQ,OAAA,CAAA,KAAA,CAAM,WAAW,IAAI,CAAA;AAC7B,IAAA,OAAA,CAAQ,MAAM,MAAO,EAAA;AACrB,IAAQ,OAAA,CAAA,KAAA,CAAM,EAAG,CAAA,MAAA,EAAQ,MAAM,CAAA;AAAA,GAChC,CAAA;AACH;AAOA,eAAsB,mBAAsB,GAAA;AAC1C,EAAA,MAAM,UAAU,sBAAuB,EAAA;AAEvC,EAAI,IAAA,OAAA,CAAQ,WAAW,CAAG,EAAA;AACxB,IAAA,OAAA,CAAQ,IAAI,2FAAqB,CAAA;AAEjC,IAAA,OAAO,EAAC;AAAA;AAGV,EAAO,OAAA,eAAA;AAAA,IACL,6EAAA;AAAA,IACA,OAAA,CAAQ,GAAI,CAAA,CAAC,MAAY,MAAA;AAAA,MACvB,aAAa,MAAO,CAAA,WAAA;AAAA,MACpB,OAAO,MAAO,CAAA,KAAA;AAAA,MACd,KAAO,EAAA;AAAA,KACP,CAAA,CAAA;AAAA,IACF;AAAA,GACF;AACF;AAKO,SAAS,eAAkB,GAAA;AAChC,EAAA,MAAM,UAAU,oBAAqB,EAAA;AAErC,EAAA,IAAI,CAAC,OAAS,EAAA;AACZ,IAAA,WAAA,CAAY,wBAAwB,CAAA;AACpC,IAAA,aAAA,CAAc,0FAAsB,EAAA;AAAA,MAClC,KAAO,EAAA;AAAA,KACR,CAAA;AAAA;AAGH,EAAA,WAAA,CAAY,uBAAuB,OAAO,CAAA;AAE1C,EAAO,OAAA,OAAA;AACT;AAKA,eAAsB,sBAAiD,GAAA;AACrE,EAAA,MAAM,0BAA0B,oBAAqB,EAAA;AAErD,EAAA,IAAI,uBAAyB,EAAA;AAC3B,IAAA,WAAA,CAAY,4BAA4B,uBAAuB,CAAA;AAC/D,IAAA,OAAA,CAAQ,GAAI,CAAA;AAAA,OAAA,EAAO,KAAK,KAAK,CAAA,EAAG,uBAAuB,CAAA,EAAG,KAAK,KAAK,CAAA;AAAA,CAA8B,CAAA;AAElG,IAAO,OAAA,uBAAA;AAAA;AAGT,EAAA,mCAAA,CAAoC,0BAA0B,2IAAuC,CAAA;AACrG,EAAA,WAAA,CAAY,kCAAkC,CAAA;AAC9C,EAAA,IAAI,aAAgB,GAAA,CAAA;AAIpB,EAAM,MAAA,EAAA,GAAKA,0BAAS,eAAgB,CAAA;AAAA,IAClC,OAAO,OAAQ,CAAA,KAAA;AAAA,IACf,QAAQ,OAAQ,CAAA,MAAA;AAAA,IAChB,QAAU,EAAA;AAAA,GACX,CAAA;AAED,EAAA,IAAI,WAAc,GAAA,IAAA;AAGlB,EAAQ,OAAA,CAAA,MAAA,CAAO,MAAM,WAAa,CAAA;AAElC,EAAA,MAAM,SAAS,MAAM;AACnB,IAAA,IAAI,CAAC,WAAa,EAAA;AAIhB,MAAAA,yBAAA,CAAS,WAAW,OAAQ,CAAA,MAAA,EAAQ,GAAG,EAAE,UAAA,CAAW,SAAS,CAAE,CAAA,CAAA;AAAA;AAEjE,IAAc,WAAA,GAAA,KAAA;AACd,IAAA,WAAA,CAAY,mCAAqC,EAAA,UAAA,CAAW,aAAa,CAAA,IAAK,SAAS,CAAA;AAIvF,IAASA,yBAAA,CAAA,eAAA,CAAgB,QAAQ,MAAM,CAAA;AAEvC,IAAA,OAAA,CAAQ,MAAO,CAAA,KAAA;AAAA,MACb,CAAA,4EAAA,EAAsB,IAAK,CAAA,MAAM,CAAS,+BAAA,EAAA,IAAA,CAAK,KAAK,CAAA,eAAA,EAAQ,IAAK,CAAA,MAAM,CAAQ,KAAA,EAAA,IAAA,CAAK,KAAK,CAAA;AAAA;AAAA,KAC3F;AACA,IAAW,UAAA,CAAA,OAAA,CAAQ,CAAC,OAAA,EAAS,KAAU,KAAA;AACrC,MAAA,IAAI,UAAU,aAAe,EAAA;AAC3B,QAAQ,OAAA,CAAA,MAAA,CAAO,MAAM,CAAI,CAAA,EAAA,IAAA,CAAK,IAAI,CAAI,CAAA,EAAA,IAAA,CAAK,KAAK,CAAI,CAAA,EAAA,IAAA,CAAK,IAAI,CAAI,MAAA,EAAA,IAAA,CAAK,KAAK,CAAI,CAAA,EAAA,IAAA,CAAK,IAAI,CAAG,EAAA,OAAO,CAAG,EAAA,IAAA,CAAK,KAAK;AAAA,CAAI,CAAA;AAAA,OAC9G,MAAA;AACL,QAAQ,OAAA,CAAA,MAAA,CAAO,KAAM,CAAA,CAAA,UAAA,EAAQ,OAAO;AAAA,CAAI,CAAA;AAAA;AAC1C,KACD,CAAA;AAAA,GACH;AAEA,EAAO,MAAA,EAAA;AAEP,EAAO,OAAA,IAAI,OAAQ,CAAA,CAAC,OAAY,KAAA;AAC9B,IAAM,MAAA,MAAA,GAAS,CAAC,IAAiB,KAAA;AAC/B,MAAM,MAAA,GAAA,GAAM,KAAK,QAAS,EAAA;AAC1B,MAAA,IAAI,QAAQ,GAAU,EAAA;AAEpB,QAAA,WAAA,CAAY,mCAAmC,CAAA;AAC/C,QAAQ,OAAA,CAAA,MAAA,CAAO,MAAM,WAAa,CAAA;AAClC,QAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA;AAEhB,MAAA,IAAI,QAAQ,QAAU,EAAA;AAEpB,QAAA,aAAA,GAAA,CAAiB,aAAgB,GAAA,CAAA,GAAI,UAAW,CAAA,MAAA,IAAU,UAAW,CAAA,MAAA;AACrE,QAAO,MAAA,EAAA;AAAA,OACT,MAAA,IAAW,QAAQ,QAAU,EAAA;AAE3B,QAAiB,aAAA,GAAA,CAAA,aAAA,GAAgB,KAAK,UAAW,CAAA,MAAA;AACjD,QAAO,MAAA,EAAA;AAAA,OACE,MAAA,IAAA,GAAA,KAAQ,IAAQ,IAAA,GAAA,KAAQ,IAAM,EAAA;AAEvC,QAAQ,OAAA,CAAA,KAAA,CAAM,cAAe,CAAA,MAAA,EAAQ,MAAM,CAAA;AAC3C,QAAQ,OAAA,CAAA,KAAA,CAAM,WAAW,KAAK,CAAA;AAC9B,QAAA,OAAA,CAAQ,MAAM,KAAM,EAAA;AACpB,QAAA,EAAA,CAAG,KAAM,EAAA;AAGT,QAAQ,OAAA,CAAA,MAAA,CAAO,MAAM,WAAa,CAAA;AAElC,QAAA,OAAA,CAAQ,GAAI,CAAA;AAAA,OAAO,EAAA,IAAA,CAAK,KAAK,CAAG,EAAA,UAAA,CAAW,aAAa,CAAC,CAAA,EAAG,KAAK,KAAK,CAAA;AAAA,CAAkB,CAAA;AACxF,QAAM,MAAA,MAAA,GAAS,WAAW,aAAa,CAAA;AACvC,QAAA,IAAI,MAAQ,EAAA;AACV,UAAA,WAAA,CAAY,wCAAwC,MAAM,CAAA;AAC1D,UAAA,OAAA,CAAQ,MAAM,CAAA;AAAA;AAChB;AACF,KACF;AAEA,IAAQ,OAAA,CAAA,KAAA,CAAM,WAAW,IAAI,CAAA;AAC7B,IAAA,OAAA,CAAQ,MAAM,MAAO,EAAA;AACrB,IAAQ,OAAA,CAAA,KAAA,CAAM,EAAG,CAAA,MAAA,EAAQ,MAAM,CAAA;AAAA,GAChC,CAAA;AACH","file":"helper.cjs","sourcesContent":["import { execFileSync, execSync } from 'child_process';\nimport fs from 'fs';\nimport path from 'path';\nimport readline from 'readline';\nimport { fileURLToPath } from 'url';\nimport { inspect } from 'util';\n\nimport { AIServiceType, CommitOption, MultiSelectOption } from './types';\n\ntype ErrorReportSection = {\n heading: string;\n markdown: string;\n};\n\ntype WriteErrorReportOptions = {\n title?: string;\n scope?: string;\n args?: string[];\n traceMessages?: string[];\n extraSections?: ErrorReportSection[];\n};\n\ntype ExecutionLogStatus = 'cancelled' | 'failed' | 'partial_failure' | 'success';\n\ntype WriteExecutionLogOptions = {\n title?: string;\n scope?: string;\n status?: ExecutionLogStatus;\n args?: string[];\n startedAt?: Date;\n finishedAt?: Date;\n traceMessages?: string[];\n extraSections?: ErrorReportSection[];\n error?: unknown;\n};\n\ntype GitCommandOptions = {\n allowFailure?: boolean;\n trimOutput?: boolean;\n};\n\ntype ShellCommandProgressOptions = {\n progressIntervalMs?: number;\n progressMessage?: string;\n streamOutput?: boolean;\n};\n\ntype ShellCommandFailureDetails = {\n code: number | null;\n command: string;\n signal: NodeJS.Signals | null;\n stderr: string;\n stdout: string;\n};\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst traceMessages: string[] = [];\nconst GEMINI_CLI_PACKAGE_NAME = 'sales-frontend-gemini-cli';\nlet cachedPackageRootPath = '';\n\n/**\n * @description\n * ํ˜„์žฌ ๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ gemini-cli ํŒจํ‚ค์ง€ ๋ฃจํŠธ์ธ์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.\n * ๋ฒˆ๋“ค ๊ฒฐ๊ณผ๋ฌผ์—์„œ helper ์ฝ”๋“œ๊ฐ€ ๊ฐ ์—”ํŠธ๋ฆฌ ํŒŒ์ผ๋กœ ์ธ๋ผ์ธ๋˜๋ฉด `__dirname` ๊ธฐ์ค€์ ์ด ๋‹ฌ๋ผ์ง€๋ฏ€๋กœ,\n * package.json ์ด๋ฆ„์œผ๋กœ ์‹ค์ œ ํŒจํ‚ค์ง€ ๋ฃจํŠธ๋ฅผ ์‹๋ณ„ํ•ด์•ผ ๊ทœ์น™/์–‘์‹ ํŒŒ์ผ ๊ฒฝ๋กœ๊ฐ€ ๊นจ์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค.\n * @param directory ๊ฒ€์‚ฌํ•  ๋””๋ ‰ํ„ฐ๋ฆฌ ๊ฒฝ๋กœ\n * @returns ํ˜„์žฌ ๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ gemini-cli ํŒจํ‚ค์ง€ ๋ฃจํŠธ์ด๋ฉด true\n */\nfunction isGeminiCliPackageRoot(directory: string) {\n const packageJsonPath = path.join(directory, 'package.json');\n\n if (!fs.existsSync(packageJsonPath)) {\n return false;\n }\n\n try {\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')) as { name?: string };\n\n return packageJson.name === GEMINI_CLI_PACKAGE_NAME;\n } catch {\n return false;\n }\n}\n\n/**\n * @description\n * ํ˜„์žฌ ์‹คํ–‰ ์ค‘์ธ ๋ฒˆ๋“ค ์—”ํŠธ๋ฆฌ ๊ธฐ์ค€์œผ๋กœ gemini-cli ํŒจํ‚ค์ง€ ๋ฃจํŠธ๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค.\n * `dist/pr-review/review.js`, `dist/pr-review/gemini/gemini-commander.js`์ฒ˜๋Ÿผ\n * ์—”ํŠธ๋ฆฌ ์œ„์น˜๊ฐ€ ๋‹ฌ๋ผ๋„ ์ƒ์œ„ ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ์ˆœํšŒํ•˜๋ฉฐ package root๋ฅผ ์ฐพ๋„๋ก ์„ค๊ณ„ํ•ฉ๋‹ˆ๋‹ค.\n * @param startDirectory ํŒจํ‚ค์ง€ ๋ฃจํŠธ ํƒ์ƒ‰์„ ์‹œ์ž‘ํ•  ๋””๋ ‰ํ„ฐ๋ฆฌ\n * @returns ๊ทœ์น™/์–‘์‹ ํŒŒ์ผ์ด ์กด์žฌํ•˜๋Š” gemini-cli ํŒจํ‚ค์ง€ ๋ฃจํŠธ ๊ฒฝ๋กœ\n */\nfunction resolveGeminiCliPackageRoot(startDirectory: string = __dirname) {\n if (cachedPackageRootPath) {\n return cachedPackageRootPath;\n }\n\n let currentDirectory = startDirectory;\n\n while (true) {\n if (isGeminiCliPackageRoot(currentDirectory)) {\n cachedPackageRootPath = currentDirectory;\n\n return cachedPackageRootPath;\n }\n\n const parentDirectory = path.dirname(currentDirectory);\n\n if (parentDirectory === currentDirectory) {\n break;\n }\n\n currentDirectory = parentDirectory;\n }\n\n /**\n * @description\n * package.json ํƒ์ƒ‰์ด ์‹คํŒจํ•ด๋„ ๊ธฐ์กด ์„ค์น˜ ๊ตฌ์กฐ(dist/common -> package root)๋ฅผ ์šฐ์„  fallback์œผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.\n * ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋ฐฐํฌ ํ™˜๊ฒฝ์—์„œ๋„ ์ตœ๋Œ€ํ•œ ๊ธฐ์กด ๋™์ž‘์„ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•œ ๋ณด์ˆ˜์  ์•ˆ์ „์žฅ์น˜์ž…๋‹ˆ๋‹ค.\n */\n cachedPackageRootPath = path.resolve(startDirectory, '../..');\n\n return cachedPackageRootPath;\n}\n\n/**\n * @description\n * gemini-cli ํŒจํ‚ค์ง€ ๋ฃจํŠธ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ •์  asset ํŒŒ์ผ์˜ ์ ˆ๋Œ€ ๊ฒฝ๋กœ๋ฅผ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค.\n * ๋ฒˆ๋“ค ๊ณผ์ •์—์„œ helper ์ฝ”๋“œ๊ฐ€ ๋‹ค๋ฅธ ์—”ํŠธ๋ฆฌ์— ์ธ๋ผ์ธ๋˜์–ด๋„ ํ•ญ์ƒ ๊ฐ™์€ ์‹ค์ œ ํŒŒ์ผ์„ ๊ฐ€๋ฆฌํ‚ค๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.\n * @param relativeFilePath ํŒจํ‚ค์ง€ ๋ฃจํŠธ ๊ธฐ์ค€ ์ƒ๋Œ€ ๊ฒฝ๋กœ\n * @returns asset ํŒŒ์ผ์˜ ์ ˆ๋Œ€ ๊ฒฝ๋กœ\n */\nfunction resolvePackageAssetPath(relativeFilePath: string) {\n return path.resolve(resolveGeminiCliPackageRoot(), relativeFilePath);\n}\n\nexport const rulesPath = resolvePackageAssetPath('src/common/rules/review-rules.md');\nexport const namingRulesPath = resolvePackageAssetPath('src/common/rules/naming-rule.md');\nexport const codingConventionRulesPath = resolvePackageAssetPath('src/common/rules/coding-convention.md');\nexport const reviewFormPath = resolvePackageAssetPath('src/common/form/review-form.md');\nexport const reviewFormOneByOnePath = resolvePackageAssetPath('src/common/form/review-form-one-by-one.md');\nexport const REPORT_DIR = '.review-report';\nexport const tempDiffPath = 'temp_diff.txt';\nexport const AIServices: AIServiceType[] = ['gemini', 'claude', 'codex'];\nexport const COMMIT_FETCH_LIMIT = 20;\nexport const COMMIT_SELECTION_WINDOW = 8;\nexport const ignoreList = [\n 'package.json',\n '*.yml',\n '*.md',\n '*.lock',\n 'dist/',\n 'node_modules/',\n 'assets/',\n 'public/',\n '*.json',\n '*.yaml',\n '.review-report/' // ์ƒ์„ฑ๋˜๋Š” ๋ฆฌํฌํŠธ ํด๋”๋„ ์ œ์™ธ\n];\n\nexport function isTestMode(args: string[] = process.argv.slice(2)) {\n return args.includes('--test');\n}\n\n/**\n * @description\n * AI CLI์˜ ์ค‘๊ฐ„ stdout/stderr๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ํ„ฐ๋ฏธ๋„์— ๋…ธ์ถœํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ํŒ๋‹จํ•ฉ๋‹ˆ๋‹ค.\n * ๊ธฐ๋ณธ ์‹คํ–‰์€ ์กฐ์šฉํ•œ ๋ชจ๋“œ๋กœ ์œ ์ง€ํ•˜๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ ๋ช…์‹œ์ ์œผ๋กœ ํ”Œ๋ž˜๊ทธ๋ฅผ ์ค„ ๋•Œ๋งŒ\n * AI ์‘๋‹ต์„ ๊ทธ๋Œ€๋กœ ์ŠคํŠธ๋ฆฌ๋ฐํ•ฉ๋‹ˆ๋‹ค.\n * @param args ํ˜„์žฌ ์‹คํ–‰ ์ธ์ž ๋ชฉ๋ก\n * @returns ์‹ค์‹œ๊ฐ„ AI ์ถœ๋ ฅ ๋…ธ์ถœ ์—ฌ๋ถ€\n */\nexport function shouldStreamAIOutput(args: string[] = process.argv.slice(2)) {\n return args.includes('--stream-output');\n}\n\nexport function clearTraceMessages() {\n traceMessages.length = 0;\n}\n\nexport function getTraceMessages() {\n return [...traceMessages];\n}\n\n/**\n * @description\n * ํ„ฐ๋ฏธ๋„ ์„ ํƒ UI์—์„œ ๋™์ผํ•œ ์ƒ‰์ƒ ํ† ํฐ์„ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ANSI escape code๋ฅผ ์ƒ์ˆ˜ํ™”ํ•ฉ๋‹ˆ๋‹ค.\n * ์„œ๋น„์Šค ์„ ํƒ๊ณผ ์ปค๋ฐ‹ ์„ ํƒ์ด ๊ฐ™์€ ์‹œ๊ฐ ์–ธ์–ด๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก helper ๋‚ด๋ถ€์—์„œ๋งŒ ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค.\n */\nconst ANSI = {\n bold: '\\u001b[1m',\n cyan: '\\u001b[36m',\n dim: '\\u001b[2m',\n green: '\\u001b[32m',\n reset: '\\u001b[0m',\n yellow: '\\u001b[33m'\n} as const;\nconst ANSI_PATTERN = new RegExp(`${String.fromCharCode(27)}\\\\[[0-9;]*m`, 'g');\nconst COMBINING_MARK_PATTERN = /\\p{Mark}/u;\nconst GRAPHEME_SEGMENTER =\n typeof Intl !== 'undefined' && 'Segmenter' in Intl ? new Intl.Segmenter('ko', { granularity: 'grapheme' }) : null;\n\ntype VisibleToken = {\n value: string;\n visibleWidth: number;\n};\n\n/**\n * @description\n * ๋ฆฌ๋ทฐ ๋Œ€์ƒ ํŒŒ์ผ ํ•„ํ„ฐ๋ฅผ pathspec ๋ฐฐ์—ด ํ˜•ํƒœ๋กœ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.\n * ๋ฌธ์ž์—ด ์ปค๋งจ๋“œ์™€ argv ๊ธฐ๋ฐ˜ git ์‹คํ–‰์ด ๋ชจ๋‘ ๊ฐ™์€ ๊ธฐ์ค€์„ ๊ณต์œ ํ•˜๋„๋ก ์›๋ณธ ํŒจํ„ด์€ ๋ฐฐ์—ด๋กœ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.\n */\nfunction getGitDiffPathspecs() {\n return {\n excludePatterns: ignoreList.map((item) => `:(exclude)${item}`),\n includePatterns: ['*.ts', '*.tsx', '*.js', '*.jsx']\n };\n}\n\nfunction segmentGraphemes(value: string) {\n if (!GRAPHEME_SEGMENTER) {\n return [...value];\n }\n\n return [...GRAPHEME_SEGMENTER.segment(value)].map(({ segment }) => segment);\n}\n\nfunction isWideCodePoint(codePoint: number) {\n return (\n codePoint >= 0x1100 &&\n (codePoint <= 0x115f ||\n codePoint === 0x2329 ||\n codePoint === 0x232a ||\n (codePoint >= 0x2e80 && codePoint <= 0x3247 && codePoint !== 0x303f) ||\n (codePoint >= 0x3250 && codePoint <= 0x4dbf) ||\n (codePoint >= 0x4e00 && codePoint <= 0xa4c6) ||\n (codePoint >= 0xa960 && codePoint <= 0xa97c) ||\n (codePoint >= 0xac00 && codePoint <= 0xd7a3) ||\n (codePoint >= 0xf900 && codePoint <= 0xfaff) ||\n (codePoint >= 0xfe10 && codePoint <= 0xfe19) ||\n (codePoint >= 0xfe30 && codePoint <= 0xfe6b) ||\n (codePoint >= 0xff01 && codePoint <= 0xff60) ||\n (codePoint >= 0xffe0 && codePoint <= 0xffe6) ||\n (codePoint >= 0x1f200 && codePoint <= 0x1f251) ||\n (codePoint >= 0x20000 && codePoint <= 0x3fffd))\n );\n}\n\nfunction isEmojiCodePoint(codePoint: number) {\n return (\n (codePoint >= 0x1f1e6 && codePoint <= 0x1f1ff) ||\n (codePoint >= 0x1f300 && codePoint <= 0x1faff) ||\n (codePoint >= 0x2600 && codePoint <= 0x27bf)\n );\n}\n\nfunction getGraphemeWidth(grapheme: string) {\n let width = 0;\n\n for (const character of grapheme) {\n const codePoint = character.codePointAt(0);\n\n if (!codePoint || COMBINING_MARK_PATTERN.test(character) || codePoint === 0x200d) {\n continue;\n }\n\n if ((codePoint >= 0xfe00 && codePoint <= 0xfe0f) || (codePoint >= 0xe0100 && codePoint <= 0xe01ef)) {\n continue;\n }\n\n if (isWideCodePoint(codePoint) || isEmojiCodePoint(codePoint)) {\n width = Math.max(width, 2);\n\n continue;\n }\n\n width = Math.max(width, 1);\n }\n\n return width;\n}\n\nfunction tokenizePlainText(value: string) {\n return segmentGraphemes(value).map((segment) => ({\n value: segment,\n visibleWidth: getGraphemeWidth(segment)\n }));\n}\n\nfunction tokenizeVisibleText(value: string) {\n const tokens: VisibleToken[] = [];\n let lastIndex = 0;\n\n for (const match of value.matchAll(ANSI_PATTERN)) {\n const index = match.index ?? 0;\n\n if (index > lastIndex) {\n tokens.push(...tokenizePlainText(value.slice(lastIndex, index)));\n }\n\n tokens.push({\n value: match[0],\n visibleWidth: 0\n });\n lastIndex = index + match[0].length;\n }\n\n if (lastIndex < value.length) {\n tokens.push(...tokenizePlainText(value.slice(lastIndex)));\n }\n\n return tokens;\n}\n\n/**\n * @description\n * ๋ชจ๋‹ฌ ๊ฐ ์ค„์ด ํ„ฐ๋ฏธ๋„ ์‹ค์ œ ํญ์„ ๋„˜์ง€ ์•Š๋„๋ก ANSI ์ฝ”๋“œ๋ฅผ ๋ณด์กดํ•œ ์ฑ„ ์ž˜๋ผ๋ƒ…๋‹ˆ๋‹ค.\n * ์ค„๋ฐ”๊ฟˆ์ด ๋ฐœ์ƒํ•˜๋ฉด ๋ Œ๋” ์ค„ ์ˆ˜ ๊ณ„์‚ฐ์ด ์–ด๊ธ‹๋‚˜๋ฏ€๋กœ, ๋ชจ๋“  ์„ ํƒ ์ค„์„ 1 physical line๋กœ ๊ฐ•์ œํ•ฉ๋‹ˆ๋‹ค.\n * @param value ๋ Œ๋”ํ•  ๋ฌธ์ž์—ด\n * @param maxWidth ํ—ˆ์šฉ ์ตœ๋Œ€ ํ‘œ์‹œ ํญ\n * @returns ํ„ฐ๋ฏธ๋„ ํญ ์•ˆ์œผ๋กœ ์ •๋ฆฌ๋œ ๋ฌธ์ž์—ด\n */\nfunction truncateLineForTerminal(value: string, maxWidth: number) {\n if (maxWidth <= 0) {\n return '';\n }\n\n const tokens = tokenizeVisibleText(value);\n const totalWidth = tokens.reduce((sum, token) => sum + token.visibleWidth, 0);\n\n if (totalWidth <= maxWidth) {\n return value;\n }\n\n const ellipsis = '...';\n const ellipsisWidth = 3;\n const targetWidth = Math.max(0, maxWidth - ellipsisWidth);\n let usedWidth = 0;\n let result = '';\n\n for (const token of tokens) {\n if (token.visibleWidth === 0) {\n result += token.value;\n\n continue;\n }\n\n if (usedWidth + token.visibleWidth > targetWidth) {\n break;\n }\n\n result += token.value;\n usedWidth += token.visibleWidth;\n }\n\n return `${result}${ellipsis}${ANSI.reset}`;\n}\n\nfunction fitLinesToTerminal(lines: string[]) {\n const maxWidth = Math.max(20, (process.stdout.columns || 120) - 1);\n\n return lines.map((line) => truncateLineForTerminal(line, maxWidth));\n}\n\n/**\n * @description\n * git ์„œ๋ธŒํ”„๋กœ์„ธ์Šค๋ฅผ argv ๋ฐฐ์—ด ๊ธฐ๋ฐ˜์œผ๋กœ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.\n * ์ปค๋ฐ‹ ํ•ด์‹œ๋‚˜ ํŒŒ์ผ ๊ฒฝ๋กœ์— ๊ณต๋ฐฑ์ด ์„ž์—ฌ๋„ shell quoting ๋ฌธ์ œ ์—†์ด ๋™์ผํ•œ ๋™์ž‘์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด ๊ณตํ†ต helper๋กœ ๋ถ„๋ฆฌํ•ฉ๋‹ˆ๋‹ค.\n * @param args git ์ธ์ž ๋ฐฐ์—ด\n * @param options ์‹คํŒจ ํ—ˆ์šฉ ์—ฌ๋ถ€์™€ ์ถœ๋ ฅ trim ์—ฌ๋ถ€\n * @returns git ํ‘œ์ค€์ถœ๋ ฅ ๋ฌธ์ž์—ด\n */\nfunction runGitCommand(args: string[], options: GitCommandOptions = {}) {\n const { allowFailure = false, trimOutput = true } = options;\n\n try {\n const output = execFileSync('git', args, {\n encoding: 'utf8',\n maxBuffer: 1024 * 1024 * 20,\n stdio: ['ignore', 'pipe', 'pipe']\n });\n\n return trimOutput ? output.trim() : output;\n } catch (error) {\n helperTrace('git-command:failed', `${args.join(' ')} | ${getErrorSummary(error)}`);\n\n if (allowFailure) {\n return '';\n }\n\n throw error;\n }\n}\n\n/**\n * @description\n * shell ๋ช…๋ น์„ ๋น„๋™๊ธฐ๋กœ ์‹คํ–‰ํ•˜๋ฉด์„œ stdout/stderr๋ฅผ ๊ทธ๋Œ€๋กœ ํ˜๋ ค๋ณด๋‚ด๊ณ , ์žฅ์‹œ๊ฐ„ ์ž‘์—…์—๋Š” ๊ฒฝ๊ณผ ์‹œ๊ฐ„์„ ์ฃผ๊ธฐ์ ์œผ๋กœ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.\n * review ์‹คํ–‰์ฒ˜๋Ÿผ ์‘๋‹ต ์ƒ์„ฑ๊นŒ์ง€ ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” CLI๋ฅผ ๋ฒ„ํผ๋ง ์—†์ด ๊ธฐ๋‹ค๋ฆฌ๊ฒŒ ํ•ด ์‚ฌ์šฉ์ž๊ฐ€ ๋ฉˆ์ถค์œผ๋กœ ์˜คํ•ดํ•˜์ง€ ์•Š๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.\n * @param command ์‹คํ–‰ํ•  shell command ๋ฌธ์ž์—ด\n * @param options ์ง„ํ–‰ ๋ฉ”์‹œ์ง€์™€ ์ถœ๋ ฅ ์ฃผ๊ธฐ ์˜ต์…˜\n * @returns ์ตœ์ข… stdout/stderr ์บก์ฒ˜ ๊ฒฐ๊ณผ\n */\nexport async function executeShellCommandWithProgress(command: string, options: ShellCommandProgressOptions = {}) {\n const { progressIntervalMs = 10000, progressMessage = 'โณ ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๋Š” ์ค‘์ž…๋‹ˆ๋‹ค...', streamOutput = false } = options;\n const { spawn } = await import('child_process');\n\n return new Promise<{ stderr: string; stdout: string }>((resolve, reject) => {\n let stdout = '';\n let stderr = '';\n const startedAt = Date.now();\n console.log(progressMessage);\n\n const child = spawn('/bin/zsh', ['-lc', command], {\n stdio: ['ignore', 'pipe', 'pipe']\n });\n\n const progressTimer = setInterval(() => {\n const elapsedSeconds = Math.max(1, Math.floor((Date.now() - startedAt) / 1000));\n console.log(`${progressMessage} (${elapsedSeconds}s ๊ฒฝ๊ณผ)`);\n }, progressIntervalMs);\n\n child.stdout.on('data', (chunk: Buffer | string) => {\n const text = chunk.toString();\n stdout += text;\n\n if (streamOutput) {\n process.stdout.write(text);\n }\n });\n\n child.stderr.on('data', (chunk: Buffer | string) => {\n const text = chunk.toString();\n stderr += text;\n\n if (streamOutput) {\n process.stderr.write(text);\n }\n });\n\n child.on('error', (error) => {\n clearInterval(progressTimer);\n reject(error);\n });\n\n child.on('close', (code, signal) => {\n clearInterval(progressTimer);\n\n if (code === 0) {\n resolve({\n stderr,\n stdout\n });\n\n return;\n }\n\n const exitSummary = signal ? `signal=${signal}` : `code=${String(code ?? 'unknown')}`;\n const failureDetails: ShellCommandFailureDetails = {\n code,\n command,\n signal,\n stderr,\n stdout\n };\n\n reject(createShellCommandExecutionError(failureDetails, exitSummary));\n });\n });\n}\n\n/**\n * @description\n * shell ๋ช…๋ น ์‹คํŒจ ์‹œ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€์— ํฌํ•จํ•  ์ถœ๋ ฅ ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.\n * ์ผ๋ถ€ CLI๋Š” ์‹คํŒจ ์‚ฌ์œ ๋ฅผ stderr๊ฐ€ ์•„๋‹ˆ๋ผ stdout์œผ๋กœ๋งŒ ์ถœ๋ ฅํ•˜๋ฏ€๋กœ, ๋‘ ์ฑ„๋„์„ ํ•จ๊ป˜ ํ™•์ธํ•ด์•ผ\n * ์›์ธ ํŒŒ์•…์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๋„ˆ๋ฌด ๊ธด ์‘๋‹ต์ด ๊ทธ๋Œ€๋กœ ์—๋Ÿฌ ์ œ๋ชฉ์— ๋ถ™์ง€ ์•Š๋„๋ก ๋งˆ์ง€๋ง‰ ์ผ๋ถ€๋งŒ ์ž˜๋ผ๋ƒ…๋‹ˆ๋‹ค.\n * @param failureDetails ์‹คํŒจํ•œ shell ๋ช…๋ น์˜ ์‹คํ–‰ ๊ฒฐ๊ณผ\n * @returns ์—๋Ÿฌ ๋ฉ”์‹œ์ง€์— ๋ถ™์ผ ์ถœ๋ ฅ ์š”์•ฝ ๋ฌธ์ž์—ด\n */\nfunction getShellCommandFailurePreview(failureDetails: ShellCommandFailureDetails) {\n const stderrText = failureDetails.stderr.trim();\n const stdoutText = failureDetails.stdout.trim();\n const combinedOutput = stderrText || stdoutText;\n\n if (!combinedOutput) {\n return '';\n }\n\n const MAX_PREVIEW_LENGTH = 4000;\n\n if (combinedOutput.length <= MAX_PREVIEW_LENGTH) {\n return combinedOutput;\n }\n\n return combinedOutput.slice(-MAX_PREVIEW_LENGTH);\n}\n\n/**\n * @description\n * shell ๋ช…๋ น ์‹คํŒจ ์ •๋ณด๋ฅผ Error ๊ฐ์ฒด๋กœ ์Šน๊ฒฉํ•ฉ๋‹ˆ๋‹ค.\n * ์—๋Ÿฌ ๋ฆฌํฌํŠธ์—์„œ ์‹ค์ œ ์‹คํŒจ ์›์ธ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋„๋ก stdout/stderr/command/exit code๋ฅผ\n * Error ์ธ์Šคํ„ด์Šค์— ์ง์ ‘ ๋ถ€์ฐฉํ•ฉ๋‹ˆ๋‹ค.\n * @param failureDetails ์‹คํŒจํ•œ shell ๋ช…๋ น์˜ ์‹คํ–‰ ๊ฒฐ๊ณผ\n * @param exitSummary ์ข…๋ฃŒ ์ฝ”๋“œ ๋˜๋Š” ์‹œ๊ทธ๋„ ์š”์•ฝ\n * @returns ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๊ฐ€ ๋ถ€์ฐฉ๋œ Error ๊ฐ์ฒด\n */\nfunction createShellCommandExecutionError(failureDetails: ShellCommandFailureDetails, exitSummary: string) {\n const failurePreview = getShellCommandFailurePreview(failureDetails);\n const error = new Error(`์‰˜ ๋ช…๋ น ์‹คํ–‰ ์‹คํŒจ (${exitSummary})${failurePreview ? `\\n${failurePreview}` : ''}`) as Error &\n Record<string, unknown>;\n\n error.code = failureDetails.code;\n error.signal = failureDetails.signal;\n error.stdout = failureDetails.stdout;\n error.stderr = failureDetails.stderr;\n error.command = failureDetails.command;\n\n return error;\n}\n\n/**\n * @description\n * ๋ฆฌ๋ทฐ ๋Œ€์ƒ ํŒŒ์ผ ๋ชฉ๋ก์„ ํ•œ ์ค„ ์š”์•ฝ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.\n * ํŒŒ์ผ์ด ๋งŽ์„ ๋•Œ๋Š” ์ผ๋ถ€๋งŒ ๋…ธ์ถœํ•˜๊ณ  ๋‚˜๋จธ์ง€๋Š” ๊ฐœ์ˆ˜๋กœ ์ถ•์•ฝํ•ด ํ„ฐ๋ฏธ๋„ ์ถœ๋ ฅ์ด ๊ณผ๋„ํ•˜๊ฒŒ ๊ธธ์–ด์ง€์ง€ ์•Š๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.\n * @param files ๋ฆฌ๋ทฐ ๋Œ€์ƒ ํŒŒ์ผ ๋ชฉ๋ก\n * @param visibleCount ํ„ฐ๋ฏธ๋„์— ์ง์ ‘ ๋ณด์—ฌ์ค„ ์ตœ๋Œ€ ํŒŒ์ผ ์ˆ˜\n * @returns ํ™”๋ฉด ํ‘œ์‹œ์šฉ ์š”์•ฝ ๋ฌธ์ž์—ด\n */\nexport function formatReviewTargetFiles(files: string[], visibleCount = 5) {\n if (files.length === 0) {\n return '(์—†์Œ)';\n }\n\n const visibleFiles = files.slice(0, visibleCount);\n const hiddenCount = Math.max(0, files.length - visibleFiles.length);\n\n if (hiddenCount === 0) {\n return visibleFiles.join(', ');\n }\n\n return `${visibleFiles.join(', ')} ์™ธ ${hiddenCount}๊ฐœ`;\n}\n\nexport function createTraceLogger(scope: string, args: string[] = process.argv.slice(2)) {\n const enabled = isTestMode(args);\n\n return (step: string, detail?: string) => {\n const timestamp = new Date().toISOString();\n const message = `[${timestamp}][TRACE][${scope}] ${step}${detail ? ` | ${detail}` : ''}`;\n traceMessages.push(message);\n\n if (!enabled) {\n return;\n }\n\n console.log(message);\n };\n}\n\nconst helperTrace = createTraceLogger('helper');\n\nfunction getTimestampParts(now = new Date()) {\n return {\n YYYY: now.getFullYear(),\n MM: String(now.getMonth() + 1).padStart(2, '0'),\n DD: String(now.getDate()).padStart(2, '0'),\n HH: String(now.getHours()).padStart(2, '0'),\n mm: String(now.getMinutes()).padStart(2, '0'),\n ss: String(now.getSeconds()).padStart(2, '0')\n };\n}\n\nfunction getHumanReadableNowString(now = new Date()) {\n const { YYYY, MM, DD, HH, mm, ss } = getTimestampParts(now);\n\n return `${YYYY}-${MM}-${DD} ${HH}:${mm}:${ss}`;\n}\n\nfunction stringifyUnknown(value: unknown) {\n if (value === undefined || value === null) {\n return '';\n }\n\n if (typeof value === 'string') {\n return value;\n }\n\n if (Buffer.isBuffer(value)) {\n return value.toString();\n }\n\n if (value instanceof Error) {\n return value.stack || value.message;\n }\n\n return inspect(value, { depth: 5, breakLength: 120 });\n}\n\nexport function getErrorSummary(error: unknown) {\n if (error instanceof Error) {\n return `${error.name}: ${error.message}`;\n }\n\n return stringifyUnknown(error) || 'Unknown error';\n}\n\nfunction serializeError(error: unknown) {\n const serialized: Record<string, unknown> = {\n summary: getErrorSummary(error)\n };\n\n if (error instanceof Error) {\n serialized.name = error.name;\n serialized.message = error.message;\n serialized.stack = error.stack;\n } else {\n serialized.value = stringifyUnknown(error);\n }\n\n if (error && typeof error === 'object') {\n const errorLike = error as Record<string, unknown>;\n const extraKeys = ['code', 'errno', 'syscall', 'path', 'cmd', 'status', 'signal', 'spawnargs', 'command'];\n\n extraKeys.forEach((key) => {\n if (errorLike[key] !== undefined) {\n serialized[key] = errorLike[key];\n }\n });\n\n const stdout = stringifyUnknown(errorLike.stdout);\n if (stdout) {\n serialized.stdout = stdout;\n }\n\n const stderr = stringifyUnknown(errorLike.stderr);\n if (stderr) {\n serialized.stderr = stderr;\n }\n\n const cause = stringifyUnknown(errorLike.cause);\n if (cause) {\n serialized.cause = cause;\n }\n }\n\n return serialized;\n}\n\nexport function getNextFilePath(dir: string, baseName: string, extension: string) {\n let counter = 1;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const filePath = path.join(dir, `${baseName}-${counter}${extension}`);\n if (!fs.existsSync(filePath)) {\n return filePath;\n }\n counter++;\n }\n}\n\nexport function getAvailableFilePath(dir: string, baseName: string, extension: string) {\n const firstFilePath = path.join(dir, `${baseName}${extension}`);\n if (!fs.existsSync(firstFilePath)) {\n return firstFilePath;\n }\n\n return getNextFilePath(dir, baseName, extension);\n}\n\nexport function deleteFile(filePath: string) {\n if (fs.existsSync(filePath)) {\n fs.unlinkSync(filePath);\n }\n}\n\n/**\n * ์ž„์‹œํŒŒ์ผ ์‚ญ์ œ\n */\nexport function deleteTempDiff() {\n deleteFile(tempDiffPath);\n}\n\n/**\n * ๋ฆฌ๋ทฐ ๊ฒฐ๊ณผ ํด๋” ์ƒ์„ฑ\n */\nexport function createReportDirectory() {\n if (!fs.existsSync(REPORT_DIR)) {\n fs.mkdirSync(REPORT_DIR, { recursive: true });\n }\n}\n\n/**\n * ํ˜„์žฌ ์‹œ๊ฐ„ ๋ฌธ์ž์—ด ์ƒ์„ฑ\n */\nexport function getNowString(now = new Date()) {\n const { YYYY, MM, DD, HH, mm, ss } = getTimestampParts(now);\n\n return `${YYYY}-${MM}-${DD}_${HH}-${mm}-${ss}`;\n}\n\nexport function getErrorLogTimestamp(now = new Date()) {\n const { YYYY, MM, DD, HH, mm, ss } = getTimestampParts(now);\n\n return `${YYYY}-${MM}-${DD}-${HH}์‹œ-${mm}๋ถ„-${ss}์ดˆ`;\n}\n\nexport function writeErrorReport(error: unknown, options: WriteErrorReportOptions = {}) {\n try {\n const now = new Date();\n helperTrace('error-report:write:start', options.scope || 'unknown');\n createReportDirectory();\n\n const reportPath = getAvailableFilePath(REPORT_DIR, `error-log-${getErrorLogTimestamp(now)}`, '.md');\n const serializedError = serializeError(error);\n const traceSnapshot = options.traceMessages ?? getTraceMessages();\n const extraSections = options.extraSections || [];\n\n const report = `# Error Log\n\n- ๋ฐœ์ƒ ์‹œ๊ฐ: ${getHumanReadableNowString(now)}\n- Scope: \\`${options.scope || 'unknown'}\\`\n- ์ž‘์—… ๊ฒฝ๋กœ: \\`${process.cwd()}\\`\n- ์‹คํ–‰ ์ธ์ž: \\`${JSON.stringify(options.args ?? process.argv.slice(2))}\\`\n- ์‹คํ–‰ ํ™˜๊ฒฝ: \\`${process.platform} ${process.arch} / Node ${process.version}\\`\n\n## Summary\n\n${options.title || serializedError.summary || 'Unknown error'}\n\n## Error\n\n\\`\\`\\`json\n${JSON.stringify(serializedError, null, 2)}\n\\`\\`\\`\n\n## Trace\n\n\\`\\`\\`json\n${JSON.stringify(traceSnapshot, null, 2)}\n\\`\\`\\`${extraSections.length ? `\\n${extraSections.map((section) => `\\n## ${section.heading}\\n\\n${section.markdown}`).join('\\n')}\\n` : '\\n'}\n`;\n\n fs.writeFileSync(reportPath, report);\n helperTrace('error-report:write:done', reportPath);\n\n return reportPath;\n } catch (writeError) {\n console.error('โš ๏ธ ์—๋Ÿฌ ๋กœ๊ทธ ํŒŒ์ผ ์ƒ์„ฑ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.');\n console.error(writeError);\n\n return '';\n }\n}\n\nfunction getExecutionLogSummary(status: ExecutionLogStatus, title?: string) {\n if (title) {\n return title;\n }\n\n switch (status) {\n case 'success':\n return '๋ฆฌ๋ทฐ ์‹คํ–‰์ด ์„ฑ๊ณต์ ์œผ๋กœ ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.';\n case 'failed':\n return '๋ฆฌ๋ทฐ ์‹คํ–‰ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.';\n case 'partial_failure':\n return '๋ฆฌ๋ทฐ ์‹คํ–‰์€ ์™„๋ฃŒ๋˜์—ˆ์ง€๋งŒ ์ผ๋ถ€ ๋‹จ๊ณ„์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.';\n default:\n return '๋ฆฌ๋ทฐ ์‹คํ–‰์ด ์ทจ์†Œ๋˜์—ˆ๊ฑฐ๋‚˜ ๋ฆฌ๋ทฐ ๋Œ€์ƒ์ด ์—†์–ด ์ข…๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.';\n }\n}\n\nfunction formatExecutionDuration(startedAt: Date, finishedAt: Date) {\n const durationMs = Math.max(0, finishedAt.getTime() - startedAt.getTime());\n\n if (durationMs < 1000) {\n return `${durationMs}ms`;\n }\n\n const durationSeconds = durationMs / 1000;\n\n if (durationSeconds < 60) {\n return `${durationSeconds.toFixed(1)}s`;\n }\n\n const minutes = Math.floor(durationSeconds / 60);\n const seconds = Math.round(durationSeconds % 60);\n\n return `${minutes}m ${seconds}s`;\n}\n\n/**\n * @description\n * ์„ฑ๊ณต/์‹คํŒจ ์—ฌ๋ถ€์™€ ๋ฌด๊ด€ํ•˜๊ฒŒ ๋ฆฌ๋ทฐ ์‹คํ–‰ ์ž์ฒด์˜ ์ง„๋‹จ ๋กœ๊ทธ๋ฅผ `.review-report`์— ๋‚จ๊น๋‹ˆ๋‹ค.\n * ์—๋Ÿฌ ๋กœ๊ทธ์™€ ๋ณ„๋„๋กœ ์‹คํ–‰ ๋งฅ๋ฝ, ์ƒ์„ฑ๋œ ๋ช…๋ น์–ด, trace๋ฅผ ํ•ญ์ƒ ๋ณด์กดํ•˜์—ฌ ์žฌํ˜„๊ณผ ์›์ธ ๋ถ„์„์— ํ™œ์šฉํ•ฉ๋‹ˆ๋‹ค.\n * @param options ์‹คํ–‰ ์ƒํƒœ, ์‹œ์ž‘/์ข…๋ฃŒ ์‹œ๊ฐ, ์—๋Ÿฌ, ์ถ”๊ฐ€ ์„น์…˜ ๋“ฑ ์‹คํ–‰ ๋กœ๊ทธ ์ž‘์„ฑ ์˜ต์…˜\n * @returns ์ƒ์„ฑ๋œ ์‹คํ–‰ ๋กœ๊ทธ ํŒŒ์ผ ๊ฒฝ๋กœ. ์‹คํŒจ ์‹œ ๋นˆ ๋ฌธ์ž์—ด\n */\nexport function writeExecutionLog(options: WriteExecutionLogOptions = {}) {\n try {\n const startedAt = options.startedAt ?? new Date();\n const finishedAt = options.finishedAt ?? new Date();\n const status = options.status ?? 'success';\n helperTrace('execution-log:write:start', options.scope || 'unknown');\n createReportDirectory();\n\n const reportPath = getAvailableFilePath(REPORT_DIR, `${getNowString(finishedAt)}-execution-log`, '.md');\n const traceSnapshot = options.traceMessages ?? getTraceMessages();\n const extraSections = options.extraSections || [];\n const serializedError = options.error ? serializeError(options.error) : null;\n\n const report = `# Execution Log\n\n- ์‹œ์ž‘ ์‹œ๊ฐ: ${getHumanReadableNowString(startedAt)}\n- ์ข…๋ฃŒ ์‹œ๊ฐ: ${getHumanReadableNowString(finishedAt)}\n- ์‹คํ–‰ ์‹œ๊ฐ„: ${formatExecutionDuration(startedAt, finishedAt)}\n- ์ƒํƒœ: \\`${status}\\`\n- Scope: \\`${options.scope || 'unknown'}\\`\n- ์ž‘์—… ๊ฒฝ๋กœ: \\`${process.cwd()}\\`\n- ์‹คํ–‰ ์ธ์ž: \\`${JSON.stringify(options.args ?? process.argv.slice(2))}\\`\n- ์‹คํ–‰ ํ™˜๊ฒฝ: \\`${process.platform} ${process.arch} / Node ${process.version}\\`\n\n## Summary\n\n${getExecutionLogSummary(status, options.title)}\n${serializedError ? `\\n\\n## Error\\n\\n\\`\\`\\`json\\n${JSON.stringify(serializedError, null, 2)}\\n\\`\\`\\`` : ''}\n\n## Trace\n\n\\`\\`\\`json\n${JSON.stringify(traceSnapshot, null, 2)}\n\\`\\`\\`${extraSections.length ? `\\n${extraSections.map((section) => `\\n## ${section.heading}\\n\\n${section.markdown}`).join('\\n')}\\n` : '\\n'}\n`;\n\n fs.writeFileSync(reportPath, report);\n helperTrace('execution-log:write:done', reportPath);\n\n return reportPath;\n } catch (writeError) {\n console.error('โš ๏ธ ์‹คํ–‰ ๋กœ๊ทธ ํŒŒ์ผ ์ƒ์„ฑ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.');\n console.error(writeError);\n\n return '';\n }\n}\n\nexport function exitWithError(\n message: string,\n options: Omit<WriteErrorReportOptions, 'title'> & { error?: unknown } = {}\n): never {\n const reportPath = writeErrorReport(options.error || new Error(message), {\n ...options,\n title: message\n });\n\n console.error(message);\n\n if (options.error) {\n console.error(options.error);\n }\n\n if (reportPath) {\n console.error(`๐Ÿ“„ ์—๋Ÿฌ ๋กœ๊ทธ ์ €์žฅ ์œ„์น˜: ${reportPath}`);\n }\n\n process.exit(1);\n}\n\nfunction parseServiceFromArgs(args: string[] = process.argv.slice(2)): AIServiceType | '' {\n helperTrace('parse-service:start', `args=${JSON.stringify(args)}`);\n const serviceIndex = args.indexOf('--service');\n const rawService = serviceIndex !== -1 ? args[serviceIndex + 1] : '';\n\n if (!rawService) {\n helperTrace('parse-service:empty');\n\n return '';\n }\n\n const normalizedService = rawService.toLowerCase();\n\n if (AIServices.includes(normalizedService as AIServiceType)) {\n helperTrace('parse-service:resolved', normalizedService);\n\n return normalizedService as AIServiceType;\n }\n\n helperTrace('parse-service:invalid', rawService);\n exitWithError(\n `โŒ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค: ${rawService}. ์‚ฌ์šฉ ๊ฐ€๋Šฅ ๊ฐ’: ${AIServices.join(', ')} (์˜ˆ: --service codex)`,\n {\n scope: 'helper:parseServiceFromArgs',\n args,\n extraSections: [\n {\n heading: 'Allowed Services',\n markdown: `\\`\\`\\`json\\n${JSON.stringify(AIServices, null, 2)}\\n\\`\\`\\``\n }\n ]\n }\n );\n}\n\nexport function getGitDiffFilter() {\n const { includePatterns, excludePatterns } = getGitDiffPathspecs();\n const quote = (pattern: string) => `\"${pattern}\"`;\n const includeParams = includePatterns.map(quote).join(' ');\n const excludeParams = excludePatterns.map(quote).join(' ');\n\n return { includeParams, excludeParams };\n}\n\n/**\n * @description\n * ์ปค๋ฐ‹ ์„ ํƒ ๋ชฉ๋ก์—์„œ subject๊ฐ€ ๊ณผํ•˜๊ฒŒ ๊ธธ์–ด์ง€๋Š” ๊ฒƒ์„ ๋ง‰๊ธฐ ์œ„ํ•ด ํ‘œ์‹œ ๊ธธ์ด๋ฅผ ์ œํ•œํ•ฉ๋‹ˆ๋‹ค.\n * commit hash์™€ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋Š” ๋ณ„๋„ ํ•„๋“œ๋กœ ์œ ์ง€ํ•˜๋ฏ€๋กœ UI ๊ฐ€๋…์„ฑ์— ํ•„์š”ํ•œ subject๋งŒ ์ž๋ฆ…๋‹ˆ๋‹ค.\n * @param subject ์›๋ณธ ์ปค๋ฐ‹ ์ œ๋ชฉ\n * @returns ํ™”๋ฉด ํ‘œ์‹œ์šฉ ์ œ๋ชฉ\n */\nfunction truncateCommitSubject(subject: string) {\n if (subject.length <= 72) {\n return subject;\n }\n\n return `${subject.slice(0, 69)}...`;\n}\n\n/**\n * @description\n * ์ตœ๊ทผ ์ปค๋ฐ‹ ๋ชฉ๋ก์„ ๋ฆฌ๋ทฐ ์„ ํƒ UI์—์„œ ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.\n * git log ํฌ๋งท์„ ํ•œ ๊ณณ์—์„œ ๊ด€๋ฆฌํ•ด main review์™€ one-by-one review๊ฐ€ ๊ฐ™์€ ์ปค๋ฐ‹ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.\n * @returns ์ตœ๊ทผ ์ปค๋ฐ‹ ์˜ต์…˜ ๋ชฉ๋ก\n */\nexport function getRecentCommitOptions(): CommitOption[] {\n const output = runGitCommand(\n ['log', `-${COMMIT_FETCH_LIMIT}`, '--date=relative', '--pretty=format:%h%x09%an%x09%ar%x09%s'],\n { allowFailure: true }\n );\n\n if (!output) {\n return [];\n }\n\n return output.split('\\n').map((line) => {\n const [hash = '', author = '', relativeDate = '', ...subjectParts] = line.split('\\t');\n const subject = subjectParts.join('\\t').trim();\n\n return {\n author,\n description: `${author} | ${relativeDate}`,\n hash,\n label: `${hash} | ${truncateCommitSubject(subject)}`,\n relativeDate,\n subject\n };\n });\n}\n\n/**\n * @description\n * ์„ ํƒ๋œ ์ปค๋ฐ‹ ๋ชฉ๋ก์„ ๋ฆฌํฌํŠธ ๋ฐ diff ํ—ค๋”์— ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” markdown bullet ๋ฌธ์ž์—ด๋กœ ์ •๋ฆฌํ•ฉ๋‹ˆ๋‹ค.\n * @param commits ์‚ฌ์šฉ์ž๊ฐ€ ๊ณ ๋ฅธ ์ปค๋ฐ‹ ๋ชฉ๋ก\n * @returns ์ปค๋ฐ‹ ์š”์•ฝ markdown\n */\nexport function buildSelectedCommitSummary(commits: CommitOption[]) {\n return commits.map((commit) => `- ${commit.hash} | ${commit.subject} | ${commit.author} | ${commit.relativeDate}`).join('\\n');\n}\n\n/**\n * @description\n * ๋ฆฌ๋ทฐ ๋Œ€์ƒ pathspec ๋ฐฐ์—ด์„ git argv์— ๋ฐ”๋กœ ๋ถ™์ผ ์ˆ˜ ์žˆ๊ฒŒ ํ‰ํƒ„ํ™”ํ•ฉ๋‹ˆ๋‹ค.\n * ๋ฌธ์ž์—ด ์ปค๋งจ๋“œ์™€ ๋‹ค๋ฅธ ๊ฒฝ๋กœ ๊ธฐ๋ฐ˜ helper๋„ ๊ฐ™์€ ํ•„ํ„ฐ๋ฅผ ๊ณต์œ ํ•˜๋„๋ก helper ํ•จ์ˆ˜๋กœ ๋ถ„๋ฆฌํ•ฉ๋‹ˆ๋‹ค.\n * @returns include/exclude pathspec ๋ฐฐ์—ด\n */\nfunction getReviewPathspecArgs() {\n const { includePatterns, excludePatterns } = getGitDiffPathspecs();\n\n return [...includePatterns, ...excludePatterns];\n}\n\n/**\n * @description\n * ์„ ํƒ๋œ ์—ฌ๋Ÿฌ ์ปค๋ฐ‹์˜ ์ „์ฒด diff๋ฅผ ํ•œ ํŒŒ์ผ์— ํ•ฉ์นฉ๋‹ˆ๋‹ค.\n * ๊ฐ ์ปค๋ฐ‹์„ ๋ณ„๋„ ์„น์…˜์œผ๋กœ ๊ฐ์‹ธ AI๊ฐ€ ์ปค๋ฐ‹ ๊ฒฝ๊ณ„๋ฅผ ์žƒ์ง€ ์•Š๋„๋ก ํ•˜๋ฉฐ, ๊ธฐ์กด ๋ฆฌ๋ทฐ ๋Œ€์ƒ ํ™•์žฅ์ž ํ•„ํ„ฐ๋„ ๊ทธ๋Œ€๋กœ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.\n * @param commits ์‚ฌ์šฉ์ž๊ฐ€ ๊ณ ๋ฅธ ์ปค๋ฐ‹ ๋ชฉ๋ก\n * @returns ๋ฆฌ๋ทฐ์šฉ ํ†ตํ•ฉ diff ํ…์ŠคํŠธ\n */\nexport function buildSelectedCommitDiff(commits: CommitOption[]) {\n const reviewPathspecArgs = getReviewPathspecArgs();\n const sections = commits\n .map((commit) => {\n const diff = runGitCommand(['show', '--stat', '--patch', '--format=', commit.hash, '--', ...reviewPathspecArgs], {\n allowFailure: true,\n trimOutput: false\n }).trim();\n\n if (!diff) {\n return '';\n }\n\n return [`## ${commit.hash} ${commit.subject}`, diff].join('\\n\\n');\n })\n .filter(Boolean)\n .join('\\n\\n');\n\n if (!sections) {\n return '';\n }\n\n return ['# ์„ ํƒํ•œ ์ปค๋ฐ‹', buildSelectedCommitSummary(commits), '', '# ๋ฆฌ๋ทฐ ๋Œ€์ƒ diff', sections].join('\\n');\n}\n\n/**\n * @description\n * ์„ ํƒ๋œ ์ปค๋ฐ‹์—์„œ ์‹ค์ œ ๋ฆฌ๋ทฐ ๋Œ€์ƒ ํŒŒ์ผ ๋ชฉ๋ก๋งŒ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค.\n * one-by-one ๋ฆฌ๋ทฐ๊ฐ€ ํ˜„์žฌ ์„ ํƒ๋œ ์ปค๋ฐ‹ ์ง‘ํ•ฉ์—๋งŒ ๋ฐ˜์‘ํ•˜๋„๋ก commit๋ณ„ name-only ๊ฒฐ๊ณผ๋ฅผ ํ•ฉ์ง‘ํ•ฉ์œผ๋กœ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค.\n * @param commits ์‚ฌ์šฉ์ž๊ฐ€ ๊ณ ๋ฅธ ์ปค๋ฐ‹ ๋ชฉ๋ก\n * @returns ์ค‘๋ณต ์ œ๊ฑฐ๋œ ํŒŒ์ผ ๋ชฉ๋ก\n */\nexport function getSelectedCommitFiles(commits: CommitOption[]) {\n const reviewPathspecArgs = getReviewPathspecArgs();\n const files = new Set<string>();\n\n commits.forEach((commit) => {\n const output = runGitCommand(['show', '--pretty=format:', '--name-only', commit.hash, '--', ...reviewPathspecArgs], {\n allowFailure: true\n });\n\n output\n .split('\\n')\n .map((line) => line.trim())\n .filter(Boolean)\n .forEach((filePath) => files.add(filePath));\n });\n\n return [...files];\n}\n\n/**\n * @description\n * ํŠน์ • ํŒŒ์ผ์— ๋Œ€ํ•œ ์„ ํƒ ์ปค๋ฐ‹๋“ค์˜ diff๋งŒ ๋ชจ์•„์„œ one-by-one ๋ฆฌ๋ทฐ ์ž…๋ ฅ์œผ๋กœ ๋งŒ๋“ญ๋‹ˆ๋‹ค.\n * ๋™์ผ ํŒŒ์ผ์ด ์—ฌ๋Ÿฌ ์ปค๋ฐ‹์—์„œ ๋ฐ”๋€ ๊ฒฝ์šฐ commit section์„ ๋‚˜๋ˆ  ๋ณด์—ฌ์ค˜ ํŒŒ์ผ ๋ฆฌ๋ทฐ ์‘๋‹ต์ด ์–ด๋А ๋ณ€๊ฒฝ์„ ๋‹ค๋ฃจ๋Š”์ง€ ์ถ”์  ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.\n * @param commits ์‚ฌ์šฉ์ž๊ฐ€ ๊ณ ๋ฅธ ์ปค๋ฐ‹ ๋ชฉ๋ก\n * @param filePath ๋ฆฌ๋ทฐํ•  ํŒŒ์ผ ๊ฒฝ๋กœ\n * @returns ๋‹จ์ผ ํŒŒ์ผ ๋ฆฌ๋ทฐ์šฉ diff ํ…์ŠคํŠธ\n */\nexport function buildSelectedFileDiff(commits: CommitOption[], filePath: string) {\n const sections = commits\n .map((commit) => {\n const diff = runGitCommand(['show', '--stat', '--patch', '--format=', commit.hash, '--', filePath], {\n allowFailure: true,\n trimOutput: false\n }).trim();\n\n if (!diff) {\n return '';\n }\n\n return [`## ${commit.hash} ${commit.subject}`, diff].join('\\n\\n');\n })\n .filter(Boolean)\n .join('\\n\\n');\n\n if (!sections) {\n return '';\n }\n\n return ['# ์„ ํƒํ•œ ์ปค๋ฐ‹', buildSelectedCommitSummary(commits), '', `# ํŒŒ์ผ: ${filePath}`, sections].join('\\n\\n');\n}\n\n/**\n * openReport๋ฅผ OS๋ณ„๋กœ ๋™์ž‘ํ•˜๋„๋ก ๋ณ€๊ฒฝ\n * ์šฐ์„ ์ˆœ์œ„:\n * 1. Chrome ์‹œ๋„\n * - macOS: open -a \"Google Chrome\" \"<path>\"\n * - Ubuntu/Linux: google-chrome \"<path>\"\n * 2. ์‹คํŒจ ์‹œ ๊ธฐ๋ณธ ๋ธŒ๋ผ์šฐ์ €๋กœ ํด๋ฐฑ\n * - macOS: open \"<path>\"\n * - Ubuntu/Linux: xdg-open \"<path>\"\n * 3. ๋‘˜ ๋‹ค ์‹คํŒจํ•˜๋ฉด ์—๋Ÿฌ ์ถœ๋ ฅ\n * 4. ๋ฏธ์ง€์› ํ”Œ๋žซํผ์ด๋ฉด ํ”Œ๋žซํผ ๊ฒฝ๊ณ  ์ถœ๋ ฅ\n */\nexport function openReport(reportPath: string) {\n const resolvedPath = path.resolve(reportPath);\n const { platform } = process;\n helperTrace('open-report:start', resolvedPath);\n\n const openWithChrome = () => {\n if (platform === 'darwin') {\n execSync(`open -a \"Google Chrome\" \"${resolvedPath}\"`, { stdio: 'ignore' });\n\n return true;\n }\n\n if (platform === 'linux') {\n execSync(`google-chrome \"${resolvedPath}\"`, { stdio: 'ignore' });\n\n return true;\n }\n\n return false;\n };\n\n const openWithDefaultBrowser = () => {\n if (platform === 'darwin') {\n execSync(`open \"${resolvedPath}\"`, { stdio: 'ignore' });\n\n return true;\n }\n\n if (platform === 'linux') {\n execSync(`xdg-open \"${resolvedPath}\"`, { stdio: 'ignore' });\n\n return true;\n }\n\n return false;\n };\n\n try {\n if (openWithChrome()) {\n helperTrace('open-report:chrome:success', platform);\n console.log('๐Ÿš€ Google Chrome์—์„œ ๋ฆฌํฌํŠธ๋ฅผ ์—ด์—ˆ์Šต๋‹ˆ๋‹ค.');\n\n return;\n }\n } catch (error) {\n helperTrace('open-report:chrome:failed', getErrorSummary(error));\n // Chrome ์‹คํ–‰ ์‹คํŒจ ์‹œ ๊ธฐ๋ณธ ๋ธŒ๋ผ์šฐ์ €๋กœ ํด๋ฐฑ\n }\n\n try {\n if (openWithDefaultBrowser()) {\n helperTrace('open-report:default-browser:success', platform);\n console.log('๐Ÿš€ ๊ธฐ๋ณธ ๋ธŒ๋ผ์šฐ์ €์—์„œ ๋ฆฌํฌํŠธ๋ฅผ ์—ด์—ˆ์Šต๋‹ˆ๋‹ค.');\n\n return;\n }\n } catch (error) {\n helperTrace('open-report:default-browser:failed', getErrorSummary(error));\n console.error('โš ๏ธ ๋ธŒ๋ผ์šฐ์ € ์—ด๊ธฐ ์‹คํŒจ:', error);\n\n return;\n }\n\n helperTrace('open-report:unsupported-platform', platform);\n console.error(`โš ๏ธ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ํ”Œ๋žซํผ์ž…๋‹ˆ๋‹ค: ${platform}`);\n}\n\n/**\n * @description\n * raw mode ๊ธฐ๋ฐ˜ ์„ ํƒ UI๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ์—ด ์ˆ˜ ์žˆ๋Š” TTY ํ™˜๊ฒฝ์ธ์ง€ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.\n * CI๋‚˜ pipe ํ™˜๊ฒฝ์—์„œ๋Š” ์ปค์„œ๋ฅผ ์ œ์–ดํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ์ฆ‰์‹œ ์—๋Ÿฌ ๋ฆฌํฌํŠธ๋ฅผ ๋‚จ๊ธฐ๊ณ  ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.\n * @param scope ์—๋Ÿฌ ๋ฆฌํฌํŠธ ๊ตฌ๋ถ„์šฉ scope\n * @param message ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ค„ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€\n */\nfunction ensureInteractiveSelectionAvailable(scope: string, message: string) {\n if (process.stdin.isTTY && process.stdout.isTTY && typeof process.stdin.setRawMode === 'function') {\n return;\n }\n\n helperTrace(`${scope}:tty-missing`);\n exitWithError(message, {\n scope: `helper:${scope}`\n });\n}\n\n/**\n * @description\n * ์„ ํƒ ๋ชจ๋‹ฌ์„ ํ˜„์žฌ ์œ„์น˜์—์„œ ๋‹ค์‹œ ๊ทธ๋ฆฝ๋‹ˆ๋‹ค.\n * ๊ฐ ์ค„์€ ๋ฏธ๋ฆฌ ํ„ฐ๋ฏธ๋„ ํญ ์•ˆ์œผ๋กœ ์ž˜๋ผ physical line์ด 1์ค„๋กœ ์œ ์ง€๋˜๋ฏ€๋กœ,\n * ์ง์ „ ๋ Œ๋” ์ค„ ์ˆ˜๋งŒํผ ์œ„๋กœ ์ด๋™ํ•œ ๋’ค clearScreenDown ํ•ด๋„ ์ค‘๋ณต ์—†์ด ์•ˆ์ •์ ์œผ๋กœ ๊ฐฑ์‹ ๋ฉ๋‹ˆ๋‹ค.\n * @param lines ์ƒˆ๋กœ ๋ Œ๋”ํ•  ๋ฌธ์ž์—ด ์ค„ ๋ชฉ๋ก\n * @param previousLineCount ์ง์ „ ๋ Œ๋” ์ค„ ์ˆ˜\n * @returns ํ˜„์žฌ ๋ Œ๋” ์ค„ ์ˆ˜\n */\nfunction renderSelectionBlock(lines: string[], previousLineCount: number) {\n if (previousLineCount > 0) {\n readline.moveCursor(process.stdout, 0, -previousLineCount);\n readline.clearScreenDown(process.stdout);\n }\n\n const fittedLines = fitLinesToTerminal(lines);\n process.stdout.write(`${fittedLines.join('\\n')}\\n`);\n\n return fittedLines.length;\n}\n\n/**\n * @description\n * ํ˜„์žฌ ์ปค์„œ ๊ธฐ์ค€ visible window๋ฅผ ๊ณ„์‚ฐํ•ด ๊ธด ์ปค๋ฐ‹ ๋ชฉ๋ก๋„ ๊ณ ์ • ๋†’์ด๋กœ ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.\n * @param optionCount ์ „์ฒด ์˜ต์…˜ ๊ฐœ์ˆ˜\n * @param selectedIndex ํ˜„์žฌ ํฌ์ปค์Šค ์ธ๋ฑ์Šค\n * @param windowSize ๋™์‹œ์— ๋ณด์—ฌ์ค„ ์ตœ๋Œ€ ์˜ต์…˜ ๊ฐœ์ˆ˜\n * @returns ์‹œ์ž‘/๋ ์ธ๋ฑ์Šค\n */\nfunction getSelectionWindowRange(optionCount: number, selectedIndex: number, windowSize: number) {\n if (optionCount <= windowSize) {\n return {\n end: optionCount,\n start: 0\n };\n }\n\n const halfWindow = Math.floor(windowSize / 2);\n const maxStart = optionCount - windowSize;\n const start = Math.max(0, Math.min(selectedIndex - halfWindow, maxStart));\n\n return {\n end: Math.min(optionCount, start + windowSize),\n start\n };\n}\n\n/**\n * @description\n * ๊ณตํ†ต multi-select UI ๋ Œ๋”๋ง์— ํ•„์š”ํ•œ ๋ฌธ์ž์—ด ๋ชฉ๋ก์„ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.\n * ์„ค๋ช… ํ…์ŠคํŠธ๋Š” dim ์ฒ˜๋ฆฌํ•ด subject์™€ author/date๊ฐ€ ํ•œ ์ค„์—์„œ ๊ตฌ๋ถ„๋˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.\n * @param question ์งˆ๋ฌธ ํ—ค๋”\n * @param options ํ‘œ์‹œํ•  ์˜ต์…˜ ๋ชฉ๋ก\n * @param selectedIndex ํ˜„์žฌ ํฌ์ปค์Šค ์ธ๋ฑ์Šค\n * @param toggled ์„ ํƒ๋œ ์ธ๋ฑ์Šค Set\n * @param windowSize ๋™์‹œ์— ๋ณด์—ฌ์ค„ ์ตœ๋Œ€ ์˜ต์…˜ ๊ฐœ์ˆ˜\n * @returns ์ถœ๋ ฅ ์ค„ ๋ชฉ๋ก\n */\nfunction buildMultiSelectLines<T>(\n question: string,\n options: MultiSelectOption<T>[],\n selectedIndex: number,\n toggled: Set<number>,\n windowSize: number\n) {\n const { start, end } = getSelectionWindowRange(options.length, selectedIndex, windowSize);\n const lines = [\n `${ANSI.bold}${question}${ANSI.reset}`,\n `${ANSI.dim}โ†‘โ†“ ์ด๋™ | Space ์„ ํƒ/ํ•ด์ œ | Enter ์™„๋ฃŒ | Esc ์ทจ์†Œ${ANSI.reset}`,\n `${ANSI.dim}์„ ํƒ๋จ: ${toggled.size}๊ฐœ / ์ „์ฒด: ${options.length}๊ฐœ${ANSI.reset}`\n ];\n\n for (let index = start; index < end; index += 1) {\n const option = options[index];\n\n if (!option) {\n continue;\n }\n\n const cursor = index === selectedIndex ? `${ANSI.cyan}>${ANSI.reset}` : ' ';\n const checked = toggled.has(index) ? `${ANSI.green}โ˜‘${ANSI.reset}` : 'โ˜';\n const description = option.description ? ` ${ANSI.dim}${option.description}${ANSI.reset}` : '';\n lines.push(`${cursor} ${checked} ${option.label}${description}`);\n }\n\n if (options.length > windowSize) {\n lines.push(`${ANSI.dim}ํ‘œ์‹œ ๋ฒ”์œ„: ${start + 1}-${end} / ${options.length}${ANSI.reset}`);\n }\n\n return lines;\n}\n\n/**\n * @description\n * ์ปค๋ฐ‹ ์„ ํƒ์ฒ˜๋Ÿผ ๋ณต์ˆ˜ ์„ ํƒ์ด ํ•„์š”ํ•œ ํ„ฐ๋ฏธ๋„ ๋ชจ๋‹ฌ์„ ๊ณตํ†ต์œผ๋กœ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.\n * raw mode๋ฅผ ์ง์ ‘ ์ œ์–ดํ•ด ๋ฐฉํ–ฅํ‚ค, Space, Enter, Esc๋ฅผ ์ฝ๊ณ  ์„ ํƒ๋œ value ๋ชฉ๋ก๋งŒ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.\n * @param question ์‚ฌ์šฉ์ž ์•ˆ๋‚ด ๋ฌธ๊ตฌ\n * @param options ์„ ํƒ ์˜ต์…˜ ๋ชฉ๋ก\n * @param windowSize ๋™์‹œ์— ๋ณด์—ฌ์ค„ ์ตœ๋Œ€ ์˜ต์…˜ ๊ฐœ์ˆ˜\n * @returns ์‚ฌ์šฉ์ž๊ฐ€ ํ™•์ •ํ•œ ์„ ํƒ ๊ฐ’ ๋ฐฐ์—ด\n */\nexport async function showMultiSelect<T>(question: string, options: MultiSelectOption<T>[], windowSize = COMMIT_SELECTION_WINDOW) {\n ensureInteractiveSelectionAvailable('showMultiSelect', 'โŒ ์ปค๋ฐ‹ ์„ ํƒ ๋ชจ๋‹ฌ์€ TTY ํ™˜๊ฒฝ์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.');\n let selectedIndex = 0;\n let renderedLineCount = 0;\n const toggled = new Set<number>();\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n terminal: true\n });\n\n process.stdout.write('\\u001b[?25l');\n\n const cleanup = () => {\n if (renderedLineCount > 0) {\n readline.moveCursor(process.stdout, 0, -renderedLineCount);\n readline.clearScreenDown(process.stdout);\n renderedLineCount = 0;\n }\n process.stdin.removeListener('data', onData);\n process.stdin.setRawMode(false);\n process.stdin.pause();\n rl.close();\n process.stdout.write('\\u001b[?25h');\n };\n\n const render = () => {\n const lines = buildMultiSelectLines(question, options, selectedIndex, toggled, windowSize);\n renderedLineCount = renderSelectionBlock(lines, renderedLineCount);\n };\n\n const confirmSelection = (resolve: (value: T[]) => void) => {\n const values = [...toggled]\n .sort((left, right) => left - right)\n .map((index) => options[index]?.value)\n .filter((value): value is T => value !== undefined);\n\n cleanup();\n resolve(values);\n };\n\n const cancelSelection = (resolve: (value: T[]) => void) => {\n cleanup();\n resolve([]);\n };\n\n let onData = (_data: Buffer) => {\n // ์‹ค์ œ ๊ตฌํ˜„์€ Promise ์ƒ์„ฑ ์‹œ์ ์— ๋ฐ”์ธ๋”ฉํ•ฉ๋‹ˆ๋‹ค.\n };\n\n render();\n\n return new Promise<T[]>((resolve) => {\n onData = (data: Buffer) => {\n const key = data.toString();\n\n if (key === '\\u0003') {\n cleanup();\n process.exit(0);\n }\n\n if (key === '\\u001b') {\n cancelSelection(resolve);\n\n return;\n }\n\n if (key === '\\x1b[A') {\n selectedIndex = (selectedIndex - 1 + options.length) % options.length;\n render();\n\n return;\n }\n\n if (key === '\\x1b[B') {\n selectedIndex = (selectedIndex + 1) % options.length;\n render();\n\n return;\n }\n\n if (key === ' ') {\n if (toggled.has(selectedIndex)) {\n toggled.delete(selectedIndex);\n } else {\n toggled.add(selectedIndex);\n }\n render();\n\n return;\n }\n\n if (key === '\\r' || key === '\\n') {\n confirmSelection(resolve);\n }\n };\n\n process.stdin.setRawMode(true);\n process.stdin.resume();\n process.stdin.on('data', onData);\n });\n}\n\n/**\n * @description\n * ์ตœ๊ทผ ์ปค๋ฐ‹ ๋ชฉ๋ก์„ modal UI๋กœ ์„ ํƒ๋ฐ›์•„ review ์—”ํŠธ๋ฆฌํฌ์ธํŠธ์—์„œ ๋ฐ”๋กœ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.\n * @returns ์‚ฌ์šฉ์ž๊ฐ€ ๊ณ ๋ฅธ ์ปค๋ฐ‹ ๋ชฉ๋ก\n */\nexport async function selectReviewCommits() {\n const commits = getRecentCommitOptions();\n\n if (commits.length === 0) {\n console.log('โ„น๏ธ ๋ฆฌ๋ทฐํ•  ์ตœ๊ทผ ์ปค๋ฐ‹์ด ์—†์Šต๋‹ˆ๋‹ค.');\n\n return [];\n }\n\n return showMultiSelect<CommitOption>(\n '๋ฆฌ๋ทฐํ•  ์ปค๋ฐ‹์„ ์„ ํƒํ•ด์ฃผ์„ธ์š”.',\n commits.map((commit) => ({\n description: commit.description,\n label: commit.label,\n value: commit\n })),\n COMMIT_SELECTION_WINDOW\n );\n}\n\n/**\n * AI ์„œ๋น„์Šค ์„ ํƒ\n */\nexport function selectAIService() {\n const service = parseServiceFromArgs();\n\n if (!service) {\n helperTrace('select-service:missing');\n exitWithError('โŒ ์„œ๋น„์Šค๊ฐ€ ์„ ํƒ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.', {\n scope: 'helper:selectAIService'\n });\n }\n\n helperTrace('select-service:done', service);\n\n return service;\n}\n\n/**\n * ํ„ฐ๋ฏธ๋„์—์„œ ๋ผ๋””์˜ค ๋ฒ„ํŠผ ํ˜•ํƒœ๋กœ AI ์„œ๋น„์Šค๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.\n */\nexport async function showSelectionAIService(): Promise<AIServiceType> {\n const selectedServiceFromArgs = parseServiceFromArgs();\n\n if (selectedServiceFromArgs) {\n helperTrace('show-selection:from-args', selectedServiceFromArgs);\n console.log(`\\nโœ… ${ANSI.green}${selectedServiceFromArgs}${ANSI.reset} ์„œ๋น„์Šค๊ฐ€ ์„ ํƒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. (--service)\\n`);\n\n return selectedServiceFromArgs;\n }\n\n ensureInteractiveSelectionAvailable('showSelectionAIService', 'โŒ AI ์„œ๋น„์Šค ์„ ํƒ UI๋Š” TTY ํ™˜๊ฒฝ์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.');\n helperTrace('show-selection:interactive:start');\n let selectedIndex = 0;\n\n // Use readline to handle keypresses\n // ํ‚ค ์ž…๋ ฅ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด readline ์ธํ„ฐํŽ˜์ด์Šค ์‚ฌ์šฉ\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n terminal: true\n });\n\n let firstRender = true;\n\n // Hide cursor\n process.stdout.write('\\u001b[?25l');\n\n const render = () => {\n if (!firstRender) {\n // Move cursor back to the starting line of the selection UI\n // We print (1 question line + services.length lines)\n // ์„ ํƒ UI์˜ ์‹œ์ž‘ ๋ผ์ธ์œผ๋กœ ์ปค์„œ ์ด๋™ (์งˆ๋ฌธ 1์ค„ + ์„œ๋น„์Šค ๋ชฉ๋ก N์ค„)\n readline.moveCursor(process.stdout, 0, -(AIServices.length + 1));\n }\n firstRender = false;\n helperTrace('show-selection:interactive:render', AIServices[selectedIndex] || 'unknown');\n\n // Clear everything from cursor down to avoid ghosting/overlaps\n // ์ž”์ƒ์ด๋‚˜ ๊ฒน์นจ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์ปค์„œ ์œ„์น˜๋ถ€ํ„ฐ ์•„๋ž˜์ชฝ ๋ชจ๋‘ ์ง€์›€\n readline.clearScreenDown(process.stdout);\n\n process.stdout.write(\n `๐Ÿค– AI ์„œ๋น„์Šค๋ฅผ ์„ ํƒํ•ด์ฃผ์„ธ์š” (${ANSI.yellow}โ†‘โ†“ ๋ฐฉํ–ฅํ‚ค${ANSI.reset} ์ด๋™, ${ANSI.yellow}Enter${ANSI.reset} ์„ ํƒ):\\n`\n );\n AIServices.forEach((service, index) => {\n if (index === selectedIndex) {\n process.stdout.write(` ${ANSI.cyan}>${ANSI.reset} ${ANSI.cyan}โ—‰${ANSI.reset} ${ANSI.bold}${service}${ANSI.reset}\\n`);\n } else {\n process.stdout.write(` โ—ฏ ${service}\\n`);\n }\n });\n };\n\n render();\n\n return new Promise((resolve) => {\n const onData = (data: Buffer) => {\n const key = data.toString();\n if (key === '\\u0003') {\n // Ctrl+C\n helperTrace('show-selection:interactive:ctrl-c');\n process.stdout.write('\\u001b[?25h'); // Show cursor\n process.exit(0);\n }\n if (key === '\\x1b[A') {\n // Up arrow\n selectedIndex = (selectedIndex - 1 + AIServices.length) % AIServices.length;\n render();\n } else if (key === '\\x1b[B') {\n // Down arrow\n selectedIndex = (selectedIndex + 1) % AIServices.length;\n render();\n } else if (key === '\\r' || key === '\\n') {\n // Enter\n process.stdin.removeListener('data', onData);\n process.stdin.setRawMode(false);\n process.stdin.pause();\n rl.close();\n\n // Show cursor\n process.stdout.write('\\u001b[?25h');\n\n console.log(`\\nโœ… ${ANSI.green}${AIServices[selectedIndex]}${ANSI.reset} ์„œ๋น„์Šค๊ฐ€ ์„ ํƒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.\\n`);\n const result = AIServices[selectedIndex];\n if (result) {\n helperTrace('show-selection:interactive:confirmed', result);\n resolve(result);\n }\n }\n };\n\n process.stdin.setRawMode(true);\n process.stdin.resume();\n process.stdin.on('data', onData);\n });\n}\n"]}
@@ -11,6 +11,18 @@ type WriteErrorReportOptions = {
11
11
  traceMessages?: string[];
12
12
  extraSections?: ErrorReportSection[];
13
13
  };
14
+ type ExecutionLogStatus = 'cancelled' | 'failed' | 'partial_failure' | 'success';
15
+ type WriteExecutionLogOptions = {
16
+ title?: string;
17
+ scope?: string;
18
+ status?: ExecutionLogStatus;
19
+ args?: string[];
20
+ startedAt?: Date;
21
+ finishedAt?: Date;
22
+ traceMessages?: string[];
23
+ extraSections?: ErrorReportSection[];
24
+ error?: unknown;
25
+ };
14
26
  type ShellCommandProgressOptions = {
15
27
  progressIntervalMs?: number;
16
28
  progressMessage?: string;
@@ -28,6 +40,15 @@ declare const COMMIT_FETCH_LIMIT = 20;
28
40
  declare const COMMIT_SELECTION_WINDOW = 8;
29
41
  declare const ignoreList: string[];
30
42
  declare function isTestMode(args?: string[]): boolean;
43
+ /**
44
+ * @description
45
+ * AI CLI์˜ ์ค‘๊ฐ„ stdout/stderr๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ํ„ฐ๋ฏธ๋„์— ๋…ธ์ถœํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ํŒ๋‹จํ•ฉ๋‹ˆ๋‹ค.
46
+ * ๊ธฐ๋ณธ ์‹คํ–‰์€ ์กฐ์šฉํ•œ ๋ชจ๋“œ๋กœ ์œ ์ง€ํ•˜๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ ๋ช…์‹œ์ ์œผ๋กœ ํ”Œ๋ž˜๊ทธ๋ฅผ ์ค„ ๋•Œ๋งŒ
47
+ * AI ์‘๋‹ต์„ ๊ทธ๋Œ€๋กœ ์ŠคํŠธ๋ฆฌ๋ฐํ•ฉ๋‹ˆ๋‹ค.
48
+ * @param args ํ˜„์žฌ ์‹คํ–‰ ์ธ์ž ๋ชฉ๋ก
49
+ * @returns ์‹ค์‹œ๊ฐ„ AI ์ถœ๋ ฅ ๋…ธ์ถœ ์—ฌ๋ถ€
50
+ */
51
+ declare function shouldStreamAIOutput(args?: string[]): boolean;
31
52
  declare function clearTraceMessages(): void;
32
53
  declare function getTraceMessages(): string[];
33
54
  /**
@@ -70,6 +91,14 @@ declare function createReportDirectory(): void;
70
91
  declare function getNowString(now?: Date): string;
71
92
  declare function getErrorLogTimestamp(now?: Date): string;
72
93
  declare function writeErrorReport(error: unknown, options?: WriteErrorReportOptions): string;
94
+ /**
95
+ * @description
96
+ * ์„ฑ๊ณต/์‹คํŒจ ์—ฌ๋ถ€์™€ ๋ฌด๊ด€ํ•˜๊ฒŒ ๋ฆฌ๋ทฐ ์‹คํ–‰ ์ž์ฒด์˜ ์ง„๋‹จ ๋กœ๊ทธ๋ฅผ `.review-report`์— ๋‚จ๊น๋‹ˆ๋‹ค.
97
+ * ์—๋Ÿฌ ๋กœ๊ทธ์™€ ๋ณ„๋„๋กœ ์‹คํ–‰ ๋งฅ๋ฝ, ์ƒ์„ฑ๋œ ๋ช…๋ น์–ด, trace๋ฅผ ํ•ญ์ƒ ๋ณด์กดํ•˜์—ฌ ์žฌํ˜„๊ณผ ์›์ธ ๋ถ„์„์— ํ™œ์šฉํ•ฉ๋‹ˆ๋‹ค.
98
+ * @param options ์‹คํ–‰ ์ƒํƒœ, ์‹œ์ž‘/์ข…๋ฃŒ ์‹œ๊ฐ, ์—๋Ÿฌ, ์ถ”๊ฐ€ ์„น์…˜ ๋“ฑ ์‹คํ–‰ ๋กœ๊ทธ ์ž‘์„ฑ ์˜ต์…˜
99
+ * @returns ์ƒ์„ฑ๋œ ์‹คํ–‰ ๋กœ๊ทธ ํŒŒ์ผ ๊ฒฝ๋กœ. ์‹คํŒจ ์‹œ ๋นˆ ๋ฌธ์ž์—ด
100
+ */
101
+ declare function writeExecutionLog(options?: WriteExecutionLogOptions): string;
73
102
  declare function exitWithError(message: string, options?: Omit<WriteErrorReportOptions, 'title'> & {
74
103
  error?: unknown;
75
104
  }): never;
@@ -154,4 +183,4 @@ declare function selectAIService(): AIServiceType;
154
183
  */
155
184
  declare function showSelectionAIService(): Promise<AIServiceType>;
156
185
 
157
- export { AIServices, COMMIT_FETCH_LIMIT, COMMIT_SELECTION_WINDOW, REPORT_DIR, buildSelectedCommitDiff, buildSelectedCommitSummary, buildSelectedFileDiff, clearTraceMessages, codingConventionRulesPath, createReportDirectory, createTraceLogger, deleteFile, deleteTempDiff, executeShellCommandWithProgress, exitWithError, formatReviewTargetFiles, getAvailableFilePath, getErrorLogTimestamp, getErrorSummary, getGitDiffFilter, getNextFilePath, getNowString, getRecentCommitOptions, getSelectedCommitFiles, getTraceMessages, ignoreList, isTestMode, namingRulesPath, openReport, reviewFormOneByOnePath, reviewFormPath, rulesPath, selectAIService, selectReviewCommits, showMultiSelect, showSelectionAIService, tempDiffPath, writeErrorReport };
186
+ export { AIServices, COMMIT_FETCH_LIMIT, COMMIT_SELECTION_WINDOW, REPORT_DIR, buildSelectedCommitDiff, buildSelectedCommitSummary, buildSelectedFileDiff, clearTraceMessages, codingConventionRulesPath, createReportDirectory, createTraceLogger, deleteFile, deleteTempDiff, executeShellCommandWithProgress, exitWithError, formatReviewTargetFiles, getAvailableFilePath, getErrorLogTimestamp, getErrorSummary, getGitDiffFilter, getNextFilePath, getNowString, getRecentCommitOptions, getSelectedCommitFiles, getTraceMessages, ignoreList, isTestMode, namingRulesPath, openReport, reviewFormOneByOnePath, reviewFormPath, rulesPath, selectAIService, selectReviewCommits, shouldStreamAIOutput, showMultiSelect, showSelectionAIService, tempDiffPath, writeErrorReport, writeExecutionLog };