@review-my-code/rmcode 0.1.2 → 0.1.4
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/README.md +1 -1
- package/dist/cli.js +224 -32
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ rmcode --staged # review staged changes
|
|
|
21
21
|
rmcode --unstaged # review unstaged changes
|
|
22
22
|
rmcode --all # review uncommitted tracked changes and safe text files
|
|
23
23
|
rmcode src/auth.ts # review one file
|
|
24
|
-
git diff main | rmcode
|
|
24
|
+
git diff main | rmcode # review a custom diff; language is detected from filenames
|
|
25
25
|
rmcode --json --fail-on-findings
|
|
26
26
|
```
|
|
27
27
|
|
package/dist/cli.js
CHANGED
|
@@ -9,7 +9,7 @@ const path_1 = require("path");
|
|
|
9
9
|
const readline_1 = require("readline");
|
|
10
10
|
const API_URL = process.env.RMC_API_URL || "https://review-my-code.com";
|
|
11
11
|
const APP_URL = process.env.RMC_APP_URL || "https://review-my-code.com";
|
|
12
|
-
const VERSION = "0.1.
|
|
12
|
+
const VERSION = "0.1.4";
|
|
13
13
|
const FREE_PLAN_CREDITS_PER_MONTH = 30;
|
|
14
14
|
const REQUEST_TIMEOUT_MS = 290_000;
|
|
15
15
|
const POLL_TIMEOUT_MS = 10 * 60_000;
|
|
@@ -199,7 +199,7 @@ function pseudoDiffForNewFile(file, worktreeRoot) {
|
|
|
199
199
|
}
|
|
200
200
|
function gitRepoName() {
|
|
201
201
|
try {
|
|
202
|
-
const remote =
|
|
202
|
+
const remote = gitQuiet(["remote", "get-url", "origin"]);
|
|
203
203
|
const m = remote.match(/github\.com[:/]([^/]+\/[^/.]+)/);
|
|
204
204
|
return m ? m[1] : null;
|
|
205
205
|
}
|
|
@@ -215,6 +215,36 @@ function currentBranch() {
|
|
|
215
215
|
return "unknown";
|
|
216
216
|
}
|
|
217
217
|
}
|
|
218
|
+
function headCommitSubject() {
|
|
219
|
+
try {
|
|
220
|
+
return gitQuiet(["log", "-1", "--pretty=%s"]) || null;
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
function firstNonEmpty(...values) {
|
|
227
|
+
for (const value of values) {
|
|
228
|
+
const trimmed = value?.trim();
|
|
229
|
+
if (trimmed)
|
|
230
|
+
return trimmed;
|
|
231
|
+
}
|
|
232
|
+
return undefined;
|
|
233
|
+
}
|
|
234
|
+
function parseOptionalPositiveInt(value) {
|
|
235
|
+
const trimmed = value?.trim();
|
|
236
|
+
if (!trimmed)
|
|
237
|
+
return undefined;
|
|
238
|
+
const parsed = Number.parseInt(trimmed, 10);
|
|
239
|
+
return Number.isInteger(parsed) && parsed >= 0 ? parsed : undefined;
|
|
240
|
+
}
|
|
241
|
+
function contextOptionsFromCli(options) {
|
|
242
|
+
return {
|
|
243
|
+
prTitle: firstNonEmpty(options.title, process.env.RMC_PR_TITLE, headCommitSubject()),
|
|
244
|
+
prNumber: parseOptionalPositiveInt(firstNonEmpty(options.prNumber, process.env.RMC_PR_NUMBER)),
|
|
245
|
+
sourceRepo: firstNonEmpty(options.sourceRepo, process.env.RMC_SOURCE_REPO, gitRepoName(), "local/repo"),
|
|
246
|
+
};
|
|
247
|
+
}
|
|
218
248
|
function filesFromDiff(diff) {
|
|
219
249
|
const files = new Set();
|
|
220
250
|
const re = /^diff --git a\/.+ b\/(.+)$/gm;
|
|
@@ -466,7 +496,7 @@ async function ensureExtractor(info) {
|
|
|
466
496
|
* diff's base state and return the ContextBundle, or null when extraction
|
|
467
497
|
* is unavailable. Throws ExtractorIntegrityError on checksum mismatch.
|
|
468
498
|
*/
|
|
469
|
-
async function extractContextBundle(diff, baseRef) {
|
|
499
|
+
async function extractContextBundle(diff, baseRef, contextOptions = {}) {
|
|
470
500
|
const info = await fetchExtractorInfo();
|
|
471
501
|
if (!info)
|
|
472
502
|
return null;
|
|
@@ -490,10 +520,11 @@ async function extractContextBundle(diff, baseRef) {
|
|
|
490
520
|
(0, fs_1.writeFileSync)(diffPath, diff);
|
|
491
521
|
const result = (0, child_process_1.spawnSync)(process.execPath, [
|
|
492
522
|
extractorPath,
|
|
493
|
-
|
|
523
|
+
`--pr=${contextOptions.prNumber ?? 0}`,
|
|
494
524
|
`--diff-file=${diffPath}`,
|
|
495
525
|
`--output-bundle=${bundlePath}`,
|
|
496
|
-
`--source-repo=${
|
|
526
|
+
`--source-repo=${contextOptions.sourceRepo || "local/repo"}`,
|
|
527
|
+
`--pr-title=${contextOptions.prTitle || ""}`,
|
|
497
528
|
`--tier=${info.tier || "free"}`,
|
|
498
529
|
], {
|
|
499
530
|
cwd: baseDir,
|
|
@@ -544,11 +575,11 @@ async function extractContextBundle(diff, baseRef) {
|
|
|
544
575
|
* Reports progress on the shared review spinner so the run renders as one
|
|
545
576
|
* phase-aware line. Exits the process on extractor checksum mismatch.
|
|
546
577
|
*/
|
|
547
|
-
async function maybeExtractContext(diff, spinner, baseRef) {
|
|
578
|
+
async function maybeExtractContext(diff, spinner, baseRef, contextOptions = {}) {
|
|
548
579
|
if (!API_KEY || !baseRef || !isGitRepo())
|
|
549
580
|
return null;
|
|
550
581
|
try {
|
|
551
|
-
const bundle = await extractContextBundle(diff, baseRef);
|
|
582
|
+
const bundle = await extractContextBundle(diff, baseRef, contextOptions);
|
|
552
583
|
if (bundle)
|
|
553
584
|
return bundle;
|
|
554
585
|
}
|
|
@@ -775,7 +806,7 @@ function createSpinner(msg) {
|
|
|
775
806
|
};
|
|
776
807
|
}
|
|
777
808
|
// ── Review runner ─────────────────────────────────────────────────────
|
|
778
|
-
async function runReview(content, files, label, jsonMode, failOnFindings, type = "diff", language, baseRef) {
|
|
809
|
+
async function runReview(content, files, label, jsonMode, failOnFindings, type = "diff", language, baseRef, contextOptions = {}) {
|
|
779
810
|
const startedAt = Date.now();
|
|
780
811
|
const lang = language || detectLanguage(files);
|
|
781
812
|
const uploadMsg = `Uploading review request (${files.length} file${files.length !== 1 ? "s" : ""}, ${lang})`;
|
|
@@ -786,7 +817,7 @@ async function runReview(content, files, label, jsonMode, failOnFindings, type =
|
|
|
786
817
|
const willExtract = type === "diff" && Boolean(API_KEY) && Boolean(baseRef) && isGitRepo();
|
|
787
818
|
const spinner = createSpinner(willExtract ? "Extracting repository context" : uploadMsg);
|
|
788
819
|
const bundle = willExtract
|
|
789
|
-
? await maybeExtractContext(content, spinner, baseRef)
|
|
820
|
+
? await maybeExtractContext(content, spinner, baseRef, contextOptions)
|
|
790
821
|
: null;
|
|
791
822
|
if (willExtract)
|
|
792
823
|
spinner.update(uploadMsg);
|
|
@@ -834,13 +865,17 @@ ${header}
|
|
|
834
865
|
${style("rmcode <file>", c.cyan)} Review a single local file
|
|
835
866
|
${style("rmcode login", c.cyan)} Set up your API key
|
|
836
867
|
${style("rmcode install", c.cyan)} Install the GitHub App for automatic PR reviews
|
|
868
|
+
${style("rmcode update", c.cyan)} Update rmcode to the latest version
|
|
837
869
|
${style("rmcode help", c.cyan)} Show this help
|
|
838
870
|
|
|
839
871
|
${style("OPTIONS", c.bold)}
|
|
840
872
|
|
|
841
873
|
--json Output the full API response as JSON (for CI/agents)
|
|
842
874
|
--fail-on-findings Exit 2 when JSON output contains findings
|
|
843
|
-
--lang <language>
|
|
875
|
+
--lang <language> Optional language hint for raw stdin snippets
|
|
876
|
+
--title <text> Optional PR title hint for repository-context reviews
|
|
877
|
+
--pr-number <n> Optional PR number hint for CI/benchmark parity
|
|
878
|
+
--source-repo <repo> Optional owner/repo hint when no origin remote exists
|
|
844
879
|
--help, -h Show this help
|
|
845
880
|
--version, -v Show version
|
|
846
881
|
|
|
@@ -862,7 +897,7 @@ ${header}
|
|
|
862
897
|
rmcode --staged
|
|
863
898
|
|
|
864
899
|
${style("# Review a specific range", c.dim)}
|
|
865
|
-
git diff abc123..def456 | rmcode
|
|
900
|
+
git diff abc123..def456 | rmcode
|
|
866
901
|
|
|
867
902
|
${style("# Review one file", c.dim)}
|
|
868
903
|
rmcode src/auth.ts
|
|
@@ -878,6 +913,9 @@ ${header}
|
|
|
878
913
|
RMC_API_KEY API key for authenticated reviews (get one: rmcode login)
|
|
879
914
|
RMC_API_URL API endpoint (default: https://review-my-code.com)
|
|
880
915
|
RMC_APP_URL App URL for login (default: https://review-my-code.com)
|
|
916
|
+
RMC_PR_TITLE Optional PR title hint for repository-context reviews
|
|
917
|
+
RMC_PR_NUMBER Optional PR number hint for CI/benchmark parity
|
|
918
|
+
RMC_SOURCE_REPO Optional owner/repo hint when no origin remote exists
|
|
881
919
|
|
|
882
920
|
${style("PRIVACY", c.bold)}
|
|
883
921
|
|
|
@@ -889,33 +927,181 @@ ${header}
|
|
|
889
927
|
${style("https://review-my-code.com", c.dim)}
|
|
890
928
|
`);
|
|
891
929
|
}
|
|
892
|
-
// ──
|
|
893
|
-
|
|
930
|
+
// ── Self-update ───────────────────────────────────────────────────────
|
|
931
|
+
const PACKAGE_NAME = "@review-my-code/rmcode";
|
|
932
|
+
const REGISTRY_LATEST_URL = process.env.RMC_REGISTRY_LATEST_URL ||
|
|
933
|
+
"https://registry.npmjs.org/@review-my-code%2Frmcode/latest";
|
|
934
|
+
/** Resolved real path of the running entry script, for install detection. */
|
|
935
|
+
function entryScriptPath() {
|
|
936
|
+
const binPath = process.argv[1] || "";
|
|
894
937
|
try {
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
938
|
+
return (0, fs_1.realpathSync)(binPath);
|
|
939
|
+
}
|
|
940
|
+
catch {
|
|
941
|
+
return binPath;
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
function isNpxInvocation(binPath) {
|
|
945
|
+
// npm's exec cache lives under .../_npx/<hash>/; older layouts use /npx/.
|
|
946
|
+
return /[\\/]_?npx[\\/]/.test(binPath);
|
|
947
|
+
}
|
|
948
|
+
function updateCommandFor(binPath) {
|
|
949
|
+
const ext = process.platform === "win32" ? ".cmd" : "";
|
|
950
|
+
if (/[\\/]pnpm[\\/]/.test(binPath))
|
|
951
|
+
return { cmd: `pnpm${ext}`, args: ["add", "-g", `${PACKAGE_NAME}@latest`] };
|
|
952
|
+
if (/[\\/]bun[\\/]/.test(binPath))
|
|
953
|
+
return { cmd: "bun", args: ["add", "-g", `${PACKAGE_NAME}@latest`] };
|
|
954
|
+
return {
|
|
955
|
+
cmd: `npm${ext}`,
|
|
956
|
+
args: ["install", "-g", `${PACKAGE_NAME}@latest`],
|
|
957
|
+
};
|
|
958
|
+
}
|
|
959
|
+
async function runUpdate() {
|
|
960
|
+
const binPath = entryScriptPath();
|
|
961
|
+
if (isNpxInvocation(binPath)) {
|
|
962
|
+
console.log(`\n ${style("Running via npx — already using the latest published version each run.", c.dim)}\n`);
|
|
963
|
+
return;
|
|
964
|
+
}
|
|
965
|
+
const { cmd, args } = updateCommandFor(binPath);
|
|
966
|
+
console.log(`\n ${style(`Updating ${PACKAGE_NAME} via ${cmd}...`, c.bold)}\n`);
|
|
967
|
+
const result = (0, child_process_1.spawnSync)(cmd, args, { stdio: "inherit" });
|
|
968
|
+
if (result.status === 0) {
|
|
969
|
+
const latest = await fetchLatestVersion().catch(() => null);
|
|
970
|
+
console.log(`\n ${style("✓", c.green)} ${latest
|
|
971
|
+
? `Updated to v${latest}.`
|
|
972
|
+
: "Updated. Run rmcode --version to confirm."}\n`);
|
|
973
|
+
return;
|
|
974
|
+
}
|
|
975
|
+
console.error(style(`\n Update failed. Run it manually:`, c.red));
|
|
976
|
+
console.error(` ${style([cmd, ...args].join(" "), c.cyan, c.bold)}\n`);
|
|
977
|
+
process.exit(1);
|
|
978
|
+
}
|
|
979
|
+
// ── Update nudge ──────────────────────────────────────────────────────
|
|
980
|
+
//
|
|
981
|
+
// After a successful human-mode review, print at most one dim line when a
|
|
982
|
+
// newer version is published. The registry is queried at most once per
|
|
983
|
+
// 24h (cached in ~/.config/rmcode/update-check.json) and only after the
|
|
984
|
+
// review output has been printed. Any failure here is silently swallowed
|
|
985
|
+
// — the nudge must never affect review output or exit codes.
|
|
986
|
+
const UPDATE_CHECK_TIMEOUT_MS = 1_500;
|
|
987
|
+
const UPDATE_CHECK_TTL_MS = 24 * 60 * 60 * 1000;
|
|
988
|
+
function updateCachePath() {
|
|
989
|
+
return (0, path_1.join)((0, os_1.homedir)(), ".config", "rmcode", "update-check.json");
|
|
990
|
+
}
|
|
991
|
+
async function fetchLatestVersion() {
|
|
992
|
+
const resp = await fetch(REGISTRY_LATEST_URL, {
|
|
993
|
+
signal: AbortSignal.timeout(UPDATE_CHECK_TIMEOUT_MS),
|
|
994
|
+
});
|
|
995
|
+
if (!resp.ok)
|
|
996
|
+
return null;
|
|
997
|
+
const data = (await resp.json());
|
|
998
|
+
return typeof data.version === "string" ? data.version : null;
|
|
999
|
+
}
|
|
1000
|
+
/** Latest published version, from the daily cache when fresh. */
|
|
1001
|
+
async function latestPublishedVersion() {
|
|
1002
|
+
const cachePath = updateCachePath();
|
|
1003
|
+
try {
|
|
1004
|
+
const cached = JSON.parse((0, fs_1.readFileSync)(cachePath, "utf-8"));
|
|
1005
|
+
if (typeof cached.latest === "string" &&
|
|
1006
|
+
typeof cached.checkedAt === "number" &&
|
|
1007
|
+
Date.now() - cached.checkedAt < UPDATE_CHECK_TTL_MS) {
|
|
1008
|
+
return cached.latest;
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
catch {
|
|
1012
|
+
// Missing or unreadable cache — fall through to a fresh fetch.
|
|
1013
|
+
}
|
|
1014
|
+
const latest = await fetchLatestVersion();
|
|
1015
|
+
if (!latest)
|
|
1016
|
+
return null;
|
|
1017
|
+
try {
|
|
1018
|
+
(0, fs_1.mkdirSync)((0, path_1.join)((0, os_1.homedir)(), ".config", "rmcode"), { recursive: true });
|
|
1019
|
+
(0, fs_1.writeFileSync)(cachePath, JSON.stringify({ latest, checkedAt: Date.now() }));
|
|
1020
|
+
}
|
|
1021
|
+
catch {
|
|
1022
|
+
// Cache writes are best-effort.
|
|
1023
|
+
}
|
|
1024
|
+
return latest;
|
|
1025
|
+
}
|
|
1026
|
+
/** Hand-rolled x.y.z compare: 1 if a > b, -1 if a < b, 0 if equal. */
|
|
1027
|
+
function compareVersions(a, b) {
|
|
1028
|
+
const pa = a.split(".").map((n) => parseInt(n, 10));
|
|
1029
|
+
const pb = b.split(".").map((n) => parseInt(n, 10));
|
|
1030
|
+
for (let i = 0; i < 3; i++) {
|
|
1031
|
+
const da = pa[i] || 0;
|
|
1032
|
+
const db = pb[i] || 0;
|
|
1033
|
+
if (da !== db)
|
|
1034
|
+
return da > db ? 1 : -1;
|
|
1035
|
+
}
|
|
1036
|
+
return 0;
|
|
1037
|
+
}
|
|
1038
|
+
async function maybeShowUpdateNudge() {
|
|
1039
|
+
if (noColor || isCI)
|
|
1040
|
+
return;
|
|
1041
|
+
try {
|
|
1042
|
+
const latest = await latestPublishedVersion();
|
|
1043
|
+
if (latest && compareVersions(latest, VERSION) > 0) {
|
|
1044
|
+
console.log(style(` Update available ${VERSION} → ${latest} · run rmcode update`, c.dim));
|
|
904
1045
|
}
|
|
905
1046
|
}
|
|
906
1047
|
catch {
|
|
907
1048
|
/* silent */
|
|
908
1049
|
}
|
|
909
1050
|
}
|
|
1051
|
+
async function enforceLatestCliForReview(jsonMode) {
|
|
1052
|
+
let latest = null;
|
|
1053
|
+
try {
|
|
1054
|
+
latest = await fetchLatestVersion();
|
|
1055
|
+
}
|
|
1056
|
+
catch {
|
|
1057
|
+
return;
|
|
1058
|
+
}
|
|
1059
|
+
if (!latest || compareVersions(latest, VERSION) <= 0)
|
|
1060
|
+
return;
|
|
1061
|
+
const update = updateCommandFor(entryScriptPath());
|
|
1062
|
+
const command = [update.cmd, ...update.args].join(" ");
|
|
1063
|
+
const error = `Update required: rmcode v${latest} is available, but this is v${VERSION}. Run \`${command}\` before reviewing.`;
|
|
1064
|
+
if (jsonMode) {
|
|
1065
|
+
console.log(JSON.stringify({
|
|
1066
|
+
success: false,
|
|
1067
|
+
error,
|
|
1068
|
+
code: "RMC-1006",
|
|
1069
|
+
meta: {
|
|
1070
|
+
currentVersion: VERSION,
|
|
1071
|
+
latestVersion: latest,
|
|
1072
|
+
updateCommand: command,
|
|
1073
|
+
},
|
|
1074
|
+
}));
|
|
1075
|
+
}
|
|
1076
|
+
else {
|
|
1077
|
+
console.error(style(`\n ${error}\n`, c.yellow));
|
|
1078
|
+
}
|
|
1079
|
+
process.exit(1);
|
|
1080
|
+
}
|
|
910
1081
|
function parseArgs(args) {
|
|
911
1082
|
const flags = new Set();
|
|
912
1083
|
const options = {};
|
|
913
1084
|
const positional = [];
|
|
1085
|
+
const optionAliases = {
|
|
1086
|
+
"--lang": "lang",
|
|
1087
|
+
"--title": "title",
|
|
1088
|
+
"--pr-title": "title",
|
|
1089
|
+
"--pr-number": "prNumber",
|
|
1090
|
+
"--source-repo": "sourceRepo",
|
|
1091
|
+
};
|
|
914
1092
|
for (let i = 0; i < args.length; i++) {
|
|
915
1093
|
const arg = args[i];
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
1094
|
+
const eq = arg.indexOf("=");
|
|
1095
|
+
const rawOption = eq > 0 ? arg.slice(0, eq) : arg;
|
|
1096
|
+
const optionName = optionAliases[rawOption];
|
|
1097
|
+
if (optionName) {
|
|
1098
|
+
if (eq > 0) {
|
|
1099
|
+
options[optionName] = arg.slice(eq + 1);
|
|
1100
|
+
}
|
|
1101
|
+
else {
|
|
1102
|
+
options[optionName] = args[i + 1];
|
|
1103
|
+
i++;
|
|
1104
|
+
}
|
|
919
1105
|
}
|
|
920
1106
|
else if (arg.startsWith("-")) {
|
|
921
1107
|
flags.add(arg);
|
|
@@ -958,6 +1144,10 @@ async function main() {
|
|
|
958
1144
|
console.error(style(` Run: rmcode help\n`, c.dim));
|
|
959
1145
|
process.exit(1);
|
|
960
1146
|
}
|
|
1147
|
+
if (positional[0] === "update") {
|
|
1148
|
+
await runUpdate();
|
|
1149
|
+
return;
|
|
1150
|
+
}
|
|
961
1151
|
if (positional[0] === "install") {
|
|
962
1152
|
console.log(`\n ${style("Install the GitHub App for automatic PR reviews:", c.bold)}\n`);
|
|
963
1153
|
console.log(` ${style("https://github.com/apps/rmcode-ai", c.cyan, c.bold)}\n`);
|
|
@@ -988,11 +1178,13 @@ async function main() {
|
|
|
988
1178
|
}
|
|
989
1179
|
const jsonMode = flags.has("--json");
|
|
990
1180
|
const failOnFindings = flags.has("--fail-on-findings");
|
|
1181
|
+
const contextOptions = contextOptionsFromCli(options);
|
|
991
1182
|
if (positional.length > 1) {
|
|
992
1183
|
console.error(style(`\n Unknown command: ${positional[0]}`, c.red));
|
|
993
1184
|
console.error(style(` Run: rmcode help\n`, c.dim));
|
|
994
1185
|
process.exit(1);
|
|
995
1186
|
}
|
|
1187
|
+
await enforceLatestCliForReview(jsonMode);
|
|
996
1188
|
// Brand header for review runs — stderr so any stdout consumers stay
|
|
997
1189
|
// safe; hidden in --json, non-TTY, NO_COLOR, and CI.
|
|
998
1190
|
if (!jsonMode && !noColor && !isCI) {
|
|
@@ -1000,7 +1192,6 @@ async function main() {
|
|
|
1000
1192
|
}
|
|
1001
1193
|
// Piped stdin
|
|
1002
1194
|
if (hasPipedStdin()) {
|
|
1003
|
-
const lang = options.lang || "javascript";
|
|
1004
1195
|
const rl = (0, readline_1.createInterface)({ input: process.stdin });
|
|
1005
1196
|
const lines = [];
|
|
1006
1197
|
for await (const line of rl)
|
|
@@ -1010,11 +1201,12 @@ async function main() {
|
|
|
1010
1201
|
console.error(style(" No input received on stdin.", c.red));
|
|
1011
1202
|
process.exit(1);
|
|
1012
1203
|
}
|
|
1204
|
+
const stdinType = looksLikeUnifiedDiff(code) ? "diff" : "snippet";
|
|
1205
|
+
const stdinFiles = stdinType === "diff" ? filesFromDiff(code) : [];
|
|
1206
|
+
const lang = options.lang || detectLanguage(stdinFiles);
|
|
1013
1207
|
const startedAt = Date.now();
|
|
1014
1208
|
const spinner = createSpinner(`Uploading review request (stdin, ${lang})`);
|
|
1015
1209
|
try {
|
|
1016
|
-
const stdinType = looksLikeUnifiedDiff(code) ? "diff" : "snippet";
|
|
1017
|
-
const stdinFiles = stdinType === "diff" ? filesFromDiff(code) : [];
|
|
1018
1210
|
const result = await callAPI(code, lang, stdinType, stdinFiles, null, spinner);
|
|
1019
1211
|
spinner.stop("Reviewed stdin");
|
|
1020
1212
|
if (jsonMode) {
|
|
@@ -1054,9 +1246,9 @@ async function main() {
|
|
|
1054
1246
|
console.error(style(` ${file} is empty.`, c.yellow));
|
|
1055
1247
|
process.exit(0);
|
|
1056
1248
|
}
|
|
1057
|
-
await runReview(code, [file], file, jsonMode, failOnFindings, "file", detectLanguage([file]));
|
|
1249
|
+
await runReview(code, [file], file, jsonMode, failOnFindings, "file", detectLanguage([file]), undefined, contextOptions);
|
|
1058
1250
|
if (!jsonMode)
|
|
1059
|
-
await
|
|
1251
|
+
await maybeShowUpdateNudge();
|
|
1060
1252
|
return;
|
|
1061
1253
|
}
|
|
1062
1254
|
// Git modes
|
|
@@ -1101,14 +1293,14 @@ async function main() {
|
|
|
1101
1293
|
process.exit(0);
|
|
1102
1294
|
}
|
|
1103
1295
|
}
|
|
1104
|
-
await runReview(diff, files, label, jsonMode, failOnFindings, "diff", undefined, baseRef);
|
|
1296
|
+
await runReview(diff, files, label, jsonMode, failOnFindings, "diff", undefined, baseRef, contextOptions);
|
|
1105
1297
|
if (!jsonMode && !API_KEY) {
|
|
1106
1298
|
console.log(style(` Get ${FREE_PLAN_CREDITS_PER_MONTH} credits/month free: rmcode login`, c.dim));
|
|
1107
1299
|
console.log(style(" Auto-review every PR: rmcode install", c.dim));
|
|
1108
1300
|
console.log();
|
|
1109
1301
|
}
|
|
1110
1302
|
if (!jsonMode)
|
|
1111
|
-
await
|
|
1303
|
+
await maybeShowUpdateNudge();
|
|
1112
1304
|
}
|
|
1113
1305
|
main()
|
|
1114
1306
|
.then(() => {
|
package/package.json
CHANGED