sales-frontend-gemini-cli 0.4.1 → 0.4.2
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 +226 -32
- package/dist/common/helper.cjs.map +1 -1
- package/dist/common/helper.d.cts +22 -2
- package/dist/common/helper.d.ts +22 -2
- package/dist/common/helper.js +220 -33
- package/dist/common/helper.js.map +1 -1
- package/dist/pr-review/claude/claude-commander.cjs +8 -1
- package/dist/pr-review/claude/claude-commander.cjs.map +1 -1
- package/dist/pr-review/claude/claude-commander.js +8 -1
- package/dist/pr-review/claude/claude-commander.js.map +1 -1
- package/dist/pr-review/claude/installation-claude.cjs +178 -8
- package/dist/pr-review/claude/installation-claude.cjs.map +1 -1
- package/dist/pr-review/claude/installation-claude.js +177 -8
- package/dist/pr-review/claude/installation-claude.js.map +1 -1
- package/dist/pr-review/codex/codex-commander.cjs +6 -1
- package/dist/pr-review/codex/codex-commander.cjs.map +1 -1
- package/dist/pr-review/codex/codex-commander.js +6 -1
- package/dist/pr-review/codex/codex-commander.js.map +1 -1
- package/dist/pr-review/codex/installation-codex.cjs +178 -8
- package/dist/pr-review/codex/installation-codex.cjs.map +1 -1
- package/dist/pr-review/codex/installation-codex.js +177 -8
- package/dist/pr-review/codex/installation-codex.js.map +1 -1
- package/dist/pr-review/gemini/gemini-commander.cjs +7 -1
- package/dist/pr-review/gemini/gemini-commander.cjs.map +1 -1
- package/dist/pr-review/gemini/gemini-commander.js +7 -1
- package/dist/pr-review/gemini/gemini-commander.js.map +1 -1
- package/dist/pr-review/gemini/installation-gemini.cjs +178 -8
- package/dist/pr-review/gemini/installation-gemini.cjs.map +1 -1
- package/dist/pr-review/gemini/installation-gemini.js +177 -8
- package/dist/pr-review/gemini/installation-gemini.js.map +1 -1
- package/dist/pr-review/review-one-by-one.cjs +368 -108
- package/dist/pr-review/review-one-by-one.cjs.map +1 -1
- package/dist/pr-review/review-one-by-one.js +368 -108
- package/dist/pr-review/review-one-by-one.js.map +1 -1
- package/dist/pr-review/review.cjs +316 -80
- package/dist/pr-review/review.cjs.map +1 -1
- package/dist/pr-review/review.js +316 -80
- package/dist/pr-review/review.js.map +1 -1
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
var child_process = require('child_process');
|
|
5
|
-
var
|
|
5
|
+
var fs = require('fs');
|
|
6
6
|
var util = require('util');
|
|
7
7
|
var path = require('path');
|
|
8
8
|
var readline = require('readline');
|
|
@@ -11,12 +11,13 @@ var url = require('url');
|
|
|
11
11
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
12
12
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
13
13
|
|
|
14
|
-
var
|
|
14
|
+
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
15
15
|
var util__default = /*#__PURE__*/_interopDefault(util);
|
|
16
16
|
var path__default = /*#__PURE__*/_interopDefault(path);
|
|
17
17
|
var readline__default = /*#__PURE__*/_interopDefault(readline);
|
|
18
18
|
|
|
19
19
|
var __dirname$1 = path__default.default.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('review-one-by-one.cjs', document.baseURI).href))));
|
|
20
|
+
var traceMessages = [];
|
|
20
21
|
var rulesPath = path__default.default.resolve(__dirname$1, "../../src/common/rules/review-rules.md");
|
|
21
22
|
var namingRulesPath = path__default.default.resolve(__dirname$1, "../../src/common/rules/naming-rule.md");
|
|
22
23
|
var codingConventionRulesPath = path__default.default.resolve(__dirname$1, "../../src/common/rules/coding-convention.md");
|
|
@@ -39,66 +40,226 @@ var ignoreList = [
|
|
|
39
40
|
".review-report/"
|
|
40
41
|
// 생성되는 리포트 폴더도 제외
|
|
41
42
|
];
|
|
42
|
-
function parseServiceFromArgs(args4 = process.argv.slice(2)) {
|
|
43
|
-
const serviceIndex = args4.indexOf("--service");
|
|
44
|
-
const rawService = serviceIndex !== -1 ? args4[serviceIndex + 1] : "";
|
|
45
|
-
if (!rawService) {
|
|
46
|
-
return "";
|
|
47
|
-
}
|
|
48
|
-
const normalizedService = rawService.toLowerCase();
|
|
49
|
-
if (AIServices.includes(normalizedService)) {
|
|
50
|
-
return normalizedService;
|
|
51
|
-
}
|
|
52
|
-
console.error(
|
|
53
|
-
`\u274C \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uC11C\uBE44\uC2A4\uC785\uB2C8\uB2E4: ${rawService}. \uC0AC\uC6A9 \uAC00\uB2A5 \uAC12: ${AIServices.join(", ")} (\uC608: --service codex)`
|
|
54
|
-
);
|
|
55
|
-
process.exit(1);
|
|
56
|
-
}
|
|
57
43
|
function isTestMode(args4 = process.argv.slice(2)) {
|
|
58
44
|
return args4.includes("--test");
|
|
59
45
|
}
|
|
46
|
+
function clearTraceMessages() {
|
|
47
|
+
traceMessages.length = 0;
|
|
48
|
+
}
|
|
49
|
+
function getTraceMessages() {
|
|
50
|
+
return [...traceMessages];
|
|
51
|
+
}
|
|
60
52
|
function createTraceLogger(scope, args4 = process.argv.slice(2)) {
|
|
61
53
|
const enabled = isTestMode(args4);
|
|
62
54
|
return (step, detail) => {
|
|
55
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
56
|
+
const message = `[${timestamp}][TRACE][${scope}] ${step}${detail ? ` | ${detail}` : ""}`;
|
|
57
|
+
traceMessages.push(message);
|
|
63
58
|
if (!enabled) {
|
|
64
59
|
return;
|
|
65
60
|
}
|
|
66
|
-
console.log(
|
|
61
|
+
console.log(message);
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
var helperTrace = createTraceLogger("helper");
|
|
65
|
+
function getTimestampParts(now = /* @__PURE__ */ new Date()) {
|
|
66
|
+
return {
|
|
67
|
+
YYYY: now.getFullYear(),
|
|
68
|
+
MM: String(now.getMonth() + 1).padStart(2, "0"),
|
|
69
|
+
DD: String(now.getDate()).padStart(2, "0"),
|
|
70
|
+
HH: String(now.getHours()).padStart(2, "0"),
|
|
71
|
+
mm: String(now.getMinutes()).padStart(2, "0"),
|
|
72
|
+
ss: String(now.getSeconds()).padStart(2, "0")
|
|
67
73
|
};
|
|
68
74
|
}
|
|
75
|
+
function getHumanReadableNowString(now = /* @__PURE__ */ new Date()) {
|
|
76
|
+
const { YYYY, MM, DD, HH, mm, ss } = getTimestampParts(now);
|
|
77
|
+
return `${YYYY}-${MM}-${DD} ${HH}:${mm}:${ss}`;
|
|
78
|
+
}
|
|
79
|
+
function stringifyUnknown(value) {
|
|
80
|
+
if (value === void 0 || value === null) {
|
|
81
|
+
return "";
|
|
82
|
+
}
|
|
83
|
+
if (typeof value === "string") {
|
|
84
|
+
return value;
|
|
85
|
+
}
|
|
86
|
+
if (Buffer.isBuffer(value)) {
|
|
87
|
+
return value.toString();
|
|
88
|
+
}
|
|
89
|
+
if (value instanceof Error) {
|
|
90
|
+
return value.stack || value.message;
|
|
91
|
+
}
|
|
92
|
+
return util.inspect(value, { depth: 5, breakLength: 120 });
|
|
93
|
+
}
|
|
94
|
+
function getErrorSummary(error) {
|
|
95
|
+
if (error instanceof Error) {
|
|
96
|
+
return `${error.name}: ${error.message}`;
|
|
97
|
+
}
|
|
98
|
+
return stringifyUnknown(error) || "Unknown error";
|
|
99
|
+
}
|
|
100
|
+
function serializeError(error) {
|
|
101
|
+
const serialized = {
|
|
102
|
+
summary: getErrorSummary(error)
|
|
103
|
+
};
|
|
104
|
+
if (error instanceof Error) {
|
|
105
|
+
serialized.name = error.name;
|
|
106
|
+
serialized.message = error.message;
|
|
107
|
+
serialized.stack = error.stack;
|
|
108
|
+
} else {
|
|
109
|
+
serialized.value = stringifyUnknown(error);
|
|
110
|
+
}
|
|
111
|
+
if (error && typeof error === "object") {
|
|
112
|
+
const errorLike = error;
|
|
113
|
+
const extraKeys = ["code", "errno", "syscall", "path", "cmd", "status", "signal", "spawnargs"];
|
|
114
|
+
extraKeys.forEach((key) => {
|
|
115
|
+
if (errorLike[key] !== void 0) {
|
|
116
|
+
serialized[key] = errorLike[key];
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
const stdout = stringifyUnknown(errorLike.stdout);
|
|
120
|
+
if (stdout) {
|
|
121
|
+
serialized.stdout = stdout;
|
|
122
|
+
}
|
|
123
|
+
const stderr = stringifyUnknown(errorLike.stderr);
|
|
124
|
+
if (stderr) {
|
|
125
|
+
serialized.stderr = stderr;
|
|
126
|
+
}
|
|
127
|
+
const cause = stringifyUnknown(errorLike.cause);
|
|
128
|
+
if (cause) {
|
|
129
|
+
serialized.cause = cause;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return serialized;
|
|
133
|
+
}
|
|
69
134
|
function getNextFilePath(dir, baseName, extension) {
|
|
70
135
|
let counter = 1;
|
|
71
136
|
while (true) {
|
|
72
137
|
const filePath = path__default.default.join(dir, `${baseName}-${counter}${extension}`);
|
|
73
|
-
if (!
|
|
138
|
+
if (!fs__default.default.existsSync(filePath)) {
|
|
74
139
|
return filePath;
|
|
75
140
|
}
|
|
76
141
|
counter++;
|
|
77
142
|
}
|
|
78
143
|
}
|
|
144
|
+
function getAvailableFilePath(dir, baseName, extension) {
|
|
145
|
+
const firstFilePath = path__default.default.join(dir, `${baseName}${extension}`);
|
|
146
|
+
if (!fs__default.default.existsSync(firstFilePath)) {
|
|
147
|
+
return firstFilePath;
|
|
148
|
+
}
|
|
149
|
+
return getNextFilePath(dir, baseName, extension);
|
|
150
|
+
}
|
|
79
151
|
function deleteFile(filePath) {
|
|
80
|
-
if (
|
|
81
|
-
|
|
152
|
+
if (fs__default.default.existsSync(filePath)) {
|
|
153
|
+
fs__default.default.unlinkSync(filePath);
|
|
82
154
|
}
|
|
83
155
|
}
|
|
84
156
|
function deleteTempDiff() {
|
|
85
157
|
deleteFile(tempDiffPath);
|
|
86
158
|
}
|
|
87
159
|
function createReportDirectory() {
|
|
88
|
-
if (!
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
function getNowString() {
|
|
93
|
-
const
|
|
94
|
-
const YYYY = now.getFullYear();
|
|
95
|
-
const MM = String(now.getMonth() + 1).padStart(2, "0");
|
|
96
|
-
const DD = String(now.getDate()).padStart(2, "0");
|
|
97
|
-
const HH = String(now.getHours()).padStart(2, "0");
|
|
98
|
-
const mm = String(now.getMinutes()).padStart(2, "0");
|
|
99
|
-
const ss = String(now.getSeconds()).padStart(2, "0");
|
|
160
|
+
if (!fs__default.default.existsSync(REPORT_DIR)) {
|
|
161
|
+
fs__default.default.mkdirSync(REPORT_DIR, { recursive: true });
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
function getNowString(now = /* @__PURE__ */ new Date()) {
|
|
165
|
+
const { YYYY, MM, DD, HH, mm, ss } = getTimestampParts(now);
|
|
100
166
|
return `${YYYY}-${MM}-${DD}_${HH}-${mm}-${ss}`;
|
|
101
167
|
}
|
|
168
|
+
function getErrorLogTimestamp(now = /* @__PURE__ */ new Date()) {
|
|
169
|
+
const { YYYY, MM, DD, HH, mm, ss } = getTimestampParts(now);
|
|
170
|
+
return `${YYYY}-${MM}-${DD}-${HH}\uC2DC-${mm}\uBD84-${ss}\uCD08`;
|
|
171
|
+
}
|
|
172
|
+
function writeErrorReport(error, options = {}) {
|
|
173
|
+
try {
|
|
174
|
+
const now = /* @__PURE__ */ new Date();
|
|
175
|
+
helperTrace("error-report:write:start", options.scope || "unknown");
|
|
176
|
+
createReportDirectory();
|
|
177
|
+
const reportPath = getAvailableFilePath(REPORT_DIR, `error-log-${getErrorLogTimestamp(now)}`, ".md");
|
|
178
|
+
const serializedError = serializeError(error);
|
|
179
|
+
const traceSnapshot = options.traceMessages ?? getTraceMessages();
|
|
180
|
+
const extraSections = options.extraSections || [];
|
|
181
|
+
const report = `# Error Log
|
|
182
|
+
|
|
183
|
+
- \uBC1C\uC0DD \uC2DC\uAC01: ${getHumanReadableNowString(now)}
|
|
184
|
+
- Scope: \`${options.scope || "unknown"}\`
|
|
185
|
+
- \uC791\uC5C5 \uACBD\uB85C: \`${process.cwd()}\`
|
|
186
|
+
- \uC2E4\uD589 \uC778\uC790: \`${JSON.stringify(options.args ?? process.argv.slice(2))}\`
|
|
187
|
+
- \uC2E4\uD589 \uD658\uACBD: \`${process.platform} ${process.arch} / Node ${process.version}\`
|
|
188
|
+
|
|
189
|
+
## Summary
|
|
190
|
+
|
|
191
|
+
${options.title || serializedError.summary || "Unknown error"}
|
|
192
|
+
|
|
193
|
+
## Error
|
|
194
|
+
|
|
195
|
+
\`\`\`json
|
|
196
|
+
${JSON.stringify(serializedError, null, 2)}
|
|
197
|
+
\`\`\`
|
|
198
|
+
|
|
199
|
+
## Trace
|
|
200
|
+
|
|
201
|
+
\`\`\`json
|
|
202
|
+
${JSON.stringify(traceSnapshot, null, 2)}
|
|
203
|
+
\`\`\`${extraSections.length ? `
|
|
204
|
+
${extraSections.map((section) => `
|
|
205
|
+
## ${section.heading}
|
|
206
|
+
|
|
207
|
+
${section.markdown}`).join("\n")}
|
|
208
|
+
` : "\n"}
|
|
209
|
+
`;
|
|
210
|
+
fs__default.default.writeFileSync(reportPath, report);
|
|
211
|
+
helperTrace("error-report:write:done", reportPath);
|
|
212
|
+
return reportPath;
|
|
213
|
+
} catch (writeError) {
|
|
214
|
+
console.error("\u26A0\uFE0F \uC5D0\uB7EC \uB85C\uADF8 \uD30C\uC77C \uC0DD\uC131\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.");
|
|
215
|
+
console.error(writeError);
|
|
216
|
+
return "";
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
function exitWithError(message, options = {}) {
|
|
220
|
+
const reportPath = writeErrorReport(options.error || new Error(message), {
|
|
221
|
+
...options,
|
|
222
|
+
title: message
|
|
223
|
+
});
|
|
224
|
+
console.error(message);
|
|
225
|
+
if (options.error) {
|
|
226
|
+
console.error(options.error);
|
|
227
|
+
}
|
|
228
|
+
if (reportPath) {
|
|
229
|
+
console.error(`\u{1F4C4} \uC5D0\uB7EC \uB85C\uADF8 \uC800\uC7A5 \uC704\uCE58: ${reportPath}`);
|
|
230
|
+
}
|
|
231
|
+
process.exit(1);
|
|
232
|
+
}
|
|
233
|
+
function parseServiceFromArgs(args4 = process.argv.slice(2)) {
|
|
234
|
+
helperTrace("parse-service:start", `args=${JSON.stringify(args4)}`);
|
|
235
|
+
const serviceIndex = args4.indexOf("--service");
|
|
236
|
+
const rawService = serviceIndex !== -1 ? args4[serviceIndex + 1] : "";
|
|
237
|
+
if (!rawService) {
|
|
238
|
+
helperTrace("parse-service:empty");
|
|
239
|
+
return "";
|
|
240
|
+
}
|
|
241
|
+
const normalizedService = rawService.toLowerCase();
|
|
242
|
+
if (AIServices.includes(normalizedService)) {
|
|
243
|
+
helperTrace("parse-service:resolved", normalizedService);
|
|
244
|
+
return normalizedService;
|
|
245
|
+
}
|
|
246
|
+
helperTrace("parse-service:invalid", rawService);
|
|
247
|
+
exitWithError(
|
|
248
|
+
`\u274C \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uC11C\uBE44\uC2A4\uC785\uB2C8\uB2E4: ${rawService}. \uC0AC\uC6A9 \uAC00\uB2A5 \uAC12: ${AIServices.join(", ")} (\uC608: --service codex)`,
|
|
249
|
+
{
|
|
250
|
+
scope: "helper:parseServiceFromArgs",
|
|
251
|
+
args: args4,
|
|
252
|
+
extraSections: [
|
|
253
|
+
{
|
|
254
|
+
heading: "Allowed Services",
|
|
255
|
+
markdown: `\`\`\`json
|
|
256
|
+
${JSON.stringify(AIServices, null, 2)}
|
|
257
|
+
\`\`\``
|
|
258
|
+
}
|
|
259
|
+
]
|
|
260
|
+
}
|
|
261
|
+
);
|
|
262
|
+
}
|
|
102
263
|
function getGitDiffFilter() {
|
|
103
264
|
const includeExtensions = ["*.ts", "*.tsx", "*.js", "*.jsx"];
|
|
104
265
|
const excludePatterns = ignoreList.map((item) => `:(exclude)${item}`);
|
|
@@ -110,6 +271,7 @@ function getGitDiffFilter() {
|
|
|
110
271
|
function openReport(reportPath) {
|
|
111
272
|
const resolvedPath = path__default.default.resolve(reportPath);
|
|
112
273
|
const { platform } = process;
|
|
274
|
+
helperTrace("open-report:start", resolvedPath);
|
|
113
275
|
const openWithChrome = () => {
|
|
114
276
|
if (platform === "darwin") {
|
|
115
277
|
child_process.execSync(`open -a "Google Chrome" "${resolvedPath}"`, { stdio: "ignore" });
|
|
@@ -134,32 +296,41 @@ function openReport(reportPath) {
|
|
|
134
296
|
};
|
|
135
297
|
try {
|
|
136
298
|
if (openWithChrome()) {
|
|
299
|
+
helperTrace("open-report:chrome:success", platform);
|
|
137
300
|
console.log("\u{1F680} Google Chrome\uC5D0\uC11C \uB9AC\uD3EC\uD2B8\uB97C \uC5F4\uC5C8\uC2B5\uB2C8\uB2E4.");
|
|
138
301
|
return;
|
|
139
302
|
}
|
|
140
|
-
} catch {
|
|
303
|
+
} catch (error) {
|
|
304
|
+
helperTrace("open-report:chrome:failed", getErrorSummary(error));
|
|
141
305
|
}
|
|
142
306
|
try {
|
|
143
307
|
if (openWithDefaultBrowser()) {
|
|
308
|
+
helperTrace("open-report:default-browser:success", platform);
|
|
144
309
|
console.log("\u{1F680} \uAE30\uBCF8 \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uB9AC\uD3EC\uD2B8\uB97C \uC5F4\uC5C8\uC2B5\uB2C8\uB2E4.");
|
|
145
310
|
return;
|
|
146
311
|
}
|
|
147
|
-
} catch (
|
|
148
|
-
|
|
312
|
+
} catch (error) {
|
|
313
|
+
helperTrace("open-report:default-browser:failed", getErrorSummary(error));
|
|
314
|
+
console.error("\u26A0\uFE0F \uBE0C\uB77C\uC6B0\uC800 \uC5F4\uAE30 \uC2E4\uD328:", error);
|
|
149
315
|
return;
|
|
150
316
|
}
|
|
317
|
+
helperTrace("open-report:unsupported-platform", platform);
|
|
151
318
|
console.error(`\u26A0\uFE0F \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uD50C\uB7AB\uD3FC\uC785\uB2C8\uB2E4: ${platform}`);
|
|
152
319
|
}
|
|
153
320
|
function getDiffArgs() {
|
|
154
321
|
const args4 = process.argv.slice(2);
|
|
155
322
|
const commitIndex = args4.indexOf("--commit");
|
|
156
323
|
const { includeParams, excludeParams } = getGitDiffFilter();
|
|
324
|
+
helperTrace("diff-args:resolve:start", `args=${JSON.stringify(args4)}`);
|
|
157
325
|
let diffArgs = "";
|
|
158
326
|
if (commitIndex !== -1) {
|
|
159
327
|
const commitHash = args4[commitIndex + 1];
|
|
160
328
|
if (!commitHash) {
|
|
161
|
-
|
|
162
|
-
|
|
329
|
+
helperTrace("diff-args:commit-hash-missing");
|
|
330
|
+
exitWithError("\u274C \uCEE4\uBC0B \uD574\uC2DC\uAC00 \uC81C\uACF5\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.", {
|
|
331
|
+
scope: "helper:getDiffArgs",
|
|
332
|
+
args: args4
|
|
333
|
+
});
|
|
163
334
|
}
|
|
164
335
|
const nextArg = args4[commitIndex + 2];
|
|
165
336
|
let n = 0;
|
|
@@ -169,28 +340,37 @@ function getDiffArgs() {
|
|
|
169
340
|
n = 0;
|
|
170
341
|
}
|
|
171
342
|
}
|
|
343
|
+
helperTrace("diff-args:commit-mode", `${commitHash}~${n + 1} ${commitHash}`);
|
|
172
344
|
console.log(`\u2139\uFE0F \uCEE4\uBC0B '${commitHash}' ${n > 0 ? ` \uD3EC\uD568 \uCD1D ${n + 1}\uAC1C\uC758 \uCEE4\uBC0B` : ""}\uC744 \uB9AC\uBDF0\uD569\uB2C8\uB2E4...`);
|
|
173
345
|
diffArgs = `${commitHash}~${n + 1} ${commitHash}`;
|
|
174
346
|
} else {
|
|
175
347
|
try {
|
|
348
|
+
helperTrace("diff-args:unstaged-check:start");
|
|
176
349
|
const check = child_process.execSync(`git diff --name-only -- ${includeParams} ${excludeParams}`).toString();
|
|
177
350
|
if (!check.trim()) {
|
|
351
|
+
helperTrace("diff-args:unstaged-check:empty", "use HEAD~1 HEAD");
|
|
178
352
|
console.log("\u2139\uFE0F Unstaged \uBCC0\uACBD\uC0AC\uD56D\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. \uB9C8\uC9C0\uB9C9 \uCEE4\uBC0B(HEAD)\uC744 \uB9AC\uBDF0\uD569\uB2C8\uB2E4...");
|
|
179
353
|
diffArgs = "HEAD~1 HEAD";
|
|
354
|
+
} else {
|
|
355
|
+
helperTrace("diff-args:unstaged-check:has-changes", `length=${check.length}`);
|
|
180
356
|
}
|
|
181
|
-
} catch {
|
|
357
|
+
} catch (error) {
|
|
358
|
+
helperTrace("diff-args:unstaged-check:failed", getErrorSummary(error));
|
|
182
359
|
}
|
|
183
360
|
}
|
|
361
|
+
helperTrace("diff-args:resolve:done", diffArgs || "(default)");
|
|
184
362
|
return diffArgs;
|
|
185
363
|
}
|
|
186
364
|
async function showSelectionAIService() {
|
|
187
365
|
const selectedServiceFromArgs = parseServiceFromArgs();
|
|
188
366
|
if (selectedServiceFromArgs) {
|
|
367
|
+
helperTrace("show-selection:from-args", selectedServiceFromArgs);
|
|
189
368
|
console.log(`
|
|
190
369
|
\u2705 \x1B[32m${selectedServiceFromArgs}\x1B[0m \uC11C\uBE44\uC2A4\uAC00 \uC120\uD0DD\uB418\uC5C8\uC2B5\uB2C8\uB2E4. (--service)
|
|
191
370
|
`);
|
|
192
371
|
return selectedServiceFromArgs;
|
|
193
372
|
}
|
|
373
|
+
helperTrace("show-selection:interactive:start");
|
|
194
374
|
let selectedIndex = 0;
|
|
195
375
|
const rl = readline__default.default.createInterface({
|
|
196
376
|
input: process.stdin,
|
|
@@ -204,6 +384,7 @@ async function showSelectionAIService() {
|
|
|
204
384
|
readline__default.default.moveCursor(process.stdout, 0, -(AIServices.length + 1));
|
|
205
385
|
}
|
|
206
386
|
firstRender = false;
|
|
387
|
+
helperTrace("show-selection:interactive:render", AIServices[selectedIndex] || "unknown");
|
|
207
388
|
readline__default.default.clearScreenDown(process.stdout);
|
|
208
389
|
process.stdout.write(
|
|
209
390
|
"\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"
|
|
@@ -223,6 +404,7 @@ async function showSelectionAIService() {
|
|
|
223
404
|
const onData = (data) => {
|
|
224
405
|
const key = data.toString();
|
|
225
406
|
if (key === "") {
|
|
407
|
+
helperTrace("show-selection:interactive:ctrl-c");
|
|
226
408
|
process.stdout.write("\x1B[?25h");
|
|
227
409
|
process.exit(0);
|
|
228
410
|
}
|
|
@@ -243,6 +425,7 @@ async function showSelectionAIService() {
|
|
|
243
425
|
`);
|
|
244
426
|
const result = AIServices[selectedIndex];
|
|
245
427
|
if (result) {
|
|
428
|
+
helperTrace("show-selection:interactive:confirmed", result);
|
|
246
429
|
resolve(result);
|
|
247
430
|
}
|
|
248
431
|
}
|
|
@@ -356,14 +539,17 @@ var createClaudeCommand = (tempDiffPath2, reviewFormPath2) => {
|
|
|
356
539
|
{ path: namingRulesPath, display: "\uB124\uC774\uBC0D \uADDC\uCE59" },
|
|
357
540
|
{ path: codingConventionRulesPath, display: "\uCF54\uB529 \uCEE8\uBCA4\uC158" }
|
|
358
541
|
];
|
|
359
|
-
const existingRuleFiles = rules.filter((rule) =>
|
|
542
|
+
const existingRuleFiles = rules.filter((rule) => fs__default.default.existsSync(rule.path)).map((rule) => rule.path);
|
|
360
543
|
trace("rules:loaded", `count=${existingRuleFiles.length}`);
|
|
361
|
-
const reviewFormExists =
|
|
544
|
+
const reviewFormExists = fs__default.default.existsSync(reviewFormPath2);
|
|
362
545
|
trace("reviewForm:status", reviewFormExists ? "exists" : "missing");
|
|
363
546
|
const systemPromptFiles = reviewFormExists ? [...existingRuleFiles, reviewFormPath2] : existingRuleFiles;
|
|
364
547
|
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.";
|
|
548
|
+
trace("prompt:prepared", `length=${prompt.length}`);
|
|
549
|
+
trace("system-prompt-files", `count=${systemPromptFiles.length}`);
|
|
365
550
|
const modelCandidates = toUnique(customModel ? [customModel, ...aliasFallbacks] : aliasFallbacks);
|
|
366
551
|
trace("model:candidates", modelCandidates.join(", "));
|
|
552
|
+
trace("command:candidates:count", String(modelCandidates.length + 1));
|
|
367
553
|
if (customModel) {
|
|
368
554
|
console.warn(
|
|
369
555
|
`\u26A0\uFE0F \uCEE4\uC2A4\uD140 \uBAA8\uB378(${customModel})\uC744 \uC6B0\uC120 \uC2DC\uB3C4\uD558\uACE0 \uC2E4\uD328\uD558\uBA74 alias(${aliasFallbacks.join(
|
|
@@ -404,6 +590,7 @@ var createClaudeCommand = (tempDiffPath2, reviewFormPath2) => {
|
|
|
404
590
|
\uC0DD\uC131\uB420 \uBA85\uB839\uC5B4 \uBBF8\uB9AC\uBCF4\uAE30:
|
|
405
591
|
${safeCommand}"`;
|
|
406
592
|
}
|
|
593
|
+
trace("command:mode", "execute");
|
|
407
594
|
trace("createClaudeCommand:end");
|
|
408
595
|
return command;
|
|
409
596
|
};
|
|
@@ -414,23 +601,25 @@ function checkClaudeCliInstalled() {
|
|
|
414
601
|
trace2("version-check:run", "claude --version");
|
|
415
602
|
child_process.execSync("claude --version", { stdio: "ignore" });
|
|
416
603
|
trace2("version-check:ok");
|
|
417
|
-
} catch {
|
|
418
|
-
trace2("version-check:failed",
|
|
604
|
+
} catch (error) {
|
|
605
|
+
trace2("version-check:failed", getErrorSummary(error));
|
|
606
|
+
trace2("install:start", "@anthropic-ai/claude-code");
|
|
419
607
|
console.log(
|
|
420
608
|
"\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"
|
|
421
609
|
);
|
|
422
610
|
try {
|
|
423
611
|
child_process.execSync("npm install -g @anthropic-ai/claude-code", { stdio: "inherit" });
|
|
424
|
-
trace2("install:ok", "
|
|
612
|
+
trace2("install:ok", "login-required");
|
|
425
613
|
console.log("\u2705 claude-cli \uC124\uCE58\uAC00 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.");
|
|
426
614
|
console.log("\u26A0\uFE0F claude-cli \uC0AC\uC6A9\uC744 \uC704\uD574 \uC778\uC99D\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.");
|
|
427
615
|
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.');
|
|
428
616
|
process.exit(1);
|
|
429
617
|
} catch (installError) {
|
|
430
|
-
trace2("install:failed");
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
618
|
+
trace2("install:failed", getErrorSummary(installError));
|
|
619
|
+
exitWithError("\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).", {
|
|
620
|
+
scope: "installation-claude",
|
|
621
|
+
error: installError
|
|
622
|
+
});
|
|
434
623
|
}
|
|
435
624
|
}
|
|
436
625
|
trace2("checkClaudeCliInstalled:end");
|
|
@@ -481,10 +670,10 @@ var createCodexCommand = (tempDiffPath2, reviewFormPath2) => {
|
|
|
481
670
|
trace3("createCodexCommand:start", `tempDiffPath=${tempDiffPath2}, reviewFormPath=${reviewFormPath2}`);
|
|
482
671
|
const customModel = getArgValue2("--model");
|
|
483
672
|
const reasoningEffort = resolveReasoningEffort2();
|
|
484
|
-
const rules = [rulesPath, namingRulesPath, codingConventionRulesPath].filter((filePath) =>
|
|
673
|
+
const rules = [rulesPath, namingRulesPath, codingConventionRulesPath].filter((filePath) => fs__default.default.existsSync(filePath)).map((filePath) => `- ${filePath}`).join("\n");
|
|
485
674
|
const rulesCount = rules ? rules.split("\n").length : 0;
|
|
486
675
|
trace3("rules:loaded", `count=${rulesCount}`);
|
|
487
|
-
const hasReviewForm =
|
|
676
|
+
const hasReviewForm = fs__default.default.existsSync(reviewFormPath2);
|
|
488
677
|
const reviewFormLine = hasReviewForm ? `- ${reviewFormPath2}` : "";
|
|
489
678
|
trace3("reviewForm:status", reviewFormLine ? "exists" : "missing");
|
|
490
679
|
const prompt = `\uC544\uB798 \uD30C\uC77C\uB4E4\uC744 \uCC38\uACE0\uD574\uC11C \uCF54\uB4DC \uB9AC\uBDF0\uB97C \uC9C4\uD589\uD574\uC918.
|
|
@@ -496,6 +685,7 @@ ${reviewFormLine || "- (\uC5C6\uC74C)"}
|
|
|
496
685
|
- ${tempDiffPath2}
|
|
497
686
|
|
|
498
687
|
\uBC18\uB4DC\uC2DC \uB9AC\uBDF0 \uC591\uC2DD\uC5D0 \uB9DE\uCDB0 \uC791\uC131\uD574\uC918.`;
|
|
688
|
+
trace3("prompt:prepared", `length=${prompt.length}`);
|
|
499
689
|
let command = "";
|
|
500
690
|
if (customModel) {
|
|
501
691
|
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.");
|
|
@@ -521,6 +711,7 @@ ${reviewFormLine || "- (\uC5C6\uC74C)"}
|
|
|
521
711
|
\uC0DD\uC131\uB420 \uBA85\uB839\uC5B4 \uBBF8\uB9AC\uBCF4\uAE30:
|
|
522
712
|
${safeCommand}"`;
|
|
523
713
|
}
|
|
714
|
+
trace3("command:mode", "execute");
|
|
524
715
|
trace3("createCodexCommand:end");
|
|
525
716
|
return command;
|
|
526
717
|
};
|
|
@@ -531,21 +722,23 @@ function checkCodexCliInstalled() {
|
|
|
531
722
|
trace4("version-check:run", "codex --version");
|
|
532
723
|
child_process.execSync("codex --version", { stdio: "ignore" });
|
|
533
724
|
trace4("version-check:ok");
|
|
534
|
-
} catch {
|
|
535
|
-
trace4("version-check:failed",
|
|
725
|
+
} catch (error) {
|
|
726
|
+
trace4("version-check:failed", getErrorSummary(error));
|
|
727
|
+
trace4("install:start", "@openai/codex");
|
|
536
728
|
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");
|
|
537
729
|
try {
|
|
538
730
|
child_process.execSync("npm install -g @openai/codex", { stdio: "inherit" });
|
|
539
|
-
trace4("install:ok", "
|
|
731
|
+
trace4("install:ok", "login-required");
|
|
540
732
|
console.log("\u2705 codex-cli \uC124\uCE58\uAC00 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.");
|
|
541
733
|
console.log("\u26A0\uFE0F codex-cli \uC0AC\uC6A9\uC744 \uC704\uD574 \uC778\uC99D\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.");
|
|
542
734
|
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.');
|
|
543
735
|
process.exit(1);
|
|
544
736
|
} catch (installError) {
|
|
545
|
-
trace4("install:failed");
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
737
|
+
trace4("install:failed", getErrorSummary(installError));
|
|
738
|
+
exitWithError("\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).", {
|
|
739
|
+
scope: "installation-codex",
|
|
740
|
+
error: installError
|
|
741
|
+
});
|
|
549
742
|
}
|
|
550
743
|
}
|
|
551
744
|
trace4("checkCodexCliInstalled:end");
|
|
@@ -653,17 +846,19 @@ var createGeminiCommand = (tempDiffPath2, reviewFormPath2) => {
|
|
|
653
846
|
{ path: namingRulesPath, display: "\uB124\uC774\uBC0D \uADDC\uCE59" },
|
|
654
847
|
{ path: codingConventionRulesPath, display: "\uCF54\uB529 \uCEE8\uBCA4\uC158" }
|
|
655
848
|
];
|
|
656
|
-
const validRules = rules.filter((rule) =>
|
|
849
|
+
const validRules = rules.filter((rule) => fs__default.default.existsSync(rule.path)).map((rule) => `@${rule.path}`).join(", ");
|
|
657
850
|
const rulesCount = validRules ? validRules.split(",").length : 0;
|
|
658
851
|
trace5("rules:loaded", `count=${rulesCount}`);
|
|
659
|
-
const reviewFormRef =
|
|
852
|
+
const reviewFormRef = fs__default.default.existsSync(reviewFormPath2) ? `@${reviewFormPath2}` : "(\uC5C6\uC74C)";
|
|
660
853
|
trace5("reviewForm:status", reviewFormRef === "(\uC5C6\uC74C)" ? "missing" : "exists");
|
|
661
854
|
const reasoningInstruction = getReasoningInstruction(reasoningEffort);
|
|
662
855
|
const prompt = `\uB2E4\uC74C \uADDC\uCE59\uB4E4\uC744 \uCC38\uACE0\uD574\uC11C(${validRules || "(\uC5C6\uC74C)"}) \uC774 diff(@${tempDiffPath2})\uB97C \uB9AC\uBDF0\uD574\uC918.
|
|
663
856
|
\uB9AC\uBDF0 \uC591\uC2DD\uC740 ${reviewFormRef} \uC5D0 \uB9DE\uCDB0\uC11C \uC791\uC131\uD574\uC918.
|
|
664
857
|
\uCD94\uB860 \uAC15\uB3C4 \uC9C0\uCE68: ${reasoningInstruction}`;
|
|
858
|
+
trace5("prompt:prepared", `length=${prompt.length}`);
|
|
665
859
|
const modelCandidates = toUnique2(customModel ? [customModel, ...aliasFallbacks] : aliasFallbacks);
|
|
666
860
|
trace5("model:candidates", modelCandidates.join(", "));
|
|
861
|
+
trace5("command:candidates:count", String(modelCandidates.length + 1));
|
|
667
862
|
if (customModel) {
|
|
668
863
|
console.warn(
|
|
669
864
|
`\u26A0\uFE0F \uCEE4\uC2A4\uD140 \uBAA8\uB378(${customModel})\uC744 \uC6B0\uC120 \uC2DC\uB3C4\uD558\uACE0 \uC2E4\uD328\uD558\uBA74 alias(${aliasFallbacks.join(
|
|
@@ -686,6 +881,7 @@ var createGeminiCommand = (tempDiffPath2, reviewFormPath2) => {
|
|
|
686
881
|
\uC0DD\uC131\uB420 \uBA85\uB839\uC5B4 \uBBF8\uB9AC\uBCF4\uAE30:
|
|
687
882
|
${safeCommand}"`;
|
|
688
883
|
}
|
|
884
|
+
trace5("command:mode", "execute");
|
|
689
885
|
trace5("createGeminiCommand:end");
|
|
690
886
|
return command;
|
|
691
887
|
};
|
|
@@ -696,21 +892,23 @@ function checkGeminiCliInstalled() {
|
|
|
696
892
|
trace6("version-check:run", "gemini --version");
|
|
697
893
|
child_process.execSync("gemini --version", { stdio: "ignore" });
|
|
698
894
|
trace6("version-check:ok");
|
|
699
|
-
} catch {
|
|
700
|
-
trace6("version-check:failed",
|
|
895
|
+
} catch (error) {
|
|
896
|
+
trace6("version-check:failed", getErrorSummary(error));
|
|
897
|
+
trace6("install:start", "@google/gemini-cli");
|
|
701
898
|
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");
|
|
702
899
|
try {
|
|
703
900
|
child_process.execSync("npm install -g @google/gemini-cli", { stdio: "inherit" });
|
|
704
|
-
trace6("install:ok", "
|
|
901
|
+
trace6("install:ok", "login-required");
|
|
705
902
|
console.log("\u2705 gemini-cli \uC124\uCE58\uAC00 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.");
|
|
706
903
|
console.log("\u26A0\uFE0F Gemini API \uC0AC\uC6A9\uC744 \uC704\uD574 \uC778\uC99D\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.");
|
|
707
904
|
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.');
|
|
708
905
|
process.exit(1);
|
|
709
906
|
} catch (installError) {
|
|
710
|
-
trace6("install:failed");
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
907
|
+
trace6("install:failed", getErrorSummary(installError));
|
|
908
|
+
exitWithError("\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).", {
|
|
909
|
+
scope: "installation-gemini",
|
|
910
|
+
error: installError
|
|
911
|
+
});
|
|
714
912
|
}
|
|
715
913
|
}
|
|
716
914
|
trace6("checkGeminiCliInstalled:end");
|
|
@@ -720,30 +918,34 @@ function checkGeminiCliInstalled() {
|
|
|
720
918
|
var execAsync = util__default.default.promisify(child_process.exec);
|
|
721
919
|
async function main() {
|
|
722
920
|
const args4 = process.argv.slice(2);
|
|
921
|
+
clearTraceMessages();
|
|
723
922
|
const isTest = isTestMode(args4);
|
|
724
923
|
const trace7 = createTraceLogger("review-one-by-one", args4);
|
|
725
924
|
trace7("main:start", `args=${JSON.stringify(args4)}`);
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
switch (service) {
|
|
730
|
-
case "gemini":
|
|
731
|
-
trace7("install-check:start", "service=gemini");
|
|
732
|
-
checkGeminiCliInstalled();
|
|
733
|
-
trace7("install-check:done", "service=gemini");
|
|
734
|
-
break;
|
|
735
|
-
case "claude":
|
|
736
|
-
trace7("install-check:start", "service=claude");
|
|
737
|
-
checkClaudeCliInstalled();
|
|
738
|
-
trace7("install-check:done", "service=claude");
|
|
739
|
-
break;
|
|
740
|
-
case "codex":
|
|
741
|
-
trace7("install-check:start", "service=codex");
|
|
742
|
-
checkCodexCliInstalled();
|
|
743
|
-
trace7("install-check:done", "service=codex");
|
|
744
|
-
break;
|
|
745
|
-
}
|
|
925
|
+
let service = "";
|
|
926
|
+
let savedDiffPath = "";
|
|
927
|
+
let savedReportPath = "";
|
|
746
928
|
try {
|
|
929
|
+
trace7("service-selection:start");
|
|
930
|
+
service = await showSelectionAIService();
|
|
931
|
+
trace7("service-selection:done", `service=${service}`);
|
|
932
|
+
switch (service) {
|
|
933
|
+
case "gemini":
|
|
934
|
+
trace7("install-check:start", "service=gemini");
|
|
935
|
+
checkGeminiCliInstalled();
|
|
936
|
+
trace7("install-check:done", "service=gemini");
|
|
937
|
+
break;
|
|
938
|
+
case "claude":
|
|
939
|
+
trace7("install-check:start", "service=claude");
|
|
940
|
+
checkClaudeCliInstalled();
|
|
941
|
+
trace7("install-check:done", "service=claude");
|
|
942
|
+
break;
|
|
943
|
+
case "codex":
|
|
944
|
+
trace7("install-check:start", "service=codex");
|
|
945
|
+
checkCodexCliInstalled();
|
|
946
|
+
trace7("install-check:done", "service=codex");
|
|
947
|
+
break;
|
|
948
|
+
}
|
|
747
949
|
trace7("review-flow:start");
|
|
748
950
|
console.log("\u{1F680} AI Code Review\uB97C \uC2DC\uC791\uD569\uB2C8\uB2E4...");
|
|
749
951
|
trace7("report-dir:create:start");
|
|
@@ -751,6 +953,7 @@ async function main() {
|
|
|
751
953
|
trace7("report-dir:create:done");
|
|
752
954
|
const { includeParams, excludeParams } = getGitDiffFilter();
|
|
753
955
|
trace7("diff-filter:loaded", `include=${includeParams} | exclude=${excludeParams}`);
|
|
956
|
+
trace7("diff-args:build:start");
|
|
754
957
|
const diffArgs = getDiffArgs();
|
|
755
958
|
trace7("diff-args:build:done", `diffArgs=${diffArgs || "(default)"}`);
|
|
756
959
|
const filesCommand = `git diff --name-only ${diffArgs} -- ${includeParams} ${excludeParams}`;
|
|
@@ -770,26 +973,26 @@ async function main() {
|
|
|
770
973
|
trace7("full-diff:done", `length=${fullDiff.length}`);
|
|
771
974
|
trace7("timestamp:created", nowStr);
|
|
772
975
|
trace7("temp-diff:write:start", tempDiffPath);
|
|
773
|
-
|
|
976
|
+
fs__default.default.writeFileSync(tempDiffPath, fullDiff);
|
|
774
977
|
trace7("temp-diff:write:done");
|
|
775
978
|
trace7("saved-diff:copy:start");
|
|
776
|
-
|
|
777
|
-
|
|
979
|
+
savedDiffPath = getNextFilePath(REPORT_DIR, `${nowStr}-diff`, ".txt");
|
|
980
|
+
fs__default.default.copyFileSync(tempDiffPath, savedDiffPath);
|
|
778
981
|
trace7("saved-diff:copy:done", savedDiffPath);
|
|
779
|
-
|
|
982
|
+
savedReportPath = getNextFilePath(REPORT_DIR, nowStr, ".md");
|
|
780
983
|
trace7("saved-report:path", savedReportPath);
|
|
781
984
|
const promises = fileList.map(async (file) => {
|
|
985
|
+
const tempOneFileDiffPath = `temp_diff_${file.replace(/\//g, "_")}.txt`;
|
|
986
|
+
let command = "";
|
|
782
987
|
try {
|
|
783
988
|
trace7("file-review:start", file);
|
|
784
989
|
console.log(`\u{1F50D} Reviewing: ${file}...`);
|
|
785
990
|
trace7("file-diff:run", file);
|
|
786
991
|
const fileDiff = child_process.execSync(`git diff ${diffArgs} -- "${file}"`).toString();
|
|
787
992
|
trace7("file-diff:done", `${file} | length=${fileDiff.length}`);
|
|
788
|
-
const tempOneFileDiffPath = `temp_diff_${file.replace(/\//g, "_")}.txt`;
|
|
789
993
|
trace7("file-temp-diff:write:start", tempOneFileDiffPath);
|
|
790
|
-
|
|
994
|
+
fs__default.default.writeFileSync(tempOneFileDiffPath, fileDiff);
|
|
791
995
|
trace7("file-temp-diff:write:done", tempOneFileDiffPath);
|
|
792
|
-
let command = "";
|
|
793
996
|
trace7("file-command:create:start", file);
|
|
794
997
|
switch (service) {
|
|
795
998
|
case "gemini":
|
|
@@ -802,7 +1005,7 @@ async function main() {
|
|
|
802
1005
|
command = createCodexCommand(tempOneFileDiffPath, reviewFormOneByOnePath);
|
|
803
1006
|
break;
|
|
804
1007
|
}
|
|
805
|
-
trace7("file-command:create:done", file);
|
|
1008
|
+
trace7("file-command:create:done", `${file} | commandLength=${command.length}`);
|
|
806
1009
|
trace7("file-command:exec:start", file);
|
|
807
1010
|
const { stdout } = await execAsync(command, { maxBuffer: 1024 * 1024 * 20 });
|
|
808
1011
|
const result = stdout.toString();
|
|
@@ -816,11 +1019,11 @@ ${result}
|
|
|
816
1019
|
`;
|
|
817
1020
|
console.log(tempReport);
|
|
818
1021
|
trace7("file-report:append:start", file);
|
|
819
|
-
|
|
1022
|
+
fs__default.default.appendFileSync(savedReportPath, tempReport);
|
|
820
1023
|
trace7("file-report:append:done", file);
|
|
821
1024
|
if (isTest) {
|
|
822
1025
|
trace7("file-test-command:append:start", file);
|
|
823
|
-
|
|
1026
|
+
fs__default.default.appendFileSync(savedReportPath, `
|
|
824
1027
|
|
|
825
1028
|
## \uC0AC\uC6A9\uB41C \uBA85\uB839\uC5B4
|
|
826
1029
|
|
|
@@ -829,26 +1032,51 @@ ${command}`);
|
|
|
829
1032
|
}
|
|
830
1033
|
trace7("file-review:end", file);
|
|
831
1034
|
} catch (err) {
|
|
832
|
-
trace7("file-review:catch", file);
|
|
1035
|
+
trace7("file-review:catch", `${file} | ${getErrorSummary(err)}`);
|
|
1036
|
+
const errorLogPath = writeErrorReport(err, {
|
|
1037
|
+
scope: "review-one-by-one:file",
|
|
1038
|
+
args: args4,
|
|
1039
|
+
extraSections: [
|
|
1040
|
+
{
|
|
1041
|
+
heading: "Execution Context",
|
|
1042
|
+
markdown: `\`\`\`json
|
|
1043
|
+
${JSON.stringify(
|
|
1044
|
+
{
|
|
1045
|
+
service,
|
|
1046
|
+
file,
|
|
1047
|
+
command: command || null,
|
|
1048
|
+
tempOneFileDiffPath,
|
|
1049
|
+
savedDiffPath: savedDiffPath || null,
|
|
1050
|
+
savedReportPath: savedReportPath || null
|
|
1051
|
+
},
|
|
1052
|
+
null,
|
|
1053
|
+
2
|
|
1054
|
+
)}
|
|
1055
|
+
\`\`\``
|
|
1056
|
+
}
|
|
1057
|
+
]
|
|
1058
|
+
});
|
|
833
1059
|
console.error(`\u274C Error reviewing file ${file}:`, err);
|
|
1060
|
+
if (errorLogPath) {
|
|
1061
|
+
console.error(`\u{1F4C4} \uC5D0\uB7EC \uB85C\uADF8 \uC800\uC7A5 \uC704\uCE58: ${errorLogPath}`);
|
|
1062
|
+
}
|
|
834
1063
|
const errorReport = `### File: ${file}
|
|
835
1064
|
\u274C Review Failed
|
|
836
1065
|
\`\`\`
|
|
837
|
-
${err}
|
|
1066
|
+
${getErrorSummary(err)}
|
|
838
1067
|
\`\`\`
|
|
839
1068
|
|
|
840
1069
|
`;
|
|
841
|
-
|
|
1070
|
+
fs__default.default.appendFileSync(savedReportPath, errorReport);
|
|
842
1071
|
try {
|
|
843
|
-
|
|
844
|
-
if (fs5__default.default.existsSync(tempOneFileDiffPath)) {
|
|
1072
|
+
if (fs__default.default.existsSync(tempOneFileDiffPath)) {
|
|
845
1073
|
trace7("file-temp-diff:delete:start(catch)", tempOneFileDiffPath);
|
|
846
1074
|
deleteFile(tempOneFileDiffPath);
|
|
847
1075
|
trace7("file-temp-diff:delete:done(catch)", tempOneFileDiffPath);
|
|
848
1076
|
}
|
|
849
|
-
} catch (
|
|
850
|
-
trace7("file-temp-diff:delete:failed(catch)", file);
|
|
851
|
-
console.error(`\u274C Error deleting temp file for ${file}:`,
|
|
1077
|
+
} catch (cleanupError) {
|
|
1078
|
+
trace7("file-temp-diff:delete:failed(catch)", `${file} | ${getErrorSummary(cleanupError)}`);
|
|
1079
|
+
console.error(`\u274C Error deleting temp file for ${file}:`, cleanupError);
|
|
852
1080
|
}
|
|
853
1081
|
}
|
|
854
1082
|
});
|
|
@@ -867,12 +1095,44 @@ ${err}
|
|
|
867
1095
|
trace7("cleanup-temp-diff:done");
|
|
868
1096
|
trace7("review-flow:end");
|
|
869
1097
|
} catch (error) {
|
|
870
|
-
trace7("review-flow:catch");
|
|
1098
|
+
trace7("review-flow:catch", getErrorSummary(error));
|
|
1099
|
+
let errorReportPath = "";
|
|
1100
|
+
trace7("cleanup-temp-diff:start(catch)");
|
|
1101
|
+
try {
|
|
1102
|
+
deleteTempDiff();
|
|
1103
|
+
trace7("cleanup-temp-diff:done(catch)");
|
|
1104
|
+
} catch (cleanupError) {
|
|
1105
|
+
trace7("cleanup-temp-diff:failed(catch)", getErrorSummary(cleanupError));
|
|
1106
|
+
console.error("\u26A0\uFE0F \uC784\uC2DC diff \uC815\uB9AC \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.");
|
|
1107
|
+
console.error(cleanupError);
|
|
1108
|
+
}
|
|
1109
|
+
trace7("error-report:prepare", `service=${service || "unknown"}`);
|
|
1110
|
+
errorReportPath = writeErrorReport(error, {
|
|
1111
|
+
scope: "review-one-by-one",
|
|
1112
|
+
args: args4,
|
|
1113
|
+
extraSections: [
|
|
1114
|
+
{
|
|
1115
|
+
heading: "Execution Context",
|
|
1116
|
+
markdown: `\`\`\`json
|
|
1117
|
+
${JSON.stringify(
|
|
1118
|
+
{
|
|
1119
|
+
service: service || null,
|
|
1120
|
+
tempDiffPath,
|
|
1121
|
+
savedDiffPath: savedDiffPath || null,
|
|
1122
|
+
savedReportPath: savedReportPath || null
|
|
1123
|
+
},
|
|
1124
|
+
null,
|
|
1125
|
+
2
|
|
1126
|
+
)}
|
|
1127
|
+
\`\`\``
|
|
1128
|
+
}
|
|
1129
|
+
]
|
|
1130
|
+
});
|
|
871
1131
|
console.error("\u274C \uB9AC\uBDF0 \uB3C4\uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.");
|
|
872
1132
|
console.error(error);
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
1133
|
+
if (errorReportPath) {
|
|
1134
|
+
console.error(`\u{1F4C4} \uC5D0\uB7EC \uB85C\uADF8 \uC800\uC7A5 \uC704\uCE58: ${errorReportPath}`);
|
|
1135
|
+
}
|
|
876
1136
|
process.exit(1);
|
|
877
1137
|
}
|
|
878
1138
|
}
|