sales-frontend-gemini-cli 0.4.3 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/common/helper.cjs +227 -20
- package/dist/common/helper.cjs.map +1 -1
- package/dist/common/helper.d.cts +30 -1
- package/dist/common/helper.d.ts +30 -1
- package/dist/common/helper.js +226 -21
- package/dist/common/helper.js.map +1 -1
- package/dist/common/types.d.cts +3 -1
- package/dist/common/types.d.ts +3 -1
- package/dist/pr-review/claude/claude-commander.cjs +10 -3
- package/dist/pr-review/claude/claude-commander.cjs.map +1 -1
- package/dist/pr-review/claude/claude-commander.js +10 -3
- package/dist/pr-review/claude/claude-commander.js.map +1 -1
- package/dist/pr-review/claude/installation-claude.cjs +1 -1
- package/dist/pr-review/claude/installation-claude.cjs.map +1 -1
- package/dist/pr-review/claude/installation-claude.js +1 -1
- package/dist/pr-review/claude/installation-claude.js.map +1 -1
- package/dist/pr-review/codex/codex-commander.cjs +14 -4
- package/dist/pr-review/codex/codex-commander.cjs.map +1 -1
- package/dist/pr-review/codex/codex-commander.d.cts +1 -1
- package/dist/pr-review/codex/codex-commander.d.ts +1 -1
- package/dist/pr-review/codex/codex-commander.js +14 -4
- package/dist/pr-review/codex/codex-commander.js.map +1 -1
- package/dist/pr-review/codex/installation-codex.cjs +1 -1
- package/dist/pr-review/codex/installation-codex.cjs.map +1 -1
- package/dist/pr-review/codex/installation-codex.js +1 -1
- package/dist/pr-review/codex/installation-codex.js.map +1 -1
- package/dist/pr-review/gemini/gemini-commander.cjs +12 -12
- package/dist/pr-review/gemini/gemini-commander.cjs.map +1 -1
- package/dist/pr-review/gemini/gemini-commander.js +12 -12
- package/dist/pr-review/gemini/gemini-commander.js.map +1 -1
- package/dist/pr-review/gemini/installation-gemini.cjs +1 -1
- package/dist/pr-review/gemini/installation-gemini.cjs.map +1 -1
- package/dist/pr-review/gemini/installation-gemini.js +1 -1
- package/dist/pr-review/gemini/installation-gemini.js.map +1 -1
- package/dist/pr-review/review-one-by-one.cjs +296 -42
- package/dist/pr-review/review-one-by-one.cjs.map +1 -1
- package/dist/pr-review/review-one-by-one.js +296 -42
- package/dist/pr-review/review-one-by-one.js.map +1 -1
- package/dist/pr-review/review.cjs +327 -42
- package/dist/pr-review/review.cjs.map +1 -1
- package/dist/pr-review/review.js +327 -42
- package/dist/pr-review/review.js.map +1 -1
- package/package.json +1 -1
|
@@ -80,6 +80,9 @@ var ignoreList = [
|
|
|
80
80
|
function isTestMode(args4 = process.argv.slice(2)) {
|
|
81
81
|
return args4.includes("--test");
|
|
82
82
|
}
|
|
83
|
+
function shouldStreamAIOutput(args4 = process.argv.slice(2)) {
|
|
84
|
+
return args4.includes("--stream-output");
|
|
85
|
+
}
|
|
83
86
|
function clearTraceMessages() {
|
|
84
87
|
traceMessages.length = 0;
|
|
85
88
|
}
|
|
@@ -206,15 +209,51 @@ function runGitCommand(args4, options = {}) {
|
|
|
206
209
|
throw error;
|
|
207
210
|
}
|
|
208
211
|
}
|
|
212
|
+
function resolveShellLaunchConfig() {
|
|
213
|
+
const candidates = [];
|
|
214
|
+
const seen = /* @__PURE__ */ new Set();
|
|
215
|
+
const appendCandidate = (executable, shellArgs) => {
|
|
216
|
+
const normalizedExecutable = executable?.trim();
|
|
217
|
+
if (!normalizedExecutable) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
if (path__default.default.isAbsolute(normalizedExecutable) && !fs__default.default.existsSync(normalizedExecutable)) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
const key = `${normalizedExecutable}::${shellArgs.join("\0")}`;
|
|
224
|
+
if (seen.has(key)) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
seen.add(key);
|
|
228
|
+
candidates.push({
|
|
229
|
+
executable: normalizedExecutable,
|
|
230
|
+
shellArgs
|
|
231
|
+
});
|
|
232
|
+
};
|
|
233
|
+
const shellFromEnv = process.env.SHELL?.trim();
|
|
234
|
+
const envShellName = shellFromEnv ? path__default.default.basename(shellFromEnv) : "";
|
|
235
|
+
if (["bash", "zsh", "ksh"].includes(envShellName)) {
|
|
236
|
+
appendCandidate(shellFromEnv, ["-lc"]);
|
|
237
|
+
}
|
|
238
|
+
["/bin/bash", "/usr/bin/bash", "bash", "/bin/zsh", "/usr/bin/zsh", "zsh"].forEach((shellPath) => {
|
|
239
|
+
appendCandidate(shellPath, ["-lc"]);
|
|
240
|
+
});
|
|
241
|
+
["/bin/sh", "/usr/bin/sh", "sh"].forEach((shellPath) => {
|
|
242
|
+
appendCandidate(shellPath, ["-c"]);
|
|
243
|
+
});
|
|
244
|
+
return candidates[0] || { executable: "sh", shellArgs: ["-c"] };
|
|
245
|
+
}
|
|
209
246
|
async function executeShellCommandWithProgress(command, options = {}) {
|
|
210
247
|
const { progressIntervalMs = 1e4, progressMessage = "\u23F3 \uBA85\uB839\uC744 \uC2E4\uD589\uD558\uB294 \uC911\uC785\uB2C8\uB2E4...", streamOutput = false } = options;
|
|
211
248
|
const { spawn } = await import('child_process');
|
|
249
|
+
const shellLaunchConfig = resolveShellLaunchConfig();
|
|
212
250
|
return new Promise((resolve, reject) => {
|
|
213
251
|
let stdout = "";
|
|
214
252
|
let stderr = "";
|
|
215
253
|
const startedAt = Date.now();
|
|
216
254
|
console.log(progressMessage);
|
|
217
|
-
|
|
255
|
+
helperTrace("shell-command:launcher", `${shellLaunchConfig.executable} ${shellLaunchConfig.shellArgs.join(" ")}`);
|
|
256
|
+
const child = spawn(shellLaunchConfig.executable, [...shellLaunchConfig.shellArgs, command], {
|
|
218
257
|
stdio: ["ignore", "pipe", "pipe"]
|
|
219
258
|
});
|
|
220
259
|
const progressTimer = setInterval(() => {
|
|
@@ -249,11 +288,41 @@ async function executeShellCommandWithProgress(command, options = {}) {
|
|
|
249
288
|
return;
|
|
250
289
|
}
|
|
251
290
|
const exitSummary = signal ? `signal=${signal}` : `code=${String(code ?? "unknown")}`;
|
|
252
|
-
|
|
253
|
-
|
|
291
|
+
const failureDetails = {
|
|
292
|
+
code,
|
|
293
|
+
command,
|
|
294
|
+
signal,
|
|
295
|
+
stderr,
|
|
296
|
+
stdout
|
|
297
|
+
};
|
|
298
|
+
reject(createShellCommandExecutionError(failureDetails, exitSummary));
|
|
254
299
|
});
|
|
255
300
|
});
|
|
256
301
|
}
|
|
302
|
+
function getShellCommandFailurePreview(failureDetails) {
|
|
303
|
+
const stderrText = failureDetails.stderr.trim();
|
|
304
|
+
const stdoutText = failureDetails.stdout.trim();
|
|
305
|
+
const combinedOutput = stderrText || stdoutText;
|
|
306
|
+
if (!combinedOutput) {
|
|
307
|
+
return "";
|
|
308
|
+
}
|
|
309
|
+
const MAX_PREVIEW_LENGTH = 4e3;
|
|
310
|
+
if (combinedOutput.length <= MAX_PREVIEW_LENGTH) {
|
|
311
|
+
return combinedOutput;
|
|
312
|
+
}
|
|
313
|
+
return combinedOutput.slice(-4e3);
|
|
314
|
+
}
|
|
315
|
+
function createShellCommandExecutionError(failureDetails, exitSummary) {
|
|
316
|
+
const failurePreview = getShellCommandFailurePreview(failureDetails);
|
|
317
|
+
const error = new Error(`\uC258 \uBA85\uB839 \uC2E4\uD589 \uC2E4\uD328 (${exitSummary})${failurePreview ? `
|
|
318
|
+
${failurePreview}` : ""}`);
|
|
319
|
+
error.code = failureDetails.code;
|
|
320
|
+
error.signal = failureDetails.signal;
|
|
321
|
+
error.stdout = failureDetails.stdout;
|
|
322
|
+
error.stderr = failureDetails.stderr;
|
|
323
|
+
error.command = failureDetails.command;
|
|
324
|
+
return error;
|
|
325
|
+
}
|
|
257
326
|
function formatReviewTargetFiles(files, visibleCount = 5) {
|
|
258
327
|
if (files.length === 0) {
|
|
259
328
|
return "(\uC5C6\uC74C)";
|
|
@@ -326,7 +395,7 @@ function serializeError(error) {
|
|
|
326
395
|
}
|
|
327
396
|
if (error && typeof error === "object") {
|
|
328
397
|
const errorLike = error;
|
|
329
|
-
const extraKeys = ["code", "errno", "syscall", "path", "cmd", "status", "signal", "spawnargs"];
|
|
398
|
+
const extraKeys = ["code", "errno", "syscall", "path", "cmd", "status", "signal", "spawnargs", "command"];
|
|
330
399
|
extraKeys.forEach((key) => {
|
|
331
400
|
if (errorLike[key] !== void 0) {
|
|
332
401
|
serialized[key] = errorLike[key];
|
|
@@ -432,6 +501,87 @@ ${section.markdown}`).join("\n")}
|
|
|
432
501
|
return "";
|
|
433
502
|
}
|
|
434
503
|
}
|
|
504
|
+
function getExecutionLogSummary(status, title) {
|
|
505
|
+
if (title) {
|
|
506
|
+
return title;
|
|
507
|
+
}
|
|
508
|
+
switch (status) {
|
|
509
|
+
case "success":
|
|
510
|
+
return "\uB9AC\uBDF0 \uC2E4\uD589\uC774 \uC131\uACF5\uC801\uC73C\uB85C \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.";
|
|
511
|
+
case "failed":
|
|
512
|
+
return "\uB9AC\uBDF0 \uC2E4\uD589 \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.";
|
|
513
|
+
case "partial_failure":
|
|
514
|
+
return "\uB9AC\uBDF0 \uC2E4\uD589\uC740 \uC644\uB8CC\uB418\uC5C8\uC9C0\uB9CC \uC77C\uBD80 \uB2E8\uACC4\uC5D0\uC11C \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.";
|
|
515
|
+
default:
|
|
516
|
+
return "\uB9AC\uBDF0 \uC2E4\uD589\uC774 \uCDE8\uC18C\uB418\uC5C8\uAC70\uB098 \uB9AC\uBDF0 \uB300\uC0C1\uC774 \uC5C6\uC5B4 \uC885\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.";
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
function formatExecutionDuration(startedAt, finishedAt) {
|
|
520
|
+
const durationMs = Math.max(0, finishedAt.getTime() - startedAt.getTime());
|
|
521
|
+
if (durationMs < 1e3) {
|
|
522
|
+
return `${durationMs}ms`;
|
|
523
|
+
}
|
|
524
|
+
const durationSeconds = durationMs / 1e3;
|
|
525
|
+
if (durationSeconds < 60) {
|
|
526
|
+
return `${durationSeconds.toFixed(1)}s`;
|
|
527
|
+
}
|
|
528
|
+
const minutes = Math.floor(durationSeconds / 60);
|
|
529
|
+
const seconds = Math.round(durationSeconds % 60);
|
|
530
|
+
return `${minutes}m ${seconds}s`;
|
|
531
|
+
}
|
|
532
|
+
function writeExecutionLog(options = {}) {
|
|
533
|
+
try {
|
|
534
|
+
const startedAt = options.startedAt ?? /* @__PURE__ */ new Date();
|
|
535
|
+
const finishedAt = options.finishedAt ?? /* @__PURE__ */ new Date();
|
|
536
|
+
const status = options.status ?? "success";
|
|
537
|
+
helperTrace("execution-log:write:start", options.scope || "unknown");
|
|
538
|
+
createReportDirectory();
|
|
539
|
+
const reportPath = getAvailableFilePath(REPORT_DIR, `${getNowString(finishedAt)}-execution-log`, ".md");
|
|
540
|
+
const traceSnapshot = options.traceMessages ?? getTraceMessages();
|
|
541
|
+
const extraSections = options.extraSections || [];
|
|
542
|
+
const serializedError = options.error ? serializeError(options.error) : null;
|
|
543
|
+
const report = `# Execution Log
|
|
544
|
+
|
|
545
|
+
- \uC2DC\uC791 \uC2DC\uAC01: ${getHumanReadableNowString(startedAt)}
|
|
546
|
+
- \uC885\uB8CC \uC2DC\uAC01: ${getHumanReadableNowString(finishedAt)}
|
|
547
|
+
- \uC2E4\uD589 \uC2DC\uAC04: ${formatExecutionDuration(startedAt, finishedAt)}
|
|
548
|
+
- \uC0C1\uD0DC: \`${status}\`
|
|
549
|
+
- Scope: \`${options.scope || "unknown"}\`
|
|
550
|
+
- \uC791\uC5C5 \uACBD\uB85C: \`${process.cwd()}\`
|
|
551
|
+
- \uC2E4\uD589 \uC778\uC790: \`${JSON.stringify(options.args ?? process.argv.slice(2))}\`
|
|
552
|
+
- \uC2E4\uD589 \uD658\uACBD: \`${process.platform} ${process.arch} / Node ${process.version}\`
|
|
553
|
+
|
|
554
|
+
## Summary
|
|
555
|
+
|
|
556
|
+
${getExecutionLogSummary(status, options.title)}
|
|
557
|
+
${serializedError ? `
|
|
558
|
+
|
|
559
|
+
## Error
|
|
560
|
+
|
|
561
|
+
\`\`\`json
|
|
562
|
+
${JSON.stringify(serializedError, null, 2)}
|
|
563
|
+
\`\`\`` : ""}
|
|
564
|
+
|
|
565
|
+
## Trace
|
|
566
|
+
|
|
567
|
+
\`\`\`json
|
|
568
|
+
${JSON.stringify(traceSnapshot, null, 2)}
|
|
569
|
+
\`\`\`${extraSections.length ? `
|
|
570
|
+
${extraSections.map((section) => `
|
|
571
|
+
## ${section.heading}
|
|
572
|
+
|
|
573
|
+
${section.markdown}`).join("\n")}
|
|
574
|
+
` : "\n"}
|
|
575
|
+
`;
|
|
576
|
+
fs__default.default.writeFileSync(reportPath, report);
|
|
577
|
+
helperTrace("execution-log:write:done", reportPath);
|
|
578
|
+
return reportPath;
|
|
579
|
+
} catch (writeError) {
|
|
580
|
+
console.error("\u26A0\uFE0F \uC2E4\uD589 \uB85C\uADF8 \uD30C\uC77C \uC0DD\uC131\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.");
|
|
581
|
+
console.error(writeError);
|
|
582
|
+
return "";
|
|
583
|
+
}
|
|
584
|
+
}
|
|
435
585
|
function exitWithError(message, options = {}) {
|
|
436
586
|
const reportPath = writeErrorReport(options.error || new Error(message), {
|
|
437
587
|
...options,
|
|
@@ -482,6 +632,62 @@ function truncateCommitSubject(subject) {
|
|
|
482
632
|
}
|
|
483
633
|
return `${subject.slice(0, 69)}...`;
|
|
484
634
|
}
|
|
635
|
+
function formatReviewTargetFileCount(fileCount) {
|
|
636
|
+
return fileCount === 0 ? "\uBCC0\uACBD \uC5C6\uC74C" : `${fileCount}\uAC1C \uD30C\uC77C`;
|
|
637
|
+
}
|
|
638
|
+
function buildReviewTargetSectionTitle(target) {
|
|
639
|
+
return target.kind === "commit" ? `${target.hash} ${target.subject}` : `${target.hash} | ${target.subject}`;
|
|
640
|
+
}
|
|
641
|
+
function buildReviewTargetSummaryLine(target) {
|
|
642
|
+
if (target.kind === "commit") {
|
|
643
|
+
return `- ${target.hash} | ${target.subject} | ${target.author} | ${target.relativeDate}`;
|
|
644
|
+
}
|
|
645
|
+
return `- ${target.hash} | ${target.subject}`;
|
|
646
|
+
}
|
|
647
|
+
function buildReviewTargetDiffArgs(target, filePath) {
|
|
648
|
+
const reviewPathspecArgs = getReviewPathspecArgs();
|
|
649
|
+
if (target.kind === "commit") {
|
|
650
|
+
return ["show", "--stat", "--patch", "--format=", target.hash, "--", ...reviewPathspecArgs];
|
|
651
|
+
}
|
|
652
|
+
const diffArgs = ["diff"];
|
|
653
|
+
if (target.kind === "staged") {
|
|
654
|
+
diffArgs.push("--cached");
|
|
655
|
+
}
|
|
656
|
+
diffArgs.push("--stat", "--patch", "--");
|
|
657
|
+
return [...diffArgs, ...reviewPathspecArgs];
|
|
658
|
+
}
|
|
659
|
+
function buildReviewTargetFileArgs(target) {
|
|
660
|
+
const reviewPathspecArgs = getReviewPathspecArgs();
|
|
661
|
+
if (target.kind === "commit") {
|
|
662
|
+
return ["show", "--pretty=format:", "--name-only", target.hash, "--", ...reviewPathspecArgs];
|
|
663
|
+
}
|
|
664
|
+
const diffArgs = ["diff"];
|
|
665
|
+
if (target.kind === "staged") {
|
|
666
|
+
diffArgs.push("--cached");
|
|
667
|
+
}
|
|
668
|
+
return [...diffArgs, "--name-only", "--", ...reviewPathspecArgs];
|
|
669
|
+
}
|
|
670
|
+
function getReviewTargetFiles(target) {
|
|
671
|
+
const output = runGitCommand(buildReviewTargetFileArgs(target), {
|
|
672
|
+
allowFailure: true
|
|
673
|
+
});
|
|
674
|
+
return output.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
675
|
+
}
|
|
676
|
+
function createWorkingTreeReviewOption(kind) {
|
|
677
|
+
const files = getReviewTargetFiles({
|
|
678
|
+
hash: kind,
|
|
679
|
+
kind});
|
|
680
|
+
const subject = kind === "unstaged" ? "\uC544\uC9C1 git add \uD558\uC9C0 \uC54A\uC740 \uBCC0\uACBD\uC0AC\uD56D" : "git add \uB41C \uBCC0\uACBD\uC0AC\uD56D";
|
|
681
|
+
return {
|
|
682
|
+
author: "",
|
|
683
|
+
description: `${subject} | ${formatReviewTargetFileCount(files.length)}`,
|
|
684
|
+
hash: kind,
|
|
685
|
+
kind,
|
|
686
|
+
label: kind,
|
|
687
|
+
relativeDate: "",
|
|
688
|
+
subject
|
|
689
|
+
};
|
|
690
|
+
}
|
|
485
691
|
function getRecentCommitOptions() {
|
|
486
692
|
const output = runGitCommand(
|
|
487
693
|
["log", `-${COMMIT_FETCH_LIMIT}`, "--date=relative", "--pretty=format:%h%x09%an%x09%ar%x09%s"],
|
|
@@ -497,44 +703,43 @@ function getRecentCommitOptions() {
|
|
|
497
703
|
author,
|
|
498
704
|
description: `${author} | ${relativeDate}`,
|
|
499
705
|
hash,
|
|
706
|
+
kind: "commit",
|
|
500
707
|
label: `${hash} | ${truncateCommitSubject(subject)}`,
|
|
501
708
|
relativeDate,
|
|
502
709
|
subject
|
|
503
710
|
};
|
|
504
711
|
});
|
|
505
712
|
}
|
|
713
|
+
function getReviewTargetOptions() {
|
|
714
|
+
return [createWorkingTreeReviewOption("unstaged"), createWorkingTreeReviewOption("staged"), ...getRecentCommitOptions()];
|
|
715
|
+
}
|
|
506
716
|
function buildSelectedCommitSummary(commits) {
|
|
507
|
-
return commits.map((commit) =>
|
|
717
|
+
return commits.map((commit) => buildReviewTargetSummaryLine(commit)).join("\n");
|
|
508
718
|
}
|
|
509
719
|
function getReviewPathspecArgs() {
|
|
510
720
|
const { includePatterns, excludePatterns } = getGitDiffPathspecs();
|
|
511
721
|
return [...includePatterns, ...excludePatterns];
|
|
512
722
|
}
|
|
513
723
|
function buildSelectedCommitDiff(commits) {
|
|
514
|
-
const reviewPathspecArgs = getReviewPathspecArgs();
|
|
515
724
|
const sections = commits.map((commit) => {
|
|
516
|
-
const diff = runGitCommand(
|
|
725
|
+
const diff = runGitCommand(buildReviewTargetDiffArgs(commit), {
|
|
517
726
|
allowFailure: true,
|
|
518
727
|
trimOutput: false
|
|
519
728
|
}).trim();
|
|
520
729
|
if (!diff) {
|
|
521
730
|
return "";
|
|
522
731
|
}
|
|
523
|
-
return [`## ${commit
|
|
732
|
+
return [`## ${buildReviewTargetSectionTitle(commit)}`, diff].join("\n\n");
|
|
524
733
|
}).filter(Boolean).join("\n\n");
|
|
525
734
|
if (!sections) {
|
|
526
735
|
return "";
|
|
527
736
|
}
|
|
528
|
-
return ["# \uC120\uD0DD\uD55C \
|
|
737
|
+
return ["# \uC120\uD0DD\uD55C \uB9AC\uBDF0 \uB300\uC0C1", buildSelectedCommitSummary(commits), "", "# \uB9AC\uBDF0 \uB300\uC0C1 diff", sections].join("\n");
|
|
529
738
|
}
|
|
530
739
|
function getSelectedCommitFiles(commits) {
|
|
531
|
-
const reviewPathspecArgs = getReviewPathspecArgs();
|
|
532
740
|
const files = /* @__PURE__ */ new Set();
|
|
533
741
|
commits.forEach((commit) => {
|
|
534
|
-
|
|
535
|
-
allowFailure: true
|
|
536
|
-
});
|
|
537
|
-
output.split("\n").map((line) => line.trim()).filter(Boolean).forEach((filePath) => files.add(filePath));
|
|
742
|
+
getReviewTargetFiles(commit).forEach((filePath) => files.add(filePath));
|
|
538
743
|
});
|
|
539
744
|
return [...files];
|
|
540
745
|
}
|
|
@@ -722,13 +927,13 @@ async function showMultiSelect(question, options, windowSize = COMMIT_SELECTION_
|
|
|
722
927
|
});
|
|
723
928
|
}
|
|
724
929
|
async function selectReviewCommits() {
|
|
725
|
-
const commits =
|
|
930
|
+
const commits = getReviewTargetOptions();
|
|
726
931
|
if (commits.length === 0) {
|
|
727
|
-
console.log("\u2139\uFE0F \uB9AC\uBDF0\uD560 \
|
|
932
|
+
console.log("\u2139\uFE0F \uB9AC\uBDF0\uD560 \uB300\uC0C1\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.");
|
|
728
933
|
return [];
|
|
729
934
|
}
|
|
730
935
|
return showMultiSelect(
|
|
731
|
-
"\uB9AC\uBDF0\uD560 \
|
|
936
|
+
"\uB9AC\uBDF0\uD560 \uB300\uC0C1\uC744 \uC120\uD0DD\uD574\uC8FC\uC138\uC694.",
|
|
732
937
|
commits.map((commit) => ({
|
|
733
938
|
description: commit.description,
|
|
734
939
|
label: commit.label,
|
|
@@ -819,6 +1024,13 @@ var ALLOWED_REASONING_EFFORTS = ["minimal", "low", "medium", "high"];
|
|
|
819
1024
|
function shellQuote(value) {
|
|
820
1025
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
821
1026
|
}
|
|
1027
|
+
function toShellOptionToken(value) {
|
|
1028
|
+
const SIMPLE_SHELL_TOKEN_PATTERN = /^[A-Za-z0-9._:/=-]+$/;
|
|
1029
|
+
if (SIMPLE_SHELL_TOKEN_PATTERN.test(value)) {
|
|
1030
|
+
return value;
|
|
1031
|
+
}
|
|
1032
|
+
return shellQuote(value);
|
|
1033
|
+
}
|
|
822
1034
|
function getArgValue(flag) {
|
|
823
1035
|
const index = args.indexOf(flag);
|
|
824
1036
|
if (index === -1 || !args[index + 1]) {
|
|
@@ -898,9 +1110,9 @@ function getAliasFallbacks(primaryAlias) {
|
|
|
898
1110
|
}
|
|
899
1111
|
function buildClaudeExecCommand(options) {
|
|
900
1112
|
const { tempDiffPath: tempDiffPath2, prompt, systemPromptFiles, effort, model, fallbackModel } = options;
|
|
901
|
-
const modelOption = model ? `--model ${
|
|
902
|
-
const fallbackOption = model && fallbackModel ? `--fallback-model ${
|
|
903
|
-
const effortOption = `--effort ${
|
|
1113
|
+
const modelOption = model ? `--model ${toShellOptionToken(model)}` : "";
|
|
1114
|
+
const fallbackOption = model && fallbackModel ? `--fallback-model ${toShellOptionToken(fallbackModel)}` : "";
|
|
1115
|
+
const effortOption = `--effort ${toShellOptionToken(effort)}`;
|
|
904
1116
|
const appendedPromptFiles = systemPromptFiles.map((path3) => `--append-system-prompt-file ${shellQuote(path3)}`).join(" ");
|
|
905
1117
|
return `cat ${shellQuote(tempDiffPath2)} | claude ${[
|
|
906
1118
|
modelOption,
|
|
@@ -1025,12 +1237,22 @@ function printNotice2(message) {
|
|
|
1025
1237
|
console.warn(message);
|
|
1026
1238
|
}
|
|
1027
1239
|
}
|
|
1240
|
+
function normalizeEffort2(level) {
|
|
1241
|
+
if (level === "minimal") {
|
|
1242
|
+
return "low";
|
|
1243
|
+
}
|
|
1244
|
+
return level;
|
|
1245
|
+
}
|
|
1028
1246
|
function resolveReasoningEffort2() {
|
|
1029
1247
|
const customReasoningEffort = getArgValue2("--reasoning-effort");
|
|
1030
1248
|
if (customReasoningEffort) {
|
|
1031
1249
|
if (ALLOWED_REASONING_EFFORTS2.includes(customReasoningEffort)) {
|
|
1032
|
-
|
|
1033
|
-
|
|
1250
|
+
const normalized = normalizeEffort2(customReasoningEffort);
|
|
1251
|
+
trace3("reasoning:custom", `${customReasoningEffort} -> ${normalized}`);
|
|
1252
|
+
if (customReasoningEffort === "minimal") {
|
|
1253
|
+
printNotice2("\u26A0\uFE0F Codex\uB294 minimal\uC774 web_search \uB3C4\uAD6C\uC640 \uCDA9\uB3CC\uD560 \uC218 \uC788\uC5B4 low\uB85C \uB9E4\uD551\uD569\uB2C8\uB2E4.");
|
|
1254
|
+
}
|
|
1255
|
+
return normalized;
|
|
1034
1256
|
}
|
|
1035
1257
|
printNotice2(
|
|
1036
1258
|
`\u26A0\uFE0F \uC9C0\uC6D0\uB418\uC9C0 \uC54A\uB294 reasoning effort(${customReasoningEffort})\uC785\uB2C8\uB2E4. allowed: ${ALLOWED_REASONING_EFFORTS2.join(
|
|
@@ -1039,8 +1261,8 @@ function resolveReasoningEffort2() {
|
|
|
1039
1261
|
);
|
|
1040
1262
|
}
|
|
1041
1263
|
if (args2.includes("--flash")) {
|
|
1042
|
-
trace3("reasoning:flash-default", "
|
|
1043
|
-
return "
|
|
1264
|
+
trace3("reasoning:flash-default", "low");
|
|
1265
|
+
return "low";
|
|
1044
1266
|
}
|
|
1045
1267
|
if (args2.includes("--review")) {
|
|
1046
1268
|
trace3("reasoning:review-default", "high");
|
|
@@ -1235,7 +1457,7 @@ function buildGeminiFileReferenceSection(files) {
|
|
|
1235
1457
|
const existingFiles = files.filter((file) => fs__default.default.existsSync(file.path));
|
|
1236
1458
|
return {
|
|
1237
1459
|
count: existingFiles.length,
|
|
1238
|
-
|
|
1460
|
+
items: existingFiles.map((file) => `${file.display} ${toGeminiFileReference(file.path)}`)
|
|
1239
1461
|
};
|
|
1240
1462
|
}
|
|
1241
1463
|
var createGeminiCommand = (tempDiffPath2, reviewFormPath2) => {
|
|
@@ -1254,19 +1476,19 @@ var createGeminiCommand = (tempDiffPath2, reviewFormPath2) => {
|
|
|
1254
1476
|
const ruleSection = buildGeminiFileReferenceSection(rules);
|
|
1255
1477
|
trace5("rules:loaded", `count=${ruleSection.count}`);
|
|
1256
1478
|
const reviewFormExists = fs__default.default.existsSync(resolvedReviewFormPath);
|
|
1257
|
-
const
|
|
1479
|
+
const reviewFormText = reviewFormExists ? `\uB9AC\uBDF0 \uC591\uC2DD ${toGeminiFileReference(resolvedReviewFormPath)}` : "\uB9AC\uBDF0 \uC591\uC2DD (\uC5C6\uC74C)";
|
|
1258
1480
|
trace5("reviewForm:status", reviewFormExists ? "exists" : "missing");
|
|
1259
1481
|
const reasoningInstruction = getReasoningInstruction(reasoningEffort);
|
|
1260
|
-
const
|
|
1261
|
-
\
|
|
1262
|
-
|
|
1263
|
-
\uB9AC\uBDF0 \
|
|
1264
|
-
${
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
\
|
|
1269
|
-
|
|
1482
|
+
const ruleText = ruleSection.items.join(" ") || "(\uC5C6\uC74C)";
|
|
1483
|
+
const diffText = `\uB9AC\uBDF0 \uB300\uC0C1 diff ${toGeminiFileReference(resolvedTempDiffPath)}`;
|
|
1484
|
+
const prompt = [
|
|
1485
|
+
"\uC544\uB798 \uD30C\uC77C\uB4E4\uC744 \uC21C\uC11C\uB300\uB85C \uC77D\uACE0 \uCF54\uB4DC \uB9AC\uBDF0\uB97C \uC9C4\uD589\uD574\uC918.",
|
|
1486
|
+
`\uADDC\uCE59 \uD30C\uC77C: ${ruleText}`,
|
|
1487
|
+
`\uB9AC\uBDF0 \uC591\uC2DD \uD30C\uC77C: ${reviewFormText}`,
|
|
1488
|
+
`\uB9AC\uBDF0 \uB300\uC0C1 diff \uD30C\uC77C: ${diffText}`,
|
|
1489
|
+
"\uBC18\uB4DC\uC2DC \uB9AC\uBDF0 \uC591\uC2DD\uC5D0 \uB9DE\uCDB0 \uC791\uC131\uD574\uC918.",
|
|
1490
|
+
`\uCD94\uB860 \uAC15\uB3C4 \uC9C0\uCE68: ${reasoningInstruction}`
|
|
1491
|
+
].join(" ");
|
|
1270
1492
|
trace5("prompt:prepared", `length=${prompt.length}`);
|
|
1271
1493
|
const modelCandidates = toUnique2(customModel ? [customModel, ...aliasFallbacks] : aliasFallbacks);
|
|
1272
1494
|
trace5("model:candidates", modelCandidates.join(", "));
|
|
@@ -1329,8 +1551,10 @@ function checkGeminiCliInstalled() {
|
|
|
1329
1551
|
// src/pr-review/review.ts
|
|
1330
1552
|
async function main() {
|
|
1331
1553
|
const args4 = process.argv.slice(2);
|
|
1554
|
+
const startedAt = /* @__PURE__ */ new Date();
|
|
1332
1555
|
clearTraceMessages();
|
|
1333
1556
|
const isTest = isTestMode(args4);
|
|
1557
|
+
const shouldStreamOutput = shouldStreamAIOutput(args4);
|
|
1334
1558
|
const trace7 = createTraceLogger("review", args4);
|
|
1335
1559
|
trace7("main:start", `args=${JSON.stringify(args4)}`);
|
|
1336
1560
|
let command = "";
|
|
@@ -1339,6 +1563,12 @@ async function main() {
|
|
|
1339
1563
|
let service = "";
|
|
1340
1564
|
let selectedCommitSummary = "";
|
|
1341
1565
|
let reviewTargetFiles = [];
|
|
1566
|
+
let executionLogPath = "";
|
|
1567
|
+
let executionStatus = "cancelled";
|
|
1568
|
+
let executionTitle = "\uB9AC\uBDF0 \uC2E4\uD589\uC774 \uCDE8\uC18C\uB418\uC5C8\uAC70\uB098 \uB9AC\uBDF0 \uB300\uC0C1\uC774 \uC5C6\uC5B4 \uC885\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.";
|
|
1569
|
+
let executionError = null;
|
|
1570
|
+
let resultLength = 0;
|
|
1571
|
+
let exitCode = 0;
|
|
1342
1572
|
try {
|
|
1343
1573
|
trace7("service-selection:start");
|
|
1344
1574
|
service = await showSelectionAIService();
|
|
@@ -1362,14 +1592,18 @@ async function main() {
|
|
|
1362
1592
|
}
|
|
1363
1593
|
trace7("review-flow:start");
|
|
1364
1594
|
console.log("\u{1F680} AI Code Review\uB97C \uC2DC\uC791\uD569\uB2C8\uB2E4...");
|
|
1595
|
+
if (shouldStreamOutput) {
|
|
1596
|
+
console.log("\u2139\uFE0F AI \uC2E4\uC2DC\uAC04 \uC751\uB2F5 \uD45C\uC2DC \uBAA8\uB4DC\uAC00 \uD65C\uC131\uD654\uB418\uC5C8\uC2B5\uB2C8\uB2E4.");
|
|
1597
|
+
}
|
|
1365
1598
|
trace7("commit-selection:start");
|
|
1366
1599
|
const selectedCommits = await selectReviewCommits();
|
|
1367
1600
|
trace7("commit-selection:done", `count=${selectedCommits.length}`);
|
|
1368
1601
|
if (selectedCommits.length === 0) {
|
|
1369
1602
|
trace7("commit-selection:empty");
|
|
1370
|
-
|
|
1603
|
+
executionTitle = "\uC120\uD0DD\uB41C \uB9AC\uBDF0 \uB300\uC0C1\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.";
|
|
1604
|
+
console.log("\u2139\uFE0F \uC120\uD0DD\uB41C \uB9AC\uBDF0 \uB300\uC0C1\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.");
|
|
1371
1605
|
deleteTempDiff();
|
|
1372
|
-
|
|
1606
|
+
return;
|
|
1373
1607
|
}
|
|
1374
1608
|
selectedCommitSummary = buildSelectedCommitSummary(selectedCommits);
|
|
1375
1609
|
trace7("commit-summary:prepared", selectedCommitSummary);
|
|
@@ -1381,9 +1615,10 @@ async function main() {
|
|
|
1381
1615
|
trace7("git-diff:build:done", `length=${diff.length}`);
|
|
1382
1616
|
if (!diff.trim() && !isTest) {
|
|
1383
1617
|
trace7("empty-diff:exit");
|
|
1384
|
-
|
|
1618
|
+
executionTitle = "\uC120\uD0DD\uD55C \uB9AC\uBDF0 \uB300\uC0C1\uC5D0\uC11C \uB9AC\uBDF0\uD560 \uBCC0\uACBD\uC744 \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.";
|
|
1619
|
+
console.log("\u2139\uFE0F \uC120\uD0DD\uD55C \uB9AC\uBDF0 \uB300\uC0C1\uC5D0\uC11C \uB9AC\uBDF0\uD560 \uBCC0\uACBD\uC744 \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.");
|
|
1385
1620
|
deleteTempDiff();
|
|
1386
|
-
|
|
1621
|
+
return;
|
|
1387
1622
|
}
|
|
1388
1623
|
const nowStr = getNowString();
|
|
1389
1624
|
trace7("timestamp:created", nowStr);
|
|
@@ -1413,8 +1648,9 @@ async function main() {
|
|
|
1413
1648
|
trace7("command:exec:start");
|
|
1414
1649
|
const result = (await executeShellCommandWithProgress(command, {
|
|
1415
1650
|
progressMessage: `\u23F3 [\uB9AC\uBDF0 \uC9C4\uD589] ${service} | \uB300\uC0C1 ${reviewTargetFiles.length}\uAC1C \uD30C\uC77C`,
|
|
1416
|
-
streamOutput: isTest
|
|
1651
|
+
streamOutput: isTest || shouldStreamOutput
|
|
1417
1652
|
})).stdout;
|
|
1653
|
+
resultLength = result.length;
|
|
1418
1654
|
trace7("command:exec:done", `resultLength=${result.length}`);
|
|
1419
1655
|
trace7("report:write:start");
|
|
1420
1656
|
savedReportPath = getNextFilePath(REPORT_DIR, nowStr, ".md");
|
|
@@ -1440,9 +1676,15 @@ ${command}`);
|
|
|
1440
1676
|
deleteTempDiff();
|
|
1441
1677
|
trace7("cleanup-temp-diff:done");
|
|
1442
1678
|
trace7("review-flow:end");
|
|
1679
|
+
executionStatus = "success";
|
|
1680
|
+
executionTitle = "\uB9AC\uBDF0\uAC00 \uC131\uACF5\uC801\uC73C\uB85C \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.";
|
|
1443
1681
|
} catch (error) {
|
|
1444
1682
|
trace7("review-flow:catch", getErrorSummary(error));
|
|
1445
1683
|
let errorReportPath = "";
|
|
1684
|
+
executionStatus = "failed";
|
|
1685
|
+
executionTitle = "\uB9AC\uBDF0 \uC2E4\uD589 \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.";
|
|
1686
|
+
executionError = error;
|
|
1687
|
+
exitCode = 1;
|
|
1446
1688
|
trace7("cleanup-temp-diff:start(catch)");
|
|
1447
1689
|
try {
|
|
1448
1690
|
deleteTempDiff();
|
|
@@ -1482,7 +1724,50 @@ ${JSON.stringify(
|
|
|
1482
1724
|
if (errorReportPath) {
|
|
1483
1725
|
console.error(`\u{1F4C4} \uC5D0\uB7EC \uB85C\uADF8 \uC800\uC7A5 \uC704\uCE58: ${errorReportPath}`);
|
|
1484
1726
|
}
|
|
1485
|
-
|
|
1727
|
+
} finally {
|
|
1728
|
+
executionLogPath = writeExecutionLog({
|
|
1729
|
+
scope: "review",
|
|
1730
|
+
status: executionStatus,
|
|
1731
|
+
title: executionTitle,
|
|
1732
|
+
args: args4,
|
|
1733
|
+
startedAt,
|
|
1734
|
+
error: executionError,
|
|
1735
|
+
extraSections: [
|
|
1736
|
+
{
|
|
1737
|
+
heading: "Execution Context",
|
|
1738
|
+
markdown: `\`\`\`json
|
|
1739
|
+
${JSON.stringify(
|
|
1740
|
+
{
|
|
1741
|
+
service: service || null,
|
|
1742
|
+
selectedCommitSummary: selectedCommitSummary || null,
|
|
1743
|
+
reviewTargetFiles,
|
|
1744
|
+
command: command || null,
|
|
1745
|
+
tempDiffPath,
|
|
1746
|
+
savedDiffPath: savedDiffPath || null,
|
|
1747
|
+
savedReportPath: savedReportPath || null,
|
|
1748
|
+
shouldStreamOutput,
|
|
1749
|
+
resultLength
|
|
1750
|
+
},
|
|
1751
|
+
null,
|
|
1752
|
+
2
|
|
1753
|
+
)}
|
|
1754
|
+
\`\`\``
|
|
1755
|
+
},
|
|
1756
|
+
{
|
|
1757
|
+
heading: "Generated Command",
|
|
1758
|
+
markdown: command ? `\`\`\`sh
|
|
1759
|
+
${command}
|
|
1760
|
+
\`\`\`` : "(\uC5C6\uC74C)"
|
|
1761
|
+
}
|
|
1762
|
+
]
|
|
1763
|
+
});
|
|
1764
|
+
if (executionLogPath) {
|
|
1765
|
+
const writeLog = executionStatus === "failed" ? console.error : console.log;
|
|
1766
|
+
writeLog(`\u{1F4DD} \uC2E4\uD589 \uB85C\uADF8 \uC800\uC7A5 \uC704\uCE58: ${executionLogPath}`);
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
if (exitCode !== 0) {
|
|
1770
|
+
process.exit(exitCode);
|
|
1486
1771
|
}
|
|
1487
1772
|
}
|
|
1488
1773
|
main();
|