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