sales-frontend-gemini-cli 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/dist/common/helper.cjs +54 -3
  2. package/dist/common/helper.cjs.map +1 -1
  3. package/dist/common/helper.d.cts +15 -1
  4. package/dist/common/helper.d.ts +15 -1
  5. package/dist/common/helper.js +53 -4
  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 +26 -0
  24. package/dist/pr-review/claude/claude-commander.cjs.map +1 -1
  25. package/dist/pr-review/claude/claude-commander.js +26 -0
  26. package/dist/pr-review/claude/claude-commander.js.map +1 -1
  27. package/dist/pr-review/claude/installation-claude.cjs +38 -1
  28. package/dist/pr-review/claude/installation-claude.cjs.map +1 -1
  29. package/dist/pr-review/claude/installation-claude.js +33 -1
  30. package/dist/pr-review/claude/installation-claude.js.map +1 -1
  31. package/dist/pr-review/codex/codex-commander.cjs +88 -0
  32. package/dist/pr-review/codex/codex-commander.cjs.map +1 -0
  33. package/dist/pr-review/codex/codex-commander.d.cts +12 -0
  34. package/dist/pr-review/codex/codex-commander.d.ts +12 -0
  35. package/dist/pr-review/codex/codex-commander.js +80 -0
  36. package/dist/pr-review/codex/codex-commander.js.map +1 -0
  37. package/dist/pr-review/codex/installation-codex.cjs +62 -0
  38. package/dist/pr-review/codex/installation-codex.cjs.map +1 -0
  39. package/dist/pr-review/codex/installation-codex.d.cts +3 -0
  40. package/dist/pr-review/codex/installation-codex.d.ts +3 -0
  41. package/dist/pr-review/codex/installation-codex.js +55 -0
  42. package/dist/pr-review/codex/installation-codex.js.map +1 -0
  43. package/dist/pr-review/gemini/gemini-commander.cjs +23 -0
  44. package/dist/pr-review/gemini/gemini-commander.cjs.map +1 -1
  45. package/dist/pr-review/gemini/gemini-commander.js +23 -0
  46. package/dist/pr-review/gemini/gemini-commander.js.map +1 -1
  47. package/dist/pr-review/gemini/installation-gemini.cjs +35 -0
  48. package/dist/pr-review/gemini/installation-gemini.cjs.map +1 -1
  49. package/dist/pr-review/gemini/installation-gemini.js +30 -0
  50. package/dist/pr-review/gemini/installation-gemini.js.map +1 -1
  51. package/dist/pr-review/review-one-by-one.cjs +260 -31
  52. package/dist/pr-review/review-one-by-one.cjs.map +1 -1
  53. package/dist/pr-review/review-one-by-one.js +259 -30
  54. package/dist/pr-review/review-one-by-one.js.map +1 -1
  55. package/dist/pr-review/review.cjs +228 -14
  56. package/dist/pr-review/review.cjs.map +1 -1
  57. package/dist/pr-review/review.js +228 -14
  58. package/dist/pr-review/review.js.map +1 -1
  59. package/package.json +1 -1
  60. package/src/common/form/review-form.md +1 -1
  61. package/src/common/rules/review-rules.md +2 -0
  62. package/dist/pr-review/gemini/installation-gcloud.cjs.map +0 -1
  63. package/dist/pr-review/gemini/installation-gcloud.js.map +0 -1
  64. package/dist/pr-review/gemini/interactive-version/index.cjs.map +0 -1
  65. package/dist/pr-review/gemini/interactive-version/index.js.map +0 -1
  66. package/dist/pr-review/gemini/login.cjs.map +0 -1
  67. package/dist/pr-review/gemini/login.js.map +0 -1
  68. package/dist/pr-review/gemini/vertex-version/index.cjs.map +0 -1
  69. package/dist/pr-review/gemini/vertex-version/index.js.map +0 -1
  70. /package/dist/{pr-review/gemini → etc}/installation-gcloud.d.cts +0 -0
  71. /package/dist/{pr-review/gemini → etc}/installation-gcloud.d.ts +0 -0
  72. /package/dist/{pr-review/gemini → etc}/interactive-version/index.d.cts +0 -0
  73. /package/dist/{pr-review/gemini → etc}/interactive-version/index.d.ts +0 -0
  74. /package/dist/{pr-review/gemini → etc}/login.d.cts +0 -0
  75. /package/dist/{pr-review/gemini → etc}/login.d.ts +0 -0
  76. /package/dist/{pr-review/gemini → etc}/vertex-version/index.d.cts +0 -0
  77. /package/dist/{pr-review/gemini → etc}/vertex-version/index.d.ts +0 -0
@@ -28,6 +28,18 @@ var ignoreList = [
28
28
  ".review-report/"
29
29
  // 생성되는 리포트 폴더도 제외
30
30
  ];
31
+ function isTestMode(args4 = process.argv.slice(2)) {
32
+ return args4.includes("--test");
33
+ }
34
+ function createTraceLogger(scope, args4 = process.argv.slice(2)) {
35
+ const enabled = isTestMode(args4);
36
+ return (step, detail) => {
37
+ if (!enabled) {
38
+ return;
39
+ }
40
+ console.log(`[TRACE][${scope}] ${step}${detail ? ` | ${detail}` : ""}`);
41
+ };
42
+ }
31
43
  function getNextFilePath(dir, baseName, extension) {
32
44
  let counter = 1;
33
45
  while (true) {
@@ -70,25 +82,60 @@ function getGitDiffFilter() {
70
82
  return { includeParams, excludeParams };
71
83
  }
72
84
  function openReport(reportPath) {
85
+ const resolvedPath = path.resolve(reportPath);
86
+ const { platform } = process;
87
+ const openWithChrome = () => {
88
+ if (platform === "darwin") {
89
+ execSync(`open -a "Google Chrome" "${resolvedPath}"`, { stdio: "ignore" });
90
+ return true;
91
+ }
92
+ if (platform === "linux") {
93
+ execSync(`google-chrome "${resolvedPath}"`, { stdio: "ignore" });
94
+ return true;
95
+ }
96
+ return false;
97
+ };
98
+ const openWithDefaultBrowser = () => {
99
+ if (platform === "darwin") {
100
+ execSync(`open "${resolvedPath}"`, { stdio: "ignore" });
101
+ return true;
102
+ }
103
+ if (platform === "linux") {
104
+ execSync(`xdg-open "${resolvedPath}"`, { stdio: "ignore" });
105
+ return true;
106
+ }
107
+ return false;
108
+ };
109
+ try {
110
+ if (openWithChrome()) {
111
+ console.log("\u{1F680} Google Chrome\uC5D0\uC11C \uB9AC\uD3EC\uD2B8\uB97C \uC5F4\uC5C8\uC2B5\uB2C8\uB2E4.");
112
+ return;
113
+ }
114
+ } catch {
115
+ }
73
116
  try {
74
- execSync(`open -a "Google Chrome" "${path.resolve(reportPath)}"`);
75
- console.log(`\u{1F680} \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uB9AC\uD3EC\uD2B8\uB97C \uC5F4\uC5C8\uC2B5\uB2C8\uB2E4.`);
117
+ if (openWithDefaultBrowser()) {
118
+ console.log("\u{1F680} \uAE30\uBCF8 \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uB9AC\uD3EC\uD2B8\uB97C \uC5F4\uC5C8\uC2B5\uB2C8\uB2E4.");
119
+ return;
120
+ }
76
121
  } catch (e) {
77
122
  console.error("\u26A0\uFE0F \uBE0C\uB77C\uC6B0\uC800 \uC5F4\uAE30 \uC2E4\uD328:", e);
123
+ return;
78
124
  }
125
+ console.error(`\u26A0\uFE0F \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uD50C\uB7AB\uD3FC\uC785\uB2C8\uB2E4: ${platform}`);
79
126
  }
80
127
  function getDiffArgs() {
81
- const args3 = process.argv.slice(2);
82
- const commitIndex = args3.indexOf("--commit");
128
+ const args4 = process.argv.slice(2);
129
+ const commitIndex = args4.indexOf("--commit");
83
130
  const { includeParams, excludeParams } = getGitDiffFilter();
84
131
  let diffArgs = "";
85
132
  if (commitIndex !== -1) {
86
- const commitHash = args3[commitIndex + 1];
133
+ const commitHash = args4[commitIndex + 1];
87
134
  if (!commitHash) {
88
135
  console.error("\u274C \uCEE4\uBC0B \uD574\uC2DC\uAC00 \uC81C\uACF5\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.");
89
136
  process.exit(1);
90
137
  }
91
- const nextArg = args3[commitIndex + 2];
138
+ const nextArg = args4[commitIndex + 2];
92
139
  let n = 0;
93
140
  if (nextArg && !nextArg.startsWith("--")) {
94
141
  n = parseInt(nextArg, 10);
@@ -125,7 +172,9 @@ async function showSelectionAIService() {
125
172
  }
126
173
  firstRender = false;
127
174
  readline.clearScreenDown(process.stdout);
128
- 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");
175
+ process.stdout.write(
176
+ "\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"
177
+ );
129
178
  AIServices.forEach((service, index) => {
130
179
  if (index === selectedIndex) {
131
180
  process.stdout.write(` \x1B[36m>\x1B[0m \x1B[36m\u25C9\x1B[0m \x1B[1m${service}\x1B[0m
@@ -171,20 +220,26 @@ async function showSelectionAIService() {
171
220
  });
172
221
  }
173
222
  var args = process.argv.slice(2);
223
+ var trace = createTraceLogger("claude-commander", args);
174
224
  var createClaudeCommand = (tempDiffPath2, reviewFormPath2) => {
225
+ trace("createClaudeCommand:start", `tempDiffPath=${tempDiffPath2}, reviewFormPath=${reviewFormPath2}`);
175
226
  let modelOption = "";
176
227
  if (args.includes("--review")) {
177
228
  modelOption = "--model opus";
229
+ trace("model:review", modelOption);
178
230
  } else if (args.includes("--flash")) {
179
231
  modelOption = "--model haiku";
232
+ trace("model:flash", modelOption);
180
233
  } else {
181
234
  const modelIndex = args.indexOf("--model");
182
235
  if (modelIndex !== -1 && args[modelIndex + 1]) {
183
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.");
184
237
  modelOption = `--model ${args[modelIndex + 1]}`;
238
+ trace("model:custom", modelOption);
185
239
  } else {
186
240
  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.");
187
241
  modelOption = "--model sonnet";
242
+ trace("model:default", modelOption);
188
243
  }
189
244
  }
190
245
  const rules = [
@@ -193,50 +248,151 @@ var createClaudeCommand = (tempDiffPath2, reviewFormPath2) => {
193
248
  { path: codingConventionRulesPath, display: "\uCF54\uB529 \uCEE8\uBCA4\uC158" }
194
249
  ];
195
250
  const systemPromptFiles = rules.filter((rule) => fs.existsSync(rule.path)).map((rule) => `--append-system-prompt-file ${rule.path}`).join(" ");
251
+ trace(
252
+ "rules:loaded",
253
+ `count=${systemPromptFiles ? systemPromptFiles.split("--append-system-prompt-file").length - 1 : 0}`
254
+ );
196
255
  const reviewFormOption = fs.existsSync(reviewFormPath2) ? `--append-system-prompt-file ${reviewFormPath2}` : "";
256
+ trace("reviewForm:status", reviewFormOption ? "exists" : "missing");
197
257
  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."`;
258
+ trace("command:created");
198
259
  if (args.includes("--test")) {
199
260
  const safeCommand = command.replace(/"/g, '\\"');
261
+ trace("test-mode:return-preview");
200
262
  return `echo "[TEST MODE] Claude \uBA85\uB839\uC5B4\uAC00 \uC2E4\uD589\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.
201
263
 
202
264
  \uC0DD\uC131\uB420 \uBA85\uB839\uC5B4 \uBBF8\uB9AC\uBCF4\uAE30:
203
265
  ${safeCommand}"`;
204
266
  }
267
+ trace("createClaudeCommand:end");
205
268
  return command;
206
269
  };
270
+ var trace2 = createTraceLogger("installation-claude");
207
271
  function checkClaudeCliInstalled() {
272
+ trace2("checkClaudeCliInstalled:start");
208
273
  try {
274
+ trace2("version-check:run", "claude --version");
209
275
  execSync("claude --version", { stdio: "ignore" });
276
+ trace2("version-check:ok");
210
277
  } catch {
211
- 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");
278
+ trace2("version-check:failed", "install-start");
279
+ console.log(
280
+ "\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"
281
+ );
212
282
  try {
213
283
  execSync("npm install -g @anthropic-ai/claude-code", { stdio: "inherit" });
284
+ trace2("install:ok", "exit(1) for login");
214
285
  console.log("\u2705 claude-cli \uC124\uCE58\uAC00 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.");
215
286
  console.log("\u26A0\uFE0F claude-cli \uC0AC\uC6A9\uC744 \uC704\uD574 \uC778\uC99D\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.");
216
287
  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.');
217
288
  process.exit(1);
218
289
  } catch (installError) {
290
+ trace2("install:failed");
219
291
  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).");
220
292
  console.error(installError);
221
293
  process.exit(1);
222
294
  }
223
295
  }
296
+ trace2("checkClaudeCliInstalled:end");
224
297
  }
225
298
  var args2 = process.argv.slice(2);
226
- var createGeminiCommand = (tempDiffPath2, reviewFormPath2) => {
299
+ var trace3 = createTraceLogger("codex-commander", args2);
300
+ var createCodexCommand = (tempDiffPath2, reviewFormPath2) => {
301
+ trace3("createCodexCommand:start", `tempDiffPath=${tempDiffPath2}, reviewFormPath=${reviewFormPath2}`);
227
302
  let modelOption = "";
228
303
  if (args2.includes("--review")) {
229
- modelOption = "--model pro";
304
+ modelOption = "--model gpt-5";
305
+ trace3("model:review", modelOption);
230
306
  } else if (args2.includes("--flash")) {
231
- modelOption = "--model flash";
307
+ modelOption = "--model gpt-5-mini";
308
+ trace3("model:flash", modelOption);
232
309
  } else {
233
310
  const modelIndex = args2.indexOf("--model");
234
311
  if (modelIndex !== -1 && args2[modelIndex + 1]) {
235
312
  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.");
236
313
  modelOption = `--model ${args2[modelIndex + 1]}`;
314
+ trace3("model:custom", modelOption);
315
+ } else {
316
+ console.warn("\u26A0\uFE0F \uBAA8\uB378\uC774 \uC9C0\uC815\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uAE30\uBCF8 \uBAA8\uB378\uC778 gpt-5-mini\uB97C \uC0AC\uC6A9\uD569\uB2C8\uB2E4.");
317
+ modelOption = "--model gpt-5-mini";
318
+ trace3("model:default", modelOption);
319
+ }
320
+ }
321
+ const rules = [rulesPath, namingRulesPath, codingConventionRulesPath].filter((filePath) => fs.existsSync(filePath)).map((filePath) => `- ${filePath}`).join("\n");
322
+ const rulesCount = rules ? rules.split("\n").length : 0;
323
+ trace3("rules:loaded", `count=${rulesCount}`);
324
+ const hasReviewForm = fs.existsSync(reviewFormPath2);
325
+ const reviewFormLine = hasReviewForm ? `- ${reviewFormPath2}` : "";
326
+ trace3("reviewForm:status", reviewFormLine ? "exists" : "missing");
327
+ const prompt = `\uC544\uB798 \uD30C\uC77C\uB4E4\uC744 \uCC38\uACE0\uD574\uC11C \uCF54\uB4DC \uB9AC\uBDF0\uB97C \uC9C4\uD589\uD574\uC918.
328
+ \uADDC\uCE59 \uD30C\uC77C:
329
+ ${rules || "- (\uC5C6\uC74C)"}
330
+ \uB9AC\uBDF0 \uC591\uC2DD \uD30C\uC77C:
331
+ ${reviewFormLine || "- (\uC5C6\uC74C)"}
332
+ \uB9AC\uBDF0 \uB300\uC0C1 diff \uD30C\uC77C:
333
+ - ${tempDiffPath2}
334
+
335
+ \uBC18\uB4DC\uC2DC \uB9AC\uBDF0 \uC591\uC2DD\uC5D0 \uB9DE\uCDB0 \uC791\uC131\uD574\uC918.`;
336
+ const command = `codex exec ${modelOption} "${prompt.replace(/"/g, '\\"')}"`;
337
+ trace3("command:created");
338
+ if (args2.includes("--test")) {
339
+ const safeCommand = command.replace(/"/g, '\\"');
340
+ trace3("test-mode:return-preview");
341
+ return `echo "[TEST MODE] Codex \uBA85\uB839\uC5B4\uAC00 \uC2E4\uD589\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.
342
+
343
+ \uC0DD\uC131\uB420 \uBA85\uB839\uC5B4 \uBBF8\uB9AC\uBCF4\uAE30:
344
+ ${safeCommand}"`;
345
+ }
346
+ trace3("createCodexCommand:end");
347
+ return command;
348
+ };
349
+ var trace4 = createTraceLogger("installation-codex");
350
+ function checkCodexCliInstalled() {
351
+ trace4("checkCodexCliInstalled:start");
352
+ try {
353
+ trace4("version-check:run", "codex --version");
354
+ execSync("codex --version", { stdio: "ignore" });
355
+ trace4("version-check:ok");
356
+ } catch {
357
+ trace4("version-check:failed", "install-start");
358
+ 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");
359
+ try {
360
+ execSync("npm install -g @openai/codex", { stdio: "inherit" });
361
+ trace4("install:ok", "exit(1) for login");
362
+ console.log("\u2705 codex-cli \uC124\uCE58\uAC00 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.");
363
+ console.log("\u26A0\uFE0F codex-cli \uC0AC\uC6A9\uC744 \uC704\uD574 \uC778\uC99D\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.");
364
+ 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.');
365
+ process.exit(1);
366
+ } catch (installError) {
367
+ trace4("install:failed");
368
+ 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).");
369
+ console.error(installError);
370
+ process.exit(1);
371
+ }
372
+ }
373
+ trace4("checkCodexCliInstalled:end");
374
+ }
375
+ var args3 = process.argv.slice(2);
376
+ var trace5 = createTraceLogger("gemini-commander", args3);
377
+ var createGeminiCommand = (tempDiffPath2, reviewFormPath2) => {
378
+ trace5("createGeminiCommand:start", `tempDiffPath=${tempDiffPath2}, reviewFormPath=${reviewFormPath2}`);
379
+ let modelOption = "";
380
+ if (args3.includes("--review")) {
381
+ modelOption = "--model pro";
382
+ trace5("model:review", modelOption);
383
+ } else if (args3.includes("--flash")) {
384
+ modelOption = "--model flash";
385
+ trace5("model:flash", modelOption);
386
+ } else {
387
+ const modelIndex = args3.indexOf("--model");
388
+ if (modelIndex !== -1 && args3[modelIndex + 1]) {
389
+ 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.");
390
+ modelOption = `--model ${args3[modelIndex + 1]}`;
391
+ trace5("model:custom", modelOption);
237
392
  } else {
238
393
  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.");
239
394
  modelOption = "--model flash";
395
+ trace5("model:default", modelOption);
240
396
  }
241
397
  }
242
398
  const rules = [
@@ -245,68 +401,110 @@ var createGeminiCommand = (tempDiffPath2, reviewFormPath2) => {
245
401
  { path: codingConventionRulesPath, display: "\uCF54\uB529 \uCEE8\uBCA4\uC158" }
246
402
  ];
247
403
  const validRules = rules.filter((rule) => fs.existsSync(rule.path)).map((rule) => `@${rule.path}`).join(", ");
404
+ const rulesCount = validRules ? validRules.split(",").length : 0;
405
+ trace5("rules:loaded", `count=${rulesCount}`);
248
406
  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. "`;
249
- if (args2.includes("--test")) {
407
+ trace5("command:created");
408
+ if (args3.includes("--test")) {
250
409
  const safeCommand = command.replace(/"/g, '\\"');
410
+ trace5("test-mode:return-preview");
251
411
  return `echo "[TEST MODE] Gemini \uBA85\uB839\uC5B4\uAC00 \uC2E4\uD589\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.
252
412
 
253
413
  \uC0DD\uC131\uB420 \uBA85\uB839\uC5B4 \uBBF8\uB9AC\uBCF4\uAE30:
254
414
  ${safeCommand}"`;
255
415
  }
416
+ trace5("createGeminiCommand:end");
256
417
  return command;
257
418
  };
419
+ var trace6 = createTraceLogger("installation-gemini");
258
420
  function checkGeminiCliInstalled() {
421
+ trace6("checkGeminiCliInstalled:start");
259
422
  try {
423
+ trace6("version-check:run", "gemini --version");
260
424
  execSync("gemini --version", { stdio: "ignore" });
425
+ trace6("version-check:ok");
261
426
  } catch {
427
+ trace6("version-check:failed", "install-start");
262
428
  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");
263
429
  try {
264
430
  execSync("npm install -g @google/gemini-cli", { stdio: "inherit" });
431
+ trace6("install:ok", "exit(1) for login");
265
432
  console.log("\u2705 gemini-cli \uC124\uCE58\uAC00 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.");
266
433
  console.log("\u26A0\uFE0F Gemini API \uC0AC\uC6A9\uC744 \uC704\uD574 \uC778\uC99D\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.");
267
434
  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.');
268
435
  process.exit(1);
269
436
  } catch (installError) {
437
+ trace6("install:failed");
270
438
  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).");
271
439
  console.error(installError);
272
440
  process.exit(1);
273
441
  }
274
442
  }
443
+ trace6("checkGeminiCliInstalled:end");
275
444
  }
276
445
 
277
446
  // src/pr-review/review.ts
278
447
  async function main() {
279
- const args3 = process.argv.slice(2);
280
- const isTest = args3.includes("--test");
448
+ const args4 = process.argv.slice(2);
449
+ const isTest = isTestMode(args4);
450
+ const trace7 = createTraceLogger("review", args4);
451
+ trace7("main:start", `args=${JSON.stringify(args4)}`);
452
+ trace7("service-selection:start");
281
453
  const service = await showSelectionAIService();
454
+ trace7("service-selection:done", `service=${service}`);
282
455
  switch (service) {
283
456
  case "gemini":
457
+ trace7("install-check:start", "service=gemini");
284
458
  checkGeminiCliInstalled();
459
+ trace7("install-check:done", "service=gemini");
285
460
  break;
286
461
  case "claude":
462
+ trace7("install-check:start", "service=claude");
287
463
  checkClaudeCliInstalled();
464
+ trace7("install-check:done", "service=claude");
465
+ break;
466
+ case "codex":
467
+ trace7("install-check:start", "service=codex");
468
+ checkCodexCliInstalled();
469
+ trace7("install-check:done", "service=codex");
288
470
  break;
289
471
  }
290
472
  try {
473
+ trace7("review-flow:start");
291
474
  console.log("\u{1F680} AI Code Review\uB97C \uC2DC\uC791\uD569\uB2C8\uB2E4...");
292
475
  const nowStr = getNowString();
476
+ trace7("timestamp:created", nowStr);
477
+ trace7("report-dir:create:start");
293
478
  createReportDirectory();
479
+ trace7("report-dir:create:done");
480
+ trace7("diff-args:build:start");
294
481
  const diffArgs = getDiffArgs();
482
+ trace7("diff-args:build:done", `diffArgs=${diffArgs || "(default)"}`);
295
483
  let diff = "";
296
484
  const { includeParams, excludeParams } = getGitDiffFilter();
485
+ trace7("diff-filter:loaded", `include=${includeParams} | exclude=${excludeParams}`);
297
486
  try {
487
+ trace7("git-diff:run");
298
488
  diff = execSync(`git diff ${diffArgs} -- ${includeParams} ${excludeParams}`).toString();
489
+ trace7("git-diff:done", `length=${diff.length}`);
299
490
  } catch {
491
+ trace7("git-diff:error", "fallback-empty-diff");
300
492
  }
301
493
  if (!diff.trim() && !isTest) {
494
+ trace7("empty-diff:exit");
302
495
  console.log("\u2139\uFE0F \uB9AC\uBDF0\uD560 \uBCC0\uACBD \uC0AC\uD56D\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 (Unstaged Empty & HEAD Empty).");
303
496
  deleteTempDiff();
304
497
  process.exit(0);
305
498
  }
499
+ trace7("temp-diff:write:start", tempDiffPath);
306
500
  fs.writeFileSync(tempDiffPath, diff);
501
+ trace7("temp-diff:write:done");
502
+ trace7("saved-diff:copy:start");
307
503
  const savedDiffPath = getNextFilePath(REPORT_DIR, `${nowStr}-diff`, ".txt");
308
504
  fs.copyFileSync(tempDiffPath, savedDiffPath);
505
+ trace7("saved-diff:copy:done", savedDiffPath);
309
506
  let command = "";
507
+ trace7("command:create:start", `service=${service}`);
310
508
  switch (service) {
311
509
  case "gemini":
312
510
  command = createGeminiCommand(tempDiffPath, reviewFormPath);
@@ -315,29 +513,45 @@ async function main() {
315
513
  command = createClaudeCommand(tempDiffPath, reviewFormPath);
316
514
  break;
317
515
  case "codex":
516
+ command = createCodexCommand(tempDiffPath, reviewFormPath);
318
517
  break;
319
518
  }
519
+ trace7("command:create:done");
520
+ trace7("command:exec:start");
320
521
  const result = execSync(command).toString();
522
+ trace7("command:exec:done", `resultLength=${result.length}`);
321
523
  console.log(result);
524
+ trace7("report:write:start");
322
525
  const savedReportPath = getNextFilePath(REPORT_DIR, nowStr, ".md");
323
526
  fs.writeFileSync(savedReportPath, result);
527
+ trace7("report:write:done", savedReportPath);
324
528
  if (isTest) {
529
+ trace7("test-command:append:start");
325
530
  fs.appendFileSync(savedReportPath, `
326
531
 
327
532
  ## \uC0AC\uC6A9\uB41C \uBA85\uB839\uC5B4
328
533
 
329
534
  ${command}`);
535
+ trace7("test-command:append:done");
330
536
  }
331
537
  console.log(`
332
538
  \u2705 \uB9AC\uBDF0\uAC00 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.`);
333
539
  console.log(`\u{1F4C4} \uB9AC\uD3EC\uD2B8 \uC800\uC7A5 \uC704\uCE58: ${savedReportPath}`);
334
540
  console.log(`diff \uC800\uC7A5 \uC704\uCE58: ${savedDiffPath}`);
541
+ trace7("open-report:start");
335
542
  openReport(savedReportPath);
543
+ trace7("open-report:done");
544
+ trace7("cleanup-temp-diff:start");
336
545
  deleteTempDiff();
546
+ trace7("cleanup-temp-diff:done");
547
+ trace7("review-flow:end");
337
548
  } catch (error) {
549
+ trace7("review-flow:catch");
338
550
  console.error("\u274C \uB9AC\uBDF0 \uB3C4\uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.");
339
551
  console.error(error);
552
+ trace7("cleanup-temp-diff:start(catch)");
340
553
  deleteTempDiff();
554
+ trace7("cleanup-temp-diff:done(catch)");
341
555
  process.exit(1);
342
556
  }
343
557
  }