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