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