sales-frontend-gemini-cli 0.3.1 → 0.4.1

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 (81) hide show
  1. package/dist/common/helper.cjs +77 -6
  2. package/dist/common/helper.cjs.map +1 -1
  3. package/dist/common/helper.d.cts +16 -2
  4. package/dist/common/helper.d.ts +16 -2
  5. package/dist/common/helper.js +76 -7
  6. package/dist/common/helper.js.map +1 -1
  7. package/dist/{pr-review/gemini → etc}/installation-gcloud.cjs +1 -1
  8. package/dist/etc/installation-gcloud.cjs.map +1 -0
  9. package/dist/{pr-review/gemini → etc}/installation-gcloud.js +1 -1
  10. package/dist/etc/installation-gcloud.js.map +1 -0
  11. package/dist/{pr-review/gemini → etc}/interactive-version/index.cjs +2 -2
  12. package/dist/etc/interactive-version/index.cjs.map +1 -0
  13. package/dist/{pr-review/gemini → etc}/interactive-version/index.js +2 -2
  14. package/dist/etc/interactive-version/index.js.map +1 -0
  15. package/dist/{pr-review/gemini → etc}/login.cjs +1 -1
  16. package/dist/etc/login.cjs.map +1 -0
  17. package/dist/{pr-review/gemini → etc}/login.js +1 -1
  18. package/dist/etc/login.js.map +1 -0
  19. package/dist/{pr-review/gemini → etc}/vertex-version/index.cjs +1 -1
  20. package/dist/etc/vertex-version/index.cjs.map +1 -0
  21. package/dist/{pr-review/gemini → etc}/vertex-version/index.js +1 -1
  22. package/dist/etc/vertex-version/index.js.map +1 -0
  23. package/dist/pr-review/claude/claude-commander.cjs +150 -17
  24. package/dist/pr-review/claude/claude-commander.cjs.map +1 -1
  25. package/dist/pr-review/claude/claude-commander.d.cts +7 -8
  26. package/dist/pr-review/claude/claude-commander.d.ts +7 -8
  27. package/dist/pr-review/claude/claude-commander.js +150 -17
  28. package/dist/pr-review/claude/claude-commander.js.map +1 -1
  29. package/dist/pr-review/claude/installation-claude.cjs +38 -1
  30. package/dist/pr-review/claude/installation-claude.cjs.map +1 -1
  31. package/dist/pr-review/claude/installation-claude.js +33 -1
  32. package/dist/pr-review/claude/installation-claude.js.map +1 -1
  33. package/dist/pr-review/codex/codex-commander.cjs +126 -0
  34. package/dist/pr-review/codex/codex-commander.cjs.map +1 -0
  35. package/dist/pr-review/codex/codex-commander.d.cts +17 -0
  36. package/dist/pr-review/codex/codex-commander.d.ts +17 -0
  37. package/dist/pr-review/codex/codex-commander.js +118 -0
  38. package/dist/pr-review/codex/codex-commander.js.map +1 -0
  39. package/dist/pr-review/codex/installation-codex.cjs +62 -0
  40. package/dist/pr-review/codex/installation-codex.cjs.map +1 -0
  41. package/dist/pr-review/codex/installation-codex.d.cts +3 -0
  42. package/dist/pr-review/codex/installation-codex.d.ts +3 -0
  43. package/dist/pr-review/codex/installation-codex.js +55 -0
  44. package/dist/pr-review/codex/installation-codex.js.map +1 -0
  45. package/dist/pr-review/gemini/gemini-commander.cjs +133 -15
  46. package/dist/pr-review/gemini/gemini-commander.cjs.map +1 -1
  47. package/dist/pr-review/gemini/gemini-commander.d.cts +10 -13
  48. package/dist/pr-review/gemini/gemini-commander.d.ts +10 -13
  49. package/dist/pr-review/gemini/gemini-commander.js +133 -15
  50. package/dist/pr-review/gemini/gemini-commander.js.map +1 -1
  51. package/dist/pr-review/gemini/installation-gemini.cjs +35 -0
  52. package/dist/pr-review/gemini/installation-gemini.cjs.map +1 -1
  53. package/dist/pr-review/gemini/installation-gemini.js +30 -0
  54. package/dist/pr-review/gemini/installation-gemini.js.map +1 -1
  55. package/dist/pr-review/review-one-by-one.cjs +547 -56
  56. package/dist/pr-review/review-one-by-one.cjs.map +1 -1
  57. package/dist/pr-review/review-one-by-one.js +546 -55
  58. package/dist/pr-review/review-one-by-one.js.map +1 -1
  59. package/dist/pr-review/review.cjs +517 -41
  60. package/dist/pr-review/review.cjs.map +1 -1
  61. package/dist/pr-review/review.js +517 -41
  62. package/dist/pr-review/review.js.map +1 -1
  63. package/package.json +1 -1
  64. package/src/common/form/review-form.md +1 -1
  65. package/src/common/rules/review-rules.md +2 -0
  66. package/dist/pr-review/gemini/installation-gcloud.cjs.map +0 -1
  67. package/dist/pr-review/gemini/installation-gcloud.js.map +0 -1
  68. package/dist/pr-review/gemini/interactive-version/index.cjs.map +0 -1
  69. package/dist/pr-review/gemini/interactive-version/index.js.map +0 -1
  70. package/dist/pr-review/gemini/login.cjs.map +0 -1
  71. package/dist/pr-review/gemini/login.js.map +0 -1
  72. package/dist/pr-review/gemini/vertex-version/index.cjs.map +0 -1
  73. package/dist/pr-review/gemini/vertex-version/index.js.map +0 -1
  74. /package/dist/{pr-review/gemini → etc}/installation-gcloud.d.cts +0 -0
  75. /package/dist/{pr-review/gemini → etc}/installation-gcloud.d.ts +0 -0
  76. /package/dist/{pr-review/gemini → etc}/interactive-version/index.d.cts +0 -0
  77. /package/dist/{pr-review/gemini → etc}/interactive-version/index.d.ts +0 -0
  78. /package/dist/{pr-review/gemini → etc}/login.d.cts +0 -0
  79. /package/dist/{pr-review/gemini → etc}/login.d.ts +0 -0
  80. /package/dist/{pr-review/gemini → etc}/vertex-version/index.d.cts +0 -0
  81. /package/dist/{pr-review/gemini → etc}/vertex-version/index.d.ts +0 -0
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { exec, execSync } from 'child_process';
3
- import fs4 from 'fs';
3
+ import fs5 from 'fs';
4
4
  import util from 'util';
5
5
  import path from 'path';
6
6
  import readline from 'readline';
@@ -29,27 +29,54 @@ var ignoreList = [
29
29
  ".review-report/"
30
30
  // 생성되는 리포트 폴더도 제외
31
31
  ];
32
+ function parseServiceFromArgs(args4 = process.argv.slice(2)) {
33
+ const serviceIndex = args4.indexOf("--service");
34
+ const rawService = serviceIndex !== -1 ? args4[serviceIndex + 1] : "";
35
+ if (!rawService) {
36
+ return "";
37
+ }
38
+ const normalizedService = rawService.toLowerCase();
39
+ if (AIServices.includes(normalizedService)) {
40
+ return normalizedService;
41
+ }
42
+ console.error(
43
+ `\u274C \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uC11C\uBE44\uC2A4\uC785\uB2C8\uB2E4: ${rawService}. \uC0AC\uC6A9 \uAC00\uB2A5 \uAC12: ${AIServices.join(", ")} (\uC608: --service codex)`
44
+ );
45
+ process.exit(1);
46
+ }
47
+ function isTestMode(args4 = process.argv.slice(2)) {
48
+ return args4.includes("--test");
49
+ }
50
+ function createTraceLogger(scope, args4 = process.argv.slice(2)) {
51
+ const enabled = isTestMode(args4);
52
+ return (step, detail) => {
53
+ if (!enabled) {
54
+ return;
55
+ }
56
+ console.log(`[TRACE][${scope}] ${step}${detail ? ` | ${detail}` : ""}`);
57
+ };
58
+ }
32
59
  function getNextFilePath(dir, baseName, extension) {
33
60
  let counter = 1;
34
61
  while (true) {
35
62
  const filePath = path.join(dir, `${baseName}-${counter}${extension}`);
36
- if (!fs4.existsSync(filePath)) {
63
+ if (!fs5.existsSync(filePath)) {
37
64
  return filePath;
38
65
  }
39
66
  counter++;
40
67
  }
41
68
  }
42
69
  function deleteFile(filePath) {
43
- if (fs4.existsSync(filePath)) {
44
- fs4.unlinkSync(filePath);
70
+ if (fs5.existsSync(filePath)) {
71
+ fs5.unlinkSync(filePath);
45
72
  }
46
73
  }
47
74
  function deleteTempDiff() {
48
75
  deleteFile(tempDiffPath);
49
76
  }
50
77
  function createReportDirectory() {
51
- if (!fs4.existsSync(REPORT_DIR)) {
52
- fs4.mkdirSync(REPORT_DIR, { recursive: true });
78
+ if (!fs5.existsSync(REPORT_DIR)) {
79
+ fs5.mkdirSync(REPORT_DIR, { recursive: true });
53
80
  }
54
81
  }
55
82
  function getNowString() {
@@ -71,25 +98,60 @@ function getGitDiffFilter() {
71
98
  return { includeParams, excludeParams };
72
99
  }
73
100
  function openReport(reportPath) {
101
+ const resolvedPath = path.resolve(reportPath);
102
+ const { platform } = process;
103
+ const openWithChrome = () => {
104
+ if (platform === "darwin") {
105
+ execSync(`open -a "Google Chrome" "${resolvedPath}"`, { stdio: "ignore" });
106
+ return true;
107
+ }
108
+ if (platform === "linux") {
109
+ execSync(`google-chrome "${resolvedPath}"`, { stdio: "ignore" });
110
+ return true;
111
+ }
112
+ return false;
113
+ };
114
+ const openWithDefaultBrowser = () => {
115
+ if (platform === "darwin") {
116
+ execSync(`open "${resolvedPath}"`, { stdio: "ignore" });
117
+ return true;
118
+ }
119
+ if (platform === "linux") {
120
+ execSync(`xdg-open "${resolvedPath}"`, { stdio: "ignore" });
121
+ return true;
122
+ }
123
+ return false;
124
+ };
74
125
  try {
75
- execSync(`open -a "Google Chrome" "${path.resolve(reportPath)}"`);
76
- console.log(`\u{1F680} \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uB9AC\uD3EC\uD2B8\uB97C \uC5F4\uC5C8\uC2B5\uB2C8\uB2E4.`);
126
+ if (openWithChrome()) {
127
+ console.log("\u{1F680} Google Chrome\uC5D0\uC11C \uB9AC\uD3EC\uD2B8\uB97C \uC5F4\uC5C8\uC2B5\uB2C8\uB2E4.");
128
+ return;
129
+ }
130
+ } catch {
131
+ }
132
+ try {
133
+ if (openWithDefaultBrowser()) {
134
+ console.log("\u{1F680} \uAE30\uBCF8 \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uB9AC\uD3EC\uD2B8\uB97C \uC5F4\uC5C8\uC2B5\uB2C8\uB2E4.");
135
+ return;
136
+ }
77
137
  } catch (e) {
78
138
  console.error("\u26A0\uFE0F \uBE0C\uB77C\uC6B0\uC800 \uC5F4\uAE30 \uC2E4\uD328:", e);
139
+ return;
79
140
  }
141
+ console.error(`\u26A0\uFE0F \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uD50C\uB7AB\uD3FC\uC785\uB2C8\uB2E4: ${platform}`);
80
142
  }
81
143
  function getDiffArgs() {
82
- const args3 = process.argv.slice(2);
83
- const commitIndex = args3.indexOf("--commit");
144
+ const args4 = process.argv.slice(2);
145
+ const commitIndex = args4.indexOf("--commit");
84
146
  const { includeParams, excludeParams } = getGitDiffFilter();
85
147
  let diffArgs = "";
86
148
  if (commitIndex !== -1) {
87
- const commitHash = args3[commitIndex + 1];
149
+ const commitHash = args4[commitIndex + 1];
88
150
  if (!commitHash) {
89
151
  console.error("\u274C \uCEE4\uBC0B \uD574\uC2DC\uAC00 \uC81C\uACF5\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.");
90
152
  process.exit(1);
91
153
  }
92
- const nextArg = args3[commitIndex + 2];
154
+ const nextArg = args4[commitIndex + 2];
93
155
  let n = 0;
94
156
  if (nextArg && !nextArg.startsWith("--")) {
95
157
  n = parseInt(nextArg, 10);
@@ -112,6 +174,13 @@ function getDiffArgs() {
112
174
  return diffArgs;
113
175
  }
114
176
  async function showSelectionAIService() {
177
+ const selectedServiceFromArgs = parseServiceFromArgs();
178
+ if (selectedServiceFromArgs) {
179
+ console.log(`
180
+ \u2705 \x1B[32m${selectedServiceFromArgs}\x1B[0m \uC11C\uBE44\uC2A4\uAC00 \uC120\uD0DD\uB418\uC5C8\uC2B5\uB2C8\uB2E4. (--service)
181
+ `);
182
+ return selectedServiceFromArgs;
183
+ }
115
184
  let selectedIndex = 0;
116
185
  const rl = readline.createInterface({
117
186
  input: process.stdin,
@@ -126,7 +195,9 @@ async function showSelectionAIService() {
126
195
  }
127
196
  firstRender = false;
128
197
  readline.clearScreenDown(process.stdout);
129
- process.stdout.write("\u{1F916} AI \uC11C\uBE44\uC2A4\uB97C \uC120\uD0DD\uD574\uC8FC\uC138\uC694 (\x1B[33m\u2191\u2193 \uBC29\uD5A5\uD0A4\x1B[0m \uC774\uB3D9, \x1B[33mEnter\x1B[0m \uC120\uD0DD):\n");
198
+ process.stdout.write(
199
+ "\u{1F916} AI \uC11C\uBE44\uC2A4\uB97C \uC120\uD0DD\uD574\uC8FC\uC138\uC694 (\x1B[33m\u2191\u2193 \uBC29\uD5A5\uD0A4\x1B[0m \uC774\uB3D9, \x1B[33mEnter\x1B[0m \uC120\uD0DD):\n"
200
+ );
130
201
  AIServices.forEach((service, index) => {
131
202
  if (index === selectedIndex) {
132
203
  process.stdout.write(` \x1B[36m>\x1B[0m \x1B[36m\u25C9\x1B[0m \x1B[1m${service}\x1B[0m
@@ -172,149 +243,544 @@ async function showSelectionAIService() {
172
243
  });
173
244
  }
174
245
  var args = process.argv.slice(2);
175
- var createClaudeCommand = (tempDiffPath2, reviewFormPath2) => {
176
- let modelOption = "";
177
- if (args.includes("--review")) {
178
- modelOption = "--model opus";
179
- } else if (args.includes("--flash")) {
180
- modelOption = "--model haiku";
181
- } else {
182
- const modelIndex = args.indexOf("--model");
183
- if (modelIndex !== -1 && args[modelIndex + 1]) {
184
- console.warn("\u26A0\uFE0F \uC9C0\uC815\uD55C \uBAA8\uB378\uC774 \uC5C6\uB294 \uACBD\uC6B0, \uC5D0\uB7EC\uAC00 \uBC1C\uC0DD\uD558\uB2C8 \uC8FC\uC758\uD558\uC138\uC694.");
185
- modelOption = `--model ${args[modelIndex + 1]}`;
186
- } else {
187
- console.warn("\u26A0\uFE0F \uBAA8\uB378\uC774 \uC9C0\uC815\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uAE30\uBCF8 \uBAA8\uB378\uC778 sonnet\uC744 \uC0AC\uC6A9\uD569\uB2C8\uB2E4.");
188
- modelOption = "--model sonnet";
246
+ var trace = createTraceLogger("claude-commander", args);
247
+ var ALLOWED_REASONING_EFFORTS = ["minimal", "low", "medium", "high"];
248
+ function shellQuote(value) {
249
+ return `'${value.replace(/'/g, `'\\''`)}'`;
250
+ }
251
+ function getArgValue(flag) {
252
+ const index = args.indexOf(flag);
253
+ if (index === -1 || !args[index + 1]) {
254
+ return "";
255
+ }
256
+ return args[index + 1];
257
+ }
258
+ function toUnique(values) {
259
+ const seen = /* @__PURE__ */ new Set();
260
+ return values.filter((value) => {
261
+ if (!value || seen.has(value)) {
262
+ return false;
189
263
  }
264
+ seen.add(value);
265
+ return true;
266
+ });
267
+ }
268
+ function normalizeEffort(level) {
269
+ if (level === "minimal") {
270
+ return "low";
271
+ }
272
+ return level;
273
+ }
274
+ function resolveReasoningEffort() {
275
+ const customReasoningEffort = getArgValue("--reasoning-effort") || getArgValue("--effort");
276
+ if (customReasoningEffort) {
277
+ if (ALLOWED_REASONING_EFFORTS.includes(customReasoningEffort)) {
278
+ const normalized = normalizeEffort(customReasoningEffort);
279
+ trace("reasoning:custom", `${customReasoningEffort} -> ${normalized}`);
280
+ if (customReasoningEffort === "minimal") {
281
+ console.warn("\u26A0\uFE0F Claude\uB294 minimal\uC744 \uC9C1\uC811 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC544 low\uB85C \uB9E4\uD551\uD569\uB2C8\uB2E4.");
282
+ }
283
+ return normalized;
284
+ }
285
+ console.warn(
286
+ `\u26A0\uFE0F \uC9C0\uC6D0\uB418\uC9C0 \uC54A\uB294 reasoning effort(${customReasoningEffort})\uC785\uB2C8\uB2E4. allowed: ${ALLOWED_REASONING_EFFORTS.join(
287
+ ", "
288
+ )}`
289
+ );
290
+ }
291
+ if (args.includes("--flash")) {
292
+ trace("reasoning:flash-default", "low");
293
+ return "low";
190
294
  }
295
+ if (args.includes("--review")) {
296
+ trace("reasoning:review-default", "high");
297
+ return "high";
298
+ }
299
+ trace("reasoning:default", "medium");
300
+ return "medium";
301
+ }
302
+ function resolvePrimaryAlias() {
303
+ if (args.includes("--review")) {
304
+ trace("model:mode-alias", "opus");
305
+ return "opus";
306
+ }
307
+ if (args.includes("--flash")) {
308
+ trace("model:mode-alias", "haiku");
309
+ return "haiku";
310
+ }
311
+ trace("model:default-alias", "sonnet");
312
+ return "sonnet";
313
+ }
314
+ function getAliasFallbacks(primaryAlias) {
315
+ if (primaryAlias === "opus") {
316
+ return ["opus", "sonnet", "haiku"];
317
+ }
318
+ if (primaryAlias === "haiku") {
319
+ return ["haiku", "sonnet"];
320
+ }
321
+ return [primaryAlias, "sonnet", "haiku"];
322
+ }
323
+ function buildClaudeExecCommand(options) {
324
+ const { tempDiffPath: tempDiffPath2, prompt, systemPromptFiles, effort, model, fallbackModel } = options;
325
+ const modelOption = model ? `--model ${shellQuote(model)}` : "";
326
+ const fallbackOption = model && fallbackModel ? `--fallback-model ${shellQuote(fallbackModel)}` : "";
327
+ const effortOption = `--effort ${shellQuote(effort)}`;
328
+ const appendedPromptFiles = systemPromptFiles.map((path2) => `--append-system-prompt-file ${shellQuote(path2)}`).join(" ");
329
+ return `cat ${shellQuote(tempDiffPath2)} | claude ${[
330
+ modelOption,
331
+ fallbackOption,
332
+ effortOption,
333
+ appendedPromptFiles,
334
+ "-p",
335
+ shellQuote(prompt)
336
+ ].filter(Boolean).join(" ")}`;
337
+ }
338
+ var createClaudeCommand = (tempDiffPath2, reviewFormPath2) => {
339
+ trace("createClaudeCommand:start", `tempDiffPath=${tempDiffPath2}, reviewFormPath=${reviewFormPath2}`);
340
+ const customModel = getArgValue("--model");
341
+ const effort = resolveReasoningEffort();
342
+ const primaryAlias = resolvePrimaryAlias();
343
+ const aliasFallbacks = toUnique(getAliasFallbacks(primaryAlias));
191
344
  const rules = [
192
345
  { path: rulesPath, display: "\uB8F0\uC14B" },
193
346
  { path: namingRulesPath, display: "\uB124\uC774\uBC0D \uADDC\uCE59" },
194
347
  { path: codingConventionRulesPath, display: "\uCF54\uB529 \uCEE8\uBCA4\uC158" }
195
348
  ];
196
- const systemPromptFiles = rules.filter((rule) => fs4.existsSync(rule.path)).map((rule) => `--append-system-prompt-file ${rule.path}`).join(" ");
197
- const reviewFormOption = fs4.existsSync(reviewFormPath2) ? `--append-system-prompt-file ${reviewFormPath2}` : "";
198
- const command = `cat ${tempDiffPath2} | claude ${modelOption} ${systemPromptFiles} ${reviewFormOption} -p "\uC704 \uADDC\uCE59\uB4E4\uC744 \uCC38\uACE0\uD558\uC5EC \uC774 diff\uB97C \uCF54\uB4DC\uB9AC\uBDF0\uD574\uC918. \uB9AC\uBDF0\uC591\uC2DD\uC5D0 \uB9DE\uCDB0\uC11C \uC791\uC131\uD574\uC918."`;
349
+ const existingRuleFiles = rules.filter((rule) => fs5.existsSync(rule.path)).map((rule) => rule.path);
350
+ trace("rules:loaded", `count=${existingRuleFiles.length}`);
351
+ const reviewFormExists = fs5.existsSync(reviewFormPath2);
352
+ trace("reviewForm:status", reviewFormExists ? "exists" : "missing");
353
+ const systemPromptFiles = reviewFormExists ? [...existingRuleFiles, reviewFormPath2] : existingRuleFiles;
354
+ const prompt = "\uC704 \uADDC\uCE59\uB4E4\uC744 \uCC38\uACE0\uD558\uC5EC \uC774 diff\uB97C \uCF54\uB4DC\uB9AC\uBDF0\uD574\uC918. \uB9AC\uBDF0\uC591\uC2DD\uC5D0 \uB9DE\uCDB0\uC11C \uC791\uC131\uD574\uC918.";
355
+ const modelCandidates = toUnique(customModel ? [customModel, ...aliasFallbacks] : aliasFallbacks);
356
+ trace("model:candidates", modelCandidates.join(", "));
357
+ if (customModel) {
358
+ console.warn(
359
+ `\u26A0\uFE0F \uCEE4\uC2A4\uD140 \uBAA8\uB378(${customModel})\uC744 \uC6B0\uC120 \uC2DC\uB3C4\uD558\uACE0 \uC2E4\uD328\uD558\uBA74 alias(${aliasFallbacks.join(
360
+ " -> "
361
+ )}) \uBC0F \uAE30\uBCF8 \uBAA8\uB378 \uC21C\uC73C\uB85C \uD3F4\uBC31\uD569\uB2C8\uB2E4.`
362
+ );
363
+ } else {
364
+ console.warn(
365
+ `\u26A0\uFE0F \uBAA8\uB378\uC774 \uC9C0\uC815\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. alias(${aliasFallbacks.join(" -> ")})\uB97C \uC21C\uCC28 \uC2DC\uB3C4\uD558\uACE0 \uB9C8\uC9C0\uB9C9\uC5D0 \uAE30\uBCF8 \uBAA8\uB378\uB85C \uD3F4\uBC31\uD569\uB2C8\uB2E4.`
366
+ );
367
+ }
368
+ const commandCandidates = modelCandidates.map((model, index) => {
369
+ const fallbackModel = modelCandidates[index + 1];
370
+ return buildClaudeExecCommand({
371
+ tempDiffPath: tempDiffPath2,
372
+ prompt,
373
+ systemPromptFiles,
374
+ effort,
375
+ model,
376
+ fallbackModel
377
+ });
378
+ });
379
+ const command = [
380
+ ...commandCandidates,
381
+ buildClaudeExecCommand({
382
+ tempDiffPath: tempDiffPath2,
383
+ prompt,
384
+ systemPromptFiles,
385
+ effort
386
+ })
387
+ ].join(" || ");
388
+ trace("command:created");
199
389
  if (args.includes("--test")) {
200
390
  const safeCommand = command.replace(/"/g, '\\"');
391
+ trace("test-mode:return-preview");
201
392
  return `echo "[TEST MODE] Claude \uBA85\uB839\uC5B4\uAC00 \uC2E4\uD589\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.
202
393
 
203
394
  \uC0DD\uC131\uB420 \uBA85\uB839\uC5B4 \uBBF8\uB9AC\uBCF4\uAE30:
204
395
  ${safeCommand}"`;
205
396
  }
397
+ trace("createClaudeCommand:end");
206
398
  return command;
207
399
  };
400
+ var trace2 = createTraceLogger("installation-claude");
208
401
  function checkClaudeCliInstalled() {
402
+ trace2("checkClaudeCliInstalled:start");
209
403
  try {
404
+ trace2("version-check:run", "claude --version");
210
405
  execSync("claude --version", { stdio: "ignore" });
406
+ trace2("version-check:ok");
211
407
  } catch {
212
- console.log("\u2139\uFE0F claude-cli\uAC00 \uC124\uCE58\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uC124\uCE58\uB97C \uC9C4\uD589\uD569\uB2C8\uB2E4... npm install -g @anthropic-ai/claude-code");
408
+ trace2("version-check:failed", "install-start");
409
+ console.log(
410
+ "\u2139\uFE0F claude-cli\uAC00 \uC124\uCE58\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uC124\uCE58\uB97C \uC9C4\uD589\uD569\uB2C8\uB2E4... npm install -g @anthropic-ai/claude-code"
411
+ );
213
412
  try {
214
413
  execSync("npm install -g @anthropic-ai/claude-code", { stdio: "inherit" });
414
+ trace2("install:ok", "exit(1) for login");
215
415
  console.log("\u2705 claude-cli \uC124\uCE58\uAC00 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.");
216
416
  console.log("\u26A0\uFE0F claude-cli \uC0AC\uC6A9\uC744 \uC704\uD574 \uC778\uC99D\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.");
217
417
  console.log(' \uD130\uBBF8\uB110\uC5D0\uC11C "claude" \uB97C \uC785\uB825\uD558\uC5EC \uBE0C\uB77C\uC6B0\uC800 \uB85C\uADF8\uC778\uC744 \uC644\uB8CC\uD55C \uD6C4, \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uC8FC\uC138\uC694.');
218
418
  process.exit(1);
219
419
  } catch (installError) {
420
+ trace2("install:failed");
220
421
  console.error("\u274C claude-cli \uC124\uCE58 \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4. \uAD8C\uD55C \uBB38\uC81C\uC77C \uC218 \uC788\uC2B5\uB2C8\uB2E4 (sudo \uD544\uC694).");
221
422
  console.error(installError);
222
423
  process.exit(1);
223
424
  }
224
425
  }
426
+ trace2("checkClaudeCliInstalled:end");
225
427
  }
226
428
  var args2 = process.argv.slice(2);
227
- var createGeminiCommand = (tempDiffPath2, reviewFormPath2) => {
228
- let modelOption = "";
429
+ var trace3 = createTraceLogger("codex-commander", args2);
430
+ var ALLOWED_REASONING_EFFORTS2 = ["minimal", "low", "medium", "high"];
431
+ function shellQuote2(value) {
432
+ return `'${value.replace(/'/g, `'\\''`)}'`;
433
+ }
434
+ function getArgValue2(flag) {
435
+ const index = args2.indexOf(flag);
436
+ if (index === -1 || !args2[index + 1]) {
437
+ return "";
438
+ }
439
+ return args2[index + 1];
440
+ }
441
+ function resolveReasoningEffort2() {
442
+ const customReasoningEffort = getArgValue2("--reasoning-effort");
443
+ if (customReasoningEffort) {
444
+ if (ALLOWED_REASONING_EFFORTS2.includes(customReasoningEffort)) {
445
+ trace3("reasoning:custom", customReasoningEffort);
446
+ return customReasoningEffort;
447
+ }
448
+ console.warn(
449
+ `\u26A0\uFE0F \uC9C0\uC6D0\uB418\uC9C0 \uC54A\uB294 reasoning effort(${customReasoningEffort})\uC785\uB2C8\uB2E4. allowed: ${ALLOWED_REASONING_EFFORTS2.join(
450
+ ", "
451
+ )}`
452
+ );
453
+ }
454
+ if (args2.includes("--flash")) {
455
+ trace3("reasoning:flash-default", "minimal");
456
+ return "minimal";
457
+ }
229
458
  if (args2.includes("--review")) {
230
- modelOption = "--model pro";
231
- } else if (args2.includes("--flash")) {
232
- modelOption = "--model flash";
459
+ trace3("reasoning:review-default", "high");
460
+ return "high";
461
+ }
462
+ trace3("reasoning:default", "medium");
463
+ return "medium";
464
+ }
465
+ function buildCodexExecCommand(prompt, reasoningEffort, model) {
466
+ const modelOption = model ? `--model ${shellQuote2(model)}` : "";
467
+ const reasoningOption = `-c ${shellQuote2(`model_reasoning_effort="${reasoningEffort}"`)}`;
468
+ return `codex exec ${[modelOption, reasoningOption, shellQuote2(prompt)].filter(Boolean).join(" ")}`;
469
+ }
470
+ var createCodexCommand = (tempDiffPath2, reviewFormPath2) => {
471
+ trace3("createCodexCommand:start", `tempDiffPath=${tempDiffPath2}, reviewFormPath=${reviewFormPath2}`);
472
+ const customModel = getArgValue2("--model");
473
+ const reasoningEffort = resolveReasoningEffort2();
474
+ const rules = [rulesPath, namingRulesPath, codingConventionRulesPath].filter((filePath) => fs5.existsSync(filePath)).map((filePath) => `- ${filePath}`).join("\n");
475
+ const rulesCount = rules ? rules.split("\n").length : 0;
476
+ trace3("rules:loaded", `count=${rulesCount}`);
477
+ const hasReviewForm = fs5.existsSync(reviewFormPath2);
478
+ const reviewFormLine = hasReviewForm ? `- ${reviewFormPath2}` : "";
479
+ trace3("reviewForm:status", reviewFormLine ? "exists" : "missing");
480
+ const prompt = `\uC544\uB798 \uD30C\uC77C\uB4E4\uC744 \uCC38\uACE0\uD574\uC11C \uCF54\uB4DC \uB9AC\uBDF0\uB97C \uC9C4\uD589\uD574\uC918.
481
+ \uADDC\uCE59 \uD30C\uC77C:
482
+ ${rules || "- (\uC5C6\uC74C)"}
483
+ \uB9AC\uBDF0 \uC591\uC2DD \uD30C\uC77C:
484
+ ${reviewFormLine || "- (\uC5C6\uC74C)"}
485
+ \uB9AC\uBDF0 \uB300\uC0C1 diff \uD30C\uC77C:
486
+ - ${tempDiffPath2}
487
+
488
+ \uBC18\uB4DC\uC2DC \uB9AC\uBDF0 \uC591\uC2DD\uC5D0 \uB9DE\uCDB0 \uC791\uC131\uD574\uC918.`;
489
+ let command = "";
490
+ if (customModel) {
491
+ console.warn("\u26A0\uFE0F \uC9C0\uC815\uD55C \uBAA8\uB378\uC774 \uC5C6\uB294 \uACBD\uC6B0, \uC5D0\uB7EC\uAC00 \uBC1C\uC0DD\uD558\uB2C8 \uC8FC\uC758\uD558\uC138\uC694.");
492
+ trace3("model:custom", customModel);
493
+ command = buildCodexExecCommand(prompt, reasoningEffort, customModel);
233
494
  } else {
234
- const modelIndex = args2.indexOf("--model");
235
- if (modelIndex !== -1 && args2[modelIndex + 1]) {
236
- console.warn("\u26A0\uFE0F \uC9C0\uC815\uD55C \uBAA8\uB378\uC774 \uC5C6\uB294 \uACBD\uC6B0, \uC5D0\uB7EC\uAC00 \uBC1C\uC0DD\uD558\uB2C8 \uC8FC\uC758\uD558\uC138\uC694.");
237
- modelOption = `--model ${args2[modelIndex + 1]}`;
238
- } else {
239
- console.warn("\u26A0\uFE0F \uBAA8\uB378\uC774 \uC9C0\uC815\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uAE30\uBCF8 \uBAA8\uB378\uC778 gemini-flash\uB97C \uC0AC\uC6A9\uD569\uB2C8\uB2E4.");
240
- modelOption = "--model flash";
495
+ const preferredModelAlias = "gpt-5";
496
+ const aliasCommand = buildCodexExecCommand(prompt, reasoningEffort, preferredModelAlias);
497
+ const fallbackCommand = buildCodexExecCommand(prompt, reasoningEffort);
498
+ console.warn(
499
+ `\u26A0\uFE0F \uBAA8\uB378\uC774 \uC9C0\uC815\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. alias(${preferredModelAlias})\uB97C \uC6B0\uC120 \uC2DC\uB3C4\uD558\uACE0 \uC2E4\uD328\uD558\uBA74 \uACC4\uC815 \uAE30\uBCF8 \uBAA8\uB378\uB85C \uC790\uB3D9 \uD3F4\uBC31\uD569\uB2C8\uB2E4.`
500
+ );
501
+ trace3("model:alias-first", preferredModelAlias);
502
+ trace3("model:fallback", "account-default");
503
+ command = `${aliasCommand} || ${fallbackCommand}`;
504
+ }
505
+ trace3("command:created");
506
+ if (args2.includes("--test")) {
507
+ const safeCommand = command.replace(/"/g, '\\"');
508
+ trace3("test-mode:return-preview");
509
+ return `echo "[TEST MODE] Codex \uBA85\uB839\uC5B4\uAC00 \uC2E4\uD589\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.
510
+
511
+ \uC0DD\uC131\uB420 \uBA85\uB839\uC5B4 \uBBF8\uB9AC\uBCF4\uAE30:
512
+ ${safeCommand}"`;
513
+ }
514
+ trace3("createCodexCommand:end");
515
+ return command;
516
+ };
517
+ var trace4 = createTraceLogger("installation-codex");
518
+ function checkCodexCliInstalled() {
519
+ trace4("checkCodexCliInstalled:start");
520
+ try {
521
+ trace4("version-check:run", "codex --version");
522
+ execSync("codex --version", { stdio: "ignore" });
523
+ trace4("version-check:ok");
524
+ } catch {
525
+ trace4("version-check:failed", "install-start");
526
+ console.log("\u2139\uFE0F codex-cli\uAC00 \uC124\uCE58\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uC124\uCE58\uB97C \uC9C4\uD589\uD569\uB2C8\uB2E4... npm install -g @openai/codex");
527
+ try {
528
+ execSync("npm install -g @openai/codex", { stdio: "inherit" });
529
+ trace4("install:ok", "exit(1) for login");
530
+ console.log("\u2705 codex-cli \uC124\uCE58\uAC00 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.");
531
+ console.log("\u26A0\uFE0F codex-cli \uC0AC\uC6A9\uC744 \uC704\uD574 \uC778\uC99D\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.");
532
+ console.log(' \uD130\uBBF8\uB110\uC5D0\uC11C "codex login" \uC744 \uC785\uB825\uD558\uC5EC \uB85C\uADF8\uC778\uC744 \uC644\uB8CC\uD55C \uD6C4, \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uC8FC\uC138\uC694.');
533
+ process.exit(1);
534
+ } catch (installError) {
535
+ trace4("install:failed");
536
+ console.error("\u274C codex-cli \uC124\uCE58 \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4. \uAD8C\uD55C \uBB38\uC81C\uC77C \uC218 \uC788\uC2B5\uB2C8\uB2E4 (sudo \uD544\uC694).");
537
+ console.error(installError);
538
+ process.exit(1);
241
539
  }
242
540
  }
541
+ trace4("checkCodexCliInstalled:end");
542
+ }
543
+ var args3 = process.argv.slice(2);
544
+ var trace5 = createTraceLogger("gemini-commander", args3);
545
+ var ALLOWED_REASONING_EFFORTS3 = ["minimal", "low", "medium", "high"];
546
+ function shellQuote3(value) {
547
+ return `'${value.replace(/'/g, `'\\''`)}'`;
548
+ }
549
+ function getArgValue3(flag) {
550
+ const index = args3.indexOf(flag);
551
+ if (index === -1 || !args3[index + 1]) {
552
+ return "";
553
+ }
554
+ return args3[index + 1];
555
+ }
556
+ function toUnique2(values) {
557
+ const seen = /* @__PURE__ */ new Set();
558
+ return values.filter((value) => {
559
+ if (!value || seen.has(value)) {
560
+ return false;
561
+ }
562
+ seen.add(value);
563
+ return true;
564
+ });
565
+ }
566
+ function resolveReasoningEffort3() {
567
+ const customReasoningEffort = getArgValue3("--reasoning-effort");
568
+ if (customReasoningEffort) {
569
+ if (ALLOWED_REASONING_EFFORTS3.includes(customReasoningEffort)) {
570
+ trace5("reasoning:custom", customReasoningEffort);
571
+ return customReasoningEffort;
572
+ }
573
+ console.warn(
574
+ `\u26A0\uFE0F \uC9C0\uC6D0\uB418\uC9C0 \uC54A\uB294 reasoning effort(${customReasoningEffort})\uC785\uB2C8\uB2E4. allowed: ${ALLOWED_REASONING_EFFORTS3.join(
575
+ ", "
576
+ )}`
577
+ );
578
+ }
579
+ if (args3.includes("--flash")) {
580
+ trace5("reasoning:flash-default", "minimal");
581
+ return "minimal";
582
+ }
583
+ if (args3.includes("--review")) {
584
+ trace5("reasoning:review-default", "high");
585
+ return "high";
586
+ }
587
+ trace5("reasoning:default", "medium");
588
+ return "medium";
589
+ }
590
+ function resolvePrimaryAlias2(reasoningEffort) {
591
+ if (args3.includes("--review")) {
592
+ trace5("model:mode-alias", "pro");
593
+ return "pro";
594
+ }
595
+ if (args3.includes("--flash")) {
596
+ trace5("model:mode-alias", "flash");
597
+ return "flash";
598
+ }
599
+ if (reasoningEffort === "high") {
600
+ trace5("model:reasoning-alias", "pro");
601
+ return "pro";
602
+ }
603
+ if (reasoningEffort === "minimal" || reasoningEffort === "low") {
604
+ trace5("model:reasoning-alias", "flash");
605
+ return "flash";
606
+ }
607
+ trace5("model:default-alias", "auto");
608
+ return "auto";
609
+ }
610
+ function getAliasFallbacks2(primaryAlias) {
611
+ if (primaryAlias === "pro") {
612
+ return ["pro", "flash", "auto"];
613
+ }
614
+ if (primaryAlias === "flash") {
615
+ return ["flash", "auto", "pro"];
616
+ }
617
+ return [primaryAlias, "auto", "flash", "pro"];
618
+ }
619
+ function getReasoningInstruction(reasoningEffort) {
620
+ if (reasoningEffort === "high") {
621
+ return "high (\uAE4A\uC774 \uC788\uB294 \uBD84\uC11D, \uC7A0\uC7AC\uC801 \uB9AC\uC2A4\uD06C\uAE4C\uC9C0 \uC810\uAC80)";
622
+ }
623
+ if (reasoningEffort === "medium") {
624
+ return "medium (\uADE0\uD615 \uC7A1\uD78C \uBD84\uC11D\uACFC \uD575\uC2EC \uC774\uC288 \uC911\uC2EC)";
625
+ }
626
+ if (reasoningEffort === "low") {
627
+ return "low (\uD575\uC2EC \uACB0\uD568 \uC704\uC8FC\uB85C \uAC04\uACB0\uD558\uAC8C \uBD84\uC11D)";
628
+ }
629
+ return "minimal (\uCE58\uBA85\uB3C4 \uB192\uC740 \uC774\uC288\uB9CC \uB9E4\uC6B0 \uAC04\uACB0\uD558\uAC8C \uBD84\uC11D)";
630
+ }
631
+ function buildGeminiExecCommand(prompt, model) {
632
+ const modelOption = model ? `--model ${shellQuote3(model)}` : "";
633
+ return `gemini ${[modelOption, "-p", shellQuote3(prompt)].filter(Boolean).join(" ")}`;
634
+ }
635
+ var createGeminiCommand = (tempDiffPath2, reviewFormPath2) => {
636
+ trace5("createGeminiCommand:start", `tempDiffPath=${tempDiffPath2}, reviewFormPath=${reviewFormPath2}`);
637
+ const customModel = getArgValue3("--model");
638
+ const reasoningEffort = resolveReasoningEffort3();
639
+ const primaryAlias = resolvePrimaryAlias2(reasoningEffort);
640
+ const aliasFallbacks = toUnique2(getAliasFallbacks2(primaryAlias));
243
641
  const rules = [
244
642
  { path: rulesPath, display: "\uB8F0\uC14B" },
245
643
  { path: namingRulesPath, display: "\uB124\uC774\uBC0D \uADDC\uCE59" },
246
644
  { path: codingConventionRulesPath, display: "\uCF54\uB529 \uCEE8\uBCA4\uC158" }
247
645
  ];
248
- const validRules = rules.filter((rule) => fs4.existsSync(rule.path)).map((rule) => `@${rule.path}`).join(", ");
249
- const command = `gemini ${modelOption} -p "\uB2E4\uC74C \uADDC\uCE59\uB4E4\uC744 \uCC38\uACE0\uD574\uC11C(${validRules}) \uC774 diff(@${tempDiffPath2})\uB97C \uB9AC\uBDF0\uD574\uC918. \uB9AC\uBDF0\uC591\uC2DD\uC740 @${reviewFormPath2} \uC5D0 \uB9DE\uCDB0\uC11C \uC791\uC131\uD574\uC918. "`;
250
- if (args2.includes("--test")) {
646
+ const validRules = rules.filter((rule) => fs5.existsSync(rule.path)).map((rule) => `@${rule.path}`).join(", ");
647
+ const rulesCount = validRules ? validRules.split(",").length : 0;
648
+ trace5("rules:loaded", `count=${rulesCount}`);
649
+ const reviewFormRef = fs5.existsSync(reviewFormPath2) ? `@${reviewFormPath2}` : "(\uC5C6\uC74C)";
650
+ trace5("reviewForm:status", reviewFormRef === "(\uC5C6\uC74C)" ? "missing" : "exists");
651
+ const reasoningInstruction = getReasoningInstruction(reasoningEffort);
652
+ const prompt = `\uB2E4\uC74C \uADDC\uCE59\uB4E4\uC744 \uCC38\uACE0\uD574\uC11C(${validRules || "(\uC5C6\uC74C)"}) \uC774 diff(@${tempDiffPath2})\uB97C \uB9AC\uBDF0\uD574\uC918.
653
+ \uB9AC\uBDF0 \uC591\uC2DD\uC740 ${reviewFormRef} \uC5D0 \uB9DE\uCDB0\uC11C \uC791\uC131\uD574\uC918.
654
+ \uCD94\uB860 \uAC15\uB3C4 \uC9C0\uCE68: ${reasoningInstruction}`;
655
+ const modelCandidates = toUnique2(customModel ? [customModel, ...aliasFallbacks] : aliasFallbacks);
656
+ trace5("model:candidates", modelCandidates.join(", "));
657
+ if (customModel) {
658
+ console.warn(
659
+ `\u26A0\uFE0F \uCEE4\uC2A4\uD140 \uBAA8\uB378(${customModel})\uC744 \uC6B0\uC120 \uC2DC\uB3C4\uD558\uACE0 \uC2E4\uD328\uD558\uBA74 alias(${aliasFallbacks.join(
660
+ " -> "
661
+ )}) \uBC0F \uAE30\uBCF8 \uBAA8\uB378 \uC21C\uC73C\uB85C \uD3F4\uBC31\uD569\uB2C8\uB2E4.`
662
+ );
663
+ } else {
664
+ console.warn(
665
+ `\u26A0\uFE0F \uBAA8\uB378\uC774 \uC9C0\uC815\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. alias(${aliasFallbacks.join(" -> ")})\uB97C \uC21C\uCC28 \uC2DC\uB3C4\uD558\uACE0 \uB9C8\uC9C0\uB9C9\uC5D0 \uAE30\uBCF8 \uBAA8\uB378\uB85C \uD3F4\uBC31\uD569\uB2C8\uB2E4.`
666
+ );
667
+ }
668
+ const commandCandidates = modelCandidates.map((model) => buildGeminiExecCommand(prompt, model));
669
+ const command = [...commandCandidates, buildGeminiExecCommand(prompt)].join(" || ");
670
+ trace5("command:created");
671
+ if (args3.includes("--test")) {
251
672
  const safeCommand = command.replace(/"/g, '\\"');
673
+ trace5("test-mode:return-preview");
252
674
  return `echo "[TEST MODE] Gemini \uBA85\uB839\uC5B4\uAC00 \uC2E4\uD589\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.
253
675
 
254
676
  \uC0DD\uC131\uB420 \uBA85\uB839\uC5B4 \uBBF8\uB9AC\uBCF4\uAE30:
255
677
  ${safeCommand}"`;
256
678
  }
679
+ trace5("createGeminiCommand:end");
257
680
  return command;
258
681
  };
682
+ var trace6 = createTraceLogger("installation-gemini");
259
683
  function checkGeminiCliInstalled() {
684
+ trace6("checkGeminiCliInstalled:start");
260
685
  try {
686
+ trace6("version-check:run", "gemini --version");
261
687
  execSync("gemini --version", { stdio: "ignore" });
688
+ trace6("version-check:ok");
262
689
  } catch {
690
+ trace6("version-check:failed", "install-start");
263
691
  console.log("\u2139\uFE0F gemini-cli\uAC00 \uC124\uCE58\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uC124\uCE58\uB97C \uC9C4\uD589\uD569\uB2C8\uB2E4... npm install -g @google/gemini-cli");
264
692
  try {
265
693
  execSync("npm install -g @google/gemini-cli", { stdio: "inherit" });
694
+ trace6("install:ok", "exit(1) for login");
266
695
  console.log("\u2705 gemini-cli \uC124\uCE58\uAC00 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.");
267
696
  console.log("\u26A0\uFE0F Gemini API \uC0AC\uC6A9\uC744 \uC704\uD574 \uC778\uC99D\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.");
268
697
  console.log(' \uD130\uBBF8\uB110\uC5D0\uC11C "gemini" \uB97C \uC785\uB825\uD558\uC5EC \uBE0C\uB77C\uC6B0\uC800 \uB85C\uADF8\uC778\uC744 \uC644\uB8CC\uD55C \uD6C4, \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uC8FC\uC138\uC694.');
269
698
  process.exit(1);
270
699
  } catch (installError) {
700
+ trace6("install:failed");
271
701
  console.error("\u274C gemini-cli \uC124\uCE58 \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4. \uAD8C\uD55C \uBB38\uC81C\uC77C \uC218 \uC788\uC2B5\uB2C8\uB2E4 (sudo \uD544\uC694).");
272
702
  console.error(installError);
273
703
  process.exit(1);
274
704
  }
275
705
  }
706
+ trace6("checkGeminiCliInstalled:end");
276
707
  }
277
708
 
278
709
  // src/pr-review/review-one-by-one.ts
279
710
  var execAsync = util.promisify(exec);
280
711
  async function main() {
281
- const args3 = process.argv.slice(2);
282
- const isTest = args3.includes("--test");
712
+ const args4 = process.argv.slice(2);
713
+ const isTest = isTestMode(args4);
714
+ const trace7 = createTraceLogger("review-one-by-one", args4);
715
+ trace7("main:start", `args=${JSON.stringify(args4)}`);
716
+ trace7("service-selection:start");
283
717
  const service = await showSelectionAIService();
718
+ trace7("service-selection:done", `service=${service}`);
284
719
  switch (service) {
285
720
  case "gemini":
721
+ trace7("install-check:start", "service=gemini");
286
722
  checkGeminiCliInstalled();
723
+ trace7("install-check:done", "service=gemini");
287
724
  break;
288
725
  case "claude":
726
+ trace7("install-check:start", "service=claude");
289
727
  checkClaudeCliInstalled();
728
+ trace7("install-check:done", "service=claude");
729
+ break;
730
+ case "codex":
731
+ trace7("install-check:start", "service=codex");
732
+ checkCodexCliInstalled();
733
+ trace7("install-check:done", "service=codex");
290
734
  break;
291
735
  }
292
736
  try {
737
+ trace7("review-flow:start");
293
738
  console.log("\u{1F680} AI Code Review\uB97C \uC2DC\uC791\uD569\uB2C8\uB2E4...");
739
+ trace7("report-dir:create:start");
294
740
  createReportDirectory();
741
+ trace7("report-dir:create:done");
295
742
  const { includeParams, excludeParams } = getGitDiffFilter();
743
+ trace7("diff-filter:loaded", `include=${includeParams} | exclude=${excludeParams}`);
296
744
  const diffArgs = getDiffArgs();
745
+ trace7("diff-args:build:done", `diffArgs=${diffArgs || "(default)"}`);
297
746
  const filesCommand = `git diff --name-only ${diffArgs} -- ${includeParams} ${excludeParams}`;
747
+ trace7("files-command:run", filesCommand);
298
748
  const fileList = execSync(filesCommand).toString().split("\n").filter(Boolean);
749
+ trace7("files-command:done", `fileCount=${fileList.length}`);
299
750
  if (fileList.length === 0) {
751
+ trace7("empty-file-list:exit");
300
752
  console.log("\u2139\uFE0F \uBCC0\uACBD \uC0AC\uD56D\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.");
301
753
  deleteTempDiff();
302
754
  process.exit(0);
303
755
  }
304
756
  const fullDiffCommand = `git diff ${diffArgs} -- ${includeParams} ${excludeParams}`;
757
+ trace7("full-diff:run");
305
758
  const fullDiff = execSync(fullDiffCommand).toString();
306
759
  const nowStr = getNowString();
307
- fs4.writeFileSync(tempDiffPath, fullDiff);
760
+ trace7("full-diff:done", `length=${fullDiff.length}`);
761
+ trace7("timestamp:created", nowStr);
762
+ trace7("temp-diff:write:start", tempDiffPath);
763
+ fs5.writeFileSync(tempDiffPath, fullDiff);
764
+ trace7("temp-diff:write:done");
765
+ trace7("saved-diff:copy:start");
308
766
  const savedDiffPath = getNextFilePath(REPORT_DIR, `${nowStr}-diff`, ".txt");
309
- fs4.copyFileSync(tempDiffPath, savedDiffPath);
767
+ fs5.copyFileSync(tempDiffPath, savedDiffPath);
768
+ trace7("saved-diff:copy:done", savedDiffPath);
310
769
  const savedReportPath = getNextFilePath(REPORT_DIR, nowStr, ".md");
770
+ trace7("saved-report:path", savedReportPath);
311
771
  const promises = fileList.map(async (file) => {
312
772
  try {
773
+ trace7("file-review:start", file);
313
774
  console.log(`\u{1F50D} Reviewing: ${file}...`);
775
+ trace7("file-diff:run", file);
314
776
  const fileDiff = execSync(`git diff ${diffArgs} -- "${file}"`).toString();
777
+ trace7("file-diff:done", `${file} | length=${fileDiff.length}`);
315
778
  const tempOneFileDiffPath = `temp_diff_${file.replace(/\//g, "_")}.txt`;
316
- fs4.writeFileSync(tempOneFileDiffPath, fileDiff);
779
+ trace7("file-temp-diff:write:start", tempOneFileDiffPath);
780
+ fs5.writeFileSync(tempOneFileDiffPath, fileDiff);
781
+ trace7("file-temp-diff:write:done", tempOneFileDiffPath);
317
782
  let command = "";
783
+ trace7("file-command:create:start", file);
318
784
  switch (service) {
319
785
  case "gemini":
320
786
  command = createGeminiCommand(tempOneFileDiffPath, reviewFormOneByOnePath);
@@ -323,25 +789,37 @@ async function main() {
323
789
  command = createClaudeCommand(tempOneFileDiffPath, reviewFormOneByOnePath);
324
790
  break;
325
791
  case "codex":
792
+ command = createCodexCommand(tempOneFileDiffPath, reviewFormOneByOnePath);
326
793
  break;
327
794
  }
795
+ trace7("file-command:create:done", file);
796
+ trace7("file-command:exec:start", file);
328
797
  const { stdout } = await execAsync(command, { maxBuffer: 1024 * 1024 * 20 });
329
798
  const result = stdout.toString();
799
+ trace7("file-command:exec:done", `${file} | resultLength=${result.length}`);
800
+ trace7("file-temp-diff:delete:start", tempOneFileDiffPath);
330
801
  deleteFile(tempOneFileDiffPath);
802
+ trace7("file-temp-diff:delete:done", tempOneFileDiffPath);
331
803
  const tempReport = `### File: ${file}
332
804
  ${result}
333
805
 
334
806
  `;
335
807
  console.log(tempReport);
336
- fs4.appendFileSync(savedReportPath, tempReport);
808
+ trace7("file-report:append:start", file);
809
+ fs5.appendFileSync(savedReportPath, tempReport);
810
+ trace7("file-report:append:done", file);
337
811
  if (isTest) {
338
- fs4.appendFileSync(savedReportPath, `
812
+ trace7("file-test-command:append:start", file);
813
+ fs5.appendFileSync(savedReportPath, `
339
814
 
340
815
  ## \uC0AC\uC6A9\uB41C \uBA85\uB839\uC5B4
341
816
 
342
817
  ${command}`);
818
+ trace7("file-test-command:append:done", file);
343
819
  }
820
+ trace7("file-review:end", file);
344
821
  } catch (err) {
822
+ trace7("file-review:catch", file);
345
823
  console.error(`\u274C Error reviewing file ${file}:`, err);
346
824
  const errorReport = `### File: ${file}
347
825
  \u274C Review Failed
@@ -350,28 +828,41 @@ ${err}
350
828
  \`\`\`
351
829
 
352
830
  `;
353
- fs4.appendFileSync(savedReportPath, errorReport);
831
+ fs5.appendFileSync(savedReportPath, errorReport);
354
832
  try {
355
833
  const tempOneFileDiffPath = `temp_diff_${file.replace(/\//g, "_")}.txt`;
356
- if (fs4.existsSync(tempOneFileDiffPath)) {
834
+ if (fs5.existsSync(tempOneFileDiffPath)) {
835
+ trace7("file-temp-diff:delete:start(catch)", tempOneFileDiffPath);
357
836
  deleteFile(tempOneFileDiffPath);
837
+ trace7("file-temp-diff:delete:done(catch)", tempOneFileDiffPath);
358
838
  }
359
839
  } catch (e) {
840
+ trace7("file-temp-diff:delete:failed(catch)", file);
360
841
  console.error(`\u274C Error deleting temp file for ${file}:`, e);
361
842
  }
362
843
  }
363
844
  });
845
+ trace7("parallel-review:await-start");
364
846
  await Promise.all(promises);
847
+ trace7("parallel-review:await-done");
365
848
  console.log(`
366
849
  \u2705 \uB9AC\uBDF0\uAC00 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.`);
367
850
  console.log(`\u{1F4C4} \uB9AC\uD3EC\uD2B8 \uC800\uC7A5 \uC704\uCE58: ${savedReportPath}`);
368
851
  console.log(`diff \uC800\uC7A5 \uC704\uCE58: ${savedDiffPath}`);
852
+ trace7("open-report:start");
369
853
  openReport(savedReportPath);
854
+ trace7("open-report:done");
855
+ trace7("cleanup-temp-diff:start");
370
856
  deleteTempDiff();
857
+ trace7("cleanup-temp-diff:done");
858
+ trace7("review-flow:end");
371
859
  } catch (error) {
860
+ trace7("review-flow:catch");
372
861
  console.error("\u274C \uB9AC\uBDF0 \uB3C4\uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.");
373
862
  console.error(error);
863
+ trace7("cleanup-temp-diff:start(catch)");
374
864
  deleteTempDiff();
865
+ trace7("cleanup-temp-diff:done(catch)");
375
866
  process.exit(1);
376
867
  }
377
868
  }