sales-frontend-gemini-cli 0.4.2 → 0.4.3
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 +464 -52
- package/dist/common/helper.cjs.map +1 -1
- package/dist/common/helper.d.cts +85 -3
- package/dist/common/helper.d.ts +85 -3
- package/dist/common/helper.js +455 -53
- package/dist/common/helper.js.map +1 -1
- package/dist/common/types.d.cts +24 -1
- package/dist/common/types.d.ts +24 -1
- package/dist/pr-review/claude/claude-commander.cjs +50 -9
- package/dist/pr-review/claude/claude-commander.cjs.map +1 -1
- package/dist/pr-review/claude/claude-commander.js +50 -9
- package/dist/pr-review/claude/claude-commander.js.map +1 -1
- package/dist/pr-review/claude/installation-claude.cjs +41 -5
- package/dist/pr-review/claude/installation-claude.cjs.map +1 -1
- package/dist/pr-review/claude/installation-claude.js +41 -5
- package/dist/pr-review/claude/installation-claude.js.map +1 -1
- package/dist/pr-review/codex/codex-commander.cjs +49 -8
- package/dist/pr-review/codex/codex-commander.cjs.map +1 -1
- package/dist/pr-review/codex/codex-commander.js +49 -8
- package/dist/pr-review/codex/codex-commander.js.map +1 -1
- package/dist/pr-review/codex/installation-codex.cjs +41 -5
- package/dist/pr-review/codex/installation-codex.cjs.map +1 -1
- package/dist/pr-review/codex/installation-codex.js +41 -5
- package/dist/pr-review/codex/installation-codex.js.map +1 -1
- package/dist/pr-review/gemini/gemini-commander.cjs +75 -15
- package/dist/pr-review/gemini/gemini-commander.cjs.map +1 -1
- package/dist/pr-review/gemini/gemini-commander.js +75 -15
- package/dist/pr-review/gemini/gemini-commander.js.map +1 -1
- package/dist/pr-review/gemini/installation-gemini.cjs +41 -5
- package/dist/pr-review/gemini/installation-gemini.cjs.map +1 -1
- package/dist/pr-review/gemini/installation-gemini.js +41 -5
- package/dist/pr-review/gemini/installation-gemini.js.map +1 -1
- package/dist/pr-review/review-one-by-one.cjs +489 -95
- package/dist/pr-review/review-one-by-one.cjs.map +1 -1
- package/dist/pr-review/review-one-by-one.js +490 -96
- package/dist/pr-review/review-one-by-one.js.map +1 -1
- package/dist/pr-review/review.cjs +517 -94
- package/dist/pr-review/review.cjs.map +1 -1
- package/dist/pr-review/review.js +517 -94
- package/dist/pr-review/review.js.map +1 -1
- package/package.json +4 -7
- package/src/common/rules/coding-convention.md +393 -0
- package/src/common/rules/coding-convention.pdf +0 -0
- package/src/common/rules/naming-rule.md +347 -0
- package/src/common/rules/naming-rule.pdf +0 -0
|
@@ -18,14 +18,52 @@ 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
20
|
var traceMessages = [];
|
|
21
|
-
var
|
|
22
|
-
var
|
|
23
|
-
|
|
24
|
-
path__default.default.
|
|
25
|
-
|
|
21
|
+
var GEMINI_CLI_PACKAGE_NAME = "sales-frontend-gemini-cli";
|
|
22
|
+
var cachedPackageRootPath = "";
|
|
23
|
+
function isGeminiCliPackageRoot(directory) {
|
|
24
|
+
const packageJsonPath = path__default.default.join(directory, "package.json");
|
|
25
|
+
if (!fs__default.default.existsSync(packageJsonPath)) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
const packageJson = JSON.parse(fs__default.default.readFileSync(packageJsonPath, "utf8"));
|
|
30
|
+
return packageJson.name === GEMINI_CLI_PACKAGE_NAME;
|
|
31
|
+
} catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function resolveGeminiCliPackageRoot(startDirectory = __dirname$1) {
|
|
36
|
+
if (cachedPackageRootPath) {
|
|
37
|
+
return cachedPackageRootPath;
|
|
38
|
+
}
|
|
39
|
+
let currentDirectory = startDirectory;
|
|
40
|
+
while (true) {
|
|
41
|
+
if (isGeminiCliPackageRoot(currentDirectory)) {
|
|
42
|
+
cachedPackageRootPath = currentDirectory;
|
|
43
|
+
return cachedPackageRootPath;
|
|
44
|
+
}
|
|
45
|
+
const parentDirectory = path__default.default.dirname(currentDirectory);
|
|
46
|
+
if (parentDirectory === currentDirectory) {
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
currentDirectory = parentDirectory;
|
|
50
|
+
}
|
|
51
|
+
cachedPackageRootPath = path__default.default.resolve(startDirectory, "../..");
|
|
52
|
+
return cachedPackageRootPath;
|
|
53
|
+
}
|
|
54
|
+
function resolvePackageAssetPath(relativeFilePath) {
|
|
55
|
+
return path__default.default.resolve(resolveGeminiCliPackageRoot(), relativeFilePath);
|
|
56
|
+
}
|
|
57
|
+
var rulesPath = resolvePackageAssetPath("src/common/rules/review-rules.md");
|
|
58
|
+
var namingRulesPath = resolvePackageAssetPath("src/common/rules/naming-rule.md");
|
|
59
|
+
var codingConventionRulesPath = resolvePackageAssetPath("src/common/rules/coding-convention.md");
|
|
60
|
+
resolvePackageAssetPath("src/common/form/review-form.md");
|
|
61
|
+
var reviewFormOneByOnePath = resolvePackageAssetPath("src/common/form/review-form-one-by-one.md");
|
|
26
62
|
var REPORT_DIR = ".review-report";
|
|
27
63
|
var tempDiffPath = "temp_diff.txt";
|
|
28
64
|
var AIServices = ["gemini", "claude", "codex"];
|
|
65
|
+
var COMMIT_FETCH_LIMIT = 20;
|
|
66
|
+
var COMMIT_SELECTION_WINDOW = 8;
|
|
29
67
|
var ignoreList = [
|
|
30
68
|
"package.json",
|
|
31
69
|
"*.yml",
|
|
@@ -49,6 +87,137 @@ function clearTraceMessages() {
|
|
|
49
87
|
function getTraceMessages() {
|
|
50
88
|
return [...traceMessages];
|
|
51
89
|
}
|
|
90
|
+
var ANSI = {
|
|
91
|
+
bold: "\x1B[1m",
|
|
92
|
+
cyan: "\x1B[36m",
|
|
93
|
+
dim: "\x1B[2m",
|
|
94
|
+
green: "\x1B[32m",
|
|
95
|
+
reset: "\x1B[0m",
|
|
96
|
+
yellow: "\x1B[33m"
|
|
97
|
+
};
|
|
98
|
+
var ANSI_PATTERN = new RegExp(`${String.fromCharCode(27)}\\[[0-9;]*m`, "g");
|
|
99
|
+
var COMBINING_MARK_PATTERN = /\p{Mark}/u;
|
|
100
|
+
var GRAPHEME_SEGMENTER = typeof Intl !== "undefined" && "Segmenter" in Intl ? new Intl.Segmenter("ko", { granularity: "grapheme" }) : null;
|
|
101
|
+
function getGitDiffPathspecs() {
|
|
102
|
+
return {
|
|
103
|
+
excludePatterns: ignoreList.map((item) => `:(exclude)${item}`),
|
|
104
|
+
includePatterns: ["*.ts", "*.tsx", "*.js", "*.jsx"]
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function segmentGraphemes(value) {
|
|
108
|
+
if (!GRAPHEME_SEGMENTER) {
|
|
109
|
+
return [...value];
|
|
110
|
+
}
|
|
111
|
+
return [...GRAPHEME_SEGMENTER.segment(value)].map(({ segment }) => segment);
|
|
112
|
+
}
|
|
113
|
+
function isWideCodePoint(codePoint) {
|
|
114
|
+
return codePoint >= 4352 && (codePoint <= 4447 || codePoint === 9001 || codePoint === 9002 || codePoint >= 11904 && codePoint <= 12871 && codePoint !== 12351 || codePoint >= 12880 && codePoint <= 19903 || codePoint >= 19968 && codePoint <= 42182 || codePoint >= 43360 && codePoint <= 43388 || codePoint >= 44032 && codePoint <= 55203 || codePoint >= 63744 && codePoint <= 64255 || codePoint >= 65040 && codePoint <= 65049 || codePoint >= 65072 && codePoint <= 65131 || codePoint >= 65281 && codePoint <= 65376 || codePoint >= 65504 && codePoint <= 65510 || codePoint >= 127488 && codePoint <= 127569 || codePoint >= 131072 && codePoint <= 262141);
|
|
115
|
+
}
|
|
116
|
+
function isEmojiCodePoint(codePoint) {
|
|
117
|
+
return codePoint >= 127462 && codePoint <= 127487 || codePoint >= 127744 && codePoint <= 129791 || codePoint >= 9728 && codePoint <= 10175;
|
|
118
|
+
}
|
|
119
|
+
function getGraphemeWidth(grapheme) {
|
|
120
|
+
let width = 0;
|
|
121
|
+
for (const character of grapheme) {
|
|
122
|
+
const codePoint = character.codePointAt(0);
|
|
123
|
+
if (!codePoint || COMBINING_MARK_PATTERN.test(character) || codePoint === 8205) {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
if (codePoint >= 65024 && codePoint <= 65039 || codePoint >= 917760 && codePoint <= 917999) {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (isWideCodePoint(codePoint) || isEmojiCodePoint(codePoint)) {
|
|
130
|
+
width = Math.max(width, 2);
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
width = Math.max(width, 1);
|
|
134
|
+
}
|
|
135
|
+
return width;
|
|
136
|
+
}
|
|
137
|
+
function tokenizePlainText(value) {
|
|
138
|
+
return segmentGraphemes(value).map((segment) => ({
|
|
139
|
+
value: segment,
|
|
140
|
+
visibleWidth: getGraphemeWidth(segment)
|
|
141
|
+
}));
|
|
142
|
+
}
|
|
143
|
+
function tokenizeVisibleText(value) {
|
|
144
|
+
const tokens = [];
|
|
145
|
+
let lastIndex = 0;
|
|
146
|
+
for (const match of value.matchAll(ANSI_PATTERN)) {
|
|
147
|
+
const index = match.index ?? 0;
|
|
148
|
+
if (index > lastIndex) {
|
|
149
|
+
tokens.push(...tokenizePlainText(value.slice(lastIndex, index)));
|
|
150
|
+
}
|
|
151
|
+
tokens.push({
|
|
152
|
+
value: match[0],
|
|
153
|
+
visibleWidth: 0
|
|
154
|
+
});
|
|
155
|
+
lastIndex = index + match[0].length;
|
|
156
|
+
}
|
|
157
|
+
if (lastIndex < value.length) {
|
|
158
|
+
tokens.push(...tokenizePlainText(value.slice(lastIndex)));
|
|
159
|
+
}
|
|
160
|
+
return tokens;
|
|
161
|
+
}
|
|
162
|
+
function truncateLineForTerminal(value, maxWidth) {
|
|
163
|
+
if (maxWidth <= 0) {
|
|
164
|
+
return "";
|
|
165
|
+
}
|
|
166
|
+
const tokens = tokenizeVisibleText(value);
|
|
167
|
+
const totalWidth = tokens.reduce((sum, token) => sum + token.visibleWidth, 0);
|
|
168
|
+
if (totalWidth <= maxWidth) {
|
|
169
|
+
return value;
|
|
170
|
+
}
|
|
171
|
+
const ellipsis = "...";
|
|
172
|
+
const ellipsisWidth = 3;
|
|
173
|
+
const targetWidth = Math.max(0, maxWidth - ellipsisWidth);
|
|
174
|
+
let usedWidth = 0;
|
|
175
|
+
let result = "";
|
|
176
|
+
for (const token of tokens) {
|
|
177
|
+
if (token.visibleWidth === 0) {
|
|
178
|
+
result += token.value;
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
if (usedWidth + token.visibleWidth > targetWidth) {
|
|
182
|
+
break;
|
|
183
|
+
}
|
|
184
|
+
result += token.value;
|
|
185
|
+
usedWidth += token.visibleWidth;
|
|
186
|
+
}
|
|
187
|
+
return `${result}${ellipsis}${ANSI.reset}`;
|
|
188
|
+
}
|
|
189
|
+
function fitLinesToTerminal(lines) {
|
|
190
|
+
const maxWidth = Math.max(20, (process.stdout.columns || 120) - 1);
|
|
191
|
+
return lines.map((line) => truncateLineForTerminal(line, maxWidth));
|
|
192
|
+
}
|
|
193
|
+
function runGitCommand(args4, options = {}) {
|
|
194
|
+
const { allowFailure = false, trimOutput = true } = options;
|
|
195
|
+
try {
|
|
196
|
+
const output = child_process.execFileSync("git", args4, {
|
|
197
|
+
encoding: "utf8",
|
|
198
|
+
maxBuffer: 1024 * 1024 * 20,
|
|
199
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
200
|
+
});
|
|
201
|
+
return trimOutput ? output.trim() : output;
|
|
202
|
+
} catch (error) {
|
|
203
|
+
helperTrace("git-command:failed", `${args4.join(" ")} | ${getErrorSummary(error)}`);
|
|
204
|
+
if (allowFailure) {
|
|
205
|
+
return "";
|
|
206
|
+
}
|
|
207
|
+
throw error;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
function formatReviewTargetFiles(files, visibleCount = 5) {
|
|
211
|
+
if (files.length === 0) {
|
|
212
|
+
return "(\uC5C6\uC74C)";
|
|
213
|
+
}
|
|
214
|
+
const visibleFiles = files.slice(0, visibleCount);
|
|
215
|
+
const hiddenCount = Math.max(0, files.length - visibleFiles.length);
|
|
216
|
+
if (hiddenCount === 0) {
|
|
217
|
+
return visibleFiles.join(", ");
|
|
218
|
+
}
|
|
219
|
+
return `${visibleFiles.join(", ")} \uC678 ${hiddenCount}\uAC1C`;
|
|
220
|
+
}
|
|
52
221
|
function createTraceLogger(scope, args4 = process.argv.slice(2)) {
|
|
53
222
|
const enabled = isTestMode(args4);
|
|
54
223
|
return (step, detail) => {
|
|
@@ -260,13 +429,83 @@ ${JSON.stringify(AIServices, null, 2)}
|
|
|
260
429
|
}
|
|
261
430
|
);
|
|
262
431
|
}
|
|
263
|
-
function
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
432
|
+
function truncateCommitSubject(subject) {
|
|
433
|
+
if (subject.length <= 72) {
|
|
434
|
+
return subject;
|
|
435
|
+
}
|
|
436
|
+
return `${subject.slice(0, 69)}...`;
|
|
437
|
+
}
|
|
438
|
+
function getRecentCommitOptions() {
|
|
439
|
+
const output = runGitCommand(
|
|
440
|
+
["log", `-${COMMIT_FETCH_LIMIT}`, "--date=relative", "--pretty=format:%h%x09%an%x09%ar%x09%s"],
|
|
441
|
+
{ allowFailure: true }
|
|
442
|
+
);
|
|
443
|
+
if (!output) {
|
|
444
|
+
return [];
|
|
445
|
+
}
|
|
446
|
+
return output.split("\n").map((line) => {
|
|
447
|
+
const [hash = "", author = "", relativeDate = "", ...subjectParts] = line.split(" ");
|
|
448
|
+
const subject = subjectParts.join(" ").trim();
|
|
449
|
+
return {
|
|
450
|
+
author,
|
|
451
|
+
description: `${author} | ${relativeDate}`,
|
|
452
|
+
hash,
|
|
453
|
+
label: `${hash} | ${truncateCommitSubject(subject)}`,
|
|
454
|
+
relativeDate,
|
|
455
|
+
subject
|
|
456
|
+
};
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
function buildSelectedCommitSummary(commits) {
|
|
460
|
+
return commits.map((commit) => `- ${commit.hash} | ${commit.subject} | ${commit.author} | ${commit.relativeDate}`).join("\n");
|
|
461
|
+
}
|
|
462
|
+
function getReviewPathspecArgs() {
|
|
463
|
+
const { includePatterns, excludePatterns } = getGitDiffPathspecs();
|
|
464
|
+
return [...includePatterns, ...excludePatterns];
|
|
465
|
+
}
|
|
466
|
+
function buildSelectedCommitDiff(commits) {
|
|
467
|
+
const reviewPathspecArgs = getReviewPathspecArgs();
|
|
468
|
+
const sections = commits.map((commit) => {
|
|
469
|
+
const diff = runGitCommand(["show", "--stat", "--patch", "--format=", commit.hash, "--", ...reviewPathspecArgs], {
|
|
470
|
+
allowFailure: true,
|
|
471
|
+
trimOutput: false
|
|
472
|
+
}).trim();
|
|
473
|
+
if (!diff) {
|
|
474
|
+
return "";
|
|
475
|
+
}
|
|
476
|
+
return [`## ${commit.hash} ${commit.subject}`, diff].join("\n\n");
|
|
477
|
+
}).filter(Boolean).join("\n\n");
|
|
478
|
+
if (!sections) {
|
|
479
|
+
return "";
|
|
480
|
+
}
|
|
481
|
+
return ["# \uC120\uD0DD\uD55C \uCEE4\uBC0B", buildSelectedCommitSummary(commits), "", "# \uB9AC\uBDF0 \uB300\uC0C1 diff", sections].join("\n");
|
|
482
|
+
}
|
|
483
|
+
function getSelectedCommitFiles(commits) {
|
|
484
|
+
const reviewPathspecArgs = getReviewPathspecArgs();
|
|
485
|
+
const files = /* @__PURE__ */ new Set();
|
|
486
|
+
commits.forEach((commit) => {
|
|
487
|
+
const output = runGitCommand(["show", "--pretty=format:", "--name-only", commit.hash, "--", ...reviewPathspecArgs], {
|
|
488
|
+
allowFailure: true
|
|
489
|
+
});
|
|
490
|
+
output.split("\n").map((line) => line.trim()).filter(Boolean).forEach((filePath) => files.add(filePath));
|
|
491
|
+
});
|
|
492
|
+
return [...files];
|
|
493
|
+
}
|
|
494
|
+
function buildSelectedFileDiff(commits, filePath) {
|
|
495
|
+
const sections = commits.map((commit) => {
|
|
496
|
+
const diff = runGitCommand(["show", "--stat", "--patch", "--format=", commit.hash, "--", filePath], {
|
|
497
|
+
allowFailure: true,
|
|
498
|
+
trimOutput: false
|
|
499
|
+
}).trim();
|
|
500
|
+
if (!diff) {
|
|
501
|
+
return "";
|
|
502
|
+
}
|
|
503
|
+
return [`## ${commit.hash} ${commit.subject}`, diff].join("\n\n");
|
|
504
|
+
}).filter(Boolean).join("\n\n");
|
|
505
|
+
if (!sections) {
|
|
506
|
+
return "";
|
|
507
|
+
}
|
|
508
|
+
return ["# \uC120\uD0DD\uD55C \uCEE4\uBC0B", buildSelectedCommitSummary(commits), "", `# \uD30C\uC77C: ${filePath}`, sections].join("\n\n");
|
|
270
509
|
}
|
|
271
510
|
function openReport(reportPath) {
|
|
272
511
|
const resolvedPath = path__default.default.resolve(reportPath);
|
|
@@ -317,59 +556,166 @@ function openReport(reportPath) {
|
|
|
317
556
|
helperTrace("open-report:unsupported-platform", platform);
|
|
318
557
|
console.error(`\u26A0\uFE0F \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uD50C\uB7AB\uD3FC\uC785\uB2C8\uB2E4: ${platform}`);
|
|
319
558
|
}
|
|
320
|
-
function
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
helperTrace(
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
559
|
+
function ensureInteractiveSelectionAvailable(scope, message) {
|
|
560
|
+
if (process.stdin.isTTY && process.stdout.isTTY && typeof process.stdin.setRawMode === "function") {
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
helperTrace(`${scope}:tty-missing`);
|
|
564
|
+
exitWithError(message, {
|
|
565
|
+
scope: `helper:${scope}`
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
function renderSelectionBlock(lines, previousLineCount) {
|
|
569
|
+
if (previousLineCount > 0) {
|
|
570
|
+
readline__default.default.moveCursor(process.stdout, 0, -previousLineCount);
|
|
571
|
+
readline__default.default.clearScreenDown(process.stdout);
|
|
572
|
+
}
|
|
573
|
+
const fittedLines = fitLinesToTerminal(lines);
|
|
574
|
+
process.stdout.write(`${fittedLines.join("\n")}
|
|
575
|
+
`);
|
|
576
|
+
return fittedLines.length;
|
|
577
|
+
}
|
|
578
|
+
function getSelectionWindowRange(optionCount, selectedIndex, windowSize) {
|
|
579
|
+
if (optionCount <= windowSize) {
|
|
580
|
+
return {
|
|
581
|
+
end: optionCount,
|
|
582
|
+
start: 0
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
const halfWindow = Math.floor(windowSize / 2);
|
|
586
|
+
const maxStart = optionCount - windowSize;
|
|
587
|
+
const start = Math.max(0, Math.min(selectedIndex - halfWindow, maxStart));
|
|
588
|
+
return {
|
|
589
|
+
end: Math.min(optionCount, start + windowSize),
|
|
590
|
+
start
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
function buildMultiSelectLines(question, options, selectedIndex, toggled, windowSize) {
|
|
594
|
+
const { start, end } = getSelectionWindowRange(options.length, selectedIndex, windowSize);
|
|
595
|
+
const lines = [
|
|
596
|
+
`${ANSI.bold}${question}${ANSI.reset}`,
|
|
597
|
+
`${ANSI.dim}\u2191\u2193 \uC774\uB3D9 | Space \uC120\uD0DD/\uD574\uC81C | Enter \uC644\uB8CC | Esc \uCDE8\uC18C${ANSI.reset}`,
|
|
598
|
+
`${ANSI.dim}\uC120\uD0DD\uB428: ${toggled.size}\uAC1C / \uC804\uCCB4: ${options.length}\uAC1C${ANSI.reset}`
|
|
599
|
+
];
|
|
600
|
+
for (let index = start; index < end; index += 1) {
|
|
601
|
+
const option = options[index];
|
|
602
|
+
if (!option) {
|
|
603
|
+
continue;
|
|
334
604
|
}
|
|
335
|
-
const
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
605
|
+
const cursor = index === selectedIndex ? `${ANSI.cyan}>${ANSI.reset}` : " ";
|
|
606
|
+
const checked = toggled.has(index) ? `${ANSI.green}\u2611${ANSI.reset}` : "\u2610";
|
|
607
|
+
const description = option.description ? ` ${ANSI.dim}${option.description}${ANSI.reset}` : "";
|
|
608
|
+
lines.push(`${cursor} ${checked} ${option.label}${description}`);
|
|
609
|
+
}
|
|
610
|
+
if (options.length > windowSize) {
|
|
611
|
+
lines.push(`${ANSI.dim}\uD45C\uC2DC \uBC94\uC704: ${start + 1}-${end} / ${options.length}${ANSI.reset}`);
|
|
612
|
+
}
|
|
613
|
+
return lines;
|
|
614
|
+
}
|
|
615
|
+
async function showMultiSelect(question, options, windowSize = COMMIT_SELECTION_WINDOW) {
|
|
616
|
+
ensureInteractiveSelectionAvailable("showMultiSelect", "\u274C \uCEE4\uBC0B \uC120\uD0DD \uBAA8\uB2EC\uC740 TTY \uD658\uACBD\uC5D0\uC11C\uB9CC \uC0AC\uC6A9\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.");
|
|
617
|
+
let selectedIndex = 0;
|
|
618
|
+
let renderedLineCount = 0;
|
|
619
|
+
const toggled = /* @__PURE__ */ new Set();
|
|
620
|
+
const rl = readline__default.default.createInterface({
|
|
621
|
+
input: process.stdin,
|
|
622
|
+
output: process.stdout,
|
|
623
|
+
terminal: true
|
|
624
|
+
});
|
|
625
|
+
process.stdout.write("\x1B[?25l");
|
|
626
|
+
const cleanup = () => {
|
|
627
|
+
if (renderedLineCount > 0) {
|
|
628
|
+
readline__default.default.moveCursor(process.stdout, 0, -renderedLineCount);
|
|
629
|
+
readline__default.default.clearScreenDown(process.stdout);
|
|
630
|
+
renderedLineCount = 0;
|
|
342
631
|
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
632
|
+
process.stdin.removeListener("data", onData);
|
|
633
|
+
process.stdin.setRawMode(false);
|
|
634
|
+
process.stdin.pause();
|
|
635
|
+
rl.close();
|
|
636
|
+
process.stdout.write("\x1B[?25h");
|
|
637
|
+
};
|
|
638
|
+
const render = () => {
|
|
639
|
+
const lines = buildMultiSelectLines(question, options, selectedIndex, toggled, windowSize);
|
|
640
|
+
renderedLineCount = renderSelectionBlock(lines, renderedLineCount);
|
|
641
|
+
};
|
|
642
|
+
const confirmSelection = (resolve) => {
|
|
643
|
+
const values = [...toggled].sort((left, right) => left - right).map((index) => options[index]?.value).filter((value) => value !== void 0);
|
|
644
|
+
cleanup();
|
|
645
|
+
resolve(values);
|
|
646
|
+
};
|
|
647
|
+
const cancelSelection = (resolve) => {
|
|
648
|
+
cleanup();
|
|
649
|
+
resolve([]);
|
|
650
|
+
};
|
|
651
|
+
let onData = (_data) => {
|
|
652
|
+
};
|
|
653
|
+
render();
|
|
654
|
+
return new Promise((resolve) => {
|
|
655
|
+
onData = (data) => {
|
|
656
|
+
const key = data.toString();
|
|
657
|
+
if (key === "") {
|
|
658
|
+
cleanup();
|
|
659
|
+
process.exit(0);
|
|
356
660
|
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
661
|
+
if (key === "\x1B") {
|
|
662
|
+
cancelSelection(resolve);
|
|
663
|
+
return;
|
|
664
|
+
}
|
|
665
|
+
if (key === "\x1B[A") {
|
|
666
|
+
selectedIndex = (selectedIndex - 1 + options.length) % options.length;
|
|
667
|
+
render();
|
|
668
|
+
return;
|
|
669
|
+
}
|
|
670
|
+
if (key === "\x1B[B") {
|
|
671
|
+
selectedIndex = (selectedIndex + 1) % options.length;
|
|
672
|
+
render();
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
675
|
+
if (key === " ") {
|
|
676
|
+
if (toggled.has(selectedIndex)) {
|
|
677
|
+
toggled.delete(selectedIndex);
|
|
678
|
+
} else {
|
|
679
|
+
toggled.add(selectedIndex);
|
|
680
|
+
}
|
|
681
|
+
render();
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
if (key === "\r" || key === "\n") {
|
|
685
|
+
confirmSelection(resolve);
|
|
686
|
+
}
|
|
687
|
+
};
|
|
688
|
+
process.stdin.setRawMode(true);
|
|
689
|
+
process.stdin.resume();
|
|
690
|
+
process.stdin.on("data", onData);
|
|
691
|
+
});
|
|
692
|
+
}
|
|
693
|
+
async function selectReviewCommits() {
|
|
694
|
+
const commits = getRecentCommitOptions();
|
|
695
|
+
if (commits.length === 0) {
|
|
696
|
+
console.log("\u2139\uFE0F \uB9AC\uBDF0\uD560 \uCD5C\uADFC \uCEE4\uBC0B\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.");
|
|
697
|
+
return [];
|
|
360
698
|
}
|
|
361
|
-
|
|
362
|
-
|
|
699
|
+
return showMultiSelect(
|
|
700
|
+
"\uB9AC\uBDF0\uD560 \uCEE4\uBC0B\uC744 \uC120\uD0DD\uD574\uC8FC\uC138\uC694.",
|
|
701
|
+
commits.map((commit) => ({
|
|
702
|
+
description: commit.description,
|
|
703
|
+
label: commit.label,
|
|
704
|
+
value: commit
|
|
705
|
+
})),
|
|
706
|
+
COMMIT_SELECTION_WINDOW
|
|
707
|
+
);
|
|
363
708
|
}
|
|
364
709
|
async function showSelectionAIService() {
|
|
365
710
|
const selectedServiceFromArgs = parseServiceFromArgs();
|
|
366
711
|
if (selectedServiceFromArgs) {
|
|
367
712
|
helperTrace("show-selection:from-args", selectedServiceFromArgs);
|
|
368
713
|
console.log(`
|
|
369
|
-
\u2705
|
|
714
|
+
\u2705 ${ANSI.green}${selectedServiceFromArgs}${ANSI.reset} \uC11C\uBE44\uC2A4\uAC00 \uC120\uD0DD\uB418\uC5C8\uC2B5\uB2C8\uB2E4. (--service)
|
|
370
715
|
`);
|
|
371
716
|
return selectedServiceFromArgs;
|
|
372
717
|
}
|
|
718
|
+
ensureInteractiveSelectionAvailable("showSelectionAIService", "\u274C AI \uC11C\uBE44\uC2A4 \uC120\uD0DD UI\uB294 TTY \uD658\uACBD\uC5D0\uC11C\uB9CC \uC0AC\uC6A9\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.");
|
|
373
719
|
helperTrace("show-selection:interactive:start");
|
|
374
720
|
let selectedIndex = 0;
|
|
375
721
|
const rl = readline__default.default.createInterface({
|
|
@@ -387,11 +733,12 @@ async function showSelectionAIService() {
|
|
|
387
733
|
helperTrace("show-selection:interactive:render", AIServices[selectedIndex] || "unknown");
|
|
388
734
|
readline__default.default.clearScreenDown(process.stdout);
|
|
389
735
|
process.stdout.write(
|
|
390
|
-
|
|
736
|
+
`\u{1F916} AI \uC11C\uBE44\uC2A4\uB97C \uC120\uD0DD\uD574\uC8FC\uC138\uC694 (${ANSI.yellow}\u2191\u2193 \uBC29\uD5A5\uD0A4${ANSI.reset} \uC774\uB3D9, ${ANSI.yellow}Enter${ANSI.reset} \uC120\uD0DD):
|
|
737
|
+
`
|
|
391
738
|
);
|
|
392
739
|
AIServices.forEach((service, index) => {
|
|
393
740
|
if (index === selectedIndex) {
|
|
394
|
-
process.stdout.write(`
|
|
741
|
+
process.stdout.write(` ${ANSI.cyan}>${ANSI.reset} ${ANSI.cyan}\u25C9${ANSI.reset} ${ANSI.bold}${service}${ANSI.reset}
|
|
395
742
|
`);
|
|
396
743
|
} else {
|
|
397
744
|
process.stdout.write(` \u25EF ${service}
|
|
@@ -421,7 +768,7 @@ async function showSelectionAIService() {
|
|
|
421
768
|
rl.close();
|
|
422
769
|
process.stdout.write("\x1B[?25h");
|
|
423
770
|
console.log(`
|
|
424
|
-
\u2705
|
|
771
|
+
\u2705 ${ANSI.green}${AIServices[selectedIndex]}${ANSI.reset} \uC11C\uBE44\uC2A4\uAC00 \uC120\uD0DD\uB418\uC5C8\uC2B5\uB2C8\uB2E4.
|
|
425
772
|
`);
|
|
426
773
|
const result = AIServices[selectedIndex];
|
|
427
774
|
if (result) {
|
|
@@ -448,6 +795,11 @@ function getArgValue(flag) {
|
|
|
448
795
|
}
|
|
449
796
|
return args[index + 1];
|
|
450
797
|
}
|
|
798
|
+
function printNotice(message) {
|
|
799
|
+
if (args.includes("--test")) {
|
|
800
|
+
console.warn(message);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
451
803
|
function toUnique(values) {
|
|
452
804
|
const seen = /* @__PURE__ */ new Set();
|
|
453
805
|
return values.filter((value) => {
|
|
@@ -471,11 +823,11 @@ function resolveReasoningEffort() {
|
|
|
471
823
|
const normalized = normalizeEffort(customReasoningEffort);
|
|
472
824
|
trace("reasoning:custom", `${customReasoningEffort} -> ${normalized}`);
|
|
473
825
|
if (customReasoningEffort === "minimal") {
|
|
474
|
-
|
|
826
|
+
printNotice("\u26A0\uFE0F Claude\uB294 minimal\uC744 \uC9C1\uC811 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC544 low\uB85C \uB9E4\uD551\uD569\uB2C8\uB2E4.");
|
|
475
827
|
}
|
|
476
828
|
return normalized;
|
|
477
829
|
}
|
|
478
|
-
|
|
830
|
+
printNotice(
|
|
479
831
|
`\u26A0\uFE0F \uC9C0\uC6D0\uB418\uC9C0 \uC54A\uB294 reasoning effort(${customReasoningEffort})\uC785\uB2C8\uB2E4. allowed: ${ALLOWED_REASONING_EFFORTS.join(
|
|
480
832
|
", "
|
|
481
833
|
)}`
|
|
@@ -518,7 +870,7 @@ function buildClaudeExecCommand(options) {
|
|
|
518
870
|
const modelOption = model ? `--model ${shellQuote(model)}` : "";
|
|
519
871
|
const fallbackOption = model && fallbackModel ? `--fallback-model ${shellQuote(fallbackModel)}` : "";
|
|
520
872
|
const effortOption = `--effort ${shellQuote(effort)}`;
|
|
521
|
-
const appendedPromptFiles = systemPromptFiles.map((
|
|
873
|
+
const appendedPromptFiles = systemPromptFiles.map((path3) => `--append-system-prompt-file ${shellQuote(path3)}`).join(" ");
|
|
522
874
|
return `cat ${shellQuote(tempDiffPath2)} | claude ${[
|
|
523
875
|
modelOption,
|
|
524
876
|
fallbackOption,
|
|
@@ -551,13 +903,13 @@ var createClaudeCommand = (tempDiffPath2, reviewFormPath2) => {
|
|
|
551
903
|
trace("model:candidates", modelCandidates.join(", "));
|
|
552
904
|
trace("command:candidates:count", String(modelCandidates.length + 1));
|
|
553
905
|
if (customModel) {
|
|
554
|
-
|
|
906
|
+
printNotice(
|
|
555
907
|
`\u26A0\uFE0F \uCEE4\uC2A4\uD140 \uBAA8\uB378(${customModel})\uC744 \uC6B0\uC120 \uC2DC\uB3C4\uD558\uACE0 \uC2E4\uD328\uD558\uBA74 alias(${aliasFallbacks.join(
|
|
556
908
|
" -> "
|
|
557
909
|
)}) \uBC0F \uAE30\uBCF8 \uBAA8\uB378 \uC21C\uC73C\uB85C \uD3F4\uBC31\uD569\uB2C8\uB2E4.`
|
|
558
910
|
);
|
|
559
911
|
} else {
|
|
560
|
-
|
|
912
|
+
printNotice(
|
|
561
913
|
`\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.`
|
|
562
914
|
);
|
|
563
915
|
}
|
|
@@ -637,6 +989,11 @@ function getArgValue2(flag) {
|
|
|
637
989
|
}
|
|
638
990
|
return args2[index + 1];
|
|
639
991
|
}
|
|
992
|
+
function printNotice2(message) {
|
|
993
|
+
if (args2.includes("--test")) {
|
|
994
|
+
console.warn(message);
|
|
995
|
+
}
|
|
996
|
+
}
|
|
640
997
|
function resolveReasoningEffort2() {
|
|
641
998
|
const customReasoningEffort = getArgValue2("--reasoning-effort");
|
|
642
999
|
if (customReasoningEffort) {
|
|
@@ -644,7 +1001,7 @@ function resolveReasoningEffort2() {
|
|
|
644
1001
|
trace3("reasoning:custom", customReasoningEffort);
|
|
645
1002
|
return customReasoningEffort;
|
|
646
1003
|
}
|
|
647
|
-
|
|
1004
|
+
printNotice2(
|
|
648
1005
|
`\u26A0\uFE0F \uC9C0\uC6D0\uB418\uC9C0 \uC54A\uB294 reasoning effort(${customReasoningEffort})\uC785\uB2C8\uB2E4. allowed: ${ALLOWED_REASONING_EFFORTS2.join(
|
|
649
1006
|
", "
|
|
650
1007
|
)}`
|
|
@@ -688,14 +1045,14 @@ ${reviewFormLine || "- (\uC5C6\uC74C)"}
|
|
|
688
1045
|
trace3("prompt:prepared", `length=${prompt.length}`);
|
|
689
1046
|
let command = "";
|
|
690
1047
|
if (customModel) {
|
|
691
|
-
|
|
1048
|
+
printNotice2("\u26A0\uFE0F \uC9C0\uC815\uD55C \uBAA8\uB378\uC774 \uC5C6\uB294 \uACBD\uC6B0, \uC5D0\uB7EC\uAC00 \uBC1C\uC0DD\uD558\uB2C8 \uC8FC\uC758\uD558\uC138\uC694.");
|
|
692
1049
|
trace3("model:custom", customModel);
|
|
693
1050
|
command = buildCodexExecCommand(prompt, reasoningEffort, customModel);
|
|
694
1051
|
} else {
|
|
695
1052
|
const preferredModelAlias = "gpt-5";
|
|
696
1053
|
const aliasCommand = buildCodexExecCommand(prompt, reasoningEffort, preferredModelAlias);
|
|
697
1054
|
const fallbackCommand = buildCodexExecCommand(prompt, reasoningEffort);
|
|
698
|
-
|
|
1055
|
+
printNotice2(
|
|
699
1056
|
`\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.`
|
|
700
1057
|
);
|
|
701
1058
|
trace3("model:alias-first", preferredModelAlias);
|
|
@@ -756,6 +1113,11 @@ function getArgValue3(flag) {
|
|
|
756
1113
|
}
|
|
757
1114
|
return args3[index + 1];
|
|
758
1115
|
}
|
|
1116
|
+
function printNotice3(message) {
|
|
1117
|
+
if (args3.includes("--test")) {
|
|
1118
|
+
console.warn(message);
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
759
1121
|
function toUnique2(values) {
|
|
760
1122
|
const seen = /* @__PURE__ */ new Set();
|
|
761
1123
|
return values.filter((value) => {
|
|
@@ -773,7 +1135,7 @@ function resolveReasoningEffort3() {
|
|
|
773
1135
|
trace5("reasoning:custom", customReasoningEffort);
|
|
774
1136
|
return customReasoningEffort;
|
|
775
1137
|
}
|
|
776
|
-
|
|
1138
|
+
printNotice3(
|
|
777
1139
|
`\u26A0\uFE0F \uC9C0\uC6D0\uB418\uC9C0 \uC54A\uB294 reasoning effort(${customReasoningEffort})\uC785\uB2C8\uB2E4. allowed: ${ALLOWED_REASONING_EFFORTS3.join(
|
|
778
1140
|
", "
|
|
779
1141
|
)}`
|
|
@@ -835,38 +1197,57 @@ function buildGeminiExecCommand(prompt, model) {
|
|
|
835
1197
|
const modelOption = model ? `--model ${shellQuote3(model)}` : "";
|
|
836
1198
|
return `gemini ${[modelOption, "-p", shellQuote3(prompt)].filter(Boolean).join(" ")}`;
|
|
837
1199
|
}
|
|
1200
|
+
function toGeminiFileReference(filePath) {
|
|
1201
|
+
return `@${filePath}`;
|
|
1202
|
+
}
|
|
1203
|
+
function buildGeminiFileReferenceSection(files) {
|
|
1204
|
+
const existingFiles = files.filter((file) => fs__default.default.existsSync(file.path));
|
|
1205
|
+
return {
|
|
1206
|
+
count: existingFiles.length,
|
|
1207
|
+
lines: existingFiles.map((file) => `- ${file.display}: ${toGeminiFileReference(file.path)}`)
|
|
1208
|
+
};
|
|
1209
|
+
}
|
|
838
1210
|
var createGeminiCommand = (tempDiffPath2, reviewFormPath2) => {
|
|
839
1211
|
trace5("createGeminiCommand:start", `tempDiffPath=${tempDiffPath2}, reviewFormPath=${reviewFormPath2}`);
|
|
840
1212
|
const customModel = getArgValue3("--model");
|
|
841
1213
|
const reasoningEffort = resolveReasoningEffort3();
|
|
842
1214
|
const primaryAlias = resolvePrimaryAlias2(reasoningEffort);
|
|
843
1215
|
const aliasFallbacks = toUnique2(getAliasFallbacks2(primaryAlias));
|
|
1216
|
+
const resolvedTempDiffPath = path__default.default.resolve(tempDiffPath2);
|
|
1217
|
+
const resolvedReviewFormPath = path__default.default.resolve(reviewFormPath2);
|
|
844
1218
|
const rules = [
|
|
845
1219
|
{ path: rulesPath, display: "\uB8F0\uC14B" },
|
|
846
1220
|
{ path: namingRulesPath, display: "\uB124\uC774\uBC0D \uADDC\uCE59" },
|
|
847
1221
|
{ path: codingConventionRulesPath, display: "\uCF54\uB529 \uCEE8\uBCA4\uC158" }
|
|
848
1222
|
];
|
|
849
|
-
const
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
const
|
|
853
|
-
trace5("reviewForm:status",
|
|
1223
|
+
const ruleSection = buildGeminiFileReferenceSection(rules);
|
|
1224
|
+
trace5("rules:loaded", `count=${ruleSection.count}`);
|
|
1225
|
+
const reviewFormExists = fs__default.default.existsSync(resolvedReviewFormPath);
|
|
1226
|
+
const reviewFormLine = reviewFormExists ? `- \uB9AC\uBDF0 \uC591\uC2DD: ${toGeminiFileReference(resolvedReviewFormPath)}` : "- \uB9AC\uBDF0 \uC591\uC2DD: (\uC5C6\uC74C)";
|
|
1227
|
+
trace5("reviewForm:status", reviewFormExists ? "exists" : "missing");
|
|
854
1228
|
const reasoningInstruction = getReasoningInstruction(reasoningEffort);
|
|
855
|
-
const prompt = `\
|
|
856
|
-
\
|
|
1229
|
+
const prompt = `\uC544\uB798 \uD30C\uC77C\uB4E4\uC744 \uC21C\uC11C\uB300\uB85C \uC77D\uACE0 \uCF54\uB4DC \uB9AC\uBDF0\uB97C \uC9C4\uD589\uD574\uC918.
|
|
1230
|
+
\uADDC\uCE59 \uD30C\uC77C:
|
|
1231
|
+
${ruleSection.lines.join("\n") || "- (\uC5C6\uC74C)"}
|
|
1232
|
+
\uB9AC\uBDF0 \uC591\uC2DD \uD30C\uC77C:
|
|
1233
|
+
${reviewFormLine}
|
|
1234
|
+
\uB9AC\uBDF0 \uB300\uC0C1 diff \uD30C\uC77C:
|
|
1235
|
+
- \uB9AC\uBDF0 \uB300\uC0C1 diff: ${toGeminiFileReference(resolvedTempDiffPath)}
|
|
1236
|
+
|
|
1237
|
+
\uBC18\uB4DC\uC2DC \uB9AC\uBDF0 \uC591\uC2DD\uC5D0 \uB9DE\uCDB0 \uC791\uC131\uD574\uC918.
|
|
857
1238
|
\uCD94\uB860 \uAC15\uB3C4 \uC9C0\uCE68: ${reasoningInstruction}`;
|
|
858
1239
|
trace5("prompt:prepared", `length=${prompt.length}`);
|
|
859
1240
|
const modelCandidates = toUnique2(customModel ? [customModel, ...aliasFallbacks] : aliasFallbacks);
|
|
860
1241
|
trace5("model:candidates", modelCandidates.join(", "));
|
|
861
1242
|
trace5("command:candidates:count", String(modelCandidates.length + 1));
|
|
862
1243
|
if (customModel) {
|
|
863
|
-
|
|
1244
|
+
printNotice3(
|
|
864
1245
|
`\u26A0\uFE0F \uCEE4\uC2A4\uD140 \uBAA8\uB378(${customModel})\uC744 \uC6B0\uC120 \uC2DC\uB3C4\uD558\uACE0 \uC2E4\uD328\uD558\uBA74 alias(${aliasFallbacks.join(
|
|
865
1246
|
" -> "
|
|
866
1247
|
)}) \uBC0F \uAE30\uBCF8 \uBAA8\uB378 \uC21C\uC73C\uB85C \uD3F4\uBC31\uD569\uB2C8\uB2E4.`
|
|
867
1248
|
);
|
|
868
1249
|
} else {
|
|
869
|
-
|
|
1250
|
+
printNotice3(
|
|
870
1251
|
`\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.`
|
|
871
1252
|
);
|
|
872
1253
|
}
|
|
@@ -925,6 +1306,7 @@ async function main() {
|
|
|
925
1306
|
let service = "";
|
|
926
1307
|
let savedDiffPath = "";
|
|
927
1308
|
let savedReportPath = "";
|
|
1309
|
+
let selectedCommitSummary = "";
|
|
928
1310
|
try {
|
|
929
1311
|
trace7("service-selection:start");
|
|
930
1312
|
service = await showSelectionAIService();
|
|
@@ -948,29 +1330,35 @@ async function main() {
|
|
|
948
1330
|
}
|
|
949
1331
|
trace7("review-flow:start");
|
|
950
1332
|
console.log("\u{1F680} AI Code Review\uB97C \uC2DC\uC791\uD569\uB2C8\uB2E4...");
|
|
951
|
-
trace7("
|
|
952
|
-
|
|
953
|
-
trace7("
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
1333
|
+
trace7("commit-selection:start");
|
|
1334
|
+
const selectedCommits = await selectReviewCommits();
|
|
1335
|
+
trace7("commit-selection:done", `count=${selectedCommits.length}`);
|
|
1336
|
+
if (selectedCommits.length === 0) {
|
|
1337
|
+
trace7("commit-selection:empty");
|
|
1338
|
+
console.log("\u2139\uFE0F \uC120\uD0DD\uB41C \uCEE4\uBC0B\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.");
|
|
1339
|
+
deleteTempDiff();
|
|
1340
|
+
process.exit(0);
|
|
1341
|
+
}
|
|
1342
|
+
selectedCommitSummary = buildSelectedCommitSummary(selectedCommits);
|
|
1343
|
+
trace7("commit-summary:prepared", selectedCommitSummary);
|
|
1344
|
+
console.log("\u23F3 \uC120\uD0DD\uD55C \uCEE4\uBC0B\uC758 \uD30C\uC77C \uBAA9\uB85D\uACFC diff\uB97C \uC815\uB9AC\uD558\uB294 \uC911\uC785\uB2C8\uB2E4...");
|
|
1345
|
+
trace7("files-command:run");
|
|
1346
|
+
const fileList = getSelectedCommitFiles(selectedCommits);
|
|
962
1347
|
trace7("files-command:done", `fileCount=${fileList.length}`);
|
|
1348
|
+
console.log(`\u{1F4C2} \uB9AC\uBDF0 \uB300\uC0C1 \uD30C\uC77C(${fileList.length}\uAC1C): ${formatReviewTargetFiles(fileList)}`);
|
|
963
1349
|
if (fileList.length === 0) {
|
|
964
1350
|
trace7("empty-file-list:exit");
|
|
965
|
-
console.log("\u2139\uFE0F \uBCC0\uACBD \
|
|
1351
|
+
console.log("\u2139\uFE0F \uC120\uD0DD\uD55C \uCEE4\uBC0B\uC5D0\uC11C \uB9AC\uBDF0 \uB300\uC0C1 \uD30C\uC77C \uBCC0\uACBD\uC744 \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.");
|
|
966
1352
|
deleteTempDiff();
|
|
967
1353
|
process.exit(0);
|
|
968
1354
|
}
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
1355
|
+
trace7("report-dir:create:start");
|
|
1356
|
+
createReportDirectory();
|
|
1357
|
+
trace7("report-dir:create:done");
|
|
1358
|
+
trace7("full-diff:build:start");
|
|
1359
|
+
const fullDiff = buildSelectedCommitDiff(selectedCommits);
|
|
972
1360
|
const nowStr = getNowString();
|
|
973
|
-
trace7("full-diff:done", `length=${fullDiff.length}`);
|
|
1361
|
+
trace7("full-diff:build:done", `length=${fullDiff.length}`);
|
|
974
1362
|
trace7("timestamp:created", nowStr);
|
|
975
1363
|
trace7("temp-diff:write:start", tempDiffPath);
|
|
976
1364
|
fs__default.default.writeFileSync(tempDiffPath, fullDiff);
|
|
@@ -981,15 +1369,19 @@ async function main() {
|
|
|
981
1369
|
trace7("saved-diff:copy:done", savedDiffPath);
|
|
982
1370
|
savedReportPath = getNextFilePath(REPORT_DIR, nowStr, ".md");
|
|
983
1371
|
trace7("saved-report:path", savedReportPath);
|
|
984
|
-
const promises = fileList.map(async (file) => {
|
|
1372
|
+
const promises = fileList.map(async (file, index) => {
|
|
985
1373
|
const tempOneFileDiffPath = `temp_diff_${file.replace(/\//g, "_")}.txt`;
|
|
986
1374
|
let command = "";
|
|
987
1375
|
try {
|
|
988
1376
|
trace7("file-review:start", file);
|
|
989
|
-
console.log(`\u{1F50D}
|
|
990
|
-
trace7("file-diff:
|
|
991
|
-
const fileDiff =
|
|
992
|
-
trace7("file-diff:done", `${file} | length=${fileDiff.length}`);
|
|
1377
|
+
console.log(`\u{1F50D} [${index + 1}/${fileList.length}] \uB9AC\uBDF0 \uC900\uBE44: ${file}`);
|
|
1378
|
+
trace7("file-diff:build:start", file);
|
|
1379
|
+
const fileDiff = buildSelectedFileDiff(selectedCommits, file);
|
|
1380
|
+
trace7("file-diff:build:done", `${file} | length=${fileDiff.length}`);
|
|
1381
|
+
if (!fileDiff.trim()) {
|
|
1382
|
+
trace7("file-diff:empty", file);
|
|
1383
|
+
return;
|
|
1384
|
+
}
|
|
993
1385
|
trace7("file-temp-diff:write:start", tempOneFileDiffPath);
|
|
994
1386
|
fs__default.default.writeFileSync(tempOneFileDiffPath, fileDiff);
|
|
995
1387
|
trace7("file-temp-diff:write:done", tempOneFileDiffPath);
|
|
@@ -1006,6 +1398,7 @@ async function main() {
|
|
|
1006
1398
|
break;
|
|
1007
1399
|
}
|
|
1008
1400
|
trace7("file-command:create:done", `${file} | commandLength=${command.length}`);
|
|
1401
|
+
console.log(`\u23F3 [${index + 1}/${fileList.length}] \uB9AC\uBDF0 \uC9C4\uD589: ${file}`);
|
|
1009
1402
|
trace7("file-command:exec:start", file);
|
|
1010
1403
|
const { stdout } = await execAsync(command, { maxBuffer: 1024 * 1024 * 20 });
|
|
1011
1404
|
const result = stdout.toString();
|
|
@@ -1017,7 +1410,6 @@ async function main() {
|
|
|
1017
1410
|
${result}
|
|
1018
1411
|
|
|
1019
1412
|
`;
|
|
1020
|
-
console.log(tempReport);
|
|
1021
1413
|
trace7("file-report:append:start", file);
|
|
1022
1414
|
fs__default.default.appendFileSync(savedReportPath, tempReport);
|
|
1023
1415
|
trace7("file-report:append:done", file);
|
|
@@ -1043,6 +1435,7 @@ ${command}`);
|
|
|
1043
1435
|
${JSON.stringify(
|
|
1044
1436
|
{
|
|
1045
1437
|
service,
|
|
1438
|
+
selectedCommitSummary: selectedCommitSummary || null,
|
|
1046
1439
|
file,
|
|
1047
1440
|
command: command || null,
|
|
1048
1441
|
tempOneFileDiffPath,
|
|
@@ -1117,6 +1510,7 @@ ${getErrorSummary(err)}
|
|
|
1117
1510
|
${JSON.stringify(
|
|
1118
1511
|
{
|
|
1119
1512
|
service: service || null,
|
|
1513
|
+
selectedCommitSummary: selectedCommitSummary || null,
|
|
1120
1514
|
tempDiffPath,
|
|
1121
1515
|
savedDiffPath: savedDiffPath || null,
|
|
1122
1516
|
savedReportPath: savedReportPath || null
|