@plannotator/opencode 0.19.10 → 0.19.11
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/commands/plannotator-review.md +1 -1
- package/dist/index.js +986 -374
- package/package.json +2 -2
- package/plannotator.html +3 -3
- package/review-editor.html +98 -51
package/dist/index.js
CHANGED
|
@@ -42405,9 +42405,9 @@ var Thread = class {
|
|
|
42405
42405
|
stderrChunks.push(data);
|
|
42406
42406
|
});
|
|
42407
42407
|
}
|
|
42408
|
-
const exitPromise = new Promise((
|
|
42408
|
+
const exitPromise = new Promise((resolve6) => {
|
|
42409
42409
|
child.once("exit", (code, signal) => {
|
|
42410
|
-
|
|
42410
|
+
resolve6({ code, signal });
|
|
42411
42411
|
});
|
|
42412
42412
|
});
|
|
42413
42413
|
const rl2 = readline.createInterface({
|
|
@@ -42910,8 +42910,8 @@ class PiProcess {
|
|
|
42910
42910
|
}
|
|
42911
42911
|
sendAndWait(command) {
|
|
42912
42912
|
const id = `req_${++this.nextId}`;
|
|
42913
|
-
return new Promise((
|
|
42914
|
-
this.pendingRequests.set(id, { resolve:
|
|
42913
|
+
return new Promise((resolve6, reject) => {
|
|
42914
|
+
this.pendingRequests.set(id, { resolve: resolve6, reject });
|
|
42915
42915
|
this.send({ ...command, id });
|
|
42916
42916
|
});
|
|
42917
42917
|
}
|
|
@@ -43052,15 +43052,15 @@ var init_pi_sdk = __esm(() => {
|
|
|
43052
43052
|
}
|
|
43053
43053
|
const effectivePrompt = buildEffectivePrompt(prompt, this.config.systemPrompt, this._firstQuerySent);
|
|
43054
43054
|
const queue = [];
|
|
43055
|
-
let
|
|
43055
|
+
let resolve6 = null;
|
|
43056
43056
|
let done = false;
|
|
43057
43057
|
const push = (msg) => {
|
|
43058
43058
|
queue.push(msg);
|
|
43059
|
-
|
|
43059
|
+
resolve6?.();
|
|
43060
43060
|
};
|
|
43061
43061
|
const finish = () => {
|
|
43062
43062
|
done = true;
|
|
43063
|
-
|
|
43063
|
+
resolve6?.();
|
|
43064
43064
|
};
|
|
43065
43065
|
const unsubscribe = this.process.onEvent((event) => {
|
|
43066
43066
|
const mapped = mapPiEvent(event, this.id);
|
|
@@ -43092,9 +43092,9 @@ var init_pi_sdk = __esm(() => {
|
|
|
43092
43092
|
yield queue.shift();
|
|
43093
43093
|
} else {
|
|
43094
43094
|
await new Promise((r9) => {
|
|
43095
|
-
|
|
43095
|
+
resolve6 = r9;
|
|
43096
43096
|
});
|
|
43097
|
-
|
|
43097
|
+
resolve6 = null;
|
|
43098
43098
|
}
|
|
43099
43099
|
}
|
|
43100
43100
|
} finally {
|
|
@@ -43130,7 +43130,7 @@ var init_types_gen = () => {};
|
|
|
43130
43130
|
// ../../node_modules/.bun/@opencode-ai+sdk@1.3.5/node_modules/@opencode-ai/sdk/dist/gen/core/serverSentEvents.gen.js
|
|
43131
43131
|
var createSseClient = ({ onSseError, onSseEvent, responseTransformer, responseValidator, sseDefaultRetryDelay, sseMaxRetryAttempts, sseMaxRetryDelay, sseSleepFn, url, ...options }) => {
|
|
43132
43132
|
let lastEventId;
|
|
43133
|
-
const sleep = sseSleepFn ?? ((ms) => new Promise((
|
|
43133
|
+
const sleep = sseSleepFn ?? ((ms) => new Promise((resolve6) => setTimeout(resolve6, ms)));
|
|
43134
43134
|
const createStream = async function* () {
|
|
43135
43135
|
let retryDelay = sseDefaultRetryDelay ?? 3000;
|
|
43136
43136
|
let attempt = 0;
|
|
@@ -44531,7 +44531,7 @@ async function createOpencodeServer(options) {
|
|
|
44531
44531
|
OPENCODE_CONFIG_CONTENT: JSON.stringify(options.config ?? {})
|
|
44532
44532
|
}
|
|
44533
44533
|
});
|
|
44534
|
-
const url = await new Promise((
|
|
44534
|
+
const url = await new Promise((resolve6, reject) => {
|
|
44535
44535
|
const id = setTimeout(() => {
|
|
44536
44536
|
reject(new Error(`Timeout waiting for server to start after ${options.timeout}ms`));
|
|
44537
44537
|
}, options.timeout);
|
|
@@ -44547,7 +44547,7 @@ async function createOpencodeServer(options) {
|
|
|
44547
44547
|
throw new Error(`Failed to parse server url from output: ${line}`);
|
|
44548
44548
|
}
|
|
44549
44549
|
clearTimeout(id);
|
|
44550
|
-
|
|
44550
|
+
resolve6(match[1]);
|
|
44551
44551
|
return;
|
|
44552
44552
|
}
|
|
44553
44553
|
}
|
|
@@ -61846,6 +61846,33 @@ async function startPlannotatorServer(options) {
|
|
|
61846
61846
|
|
|
61847
61847
|
// ../../packages/shared/review-core.ts
|
|
61848
61848
|
import { resolve as resolvePath } from "path";
|
|
61849
|
+
var JJ_TRUNK_REVSET = "trunk()";
|
|
61850
|
+
function parseRemoteBookmark(target) {
|
|
61851
|
+
const at = target.lastIndexOf("@");
|
|
61852
|
+
if (at <= 0 || at === target.length - 1)
|
|
61853
|
+
return null;
|
|
61854
|
+
return { name: target.slice(0, at), remote: target.slice(at + 1) };
|
|
61855
|
+
}
|
|
61856
|
+
function jjCompareTargetRevset(target) {
|
|
61857
|
+
const remoteBookmark = parseRemoteBookmark(target);
|
|
61858
|
+
if (remoteBookmark) {
|
|
61859
|
+
return `remote_bookmarks(exact:${quoteJjString(remoteBookmark.name)}, exact:${quoteJjString(remoteBookmark.remote)})`;
|
|
61860
|
+
}
|
|
61861
|
+
const localBookmark = parseJjBookmarkName(target);
|
|
61862
|
+
return localBookmark ? `bookmarks(exact:${quoteJjString(localBookmark)})` : target;
|
|
61863
|
+
}
|
|
61864
|
+
function jjLineBaseRevset(target) {
|
|
61865
|
+
const compareTarget = jjCompareTargetRevset(target);
|
|
61866
|
+
return `heads(::@ & ::(${compareTarget}))`;
|
|
61867
|
+
}
|
|
61868
|
+
function parseJjBookmarkName(target) {
|
|
61869
|
+
if (!target || target.startsWith("@") || /[()\s]/.test(target))
|
|
61870
|
+
return null;
|
|
61871
|
+
return target;
|
|
61872
|
+
}
|
|
61873
|
+
function quoteJjString(value) {
|
|
61874
|
+
return JSON.stringify(value);
|
|
61875
|
+
}
|
|
61849
61876
|
async function getCurrentBranch2(runtime, cwd) {
|
|
61850
61877
|
const result = await runtime.runGit(["rev-parse", "--abbrev-ref", "HEAD"], { cwd });
|
|
61851
61878
|
return result.exitCode === 0 ? result.stdout.trim() || "HEAD" : "HEAD";
|
|
@@ -61972,7 +61999,21 @@ async function getGitContext(runtime, cwd) {
|
|
|
61972
61999
|
diffOptions,
|
|
61973
62000
|
worktrees: worktrees.filter((wt) => wt.path !== currentTreePath),
|
|
61974
62001
|
availableBranches,
|
|
61975
|
-
|
|
62002
|
+
compareTarget: {
|
|
62003
|
+
diffTypes: ["branch", "merge-base"],
|
|
62004
|
+
fallback: "main",
|
|
62005
|
+
picker: {
|
|
62006
|
+
rowLabel: "compare against",
|
|
62007
|
+
triggerLabel: "base",
|
|
62008
|
+
triggerTitlePrefix: "Review base",
|
|
62009
|
+
searchPlaceholder: "Search branches\u2026",
|
|
62010
|
+
emptyText: "No branches match.",
|
|
62011
|
+
localGroupLabel: "Local",
|
|
62012
|
+
remoteGroupLabel: "Remote"
|
|
62013
|
+
}
|
|
62014
|
+
},
|
|
62015
|
+
cwd,
|
|
62016
|
+
vcsType: "git"
|
|
61976
62017
|
};
|
|
61977
62018
|
}
|
|
61978
62019
|
async function getUntrackedFileDiffs(runtime, srcPrefix = "a/", dstPrefix = "b/", cwd, options) {
|
|
@@ -62171,9 +62212,6 @@ async function runGitDiff(runtime, diffType, defaultBranch = "main", externalCwd
|
|
|
62171
62212
|
}
|
|
62172
62213
|
return { patch, label };
|
|
62173
62214
|
}
|
|
62174
|
-
async function runGitDiffWithContext(runtime, diffType, gitContext, options) {
|
|
62175
|
-
return runGitDiff(runtime, diffType, gitContext.defaultBranch, gitContext.cwd, options);
|
|
62176
|
-
}
|
|
62177
62215
|
async function getFileContentsForDiff(runtime, diffType, defaultBranch, filePath, oldPath, cwd) {
|
|
62178
62216
|
const oldFilePath = oldPath || filePath;
|
|
62179
62217
|
let effectiveDiffType = diffType;
|
|
@@ -62263,53 +62301,507 @@ function parseP4DiffType(diffType) {
|
|
|
62263
62301
|
return null;
|
|
62264
62302
|
}
|
|
62265
62303
|
|
|
62266
|
-
// ../../packages/
|
|
62267
|
-
|
|
62268
|
-
|
|
62269
|
-
|
|
62270
|
-
|
|
62271
|
-
|
|
62272
|
-
});
|
|
62273
|
-
|
|
62274
|
-
|
|
62275
|
-
|
|
62304
|
+
// ../../packages/shared/vcs-core.ts
|
|
62305
|
+
import { isAbsolute as isAbsolute2, relative, resolve as resolve5 } from "path";
|
|
62306
|
+
|
|
62307
|
+
// ../../packages/shared/jj-core.ts
|
|
62308
|
+
import { basename as basename2 } from "path";
|
|
62309
|
+
async function detectJjWorkspace(runtime, cwd) {
|
|
62310
|
+
const result = await runtime.runJj(["workspace", "root"], { cwd });
|
|
62311
|
+
return result.exitCode === 0 ? result.stdout.trim() || null : null;
|
|
62312
|
+
}
|
|
62313
|
+
async function getJjContext(runtime, cwd) {
|
|
62314
|
+
const root3 = await detectJjWorkspace(runtime, cwd);
|
|
62315
|
+
const targets = await listJjCompareTargets(runtime, root3 ?? cwd);
|
|
62316
|
+
const defaultTarget = selectDefaultJjCompareTarget(targets);
|
|
62317
|
+
const contextCwd = root3 ?? cwd;
|
|
62318
|
+
return {
|
|
62319
|
+
currentBranch: "",
|
|
62320
|
+
defaultBranch: defaultTarget,
|
|
62321
|
+
diffOptions: [
|
|
62322
|
+
{ id: "jj-current", label: "Current change" },
|
|
62323
|
+
{ id: "jj-last", label: "Last change" },
|
|
62324
|
+
{ id: "jj-line", label: "Line of work" },
|
|
62325
|
+
{ id: "jj-all", label: "All files" }
|
|
62326
|
+
],
|
|
62327
|
+
worktrees: [],
|
|
62328
|
+
availableBranches: targets,
|
|
62329
|
+
compareTarget: {
|
|
62330
|
+
diffTypes: ["jj-line"],
|
|
62331
|
+
fallback: defaultTarget,
|
|
62332
|
+
picker: {
|
|
62333
|
+
rowLabel: "from revision",
|
|
62334
|
+
triggerLabel: "revision",
|
|
62335
|
+
triggerTitlePrefix: "Compare against",
|
|
62336
|
+
searchPlaceholder: "Search bookmarks...",
|
|
62337
|
+
emptyText: "No bookmarks match.",
|
|
62338
|
+
localGroupLabel: "Bookmarks",
|
|
62339
|
+
remoteGroupLabel: "Remote bookmarks"
|
|
62340
|
+
}
|
|
62341
|
+
},
|
|
62342
|
+
repository: contextCwd ? { displayFallback: basename2(contextCwd) } : undefined,
|
|
62343
|
+
cwd: contextCwd,
|
|
62344
|
+
vcsType: "jj"
|
|
62345
|
+
};
|
|
62346
|
+
}
|
|
62347
|
+
async function runJjDiff(runtime, diffType, defaultBranch, cwd, options) {
|
|
62348
|
+
const compareTarget = defaultBranch.length > 0 ? defaultBranch : JJ_TRUNK_REVSET;
|
|
62349
|
+
const args = getJjDiffArgs(diffType, compareTarget, options);
|
|
62350
|
+
if (!args)
|
|
62351
|
+
return { patch: "", label: "Unknown diff type" };
|
|
62352
|
+
const result = await runtime.runJj(args.args, { cwd });
|
|
62353
|
+
if (result.exitCode !== 0) {
|
|
62354
|
+
return { patch: "", label: args.label, error: firstErrorLine(result.stderr) };
|
|
62276
62355
|
}
|
|
62277
|
-
const
|
|
62278
|
-
|
|
62279
|
-
new Response(proc.stderr).text(),
|
|
62280
|
-
proc.exited
|
|
62281
|
-
]);
|
|
62282
|
-
if (timer)
|
|
62283
|
-
clearTimeout(timer);
|
|
62284
|
-
return { stdout, stderr, exitCode };
|
|
62356
|
+
const patch = options?.hideWhitespace ? dropHunklessGitDiffChunks(result.stdout) : result.stdout;
|
|
62357
|
+
return { patch, label: args.label };
|
|
62285
62358
|
}
|
|
62286
|
-
|
|
62287
|
-
|
|
62288
|
-
|
|
62289
|
-
|
|
62290
|
-
|
|
62291
|
-
|
|
62292
|
-
|
|
62359
|
+
function dropHunklessGitDiffChunks(patch) {
|
|
62360
|
+
if (!patch.includes("diff --git "))
|
|
62361
|
+
return patch;
|
|
62362
|
+
const chunks = patch.split(/^diff --git /m);
|
|
62363
|
+
const prefix = chunks.shift() ?? "";
|
|
62364
|
+
const filtered = chunks.filter(hasReviewableGitDiffChunk).map((chunk) => `diff --git ${chunk}`).join("");
|
|
62365
|
+
return `${prefix}${filtered}`;
|
|
62366
|
+
}
|
|
62367
|
+
function hasReviewableGitDiffChunk(chunk) {
|
|
62368
|
+
if (/^@@@? /m.test(chunk))
|
|
62369
|
+
return true;
|
|
62370
|
+
return /^(new file mode|deleted file mode|old mode|new mode|rename from|rename to|copy from|copy to|GIT binary patch|Binary files |similarity index|dissimilarity index)/m.test(chunk);
|
|
62371
|
+
}
|
|
62372
|
+
async function getJjFileContentsForDiff(runtime, diffType, defaultBranch, filePath, oldPath, cwd) {
|
|
62373
|
+
validateFilePath(filePath);
|
|
62374
|
+
if (oldPath)
|
|
62375
|
+
validateFilePath(oldPath);
|
|
62376
|
+
const oldFilePath = oldPath === undefined || oldPath.length === 0 ? filePath : oldPath;
|
|
62377
|
+
const root3 = await detectJjWorkspace(runtime, cwd);
|
|
62378
|
+
const fileCwd = root3 ?? cwd;
|
|
62379
|
+
switch (diffType) {
|
|
62380
|
+
case "jj-current":
|
|
62381
|
+
return {
|
|
62382
|
+
oldContent: await jjFileContent(runtime, "@-", oldFilePath, fileCwd),
|
|
62383
|
+
newContent: await jjFileContent(runtime, "@", filePath, fileCwd)
|
|
62384
|
+
};
|
|
62385
|
+
case "jj-last": {
|
|
62386
|
+
const parentRev = await resolveJjParent(runtime, "@-", fileCwd);
|
|
62387
|
+
return {
|
|
62388
|
+
oldContent: parentRev ? await jjFileContent(runtime, parentRev, oldFilePath, fileCwd) : null,
|
|
62389
|
+
newContent: await jjFileContent(runtime, "@-", filePath, fileCwd)
|
|
62390
|
+
};
|
|
62391
|
+
}
|
|
62392
|
+
case "jj-line": {
|
|
62393
|
+
const compareTarget = defaultBranch.length > 0 ? defaultBranch : JJ_TRUNK_REVSET;
|
|
62394
|
+
return {
|
|
62395
|
+
oldContent: await jjFileContent(runtime, jjLineBaseRevset(compareTarget), oldFilePath, fileCwd),
|
|
62396
|
+
newContent: await jjFileContent(runtime, "@", filePath, fileCwd)
|
|
62397
|
+
};
|
|
62293
62398
|
}
|
|
62399
|
+
case "jj-all":
|
|
62400
|
+
return {
|
|
62401
|
+
oldContent: null,
|
|
62402
|
+
newContent: await jjFileContent(runtime, "@", filePath, fileCwd)
|
|
62403
|
+
};
|
|
62404
|
+
default:
|
|
62405
|
+
return { oldContent: null, newContent: null };
|
|
62294
62406
|
}
|
|
62295
|
-
};
|
|
62296
|
-
function getGitContext2(cwd) {
|
|
62297
|
-
return getGitContext(runtime, cwd);
|
|
62298
62407
|
}
|
|
62299
|
-
function
|
|
62300
|
-
|
|
62408
|
+
function getJjDiffArgs(diffType, compareTarget, options) {
|
|
62409
|
+
const whitespaceArgs = options?.hideWhitespace ? ["-w"] : [];
|
|
62410
|
+
switch (diffType) {
|
|
62411
|
+
case "jj-current":
|
|
62412
|
+
return { args: ["diff", "--git", ...whitespaceArgs, "-r", "@"], label: "Current change" };
|
|
62413
|
+
case "jj-last":
|
|
62414
|
+
return { args: ["diff", "--git", ...whitespaceArgs, "-r", "@-"], label: "Last change" };
|
|
62415
|
+
case "jj-line":
|
|
62416
|
+
return {
|
|
62417
|
+
args: ["diff", "--git", ...whitespaceArgs, "--from", jjLineBaseRevset(compareTarget), "--to", "@"],
|
|
62418
|
+
label: `Line of work vs ${compareTarget}`
|
|
62419
|
+
};
|
|
62420
|
+
case "jj-all":
|
|
62421
|
+
return { args: ["diff", "--git", ...whitespaceArgs, "--from", "root()", "--to", "@"], label: "All files" };
|
|
62422
|
+
default:
|
|
62423
|
+
return null;
|
|
62424
|
+
}
|
|
62425
|
+
}
|
|
62426
|
+
function selectDefaultJjCompareTarget(targets) {
|
|
62427
|
+
const preferredNames = ["main", "develop", "master", "trunk"];
|
|
62428
|
+
for (const name of preferredNames) {
|
|
62429
|
+
const preferredRemote = [
|
|
62430
|
+
`${name}@origin`,
|
|
62431
|
+
`${name}@upstream`,
|
|
62432
|
+
`${name}@git`,
|
|
62433
|
+
...targets.remote.filter((target) => target.startsWith(`${name}@`)).sort()
|
|
62434
|
+
].find((target) => targets.remote.includes(target));
|
|
62435
|
+
if (preferredRemote)
|
|
62436
|
+
return preferredRemote;
|
|
62437
|
+
if (targets.local.includes(name))
|
|
62438
|
+
return name;
|
|
62439
|
+
}
|
|
62440
|
+
return JJ_TRUNK_REVSET;
|
|
62441
|
+
}
|
|
62442
|
+
async function listJjCompareTargets(runtime, cwd) {
|
|
62443
|
+
const [localResult, remoteResult] = await Promise.all([
|
|
62444
|
+
runtime.runJj([
|
|
62445
|
+
"bookmark",
|
|
62446
|
+
"list",
|
|
62447
|
+
"--sort",
|
|
62448
|
+
"committer-date-",
|
|
62449
|
+
"--sort",
|
|
62450
|
+
"name",
|
|
62451
|
+
"-T",
|
|
62452
|
+
"if(remote, '', if(present, json(name) ++ '\\n', ''))"
|
|
62453
|
+
], { cwd }),
|
|
62454
|
+
runtime.runJj([
|
|
62455
|
+
"bookmark",
|
|
62456
|
+
"list",
|
|
62457
|
+
"--all-remotes",
|
|
62458
|
+
"--sort",
|
|
62459
|
+
"committer-date-",
|
|
62460
|
+
"--sort",
|
|
62461
|
+
"name",
|
|
62462
|
+
"-T",
|
|
62463
|
+
"if(remote, if(present, json(name) ++ '\\t' ++ json(remote) ++ '\\n', ''), '')"
|
|
62464
|
+
], { cwd })
|
|
62465
|
+
]);
|
|
62466
|
+
const local = localResult.exitCode === 0 ? parseJjBookmarkList(localResult.stdout) : [];
|
|
62467
|
+
const remote = remoteResult.exitCode === 0 ? parseJjRemoteBookmarkList(remoteResult.stdout) : [];
|
|
62468
|
+
return {
|
|
62469
|
+
local,
|
|
62470
|
+
remote
|
|
62471
|
+
};
|
|
62472
|
+
}
|
|
62473
|
+
function parseJjBookmarkList(stdout) {
|
|
62474
|
+
const seen = new Set;
|
|
62475
|
+
const bookmarks = [];
|
|
62476
|
+
for (const rawLine of splitJjTemplateRecords(stdout)) {
|
|
62477
|
+
const line = rawLine.trim();
|
|
62478
|
+
if (!line)
|
|
62479
|
+
continue;
|
|
62480
|
+
const bookmark = parseSerializedJjString(line);
|
|
62481
|
+
if (!bookmark || seen.has(bookmark))
|
|
62482
|
+
continue;
|
|
62483
|
+
seen.add(bookmark);
|
|
62484
|
+
bookmarks.push(bookmark);
|
|
62485
|
+
}
|
|
62486
|
+
return bookmarks;
|
|
62487
|
+
}
|
|
62488
|
+
function parseJjRemoteBookmarkList(stdout) {
|
|
62489
|
+
const seen = new Set;
|
|
62490
|
+
const bookmarks = [];
|
|
62491
|
+
for (const rawLine of splitJjTemplateRecords(stdout)) {
|
|
62492
|
+
const line = rawLine.trim();
|
|
62493
|
+
if (!line)
|
|
62494
|
+
continue;
|
|
62495
|
+
const fields = splitJjTemplateFields(line);
|
|
62496
|
+
if (!fields)
|
|
62497
|
+
continue;
|
|
62498
|
+
const [nameField, remoteField] = fields;
|
|
62499
|
+
const name = parseSerializedJjString(nameField);
|
|
62500
|
+
const remote = parseSerializedJjString(remoteField);
|
|
62501
|
+
if (!name || !remote)
|
|
62502
|
+
continue;
|
|
62503
|
+
const bookmark = `${name}@${remote}`;
|
|
62504
|
+
if (seen.has(bookmark))
|
|
62505
|
+
continue;
|
|
62506
|
+
seen.add(bookmark);
|
|
62507
|
+
bookmarks.push(bookmark);
|
|
62508
|
+
}
|
|
62509
|
+
return bookmarks;
|
|
62510
|
+
}
|
|
62511
|
+
function splitJjTemplateRecords(stdout) {
|
|
62512
|
+
return stdout.split(/\n|\\n/g);
|
|
62513
|
+
}
|
|
62514
|
+
function splitJjTemplateFields(line) {
|
|
62515
|
+
const literalTab = line.indexOf("\t");
|
|
62516
|
+
if (literalTab !== -1)
|
|
62517
|
+
return [line.slice(0, literalTab), line.slice(literalTab + 1)];
|
|
62518
|
+
const escapedTab = line.indexOf("\\t");
|
|
62519
|
+
if (escapedTab !== -1)
|
|
62520
|
+
return [line.slice(0, escapedTab), line.slice(escapedTab + 2)];
|
|
62521
|
+
return null;
|
|
62522
|
+
}
|
|
62523
|
+
function parseSerializedJjString(value) {
|
|
62524
|
+
try {
|
|
62525
|
+
const parsed = JSON.parse(value);
|
|
62526
|
+
return typeof parsed === "string" ? parsed : null;
|
|
62527
|
+
} catch {
|
|
62528
|
+
return null;
|
|
62529
|
+
}
|
|
62530
|
+
}
|
|
62531
|
+
async function jjFileContent(runtime, rev, filePath, cwd) {
|
|
62532
|
+
const result = await runtime.runJj(["file", "show", "-r", rev, "--", filePath], { cwd });
|
|
62533
|
+
return result.exitCode === 0 ? result.stdout : null;
|
|
62534
|
+
}
|
|
62535
|
+
async function resolveJjParent(runtime, rev, cwd) {
|
|
62536
|
+
const result = await runtime.runJj(["log", "-r", rev, "--no-graph", "-T", "parents.map(|p| p.change_id()).join(' ')", "--limit", "1"], { cwd });
|
|
62537
|
+
const parent = result.stdout.trim().split(/\s+/).find(Boolean);
|
|
62538
|
+
return result.exitCode === 0 && parent ? parent : null;
|
|
62539
|
+
}
|
|
62540
|
+
function firstErrorLine(stderr) {
|
|
62541
|
+
const line = stderr.split(`
|
|
62542
|
+
`).find((value) => value.trim().length > 0)?.trim();
|
|
62543
|
+
if (!line)
|
|
62544
|
+
return;
|
|
62545
|
+
return line.length > 200 ? line.slice(0, 200) + "..." : line;
|
|
62546
|
+
}
|
|
62547
|
+
|
|
62548
|
+
// ../../packages/shared/vcs-core.ts
|
|
62549
|
+
var GIT_DIFF_TYPES = new Set(["uncommitted", "staged", "unstaged", "last-commit", "branch", "merge-base", "all"]);
|
|
62550
|
+
var JJ_DIFF_TYPES = new Set(["jj-current", "jj-last", "jj-line", "jj-all"]);
|
|
62551
|
+
function selectNearestProvider(candidates, cwd) {
|
|
62552
|
+
if (candidates.length === 0)
|
|
62553
|
+
return null;
|
|
62554
|
+
const effectiveCwd = resolve5(cwd ?? process.cwd());
|
|
62555
|
+
const ranked = candidates.map((candidate) => ({
|
|
62556
|
+
...candidate,
|
|
62557
|
+
rootDepth: candidate.root ? vcsRootDepth(candidate.root) : -1,
|
|
62558
|
+
containsCwd: candidate.root ? isSameOrAncestor(candidate.root, effectiveCwd) : false
|
|
62559
|
+
})).sort((a2, b3) => {
|
|
62560
|
+
if (a2.containsCwd !== b3.containsCwd)
|
|
62561
|
+
return a2.containsCwd ? -1 : 1;
|
|
62562
|
+
if (a2.rootDepth !== b3.rootDepth)
|
|
62563
|
+
return b3.rootDepth - a2.rootDepth;
|
|
62564
|
+
return a2.order - b3.order;
|
|
62565
|
+
});
|
|
62566
|
+
return ranked[0]?.provider ?? null;
|
|
62567
|
+
}
|
|
62568
|
+
function isSameOrAncestor(root3, child) {
|
|
62569
|
+
const relativePath = relative(resolve5(root3), child);
|
|
62570
|
+
return relativePath === "" || !relativePath.startsWith("..") && !isAbsolute2(relativePath);
|
|
62301
62571
|
}
|
|
62302
|
-
function
|
|
62303
|
-
return
|
|
62572
|
+
function vcsRootDepth(root3) {
|
|
62573
|
+
return resolve5(root3).split(/[\\/]+/).filter(Boolean).length;
|
|
62304
62574
|
}
|
|
62305
|
-
function
|
|
62306
|
-
return
|
|
62575
|
+
function createGitProvider(runtime) {
|
|
62576
|
+
return {
|
|
62577
|
+
id: "git",
|
|
62578
|
+
async detect(cwd) {
|
|
62579
|
+
try {
|
|
62580
|
+
const result = await runtime.runGit(["rev-parse", "--is-inside-work-tree"], { cwd });
|
|
62581
|
+
return result.exitCode === 0;
|
|
62582
|
+
} catch {
|
|
62583
|
+
return false;
|
|
62584
|
+
}
|
|
62585
|
+
},
|
|
62586
|
+
async getRoot(cwd) {
|
|
62587
|
+
const result = await runtime.runGit(["rev-parse", "--show-toplevel"], { cwd });
|
|
62588
|
+
return result.exitCode === 0 ? result.stdout.trim() || null : null;
|
|
62589
|
+
},
|
|
62590
|
+
ownsDiffType(diffType) {
|
|
62591
|
+
return GIT_DIFF_TYPES.has(diffType) || diffType.startsWith("worktree:");
|
|
62592
|
+
},
|
|
62593
|
+
canStageFiles(diffType) {
|
|
62594
|
+
const effectiveDiffType = parseWorktreeDiffType(diffType)?.subType ?? diffType;
|
|
62595
|
+
return effectiveDiffType === "uncommitted" || effectiveDiffType === "unstaged";
|
|
62596
|
+
},
|
|
62597
|
+
getContext(cwd) {
|
|
62598
|
+
return getGitContext(runtime, cwd);
|
|
62599
|
+
},
|
|
62600
|
+
runDiff(diffType, defaultBranch, cwd, options) {
|
|
62601
|
+
return runGitDiff(runtime, diffType, defaultBranch, cwd, options);
|
|
62602
|
+
},
|
|
62603
|
+
getFileContents(diffType, defaultBranch, filePath, oldPath, cwd) {
|
|
62604
|
+
return getFileContentsForDiff(runtime, diffType, defaultBranch, filePath, oldPath, cwd);
|
|
62605
|
+
},
|
|
62606
|
+
stageFile(filePath, cwd) {
|
|
62607
|
+
return gitAddFile(runtime, filePath, cwd);
|
|
62608
|
+
},
|
|
62609
|
+
unstageFile(filePath, cwd) {
|
|
62610
|
+
return gitResetFile(runtime, filePath, cwd);
|
|
62611
|
+
},
|
|
62612
|
+
detectRemoteDefaultCompareTarget(cwd) {
|
|
62613
|
+
return detectRemoteDefaultBranch(runtime, cwd);
|
|
62614
|
+
},
|
|
62615
|
+
resolveCwd(diffType, fallbackCwd) {
|
|
62616
|
+
const parsed = parseWorktreeDiffType(diffType);
|
|
62617
|
+
return parsed?.path ?? fallbackCwd;
|
|
62618
|
+
}
|
|
62619
|
+
};
|
|
62307
62620
|
}
|
|
62308
|
-
function
|
|
62309
|
-
return
|
|
62621
|
+
function createJjProvider(runtime) {
|
|
62622
|
+
return {
|
|
62623
|
+
id: "jj",
|
|
62624
|
+
async detect(cwd) {
|
|
62625
|
+
return await detectJjWorkspace(runtime, cwd) !== null;
|
|
62626
|
+
},
|
|
62627
|
+
getRoot(cwd) {
|
|
62628
|
+
return detectJjWorkspace(runtime, cwd);
|
|
62629
|
+
},
|
|
62630
|
+
ownsDiffType(diffType) {
|
|
62631
|
+
return JJ_DIFF_TYPES.has(diffType);
|
|
62632
|
+
},
|
|
62633
|
+
getContext(cwd) {
|
|
62634
|
+
return getJjContext(runtime, cwd);
|
|
62635
|
+
},
|
|
62636
|
+
runDiff(diffType, defaultBranch, cwd, options) {
|
|
62637
|
+
return runJjDiff(runtime, diffType, defaultBranch, cwd, options);
|
|
62638
|
+
},
|
|
62639
|
+
getFileContents(diffType, defaultBranch, filePath, oldPath, cwd) {
|
|
62640
|
+
return getJjFileContentsForDiff(runtime, diffType, defaultBranch, filePath, oldPath, cwd);
|
|
62641
|
+
}
|
|
62642
|
+
};
|
|
62310
62643
|
}
|
|
62311
|
-
function
|
|
62312
|
-
|
|
62644
|
+
function createVcsApi(providers) {
|
|
62645
|
+
const providerList = [...providers];
|
|
62646
|
+
const defaultProvider = providerList.find((provider) => provider.id === "git") ?? providerList[0];
|
|
62647
|
+
const vcsCache = new Map;
|
|
62648
|
+
if (!defaultProvider) {
|
|
62649
|
+
throw new Error("createVcsApi requires at least one provider");
|
|
62650
|
+
}
|
|
62651
|
+
async function detectVcs(cwd) {
|
|
62652
|
+
const key2 = cwd ?? process.cwd();
|
|
62653
|
+
const cached = vcsCache.get(key2);
|
|
62654
|
+
if (cached)
|
|
62655
|
+
return cached;
|
|
62656
|
+
const candidates = [];
|
|
62657
|
+
for (const provider of providerList) {
|
|
62658
|
+
let root3 = null;
|
|
62659
|
+
let detected2 = false;
|
|
62660
|
+
try {
|
|
62661
|
+
if (provider.getRoot) {
|
|
62662
|
+
root3 = await provider.getRoot(cwd);
|
|
62663
|
+
detected2 = root3 !== null;
|
|
62664
|
+
} else {
|
|
62665
|
+
detected2 = await provider.detect(cwd);
|
|
62666
|
+
}
|
|
62667
|
+
} catch {
|
|
62668
|
+
continue;
|
|
62669
|
+
}
|
|
62670
|
+
if (detected2) {
|
|
62671
|
+
candidates.push({ provider, root: root3, order: candidates.length });
|
|
62672
|
+
}
|
|
62673
|
+
}
|
|
62674
|
+
const detected = selectNearestProvider(candidates, cwd) ?? defaultProvider;
|
|
62675
|
+
vcsCache.set(key2, detected);
|
|
62676
|
+
return detected;
|
|
62677
|
+
}
|
|
62678
|
+
function getProviderForDiffType(diffType) {
|
|
62679
|
+
for (const provider of providerList) {
|
|
62680
|
+
if (provider.ownsDiffType(diffType)) {
|
|
62681
|
+
return provider;
|
|
62682
|
+
}
|
|
62683
|
+
}
|
|
62684
|
+
return null;
|
|
62685
|
+
}
|
|
62686
|
+
function getProviderById(id) {
|
|
62687
|
+
return providerList.find((provider) => provider.id === id) ?? null;
|
|
62688
|
+
}
|
|
62689
|
+
function formatVcsName(id) {
|
|
62690
|
+
switch (id) {
|
|
62691
|
+
case "git":
|
|
62692
|
+
return "Git";
|
|
62693
|
+
case "jj":
|
|
62694
|
+
return "JJ";
|
|
62695
|
+
case "p4":
|
|
62696
|
+
return "P4";
|
|
62697
|
+
}
|
|
62698
|
+
}
|
|
62699
|
+
async function getProviderForSelection(vcsType, cwd) {
|
|
62700
|
+
if (!vcsType || vcsType === "auto") {
|
|
62701
|
+
return detectVcs(cwd);
|
|
62702
|
+
}
|
|
62703
|
+
const provider = getProviderById(vcsType);
|
|
62704
|
+
const vcsName = formatVcsName(vcsType);
|
|
62705
|
+
if (!provider) {
|
|
62706
|
+
throw new Error(`${vcsName} support is not available in this runtime.`);
|
|
62707
|
+
}
|
|
62708
|
+
if (!await provider.detect(cwd)) {
|
|
62709
|
+
throw new Error(`${vcsName} workspace not found.`);
|
|
62710
|
+
}
|
|
62711
|
+
return provider;
|
|
62712
|
+
}
|
|
62713
|
+
async function getProviderForOperation(diffType, cwd) {
|
|
62714
|
+
return getProviderForDiffType(diffType) ?? detectVcs(cwd);
|
|
62715
|
+
}
|
|
62716
|
+
async function getContextWithProvider(cwd, vcsType) {
|
|
62717
|
+
const provider = await getProviderForSelection(vcsType, cwd);
|
|
62718
|
+
return { provider, gitContext: await provider.getContext(cwd) };
|
|
62719
|
+
}
|
|
62720
|
+
function resolveRequestedDiffType(provider, gitContext, requestedDiffType, configuredDiffType) {
|
|
62721
|
+
if (requestedDiffType && provider.ownsDiffType(requestedDiffType)) {
|
|
62722
|
+
return requestedDiffType;
|
|
62723
|
+
}
|
|
62724
|
+
return resolveInitialDiffType(gitContext, configuredDiffType);
|
|
62725
|
+
}
|
|
62726
|
+
function resolveInitialBase(gitContext, diffType, requestedBase, ownsRequestedDiffType) {
|
|
62727
|
+
if (gitContext.vcsType === "jj") {
|
|
62728
|
+
if (diffType === "jj-line" && ownsRequestedDiffType && requestedBase) {
|
|
62729
|
+
return requestedBase;
|
|
62730
|
+
}
|
|
62731
|
+
return gitContext.defaultBranch;
|
|
62732
|
+
}
|
|
62733
|
+
return requestedBase ?? gitContext.defaultBranch;
|
|
62734
|
+
}
|
|
62735
|
+
return {
|
|
62736
|
+
detectVcs,
|
|
62737
|
+
async getVcsContext(cwd, vcsType) {
|
|
62738
|
+
return (await getContextWithProvider(cwd, vcsType)).gitContext;
|
|
62739
|
+
},
|
|
62740
|
+
async detectRemoteDefaultCompareTarget(cwd, vcsType) {
|
|
62741
|
+
const provider = await getProviderForSelection(vcsType, cwd);
|
|
62742
|
+
return provider.detectRemoteDefaultCompareTarget?.(cwd) ?? null;
|
|
62743
|
+
},
|
|
62744
|
+
async prepareLocalReviewDiff(options) {
|
|
62745
|
+
const { provider, gitContext } = await getContextWithProvider(options.cwd, options.vcsType);
|
|
62746
|
+
const ownsRequestedDiffType = options.requestedDiffType !== undefined && provider.ownsDiffType(options.requestedDiffType);
|
|
62747
|
+
const diffType = resolveRequestedDiffType(provider, gitContext, options.requestedDiffType, options.configuredDiffType);
|
|
62748
|
+
const base = resolveInitialBase(gitContext, diffType, options.requestedBase, ownsRequestedDiffType);
|
|
62749
|
+
const result = await provider.runDiff(diffType, base, gitContext.cwd ?? options.cwd, {
|
|
62750
|
+
hideWhitespace: options.hideWhitespace
|
|
62751
|
+
});
|
|
62752
|
+
return {
|
|
62753
|
+
gitContext,
|
|
62754
|
+
diffType,
|
|
62755
|
+
base,
|
|
62756
|
+
rawPatch: result.patch,
|
|
62757
|
+
gitRef: result.label,
|
|
62758
|
+
error: result.error
|
|
62759
|
+
};
|
|
62760
|
+
},
|
|
62761
|
+
async runVcsDiff(diffType, defaultBranch = "main", cwd, options) {
|
|
62762
|
+
const provider = await getProviderForOperation(diffType, cwd);
|
|
62763
|
+
return provider.runDiff(diffType, defaultBranch, cwd, options);
|
|
62764
|
+
},
|
|
62765
|
+
async getVcsFileContentsForDiff(diffType, defaultBranch, filePath, oldPath, cwd) {
|
|
62766
|
+
const provider = await getProviderForOperation(diffType, cwd);
|
|
62767
|
+
return provider.getFileContents(diffType, defaultBranch, filePath, oldPath, cwd);
|
|
62768
|
+
},
|
|
62769
|
+
async canStageFiles(diffType, cwd) {
|
|
62770
|
+
const provider = await getProviderForOperation(diffType, cwd);
|
|
62771
|
+
return provider.stageFile !== undefined && (provider.canStageFiles?.(diffType) ?? false);
|
|
62772
|
+
},
|
|
62773
|
+
async stageFile(diffType, filePath, cwd) {
|
|
62774
|
+
const provider = await getProviderForOperation(diffType, cwd);
|
|
62775
|
+
if (!provider.stageFile || !(provider.canStageFiles?.(diffType) ?? false)) {
|
|
62776
|
+
throw new Error(`Staging not available for ${provider.id}`);
|
|
62777
|
+
}
|
|
62778
|
+
return provider.stageFile(filePath, cwd);
|
|
62779
|
+
},
|
|
62780
|
+
async unstageFile(diffType, filePath, cwd) {
|
|
62781
|
+
const provider = await getProviderForOperation(diffType, cwd);
|
|
62782
|
+
if (!provider.unstageFile || !(provider.canStageFiles?.(diffType) ?? false)) {
|
|
62783
|
+
throw new Error(`Unstaging not available for ${provider.id}`);
|
|
62784
|
+
}
|
|
62785
|
+
return provider.unstageFile(filePath, cwd);
|
|
62786
|
+
},
|
|
62787
|
+
resolveVcsCwd(diffType, fallbackCwd) {
|
|
62788
|
+
const provider = getProviderForDiffType(diffType);
|
|
62789
|
+
return provider?.resolveCwd?.(diffType, fallbackCwd) ?? fallbackCwd;
|
|
62790
|
+
}
|
|
62791
|
+
};
|
|
62792
|
+
}
|
|
62793
|
+
function resolveInitialDiffType(gitContext, configuredDiffType) {
|
|
62794
|
+
if (gitContext.vcsType === "p4") {
|
|
62795
|
+
return "p4-default";
|
|
62796
|
+
}
|
|
62797
|
+
if (gitContext.vcsType === "jj") {
|
|
62798
|
+
return "jj-current";
|
|
62799
|
+
}
|
|
62800
|
+
if (gitContext.diffOptions.some((option2) => option2.id === configuredDiffType)) {
|
|
62801
|
+
return configuredDiffType;
|
|
62802
|
+
}
|
|
62803
|
+
const fallback = gitContext.diffOptions[0]?.id;
|
|
62804
|
+
return fallback ? fallback : configuredDiffType;
|
|
62313
62805
|
}
|
|
62314
62806
|
|
|
62315
62807
|
// ../../packages/server/p4.ts
|
|
@@ -62605,43 +63097,66 @@ async function getP4FileContentsForDiff(diffType, filePath, cwd) {
|
|
|
62605
63097
|
};
|
|
62606
63098
|
}
|
|
62607
63099
|
|
|
62608
|
-
// ../../packages/server/
|
|
62609
|
-
|
|
62610
|
-
|
|
62611
|
-
|
|
62612
|
-
|
|
63100
|
+
// ../../packages/server/git.ts
|
|
63101
|
+
async function runGit(args, options) {
|
|
63102
|
+
const proc = Bun.spawn(["git", "-c", "core.quotePath=false", ...args], {
|
|
63103
|
+
cwd: options?.cwd,
|
|
63104
|
+
stdout: "pipe",
|
|
63105
|
+
stderr: "pipe"
|
|
63106
|
+
});
|
|
63107
|
+
let timer;
|
|
63108
|
+
if (options?.timeoutMs) {
|
|
63109
|
+
timer = setTimeout(() => proc.kill(), options.timeoutMs);
|
|
63110
|
+
}
|
|
63111
|
+
const [stdout, stderr, exitCode] = await Promise.all([
|
|
63112
|
+
new Response(proc.stdout).text(),
|
|
63113
|
+
new Response(proc.stderr).text(),
|
|
63114
|
+
proc.exited
|
|
63115
|
+
]);
|
|
63116
|
+
if (timer)
|
|
63117
|
+
clearTimeout(timer);
|
|
63118
|
+
return { stdout, stderr, exitCode };
|
|
63119
|
+
}
|
|
63120
|
+
var runtime = {
|
|
63121
|
+
runGit,
|
|
63122
|
+
async readTextFile(path2) {
|
|
62613
63123
|
try {
|
|
62614
|
-
|
|
62615
|
-
cwd: cwd ?? undefined,
|
|
62616
|
-
stdout: "ignore",
|
|
62617
|
-
stderr: "ignore"
|
|
62618
|
-
});
|
|
62619
|
-
return await proc.exited === 0;
|
|
63124
|
+
return await Bun.file(path2).text();
|
|
62620
63125
|
} catch {
|
|
62621
|
-
return
|
|
63126
|
+
return null;
|
|
62622
63127
|
}
|
|
62623
|
-
}
|
|
62624
|
-
|
|
62625
|
-
|
|
62626
|
-
|
|
62627
|
-
|
|
62628
|
-
|
|
62629
|
-
|
|
62630
|
-
|
|
62631
|
-
|
|
62632
|
-
|
|
62633
|
-
|
|
62634
|
-
|
|
62635
|
-
|
|
62636
|
-
|
|
62637
|
-
if (diffType.startsWith("worktree:")) {
|
|
62638
|
-
const parsed = parseWorktreeDiffType(diffType);
|
|
62639
|
-
if (parsed)
|
|
62640
|
-
return parsed.path;
|
|
63128
|
+
}
|
|
63129
|
+
};
|
|
63130
|
+
|
|
63131
|
+
// ../../packages/server/jj.ts
|
|
63132
|
+
async function runJj(args, options) {
|
|
63133
|
+
try {
|
|
63134
|
+
const proc = Bun.spawn(["jj", ...args], {
|
|
63135
|
+
cwd: options?.cwd,
|
|
63136
|
+
stdout: "pipe",
|
|
63137
|
+
stderr: "pipe"
|
|
63138
|
+
});
|
|
63139
|
+
let timer;
|
|
63140
|
+
if (options?.timeoutMs) {
|
|
63141
|
+
timer = setTimeout(() => proc.kill(), options.timeoutMs);
|
|
62641
63142
|
}
|
|
62642
|
-
|
|
63143
|
+
const [stdout, stderr, exitCode] = await Promise.all([
|
|
63144
|
+
new Response(proc.stdout).text(),
|
|
63145
|
+
new Response(proc.stderr).text(),
|
|
63146
|
+
proc.exited
|
|
63147
|
+
]);
|
|
63148
|
+
if (timer)
|
|
63149
|
+
clearTimeout(timer);
|
|
63150
|
+
return { stdout, stderr, exitCode };
|
|
63151
|
+
} catch {
|
|
63152
|
+
return { stdout: "", stderr: "jj not found", exitCode: 1 };
|
|
62643
63153
|
}
|
|
63154
|
+
}
|
|
63155
|
+
var runtime2 = {
|
|
63156
|
+
runJj
|
|
62644
63157
|
};
|
|
63158
|
+
|
|
63159
|
+
// ../../packages/server/vcs.ts
|
|
62645
63160
|
var p4Provider = {
|
|
62646
63161
|
id: "p4",
|
|
62647
63162
|
async detect(cwd) {
|
|
@@ -62658,63 +63173,23 @@ var p4Provider = {
|
|
|
62658
63173
|
return getP4FileContentsForDiff(diffType, filePath, cwd);
|
|
62659
63174
|
}
|
|
62660
63175
|
};
|
|
62661
|
-
var
|
|
62662
|
-
|
|
62663
|
-
|
|
62664
|
-
|
|
62665
|
-
|
|
62666
|
-
|
|
62667
|
-
|
|
62668
|
-
|
|
62669
|
-
|
|
62670
|
-
|
|
62671
|
-
|
|
62672
|
-
|
|
62673
|
-
|
|
62674
|
-
|
|
62675
|
-
|
|
62676
|
-
|
|
62677
|
-
|
|
62678
|
-
for (const provider of providers) {
|
|
62679
|
-
if (provider.ownsDiffType(diffType))
|
|
62680
|
-
return provider;
|
|
62681
|
-
}
|
|
62682
|
-
return gitProvider;
|
|
62683
|
-
}
|
|
62684
|
-
async function getVcsContext(cwd) {
|
|
62685
|
-
const provider = await detectVcs(cwd);
|
|
62686
|
-
return provider.getContext(cwd);
|
|
62687
|
-
}
|
|
62688
|
-
async function runVcsDiff(diffType, defaultBranch = "main", cwd, options) {
|
|
62689
|
-
const provider = getProviderForDiffType(diffType);
|
|
62690
|
-
return provider.runDiff(diffType, defaultBranch, cwd, options);
|
|
62691
|
-
}
|
|
62692
|
-
async function getVcsFileContentsForDiff(diffType, defaultBranch, filePath, oldPath, cwd) {
|
|
62693
|
-
const provider = getProviderForDiffType(diffType);
|
|
62694
|
-
return provider.getFileContents(diffType, defaultBranch, filePath, oldPath, cwd);
|
|
62695
|
-
}
|
|
62696
|
-
function canStageFiles(diffType) {
|
|
62697
|
-
const provider = getProviderForDiffType(diffType);
|
|
62698
|
-
return provider.stageFile !== undefined;
|
|
62699
|
-
}
|
|
62700
|
-
async function stageFile(diffType, filePath, cwd) {
|
|
62701
|
-
const provider = getProviderForDiffType(diffType);
|
|
62702
|
-
if (!provider.stageFile) {
|
|
62703
|
-
throw new Error(`Staging not available for ${provider.id}`);
|
|
62704
|
-
}
|
|
62705
|
-
return provider.stageFile(filePath, cwd);
|
|
62706
|
-
}
|
|
62707
|
-
async function unstageFile(diffType, filePath, cwd) {
|
|
62708
|
-
const provider = getProviderForDiffType(diffType);
|
|
62709
|
-
if (!provider.unstageFile) {
|
|
62710
|
-
throw new Error(`Unstaging not available for ${provider.id}`);
|
|
62711
|
-
}
|
|
62712
|
-
return provider.unstageFile(filePath, cwd);
|
|
62713
|
-
}
|
|
62714
|
-
function resolveVcsCwd(diffType, fallbackCwd) {
|
|
62715
|
-
const provider = getProviderForDiffType(diffType);
|
|
62716
|
-
return provider.resolveCwd?.(diffType, fallbackCwd) ?? fallbackCwd;
|
|
62717
|
-
}
|
|
63176
|
+
var api = createVcsApi([
|
|
63177
|
+
createJjProvider(runtime2),
|
|
63178
|
+
createGitProvider(runtime),
|
|
63179
|
+
p4Provider
|
|
63180
|
+
]);
|
|
63181
|
+
var {
|
|
63182
|
+
detectVcs,
|
|
63183
|
+
getVcsContext,
|
|
63184
|
+
detectRemoteDefaultCompareTarget,
|
|
63185
|
+
prepareLocalReviewDiff,
|
|
63186
|
+
runVcsDiff,
|
|
63187
|
+
getVcsFileContentsForDiff,
|
|
63188
|
+
canStageFiles,
|
|
63189
|
+
stageFile,
|
|
63190
|
+
unstageFile,
|
|
63191
|
+
resolveVcsCwd
|
|
63192
|
+
} = api;
|
|
62718
63193
|
|
|
62719
63194
|
// ../../packages/shared/pr-stack.ts
|
|
62720
63195
|
function branchNameIsSafe(branch) {
|
|
@@ -62763,17 +63238,17 @@ function getPRDiffScopeOptions(metadata, hasLocalCheckout) {
|
|
|
62763
63238
|
}
|
|
62764
63239
|
];
|
|
62765
63240
|
}
|
|
62766
|
-
async function resolvePRFullStackBaseRef(
|
|
63241
|
+
async function resolvePRFullStackBaseRef(runtime3, defaultBranch, cwd) {
|
|
62767
63242
|
const remoteRef = `origin/${defaultBranch}`;
|
|
62768
|
-
const remote = await
|
|
63243
|
+
const remote = await runtime3.runGit(["show-ref", "--verify", "--quiet", `refs/remotes/${remoteRef}`], { cwd });
|
|
62769
63244
|
if (remote.exitCode === 0)
|
|
62770
63245
|
return remoteRef;
|
|
62771
|
-
const local = await
|
|
63246
|
+
const local = await runtime3.runGit(["show-ref", "--verify", "--quiet", `refs/heads/${defaultBranch}`], { cwd });
|
|
62772
63247
|
if (local.exitCode === 0)
|
|
62773
63248
|
return defaultBranch;
|
|
62774
63249
|
return null;
|
|
62775
63250
|
}
|
|
62776
|
-
async function runPRFullStackDiff(
|
|
63251
|
+
async function runPRFullStackDiff(runtime3, metadata, cwd) {
|
|
62777
63252
|
const defaultBranch = metadata.defaultBranch;
|
|
62778
63253
|
if (!defaultBranch || !branchNameIsSafe(defaultBranch)) {
|
|
62779
63254
|
return {
|
|
@@ -62782,7 +63257,7 @@ async function runPRFullStackDiff(runtime2, metadata, cwd) {
|
|
|
62782
63257
|
error: "Could not determine a safe default branch for this review."
|
|
62783
63258
|
};
|
|
62784
63259
|
}
|
|
62785
|
-
const baseRef = await resolvePRFullStackBaseRef(
|
|
63260
|
+
const baseRef = await resolvePRFullStackBaseRef(runtime3, defaultBranch, cwd);
|
|
62786
63261
|
if (!baseRef) {
|
|
62787
63262
|
return {
|
|
62788
63263
|
patch: "",
|
|
@@ -62798,7 +63273,7 @@ async function runPRFullStackDiff(runtime2, metadata, cwd) {
|
|
|
62798
63273
|
"--end-of-options",
|
|
62799
63274
|
`${baseRef}...HEAD`
|
|
62800
63275
|
];
|
|
62801
|
-
const diff = await
|
|
63276
|
+
const diff = await runtime3.runGit(diffArgs, { cwd });
|
|
62802
63277
|
if (diff.exitCode !== 0) {
|
|
62803
63278
|
const message = diff.stderr.trim() || `git ${diffArgs.join(" ")} failed`;
|
|
62804
63279
|
return {
|
|
@@ -62813,21 +63288,21 @@ async function runPRFullStackDiff(runtime2, metadata, cwd) {
|
|
|
62813
63288
|
label: `Full stack diff vs ${baseRef}`
|
|
62814
63289
|
};
|
|
62815
63290
|
}
|
|
62816
|
-
async function checkoutPRHead(
|
|
63291
|
+
async function checkoutPRHead(runtime3, metadata, cwd) {
|
|
62817
63292
|
const refSpec = metadata.platform === "github" ? `refs/pull/${metadata.number}/head` : `refs/merge-requests/${metadata.iid}/head`;
|
|
62818
|
-
const fetch2 = await
|
|
63293
|
+
const fetch2 = await runtime3.runGit(["fetch", "origin", refSpec], { cwd });
|
|
62819
63294
|
if (fetch2.exitCode !== 0)
|
|
62820
63295
|
return false;
|
|
62821
|
-
const checkout = await
|
|
63296
|
+
const checkout = await runtime3.runGit(["checkout", "FETCH_HEAD"], { cwd });
|
|
62822
63297
|
return checkout.exitCode === 0;
|
|
62823
63298
|
}
|
|
62824
63299
|
|
|
62825
63300
|
// ../../packages/server/path-utils.ts
|
|
62826
|
-
import { relative } from "path";
|
|
63301
|
+
import { relative as relative2 } from "path";
|
|
62827
63302
|
function toRelativePath2(absolutePath, cwd) {
|
|
62828
63303
|
if (!cwd)
|
|
62829
63304
|
return absolutePath;
|
|
62830
|
-
const rel =
|
|
63305
|
+
const rel = relative2(cwd, absolutePath);
|
|
62831
63306
|
if (rel.startsWith(".."))
|
|
62832
63307
|
return absolutePath;
|
|
62833
63308
|
return rel.replace(/\\/g, "/");
|
|
@@ -62877,7 +63352,7 @@ project guidance files explicitly expand your scope.
|
|
|
62877
63352
|
## Pipeline
|
|
62878
63353
|
|
|
62879
63354
|
Step 1: Gather context
|
|
62880
|
-
- Retrieve the PR diff (gh pr diff or
|
|
63355
|
+
- Retrieve the PR diff or local diff (gh pr diff, git diff, or jj diff)
|
|
62881
63356
|
- Read CLAUDE.md and REVIEW.md at the repo root and in every directory
|
|
62882
63357
|
containing modified files
|
|
62883
63358
|
- Build a map of which rules apply to which file paths
|
|
@@ -62995,6 +63470,13 @@ function buildClaudeCommand(prompt, model = "claude-opus-4-7", effort) {
|
|
|
62995
63470
|
"Bash(git remote:*)",
|
|
62996
63471
|
"Bash(git rev-parse:*)",
|
|
62997
63472
|
"Bash(git show-ref:*)",
|
|
63473
|
+
"Bash(jj status:*)",
|
|
63474
|
+
"Bash(jj diff:*)",
|
|
63475
|
+
"Bash(jj log:*)",
|
|
63476
|
+
"Bash(jj show:*)",
|
|
63477
|
+
"Bash(jj file show:*)",
|
|
63478
|
+
"Bash(jj cat:*)",
|
|
63479
|
+
"Bash(jj bookmark list:*)",
|
|
62998
63480
|
"Bash(wc:*)"
|
|
62999
63481
|
].join(",");
|
|
63000
63482
|
const disallowedTools = [
|
|
@@ -63610,64 +64092,6 @@ Ignore non-blocking issues such as style, formatting, typos, documentation, and
|
|
|
63610
64092
|
|
|
63611
64093
|
FORMATTING GUIDELINES:
|
|
63612
64094
|
The finding description should be one paragraph.`;
|
|
63613
|
-
function buildCodexReviewUserMessage(patch, diffType, options, prMetadata) {
|
|
63614
|
-
if (prMetadata) {
|
|
63615
|
-
if (options?.prDiffScope === "full-stack") {
|
|
63616
|
-
return [
|
|
63617
|
-
`Full-stack review of ${prMetadata.url}`,
|
|
63618
|
-
"",
|
|
63619
|
-
"This is a stacked PR. The diff below shows ALL accumulated changes from the repository default branch through this PR's head (not just this PR's own layer).",
|
|
63620
|
-
"Review the complete diff for issues that span the stack.",
|
|
63621
|
-
"",
|
|
63622
|
-
"```diff",
|
|
63623
|
-
patch,
|
|
63624
|
-
"```"
|
|
63625
|
-
].join(`
|
|
63626
|
-
`);
|
|
63627
|
-
}
|
|
63628
|
-
if (options?.hasLocalAccess) {
|
|
63629
|
-
return [
|
|
63630
|
-
prMetadata.url,
|
|
63631
|
-
"",
|
|
63632
|
-
"You are in a local worktree checked out at the PR head. The code is available locally.",
|
|
63633
|
-
`To see the PR changes, diff against the remote base branch: git diff origin/${prMetadata.baseBranch}...HEAD`,
|
|
63634
|
-
"Do NOT diff against the local `main` branch \u2014 it may be stale. Always use origin/."
|
|
63635
|
-
].join(`
|
|
63636
|
-
`);
|
|
63637
|
-
}
|
|
63638
|
-
return prMetadata.url;
|
|
63639
|
-
}
|
|
63640
|
-
const effectiveDiffType = diffType.startsWith("worktree:") ? diffType.split(":").pop() || "uncommitted" : diffType;
|
|
63641
|
-
switch (effectiveDiffType) {
|
|
63642
|
-
case "uncommitted":
|
|
63643
|
-
return "Review the current code changes (staged, unstaged, and untracked files) and provide prioritized findings.";
|
|
63644
|
-
case "staged":
|
|
63645
|
-
return "Review the currently staged code changes (`git diff --staged`) and provide prioritized findings.";
|
|
63646
|
-
case "unstaged":
|
|
63647
|
-
return "Review the unstaged code changes (tracked modifications and untracked files) and provide prioritized findings.";
|
|
63648
|
-
case "last-commit":
|
|
63649
|
-
return "Review the code changes introduced in the last commit (`git diff HEAD~1..HEAD`) and provide prioritized findings.";
|
|
63650
|
-
case "branch": {
|
|
63651
|
-
const base = options?.defaultBranch || "main";
|
|
63652
|
-
return `Review the code changes against the base branch '${base}'. Run \`git diff ${base}..HEAD\` to inspect the changes. Provide prioritized, actionable findings.`;
|
|
63653
|
-
}
|
|
63654
|
-
case "merge-base": {
|
|
63655
|
-
const base = options?.defaultBranch || "main";
|
|
63656
|
-
return `Review the PR-style diff against base '${base}'. First find the common ancestor with \`git merge-base ${base} HEAD\`, then run \`git diff <merge-base>..HEAD\` using that commit to inspect only the changes introduced on this branch (matches GitHub's PR view). Provide prioritized, actionable findings.`;
|
|
63657
|
-
}
|
|
63658
|
-
case "all":
|
|
63659
|
-
return "Review every file in the repository (all files shown as additions, diffed against an empty tree). Provide prioritized, actionable findings.";
|
|
63660
|
-
default:
|
|
63661
|
-
return [
|
|
63662
|
-
"Review the following code changes and provide prioritized findings.",
|
|
63663
|
-
"",
|
|
63664
|
-
"```diff",
|
|
63665
|
-
patch,
|
|
63666
|
-
"```"
|
|
63667
|
-
].join(`
|
|
63668
|
-
`);
|
|
63669
|
-
}
|
|
63670
|
-
}
|
|
63671
64095
|
async function buildCodexCommand(options) {
|
|
63672
64096
|
const { cwd, outputPath, prompt, model, reasoningEffort, fastMode } = options;
|
|
63673
64097
|
const schemaPath = await ensureSchemaFile();
|
|
@@ -63760,6 +64184,124 @@ ${f3.body}`.trim(),
|
|
|
63760
64184
|
return annotations;
|
|
63761
64185
|
}
|
|
63762
64186
|
|
|
64187
|
+
// ../../packages/server/agent-review-message.ts
|
|
64188
|
+
function buildAgentReviewUserMessage(patch, diffType, options, prMetadata) {
|
|
64189
|
+
if (prMetadata) {
|
|
64190
|
+
if (options?.prDiffScope === "full-stack") {
|
|
64191
|
+
return [
|
|
64192
|
+
`Full-stack review of ${prMetadata.url}`,
|
|
64193
|
+
"",
|
|
64194
|
+
"This is a stacked PR. The diff below shows ALL accumulated changes from the repository default branch through this PR's head (not just this PR's own layer).",
|
|
64195
|
+
"Review the complete diff for issues that span the stack.",
|
|
64196
|
+
"",
|
|
64197
|
+
"```diff",
|
|
64198
|
+
patch,
|
|
64199
|
+
"```"
|
|
64200
|
+
].join(`
|
|
64201
|
+
`);
|
|
64202
|
+
}
|
|
64203
|
+
if (options?.hasLocalAccess) {
|
|
64204
|
+
return [
|
|
64205
|
+
prMetadata.url,
|
|
64206
|
+
"",
|
|
64207
|
+
"You are in a local worktree checked out at the PR head. The code is available locally.",
|
|
64208
|
+
`To see the PR changes, diff against the remote base branch: git diff origin/${prMetadata.baseBranch}...HEAD`,
|
|
64209
|
+
"Do NOT diff against the local `main` branch; it may be stale. Always use origin/."
|
|
64210
|
+
].join(`
|
|
64211
|
+
`);
|
|
64212
|
+
}
|
|
64213
|
+
return prMetadata.url;
|
|
64214
|
+
}
|
|
64215
|
+
const instruction = getLocalDiffInstruction(diffType, options?.defaultBranch);
|
|
64216
|
+
if (instruction) {
|
|
64217
|
+
return `Review ${instruction.target}. ${instruction.inspect} Provide prioritized, actionable findings.`;
|
|
64218
|
+
}
|
|
64219
|
+
return [
|
|
64220
|
+
"Review the following code changes and provide prioritized findings.",
|
|
64221
|
+
"",
|
|
64222
|
+
"```diff",
|
|
64223
|
+
patch,
|
|
64224
|
+
"```"
|
|
64225
|
+
].join(`
|
|
64226
|
+
`);
|
|
64227
|
+
}
|
|
64228
|
+
function getLocalDiffInstruction(diffType, defaultBranch) {
|
|
64229
|
+
const effectiveDiffType = normalizeLocalDiffType(diffType);
|
|
64230
|
+
switch (effectiveDiffType) {
|
|
64231
|
+
case "uncommitted":
|
|
64232
|
+
return {
|
|
64233
|
+
target: "the current code changes (staged, unstaged, and untracked files)",
|
|
64234
|
+
inspect: "Inspect the working tree changes locally."
|
|
64235
|
+
};
|
|
64236
|
+
case "staged":
|
|
64237
|
+
return {
|
|
64238
|
+
target: "the currently staged code changes",
|
|
64239
|
+
inspect: "Run `git diff --staged` to inspect the changes."
|
|
64240
|
+
};
|
|
64241
|
+
case "unstaged":
|
|
64242
|
+
return {
|
|
64243
|
+
target: "the unstaged code changes (tracked modifications and untracked files)",
|
|
64244
|
+
inspect: "Inspect the unstaged working tree changes locally."
|
|
64245
|
+
};
|
|
64246
|
+
case "last-commit":
|
|
64247
|
+
return {
|
|
64248
|
+
target: "the code changes introduced in the last commit",
|
|
64249
|
+
inspect: "Run `git diff HEAD~1..HEAD` to inspect the changes."
|
|
64250
|
+
};
|
|
64251
|
+
case "branch": {
|
|
64252
|
+
const base = defaultBranch || "main";
|
|
64253
|
+
return {
|
|
64254
|
+
target: `the code changes against the base branch '${base}'`,
|
|
64255
|
+
inspect: `Run \`git diff ${base}..HEAD\` to inspect the changes.`
|
|
64256
|
+
};
|
|
64257
|
+
}
|
|
64258
|
+
case "merge-base": {
|
|
64259
|
+
const base = defaultBranch || "main";
|
|
64260
|
+
return {
|
|
64261
|
+
target: `the PR-style diff against base '${base}'`,
|
|
64262
|
+
inspect: `First find the common ancestor with \`git merge-base ${base} HEAD\`, then run \`git diff <merge-base>..HEAD\` using that commit to inspect only the changes introduced on this branch (matches GitHub's PR view).`
|
|
64263
|
+
};
|
|
64264
|
+
}
|
|
64265
|
+
case "all":
|
|
64266
|
+
return {
|
|
64267
|
+
target: "every file in the repository",
|
|
64268
|
+
inspect: "All files are shown as additions, diffed against an empty tree."
|
|
64269
|
+
};
|
|
64270
|
+
case "jj-current":
|
|
64271
|
+
return {
|
|
64272
|
+
target: "the current JJ change",
|
|
64273
|
+
inspect: "Run `jj diff --git -r @` to inspect the changes."
|
|
64274
|
+
};
|
|
64275
|
+
case "jj-last":
|
|
64276
|
+
return {
|
|
64277
|
+
target: "the previous JJ change",
|
|
64278
|
+
inspect: "Run `jj diff --git -r @-` to inspect the changes."
|
|
64279
|
+
};
|
|
64280
|
+
case "jj-line": {
|
|
64281
|
+
const base = defaultBranch || JJ_TRUNK_REVSET;
|
|
64282
|
+
const baseRevset = jjLineBaseRevset(base);
|
|
64283
|
+
return {
|
|
64284
|
+
target: `the JJ line of work against \`${base}\``,
|
|
64285
|
+
inspect: `Run \`jj diff --git --from ${shellQuote(baseRevset)} --to @\` to inspect the changes.`
|
|
64286
|
+
};
|
|
64287
|
+
}
|
|
64288
|
+
case "jj-all":
|
|
64289
|
+
return {
|
|
64290
|
+
target: "all files in the JJ workspace",
|
|
64291
|
+
inspect: "Run `jj diff --git --from 'root()' --to @` to inspect the changes."
|
|
64292
|
+
};
|
|
64293
|
+
default:
|
|
64294
|
+
return null;
|
|
64295
|
+
}
|
|
64296
|
+
}
|
|
64297
|
+
function normalizeLocalDiffType(diffType) {
|
|
64298
|
+
const worktree = parseWorktreeDiffType(diffType);
|
|
64299
|
+
return worktree?.subType ?? diffType;
|
|
64300
|
+
}
|
|
64301
|
+
function shellQuote(value) {
|
|
64302
|
+
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
64303
|
+
}
|
|
64304
|
+
|
|
63763
64305
|
// ../../packages/server/tour/tour-review.ts
|
|
63764
64306
|
import { join as join10 } from "path";
|
|
63765
64307
|
import { homedir as homedir6, tmpdir as tmpdir3 } from "os";
|
|
@@ -63992,7 +64534,7 @@ should reference at least one stop.
|
|
|
63992
64534
|
|
|
63993
64535
|
## Pipeline
|
|
63994
64536
|
|
|
63995
|
-
1. Read the full diff (git diff or inlined patch).
|
|
64537
|
+
1. Read the full diff (git diff, jj diff, or inlined patch).
|
|
63996
64538
|
2. Read CLAUDE.md and README.md for project context.
|
|
63997
64539
|
3. Read commit messages (git log --oneline) and PR title/body if available.
|
|
63998
64540
|
4. Identify logical groupings of change (cross-file when appropriate). These
|
|
@@ -64062,36 +64604,18 @@ function buildTourUserMessage(patch, diffType, options, prMetadata) {
|
|
|
64062
64604
|
return [prMetadata.url, "", "Walk the reviewer through this PR as a guided tour."].join(`
|
|
64063
64605
|
`);
|
|
64064
64606
|
}
|
|
64065
|
-
const
|
|
64066
|
-
|
|
64067
|
-
|
|
64068
|
-
return "Walk the reviewer through the current code changes (staged, unstaged, and untracked files) as a guided tour.";
|
|
64069
|
-
case "staged":
|
|
64070
|
-
return "Walk the reviewer through the currently staged code changes (`git diff --staged`) as a guided tour.";
|
|
64071
|
-
case "unstaged":
|
|
64072
|
-
return "Walk the reviewer through the unstaged code changes (tracked modifications and untracked files) as a guided tour.";
|
|
64073
|
-
case "last-commit":
|
|
64074
|
-
return "Walk the reviewer through the code changes introduced in the last commit (`git diff HEAD~1..HEAD`) as a guided tour.";
|
|
64075
|
-
case "branch": {
|
|
64076
|
-
const base = options?.defaultBranch || "main";
|
|
64077
|
-
return `Walk the reviewer through the code changes against the base branch '${base}' as a guided tour. Run \`git diff ${base}..HEAD\` to inspect the changes.`;
|
|
64078
|
-
}
|
|
64079
|
-
case "merge-base": {
|
|
64080
|
-
const base = options?.defaultBranch || "main";
|
|
64081
|
-
return `Walk the reviewer through the PR-style diff against base '${base}' as a guided tour. First find the common ancestor with \`git merge-base ${base} HEAD\`, then run \`git diff <merge-base>..HEAD\` using that commit to inspect only the changes introduced on this branch (matches GitHub's PR view).`;
|
|
64082
|
-
}
|
|
64083
|
-
case "all":
|
|
64084
|
-
return "Walk the reviewer through every file in the repository as a guided tour. All files are shown as additions (diffed against an empty tree).";
|
|
64085
|
-
default:
|
|
64086
|
-
return [
|
|
64087
|
-
"Walk the reviewer through the following code changes as a guided tour.",
|
|
64088
|
-
"",
|
|
64089
|
-
"```diff",
|
|
64090
|
-
patch,
|
|
64091
|
-
"```"
|
|
64092
|
-
].join(`
|
|
64093
|
-
`);
|
|
64607
|
+
const instruction = getLocalDiffInstruction(diffType, options?.defaultBranch);
|
|
64608
|
+
if (instruction) {
|
|
64609
|
+
return `Walk the reviewer through ${instruction.target} as a guided tour. ${instruction.inspect}`;
|
|
64094
64610
|
}
|
|
64611
|
+
return [
|
|
64612
|
+
"Walk the reviewer through the following code changes as a guided tour.",
|
|
64613
|
+
"",
|
|
64614
|
+
"```diff",
|
|
64615
|
+
patch,
|
|
64616
|
+
"```"
|
|
64617
|
+
].join(`
|
|
64618
|
+
`);
|
|
64095
64619
|
}
|
|
64096
64620
|
function buildTourClaudeCommand(prompt, model = "sonnet", effort) {
|
|
64097
64621
|
const allowedTools = [
|
|
@@ -64112,6 +64636,13 @@ function buildTourClaudeCommand(prompt, model = "sonnet", effort) {
|
|
|
64112
64636
|
"Bash(git remote:*)",
|
|
64113
64637
|
"Bash(git rev-parse:*)",
|
|
64114
64638
|
"Bash(git show-ref:*)",
|
|
64639
|
+
"Bash(jj status:*)",
|
|
64640
|
+
"Bash(jj diff:*)",
|
|
64641
|
+
"Bash(jj log:*)",
|
|
64642
|
+
"Bash(jj show:*)",
|
|
64643
|
+
"Bash(jj file show:*)",
|
|
64644
|
+
"Bash(jj cat:*)",
|
|
64645
|
+
"Bash(jj bookmark list:*)",
|
|
64115
64646
|
"Bash(gh pr view:*)",
|
|
64116
64647
|
"Bash(gh pr diff:*)",
|
|
64117
64648
|
"Bash(gh pr list:*)",
|
|
@@ -64315,8 +64846,8 @@ function hostnameArgs(host, args) {
|
|
|
64315
64846
|
}
|
|
64316
64847
|
return args;
|
|
64317
64848
|
}
|
|
64318
|
-
async function checkGhAuth(
|
|
64319
|
-
const result = await
|
|
64849
|
+
async function checkGhAuth(runtime3, host) {
|
|
64850
|
+
const result = await runtime3.runCommand("gh", hostnameArgs(host, ["auth", "status"]));
|
|
64320
64851
|
if (result.exitCode !== 0) {
|
|
64321
64852
|
const stderr = result.stderr.trim();
|
|
64322
64853
|
const hostHint = host !== "github.com" ? ` --hostname ${host}` : "";
|
|
@@ -64324,9 +64855,9 @@ async function checkGhAuth(runtime2, host) {
|
|
|
64324
64855
|
${stderr}`);
|
|
64325
64856
|
}
|
|
64326
64857
|
}
|
|
64327
|
-
async function getGhUser(
|
|
64858
|
+
async function getGhUser(runtime3, host) {
|
|
64328
64859
|
try {
|
|
64329
|
-
const result = await
|
|
64860
|
+
const result = await runtime3.runCommand("gh", hostnameArgs(host, ["api", "user", "--jq", ".login"]));
|
|
64330
64861
|
if (result.exitCode === 0 && result.stdout.trim()) {
|
|
64331
64862
|
return result.stdout.trim();
|
|
64332
64863
|
}
|
|
@@ -64335,17 +64866,17 @@ async function getGhUser(runtime2, host) {
|
|
|
64335
64866
|
return null;
|
|
64336
64867
|
}
|
|
64337
64868
|
}
|
|
64338
|
-
async function fetchGhPR(
|
|
64869
|
+
async function fetchGhPR(runtime3, ref) {
|
|
64339
64870
|
const repo = repoFlag(ref);
|
|
64340
64871
|
const [diffResult, viewResult, repoResult] = await Promise.all([
|
|
64341
|
-
|
|
64872
|
+
runtime3.runCommand("gh", [
|
|
64342
64873
|
"pr",
|
|
64343
64874
|
"diff",
|
|
64344
64875
|
String(ref.number),
|
|
64345
64876
|
"--repo",
|
|
64346
64877
|
repo
|
|
64347
64878
|
]),
|
|
64348
|
-
|
|
64879
|
+
runtime3.runCommand("gh", [
|
|
64349
64880
|
"pr",
|
|
64350
64881
|
"view",
|
|
64351
64882
|
String(ref.number),
|
|
@@ -64354,7 +64885,7 @@ async function fetchGhPR(runtime2, ref) {
|
|
|
64354
64885
|
"--json",
|
|
64355
64886
|
"id,title,author,baseRefName,headRefName,baseRefOid,headRefOid,url"
|
|
64356
64887
|
]),
|
|
64357
|
-
|
|
64888
|
+
runtime3.runCommand("gh", [
|
|
64358
64889
|
"repo",
|
|
64359
64890
|
"view",
|
|
64360
64891
|
repo,
|
|
@@ -64373,7 +64904,7 @@ async function fetchGhPR(runtime2, ref) {
|
|
|
64373
64904
|
const raw2 = JSON.parse(viewResult.stdout);
|
|
64374
64905
|
let mergeBaseSha;
|
|
64375
64906
|
try {
|
|
64376
|
-
const compareResult = await
|
|
64907
|
+
const compareResult = await runtime3.runCommand("gh", hostnameArgs(ref.host, [
|
|
64377
64908
|
"api",
|
|
64378
64909
|
`repos/${ref.owner}/${ref.repo}/compare/${raw2.baseRefOid}...${raw2.headRefOid}`,
|
|
64379
64910
|
"--jq",
|
|
@@ -64460,9 +64991,9 @@ function parseGhPRContext(raw2) {
|
|
|
64460
64991
|
}))
|
|
64461
64992
|
};
|
|
64462
64993
|
}
|
|
64463
|
-
async function fetchGhPRContext(
|
|
64994
|
+
async function fetchGhPRContext(runtime3, ref) {
|
|
64464
64995
|
const repo = repoFlag(ref);
|
|
64465
|
-
const result = await
|
|
64996
|
+
const result = await runtime3.runCommand("gh", [
|
|
64466
64997
|
"pr",
|
|
64467
64998
|
"view",
|
|
64468
64999
|
String(ref.number),
|
|
@@ -64477,7 +65008,7 @@ async function fetchGhPRContext(runtime2, ref) {
|
|
|
64477
65008
|
const raw2 = JSON.parse(result.stdout);
|
|
64478
65009
|
const context = parseGhPRContext(raw2);
|
|
64479
65010
|
try {
|
|
64480
|
-
context.reviewThreads = await fetchGhReviewThreads(
|
|
65011
|
+
context.reviewThreads = await fetchGhReviewThreads(runtime3, ref);
|
|
64481
65012
|
} catch {
|
|
64482
65013
|
context.reviewThreads = [];
|
|
64483
65014
|
}
|
|
@@ -64511,8 +65042,8 @@ query($owner: String!, $repo: String!, $number: Int!) {
|
|
|
64511
65042
|
}
|
|
64512
65043
|
}
|
|
64513
65044
|
}`;
|
|
64514
|
-
async function fetchGhReviewThreads(
|
|
64515
|
-
const result = await
|
|
65045
|
+
async function fetchGhReviewThreads(runtime3, ref) {
|
|
65046
|
+
const result = await runtime3.runCommand("gh", hostnameArgs(ref.host, [
|
|
64516
65047
|
"api",
|
|
64517
65048
|
"graphql",
|
|
64518
65049
|
"-f",
|
|
@@ -64548,8 +65079,8 @@ async function fetchGhReviewThreads(runtime2, ref) {
|
|
|
64548
65079
|
})) : []
|
|
64549
65080
|
}));
|
|
64550
65081
|
}
|
|
64551
|
-
async function fetchGhPRFileContent(
|
|
64552
|
-
const result = await
|
|
65082
|
+
async function fetchGhPRFileContent(runtime3, ref, sha, filePath) {
|
|
65083
|
+
const result = await runtime3.runCommand("gh", hostnameArgs(ref.host, [
|
|
64553
65084
|
"api",
|
|
64554
65085
|
`repos/${ref.owner}/${ref.repo}/contents/${encodeApiFilePath(filePath)}?ref=${sha}`,
|
|
64555
65086
|
"--jq",
|
|
@@ -64567,7 +65098,7 @@ async function fetchGhPRFileContent(runtime2, ref, sha, filePath) {
|
|
|
64567
65098
|
return null;
|
|
64568
65099
|
}
|
|
64569
65100
|
}
|
|
64570
|
-
async function fetchGhPRViewedFiles(
|
|
65101
|
+
async function fetchGhPRViewedFiles(runtime3, ref) {
|
|
64571
65102
|
const query = `
|
|
64572
65103
|
query($owner: String!, $repo: String!, $number: Int!, $cursor: String) {
|
|
64573
65104
|
repository(owner: $owner, name: $repo) {
|
|
@@ -64604,7 +65135,7 @@ async function fetchGhPRViewedFiles(runtime2, ref) {
|
|
|
64604
65135
|
if (cursor) {
|
|
64605
65136
|
args.push("-F", `cursor=${cursor}`);
|
|
64606
65137
|
}
|
|
64607
|
-
const res = await
|
|
65138
|
+
const res = await runtime3.runCommand("gh", args);
|
|
64608
65139
|
if (res.exitCode !== 0) {
|
|
64609
65140
|
throw new Error(`Failed to fetch PR viewed files: ${res.stderr.trim() || `exit code ${res.exitCode}`}`);
|
|
64610
65141
|
}
|
|
@@ -64622,7 +65153,7 @@ async function fetchGhPRViewedFiles(runtime2, ref) {
|
|
|
64622
65153
|
} while (cursor !== null);
|
|
64623
65154
|
return result;
|
|
64624
65155
|
}
|
|
64625
|
-
async function markGhFilesViewed(
|
|
65156
|
+
async function markGhFilesViewed(runtime3, ref, prNodeId, filePaths, viewed) {
|
|
64626
65157
|
if (filePaths.length === 0)
|
|
64627
65158
|
return;
|
|
64628
65159
|
const mutationName = viewed ? "markFileAsViewed" : "unmarkFileAsViewed";
|
|
@@ -64633,7 +65164,7 @@ async function markGhFilesViewed(runtime2, ref, prNodeId, filePaths, viewed) {
|
|
|
64633
65164
|
}
|
|
64634
65165
|
}
|
|
64635
65166
|
`;
|
|
64636
|
-
const results = await Promise.allSettled(filePaths.map((path2) =>
|
|
65167
|
+
const results = await Promise.allSettled(filePaths.map((path2) => runtime3.runCommandWithInput ? runtime3.runCommand("gh", hostnameArgs(ref.host, [
|
|
64637
65168
|
"api",
|
|
64638
65169
|
"graphql",
|
|
64639
65170
|
"-f",
|
|
@@ -64648,7 +65179,7 @@ async function markGhFilesViewed(runtime2, ref, prNodeId, filePaths, viewed) {
|
|
|
64648
65179
|
throw new Error(`Failed to ${mutationName} all files: ${failures[0].reason}`);
|
|
64649
65180
|
}
|
|
64650
65181
|
}
|
|
64651
|
-
async function submitGhPRReview(
|
|
65182
|
+
async function submitGhPRReview(runtime3, ref, headSha, action, body3, fileComments) {
|
|
64652
65183
|
const payload = JSON.stringify({
|
|
64653
65184
|
commit_id: headSha,
|
|
64654
65185
|
body: body3,
|
|
@@ -64657,8 +65188,8 @@ async function submitGhPRReview(runtime2, ref, headSha, action, body3, fileComme
|
|
|
64657
65188
|
});
|
|
64658
65189
|
const endpoint = `repos/${ref.owner}/${ref.repo}/pulls/${ref.number}/reviews`;
|
|
64659
65190
|
let result;
|
|
64660
|
-
if (
|
|
64661
|
-
result = await
|
|
65191
|
+
if (runtime3.runCommandWithInput) {
|
|
65192
|
+
result = await runtime3.runCommandWithInput("gh", hostnameArgs(ref.host, ["api", endpoint, "--method", "POST", "--input", "-"]), payload);
|
|
64662
65193
|
} else {
|
|
64663
65194
|
throw new Error("Runtime does not support stdin input; cannot submit PR review");
|
|
64664
65195
|
}
|
|
@@ -64679,9 +65210,9 @@ query($owner: String!, $repo: String!, $${varName}: String!) {
|
|
|
64679
65210
|
}
|
|
64680
65211
|
}`;
|
|
64681
65212
|
}
|
|
64682
|
-
async function queryPRsByRef(
|
|
65213
|
+
async function queryPRsByRef(runtime3, ref, kind, refName) {
|
|
64683
65214
|
const varName = kind === "head" ? "headRefName" : "baseRefName";
|
|
64684
|
-
const result = await
|
|
65215
|
+
const result = await runtime3.runCommand("gh", hostnameArgs(ref.host, [
|
|
64685
65216
|
"api",
|
|
64686
65217
|
"graphql",
|
|
64687
65218
|
"-f",
|
|
@@ -64699,7 +65230,7 @@ async function queryPRsByRef(runtime2, ref, kind, refName) {
|
|
|
64699
65230
|
const prs = data?.data?.repository?.pullRequests?.nodes;
|
|
64700
65231
|
return Array.isArray(prs) ? prs : [];
|
|
64701
65232
|
}
|
|
64702
|
-
async function fetchGhPRStack(
|
|
65233
|
+
async function fetchGhPRStack(runtime3, ref, metadata) {
|
|
64703
65234
|
if (metadata.platform !== "github")
|
|
64704
65235
|
return null;
|
|
64705
65236
|
const defaultBranch = metadata.defaultBranch;
|
|
@@ -64719,7 +65250,7 @@ async function fetchGhPRStack(runtime2, ref, metadata) {
|
|
|
64719
65250
|
for (let i3 = 0;i3 < maxDepth; i3++) {
|
|
64720
65251
|
if (nextHead === defaultBranch)
|
|
64721
65252
|
break;
|
|
64722
|
-
const prs = await queryPRsByRef(
|
|
65253
|
+
const prs = await queryPRsByRef(runtime3, ref, "head", nextHead);
|
|
64723
65254
|
if (prs.length === 0) {
|
|
64724
65255
|
ancestors.push({ branch: nextHead, isCurrent: false, isDefaultBranch: false });
|
|
64725
65256
|
break;
|
|
@@ -64739,7 +65270,7 @@ async function fetchGhPRStack(runtime2, ref, metadata) {
|
|
|
64739
65270
|
const descendants = [];
|
|
64740
65271
|
let nextBase = metadata.headBranch;
|
|
64741
65272
|
for (let i3 = 0;i3 < maxDepth; i3++) {
|
|
64742
|
-
const prs = await queryPRsByRef(
|
|
65273
|
+
const prs = await queryPRsByRef(runtime3, ref, "base", nextBase);
|
|
64743
65274
|
if (prs.length === 0)
|
|
64744
65275
|
break;
|
|
64745
65276
|
const pr = prs[0];
|
|
@@ -64762,8 +65293,8 @@ async function fetchGhPRStack(runtime2, ref, metadata) {
|
|
|
64762
65293
|
];
|
|
64763
65294
|
return { nodes };
|
|
64764
65295
|
}
|
|
64765
|
-
async function fetchGhPRList(
|
|
64766
|
-
const result = await
|
|
65296
|
+
async function fetchGhPRList(runtime3, ref) {
|
|
65297
|
+
const result = await runtime3.runCommand("gh", [
|
|
64767
65298
|
"pr",
|
|
64768
65299
|
"list",
|
|
64769
65300
|
"--repo",
|
|
@@ -64831,12 +65362,12 @@ ${d2.diff}`);
|
|
|
64831
65362
|
}
|
|
64832
65363
|
return parts.join("");
|
|
64833
65364
|
}
|
|
64834
|
-
async function checkGlAuth(
|
|
65365
|
+
async function checkGlAuth(runtime3, host) {
|
|
64835
65366
|
const args = ["auth", "status"];
|
|
64836
65367
|
if (host !== "gitlab.com") {
|
|
64837
65368
|
args.push("--hostname", host);
|
|
64838
65369
|
}
|
|
64839
|
-
const result = await
|
|
65370
|
+
const result = await runtime3.runCommand("glab", args);
|
|
64840
65371
|
if (result.exitCode !== 0) {
|
|
64841
65372
|
const stderr = result.stderr.trim();
|
|
64842
65373
|
const hostHint = host !== "gitlab.com" ? ` --hostname ${host}` : "";
|
|
@@ -64844,9 +65375,9 @@ async function checkGlAuth(runtime2, host) {
|
|
|
64844
65375
|
${stderr}`);
|
|
64845
65376
|
}
|
|
64846
65377
|
}
|
|
64847
|
-
async function getGlUser(
|
|
65378
|
+
async function getGlUser(runtime3, host) {
|
|
64848
65379
|
try {
|
|
64849
|
-
const result = await
|
|
65380
|
+
const result = await runtime3.runCommand("glab", apiArgs(host, "/user"));
|
|
64850
65381
|
if (result.exitCode === 0 && result.stdout.trim()) {
|
|
64851
65382
|
const user = JSON.parse(result.stdout);
|
|
64852
65383
|
return user.username ?? null;
|
|
@@ -64856,11 +65387,11 @@ async function getGlUser(runtime2, host) {
|
|
|
64856
65387
|
return null;
|
|
64857
65388
|
}
|
|
64858
65389
|
}
|
|
64859
|
-
async function fetchGlMR(
|
|
65390
|
+
async function fetchGlMR(runtime3, ref) {
|
|
64860
65391
|
const encoded = encodeProject(ref.projectPath);
|
|
64861
65392
|
const [diffResult, viewResult] = await Promise.all([
|
|
64862
|
-
|
|
64863
|
-
|
|
65393
|
+
runtime3.runCommand("glab", apiArgs(ref.host, `projects/${encoded}/merge_requests/${ref.iid}/diffs?per_page=100`, ["--paginate"])),
|
|
65394
|
+
runtime3.runCommand("glab", apiArgs(ref.host, `projects/${encoded}/merge_requests/${ref.iid}`))
|
|
64864
65395
|
]);
|
|
64865
65396
|
if (diffResult.exitCode !== 0) {
|
|
64866
65397
|
throw new Error(`Failed to fetch MR diff: ${diffResult.stderr.trim() || `exit code ${diffResult.exitCode}`}`);
|
|
@@ -64877,7 +65408,7 @@ async function fetchGlMR(runtime2, ref) {
|
|
|
64877
65408
|
let defaultBranch;
|
|
64878
65409
|
const projectEndpoint = typeof raw2.target_project_id === "number" ? `projects/${raw2.target_project_id}` : `projects/${encoded}`;
|
|
64879
65410
|
try {
|
|
64880
|
-
const projectResult = await
|
|
65411
|
+
const projectResult = await runtime3.runCommand("glab", apiArgs(ref.host, projectEndpoint));
|
|
64881
65412
|
if (projectResult.exitCode === 0 && projectResult.stdout.trim()) {
|
|
64882
65413
|
const project = JSON.parse(projectResult.stdout);
|
|
64883
65414
|
defaultBranch = project.default_branch;
|
|
@@ -64899,15 +65430,15 @@ async function fetchGlMR(runtime2, ref) {
|
|
|
64899
65430
|
};
|
|
64900
65431
|
return { metadata, rawPatch };
|
|
64901
65432
|
}
|
|
64902
|
-
async function fetchGlMRContext(
|
|
65433
|
+
async function fetchGlMRContext(runtime3, ref) {
|
|
64903
65434
|
const encoded = encodeProject(ref.projectPath);
|
|
64904
65435
|
const mrEndpoint = `projects/${encoded}/merge_requests/${ref.iid}`;
|
|
64905
65436
|
const [mrResult, notesResult, approvalsResult, pipelinesResult, issuesResult] = await Promise.all([
|
|
64906
|
-
|
|
64907
|
-
|
|
64908
|
-
|
|
64909
|
-
|
|
64910
|
-
|
|
65437
|
+
runtime3.runCommand("glab", apiArgs(ref.host, mrEndpoint)),
|
|
65438
|
+
runtime3.runCommand("glab", apiArgs(ref.host, `${mrEndpoint}/notes?sort=asc&per_page=100`)),
|
|
65439
|
+
runtime3.runCommand("glab", apiArgs(ref.host, `${mrEndpoint}/approvals`)),
|
|
65440
|
+
runtime3.runCommand("glab", apiArgs(ref.host, `${mrEndpoint}/pipelines?per_page=5`)),
|
|
65441
|
+
runtime3.runCommand("glab", apiArgs(ref.host, `${mrEndpoint}/closes_issues`))
|
|
64911
65442
|
]);
|
|
64912
65443
|
const str = (v2) => typeof v2 === "string" ? v2 : "";
|
|
64913
65444
|
const arr = (v2) => Array.isArray(v2) ? v2 : [];
|
|
@@ -64990,7 +65521,7 @@ async function fetchGlMRContext(runtime2, ref) {
|
|
|
64990
65521
|
const pipelines = JSON.parse(pipelinesResult.stdout);
|
|
64991
65522
|
if (pipelines.length > 0) {
|
|
64992
65523
|
const latest = pipelines[0];
|
|
64993
|
-
const jobsResult = await
|
|
65524
|
+
const jobsResult = await runtime3.runCommand("glab", apiArgs(ref.host, `projects/${encoded}/pipelines/${latest.id}/jobs?per_page=100`));
|
|
64994
65525
|
if (jobsResult.exitCode === 0) {
|
|
64995
65526
|
try {
|
|
64996
65527
|
const jobs = JSON.parse(jobsResult.stdout);
|
|
@@ -65044,30 +65575,30 @@ async function fetchGlMRContext(runtime2, ref) {
|
|
|
65044
65575
|
linkedIssues
|
|
65045
65576
|
};
|
|
65046
65577
|
}
|
|
65047
|
-
async function fetchGlFileContent(
|
|
65578
|
+
async function fetchGlFileContent(runtime3, ref, sha, filePath) {
|
|
65048
65579
|
const encoded = encodeProject(ref.projectPath);
|
|
65049
65580
|
const encodedPath = encodeApiFilePath(filePath);
|
|
65050
|
-
const result = await
|
|
65581
|
+
const result = await runtime3.runCommand("glab", apiArgs(ref.host, `projects/${encoded}/repository/files/${encodedPath}/raw?ref=${sha}`));
|
|
65051
65582
|
if (result.exitCode !== 0)
|
|
65052
65583
|
return null;
|
|
65053
65584
|
return result.stdout;
|
|
65054
65585
|
}
|
|
65055
|
-
async function submitGlMRReview(
|
|
65056
|
-
if (!
|
|
65586
|
+
async function submitGlMRReview(runtime3, ref, headSha, action, body3, fileComments) {
|
|
65587
|
+
if (!runtime3.runCommandWithInput) {
|
|
65057
65588
|
throw new Error("Runtime does not support stdin input; cannot submit MR review");
|
|
65058
65589
|
}
|
|
65059
65590
|
const encoded = encodeProject(ref.projectPath);
|
|
65060
65591
|
const mrEndpoint = `projects/${encoded}/merge_requests/${ref.iid}`;
|
|
65061
65592
|
if (body3 && body3.trim()) {
|
|
65062
65593
|
const notePayload = JSON.stringify({ body: body3.trim() });
|
|
65063
|
-
const noteResult = await
|
|
65594
|
+
const noteResult = await runtime3.runCommandWithInput("glab", apiArgs(ref.host, `${mrEndpoint}/notes`, ["--method", "POST", "--input", "-", "-H", "Content-Type:application/json"]), notePayload);
|
|
65064
65595
|
if (noteResult.exitCode !== 0) {
|
|
65065
65596
|
const msg = noteResult.stderr.trim() || noteResult.stdout.trim() || `exit code ${noteResult.exitCode}`;
|
|
65066
65597
|
throw new Error(`Failed to post MR note: ${msg}`);
|
|
65067
65598
|
}
|
|
65068
65599
|
}
|
|
65069
65600
|
if (fileComments.length > 0) {
|
|
65070
|
-
const mrResult = await
|
|
65601
|
+
const mrResult = await runtime3.runCommand("glab", apiArgs(ref.host, mrEndpoint));
|
|
65071
65602
|
let baseSha = headSha;
|
|
65072
65603
|
let startSha = headSha;
|
|
65073
65604
|
if (mrResult.exitCode === 0 && mrResult.stdout.trim()) {
|
|
@@ -65110,7 +65641,7 @@ async function submitGlMRReview(runtime2, ref, headSha, action, body3, fileComme
|
|
|
65110
65641
|
position.line_range = { start: startEntry, end: endEntry };
|
|
65111
65642
|
}
|
|
65112
65643
|
const payload = JSON.stringify({ body: comment2.body, position });
|
|
65113
|
-
const res = await
|
|
65644
|
+
const res = await runtime3.runCommandWithInput("glab", apiArgs(ref.host, `${mrEndpoint}/discussions`, ["--method", "POST", "--input", "-", "-H", "Content-Type:application/json"]), payload);
|
|
65114
65645
|
if (res.exitCode !== 0) {
|
|
65115
65646
|
const msg = res.stderr.trim() || res.stdout.trim() || `exit code ${res.exitCode}`;
|
|
65116
65647
|
throw new Error(`${comment2.path}:${comment2.line}: ${msg}`);
|
|
@@ -65133,7 +65664,7 @@ ${errors.join(`
|
|
|
65133
65664
|
}
|
|
65134
65665
|
}
|
|
65135
65666
|
if (action === "approve") {
|
|
65136
|
-
const approveResult = await
|
|
65667
|
+
const approveResult = await runtime3.runCommandWithInput("glab", apiArgs(ref.host, `${mrEndpoint}/approve`, ["--method", "POST", "--input", "-", "-H", "Content-Type:application/json"]), "{}");
|
|
65137
65668
|
if (approveResult.exitCode !== 0) {
|
|
65138
65669
|
const msg = approveResult.stderr.trim() || approveResult.stdout.trim() || `exit code ${approveResult.exitCode}`;
|
|
65139
65670
|
throw new Error(`Failed to approve MR: ${msg}`);
|
|
@@ -65202,58 +65733,58 @@ function parsePRUrl(url) {
|
|
|
65202
65733
|
}
|
|
65203
65734
|
return null;
|
|
65204
65735
|
}
|
|
65205
|
-
async function checkAuth(
|
|
65736
|
+
async function checkAuth(runtime3, ref) {
|
|
65206
65737
|
if (ref.platform === "github")
|
|
65207
|
-
return checkGhAuth(
|
|
65208
|
-
return checkGlAuth(
|
|
65738
|
+
return checkGhAuth(runtime3, ref.host);
|
|
65739
|
+
return checkGlAuth(runtime3, ref.host);
|
|
65209
65740
|
}
|
|
65210
|
-
async function getUser(
|
|
65741
|
+
async function getUser(runtime3, ref) {
|
|
65211
65742
|
if (ref.platform === "github")
|
|
65212
|
-
return getGhUser(
|
|
65213
|
-
return getGlUser(
|
|
65743
|
+
return getGhUser(runtime3, ref.host);
|
|
65744
|
+
return getGlUser(runtime3, ref.host);
|
|
65214
65745
|
}
|
|
65215
|
-
async function fetchPR(
|
|
65746
|
+
async function fetchPR(runtime3, ref) {
|
|
65216
65747
|
if (ref.platform === "github")
|
|
65217
|
-
return fetchGhPR(
|
|
65218
|
-
return fetchGlMR(
|
|
65748
|
+
return fetchGhPR(runtime3, ref);
|
|
65749
|
+
return fetchGlMR(runtime3, ref);
|
|
65219
65750
|
}
|
|
65220
|
-
async function fetchPRContext(
|
|
65751
|
+
async function fetchPRContext(runtime3, ref) {
|
|
65221
65752
|
if (ref.platform === "github")
|
|
65222
|
-
return fetchGhPRContext(
|
|
65223
|
-
return fetchGlMRContext(
|
|
65753
|
+
return fetchGhPRContext(runtime3, ref);
|
|
65754
|
+
return fetchGlMRContext(runtime3, ref);
|
|
65224
65755
|
}
|
|
65225
|
-
async function fetchPRFileContent(
|
|
65756
|
+
async function fetchPRFileContent(runtime3, ref, sha, filePath) {
|
|
65226
65757
|
if (ref.platform === "github")
|
|
65227
|
-
return fetchGhPRFileContent(
|
|
65228
|
-
return fetchGlFileContent(
|
|
65758
|
+
return fetchGhPRFileContent(runtime3, ref, sha, filePath);
|
|
65759
|
+
return fetchGlFileContent(runtime3, ref, sha, filePath);
|
|
65229
65760
|
}
|
|
65230
|
-
async function submitPRReview(
|
|
65761
|
+
async function submitPRReview(runtime3, ref, headSha, action, body3, fileComments) {
|
|
65231
65762
|
if (ref.platform === "github")
|
|
65232
|
-
return submitGhPRReview(
|
|
65233
|
-
return submitGlMRReview(
|
|
65763
|
+
return submitGhPRReview(runtime3, ref, headSha, action, body3, fileComments);
|
|
65764
|
+
return submitGlMRReview(runtime3, ref, headSha, action, body3, fileComments);
|
|
65234
65765
|
}
|
|
65235
|
-
async function fetchPRViewedFiles(
|
|
65766
|
+
async function fetchPRViewedFiles(runtime3, ref) {
|
|
65236
65767
|
if (ref.platform === "github")
|
|
65237
|
-
return fetchGhPRViewedFiles(
|
|
65768
|
+
return fetchGhPRViewedFiles(runtime3, ref);
|
|
65238
65769
|
return {};
|
|
65239
65770
|
}
|
|
65240
|
-
async function markPRFilesViewed(
|
|
65771
|
+
async function markPRFilesViewed(runtime3, ref, prNodeId, filePaths, viewed) {
|
|
65241
65772
|
if (ref.platform === "github")
|
|
65242
|
-
return markGhFilesViewed(
|
|
65773
|
+
return markGhFilesViewed(runtime3, ref, prNodeId, filePaths, viewed);
|
|
65243
65774
|
}
|
|
65244
|
-
async function fetchPRStack(
|
|
65775
|
+
async function fetchPRStack(runtime3, ref, metadata) {
|
|
65245
65776
|
if (ref.platform === "github")
|
|
65246
|
-
return fetchGhPRStack(
|
|
65777
|
+
return fetchGhPRStack(runtime3, ref, metadata);
|
|
65247
65778
|
return null;
|
|
65248
65779
|
}
|
|
65249
|
-
async function fetchPRList(
|
|
65780
|
+
async function fetchPRList(runtime3, ref) {
|
|
65250
65781
|
if (ref.platform === "github")
|
|
65251
|
-
return fetchGhPRList(
|
|
65782
|
+
return fetchGhPRList(runtime3, ref);
|
|
65252
65783
|
return [];
|
|
65253
65784
|
}
|
|
65254
65785
|
|
|
65255
65786
|
// ../../packages/server/pr.ts
|
|
65256
|
-
var
|
|
65787
|
+
var runtime3 = {
|
|
65257
65788
|
async runCommand(cmd, args) {
|
|
65258
65789
|
const proc = Bun.spawn([cmd, ...args], {
|
|
65259
65790
|
stdout: "pipe",
|
|
@@ -65284,34 +65815,34 @@ var runtime2 = {
|
|
|
65284
65815
|
};
|
|
65285
65816
|
var parsePRUrl2 = parsePRUrl;
|
|
65286
65817
|
function checkPRAuth(ref) {
|
|
65287
|
-
return checkAuth(
|
|
65818
|
+
return checkAuth(runtime3, ref);
|
|
65288
65819
|
}
|
|
65289
65820
|
function getPRUser(ref) {
|
|
65290
|
-
return getUser(
|
|
65821
|
+
return getUser(runtime3, ref);
|
|
65291
65822
|
}
|
|
65292
65823
|
function fetchPR2(ref) {
|
|
65293
|
-
return fetchPR(
|
|
65824
|
+
return fetchPR(runtime3, ref);
|
|
65294
65825
|
}
|
|
65295
65826
|
function fetchPRContext2(ref) {
|
|
65296
|
-
return fetchPRContext(
|
|
65827
|
+
return fetchPRContext(runtime3, ref);
|
|
65297
65828
|
}
|
|
65298
65829
|
function fetchPRFileContent2(ref, sha, filePath) {
|
|
65299
|
-
return fetchPRFileContent(
|
|
65830
|
+
return fetchPRFileContent(runtime3, ref, sha, filePath);
|
|
65300
65831
|
}
|
|
65301
65832
|
function submitPRReview2(ref, headSha, action, body3, fileComments) {
|
|
65302
|
-
return submitPRReview(
|
|
65833
|
+
return submitPRReview(runtime3, ref, headSha, action, body3, fileComments);
|
|
65303
65834
|
}
|
|
65304
65835
|
function fetchPRViewedFiles2(ref) {
|
|
65305
|
-
return fetchPRViewedFiles(
|
|
65836
|
+
return fetchPRViewedFiles(runtime3, ref);
|
|
65306
65837
|
}
|
|
65307
65838
|
function markPRFilesViewed2(ref, prNodeId, filePaths, viewed) {
|
|
65308
|
-
return markPRFilesViewed(
|
|
65839
|
+
return markPRFilesViewed(runtime3, ref, prNodeId, filePaths, viewed);
|
|
65309
65840
|
}
|
|
65310
65841
|
function fetchPRStack2(ref, metadata) {
|
|
65311
|
-
return fetchPRStack(
|
|
65842
|
+
return fetchPRStack(runtime3, ref, metadata);
|
|
65312
65843
|
}
|
|
65313
65844
|
function fetchPRList2(ref) {
|
|
65314
|
-
return fetchPRList(
|
|
65845
|
+
return fetchPRList(runtime3, ref);
|
|
65315
65846
|
}
|
|
65316
65847
|
|
|
65317
65848
|
// ../../packages/ai/index.ts
|
|
@@ -65569,6 +66100,7 @@ async function startReviewServer(options) {
|
|
|
65569
66100
|
let prMetadata = options.prMetadata;
|
|
65570
66101
|
const isPRMode = !!prMetadata;
|
|
65571
66102
|
const hasLocalAccess = !!gitContext;
|
|
66103
|
+
const sessionVcsType = gitContext?.vcsType;
|
|
65572
66104
|
let draftKey = contentHash(options.rawPatch);
|
|
65573
66105
|
const editorAnnotations = createEditorAnnotationHandler();
|
|
65574
66106
|
const externalAnnotations = createExternalAnnotationHandler("review");
|
|
@@ -65588,10 +66120,14 @@ async function startReviewServer(options) {
|
|
|
65588
66120
|
if (isPRMode && prMetadata)
|
|
65589
66121
|
prSwitchCache.set(prMetadata.url, { metadata: prMetadata, rawPatch: options.rawPatch });
|
|
65590
66122
|
const prStackTreeCache = new Map;
|
|
65591
|
-
|
|
66123
|
+
const detectedCompareTarget = () => gitContext?.defaultBranch || gitContext?.compareTarget?.fallback || "main";
|
|
66124
|
+
let currentBase = options.initialBase || detectedCompareTarget();
|
|
65592
66125
|
let baseEverSwitched = false;
|
|
66126
|
+
const resolveReviewBase = (requestedBase) => {
|
|
66127
|
+
return resolveBaseBranch(requestedBase, detectedCompareTarget());
|
|
66128
|
+
};
|
|
65593
66129
|
if (gitContext && !options.initialBase && !isPRMode) {
|
|
65594
|
-
|
|
66130
|
+
detectRemoteDefaultCompareTarget(gitContext.cwd, sessionVcsType).then((remote) => {
|
|
65595
66131
|
if (remote && !baseEverSwitched)
|
|
65596
66132
|
currentBase = remote;
|
|
65597
66133
|
});
|
|
@@ -65632,7 +66168,7 @@ async function startReviewServer(options) {
|
|
|
65632
66168
|
});
|
|
65633
66169
|
return built ? { ...built, prUrl: launchPrUrl, diffScope: launchDiffScope, diffContext } : built;
|
|
65634
66170
|
}
|
|
65635
|
-
const userMessage =
|
|
66171
|
+
const userMessage = buildAgentReviewUserMessage(currentPatch, currentDiffType, userMessageOptions, prMetadata);
|
|
65636
66172
|
if (provider === "codex") {
|
|
65637
66173
|
const model = typeof config?.model === "string" && config.model ? config.model : undefined;
|
|
65638
66174
|
const reasoningEffort = typeof config?.reasoningEffort === "string" && config.reasoningEffort ? config.reasoningEffort : undefined;
|
|
@@ -65785,6 +66321,12 @@ async function startReviewServer(options) {
|
|
|
65785
66321
|
const wslFlag = await isWSL();
|
|
65786
66322
|
const gitUser = detectGitUser();
|
|
65787
66323
|
let repoInfo = isPRMode && prMetadata ? { display: getDisplayRepo(prMetadata), branch: `${getMRLabel(prMetadata)} ${getMRNumberLabel(prMetadata)}` } : await getRepoInfo();
|
|
66324
|
+
if (gitContext?.repository?.displayFallback) {
|
|
66325
|
+
repoInfo = {
|
|
66326
|
+
...repoInfo,
|
|
66327
|
+
display: repoInfo?.display || gitContext.repository.displayFallback
|
|
66328
|
+
};
|
|
66329
|
+
}
|
|
65788
66330
|
let prRef = isPRMode && prMetadata ? prRefFromMetadata(prMetadata) : null;
|
|
65789
66331
|
const platformUser = prRef ? await getPRUser(prRef) : null;
|
|
65790
66332
|
let prStackInfo = prMetadata ? getPRStackInfo(prMetadata) : null;
|
|
@@ -65809,8 +66351,8 @@ async function startReviewServer(options) {
|
|
|
65809
66351
|
} catch {}
|
|
65810
66352
|
}
|
|
65811
66353
|
let resolveDecision;
|
|
65812
|
-
const decisionPromise = new Promise((
|
|
65813
|
-
resolveDecision =
|
|
66354
|
+
const decisionPromise = new Promise((resolve6) => {
|
|
66355
|
+
resolveDecision = resolve6;
|
|
65814
66356
|
});
|
|
65815
66357
|
let server2 = null;
|
|
65816
66358
|
for (let attempt = 1;attempt <= MAX_RETRIES2; attempt++) {
|
|
@@ -65879,9 +66421,8 @@ async function startReviewServer(options) {
|
|
|
65879
66421
|
if (typeof body3.hideWhitespace === "boolean") {
|
|
65880
66422
|
currentHideWhitespace = body3.hideWhitespace;
|
|
65881
66423
|
}
|
|
65882
|
-
const detectedBase = gitContext?.defaultBranch || "main";
|
|
65883
66424
|
const requestedBase = typeof body3.base === "string" ? body3.base : undefined;
|
|
65884
|
-
const base =
|
|
66425
|
+
const base = resolveReviewBase(requestedBase);
|
|
65885
66426
|
const defaultCwd = gitContext?.cwd;
|
|
65886
66427
|
const result = await runVcsDiff(newDiffType, base, defaultCwd, {
|
|
65887
66428
|
hideWhitespace: currentHideWhitespace
|
|
@@ -65896,7 +66437,7 @@ async function startReviewServer(options) {
|
|
|
65896
66437
|
if (gitContext) {
|
|
65897
66438
|
try {
|
|
65898
66439
|
const effectiveCwd = resolveVcsCwd(newDiffType, gitContext.cwd);
|
|
65899
|
-
updatedContext = await getVcsContext(effectiveCwd);
|
|
66440
|
+
updatedContext = await getVcsContext(effectiveCwd, sessionVcsType);
|
|
65900
66441
|
} catch {}
|
|
65901
66442
|
}
|
|
65902
66443
|
return Response.json({
|
|
@@ -66094,8 +66635,8 @@ async function startReviewServer(options) {
|
|
|
66094
66635
|
return Response.json(result);
|
|
66095
66636
|
}
|
|
66096
66637
|
if (hasLocalAccess) {
|
|
66097
|
-
const
|
|
66098
|
-
const base =
|
|
66638
|
+
const requestedBase = url.searchParams.get("base") ?? undefined;
|
|
66639
|
+
const base = resolveReviewBase(requestedBase);
|
|
66099
66640
|
const defaultCwd = gitContext?.cwd;
|
|
66100
66641
|
const result = await getVcsFileContentsForDiff(currentDiffType, base, filePath, oldPath, defaultCwd);
|
|
66101
66642
|
return Response.json(result);
|
|
@@ -66111,7 +66652,8 @@ async function startReviewServer(options) {
|
|
|
66111
66652
|
return Response.json({ error: "No file access available" }, { status: 400 });
|
|
66112
66653
|
}
|
|
66113
66654
|
if (url.pathname === "/api/git-add" && req.method === "POST") {
|
|
66114
|
-
|
|
66655
|
+
const stageCwd = resolveVcsCwd(currentDiffType, gitContext?.cwd);
|
|
66656
|
+
if (isPRMode || !await canStageFiles(currentDiffType, stageCwd)) {
|
|
66115
66657
|
return Response.json({ error: "Staging not available" }, { status: 400 });
|
|
66116
66658
|
}
|
|
66117
66659
|
try {
|
|
@@ -66119,11 +66661,10 @@ async function startReviewServer(options) {
|
|
|
66119
66661
|
if (!body3.filePath) {
|
|
66120
66662
|
return Response.json({ error: "Missing filePath" }, { status: 400 });
|
|
66121
66663
|
}
|
|
66122
|
-
const cwd = resolveVcsCwd(currentDiffType, gitContext?.cwd);
|
|
66123
66664
|
if (body3.undo) {
|
|
66124
|
-
await unstageFile(currentDiffType, body3.filePath,
|
|
66665
|
+
await unstageFile(currentDiffType, body3.filePath, stageCwd);
|
|
66125
66666
|
} else {
|
|
66126
|
-
await stageFile(currentDiffType, body3.filePath,
|
|
66667
|
+
await stageFile(currentDiffType, body3.filePath, stageCwd);
|
|
66127
66668
|
}
|
|
66128
66669
|
return Response.json({ ok: true });
|
|
66129
66670
|
} catch (err) {
|
|
@@ -66344,8 +66885,8 @@ async function startAnnotateServer(options) {
|
|
|
66344
66885
|
const externalAnnotations = createExternalAnnotationHandler("plan");
|
|
66345
66886
|
const repoInfo = await getRepoInfo();
|
|
66346
66887
|
let resolveDecision;
|
|
66347
|
-
const decisionPromise = new Promise((
|
|
66348
|
-
resolveDecision =
|
|
66888
|
+
const decisionPromise = new Promise((resolve6) => {
|
|
66889
|
+
resolveDecision = resolve6;
|
|
66349
66890
|
});
|
|
66350
66891
|
let server2 = null;
|
|
66351
66892
|
for (let attempt = 1;attempt <= MAX_RETRIES3; attempt++) {
|
|
@@ -66514,8 +67055,8 @@ var PLAN_TOOL_NAMES = {
|
|
|
66514
67055
|
codex: "ExitPlanMode",
|
|
66515
67056
|
"gemini-cli": "exit_plan_mode"
|
|
66516
67057
|
};
|
|
66517
|
-
function getPlanToolName(
|
|
66518
|
-
return
|
|
67058
|
+
function getPlanToolName(runtime4) {
|
|
67059
|
+
return runtime4 && PLAN_TOOL_NAMES[runtime4] || "ExitPlanMode";
|
|
66519
67060
|
}
|
|
66520
67061
|
function buildPlanFileRule(toolName, planFilePath) {
|
|
66521
67062
|
if (!planFilePath)
|
|
@@ -66573,11 +67114,11 @@ function getConfiguredPrompt(options) {
|
|
|
66573
67114
|
const runtimeFallback = options.runtime ? options.runtimeFallbacks?.[options.runtime] : undefined;
|
|
66574
67115
|
return runtimePrompt ?? genericPrompt ?? runtimeFallback ?? options.fallback;
|
|
66575
67116
|
}
|
|
66576
|
-
function getReviewApprovedPrompt(
|
|
67117
|
+
function getReviewApprovedPrompt(runtime4, config) {
|
|
66577
67118
|
return getConfiguredPrompt({
|
|
66578
67119
|
section: "review",
|
|
66579
67120
|
key: "approved",
|
|
66580
|
-
runtime:
|
|
67121
|
+
runtime: runtime4,
|
|
66581
67122
|
config,
|
|
66582
67123
|
fallback: DEFAULT_REVIEW_APPROVED_PROMPT
|
|
66583
67124
|
});
|
|
@@ -66590,21 +67131,21 @@ Please address this feedback.`,
|
|
|
66590
67131
|
|
|
66591
67132
|
Please address this feedback.`
|
|
66592
67133
|
};
|
|
66593
|
-
function getReviewDeniedSuffix(
|
|
67134
|
+
function getReviewDeniedSuffix(runtime4, config) {
|
|
66594
67135
|
return getConfiguredPrompt({
|
|
66595
67136
|
section: "review",
|
|
66596
67137
|
key: "denied",
|
|
66597
|
-
runtime:
|
|
67138
|
+
runtime: runtime4,
|
|
66598
67139
|
config,
|
|
66599
67140
|
fallback: DEFAULT_REVIEW_DENIED_SUFFIX,
|
|
66600
67141
|
runtimeFallbacks: REVIEW_DENIED_RUNTIME_DEFAULTS
|
|
66601
67142
|
});
|
|
66602
67143
|
}
|
|
66603
|
-
function getPlanDeniedPrompt(
|
|
67144
|
+
function getPlanDeniedPrompt(runtime4, config, vars) {
|
|
66604
67145
|
const template = getConfiguredPrompt({
|
|
66605
67146
|
section: "plan",
|
|
66606
67147
|
key: "denied",
|
|
66607
|
-
runtime:
|
|
67148
|
+
runtime: runtime4,
|
|
66608
67149
|
config,
|
|
66609
67150
|
fallback: DEFAULT_PLAN_DENIED_PROMPT
|
|
66610
67151
|
});
|
|
@@ -66613,11 +67154,11 @@ function getPlanDeniedPrompt(runtime3, config, vars) {
|
|
|
66613
67154
|
var PLAN_APPROVED_RUNTIME_DEFAULTS = {
|
|
66614
67155
|
opencode: "Plan approved!{{doneMsg}}"
|
|
66615
67156
|
};
|
|
66616
|
-
function getPlanApprovedPrompt(
|
|
67157
|
+
function getPlanApprovedPrompt(runtime4, config, vars) {
|
|
66617
67158
|
const template = getConfiguredPrompt({
|
|
66618
67159
|
section: "plan",
|
|
66619
67160
|
key: "approved",
|
|
66620
|
-
runtime:
|
|
67161
|
+
runtime: runtime4,
|
|
66621
67162
|
config,
|
|
66622
67163
|
fallback: DEFAULT_PLAN_APPROVED_PROMPT,
|
|
66623
67164
|
runtimeFallbacks: PLAN_APPROVED_RUNTIME_DEFAULTS
|
|
@@ -66634,32 +67175,32 @@ The user approved your plan but added the following notes to consider during imp
|
|
|
66634
67175
|
|
|
66635
67176
|
{{feedback}}{{proceedSuffix}}`
|
|
66636
67177
|
};
|
|
66637
|
-
function getPlanApprovedWithNotesPrompt(
|
|
67178
|
+
function getPlanApprovedWithNotesPrompt(runtime4, config, vars) {
|
|
66638
67179
|
const template = getConfiguredPrompt({
|
|
66639
67180
|
section: "plan",
|
|
66640
67181
|
key: "approvedWithNotes",
|
|
66641
|
-
runtime:
|
|
67182
|
+
runtime: runtime4,
|
|
66642
67183
|
config,
|
|
66643
67184
|
fallback: DEFAULT_PLAN_APPROVED_WITH_NOTES_PROMPT,
|
|
66644
67185
|
runtimeFallbacks: PLAN_APPROVED_WITH_NOTES_RUNTIME_DEFAULTS
|
|
66645
67186
|
});
|
|
66646
67187
|
return resolveTemplate(template, { proceedSuffix: "", ...vars });
|
|
66647
67188
|
}
|
|
66648
|
-
function getAnnotateFileFeedbackPrompt(
|
|
67189
|
+
function getAnnotateFileFeedbackPrompt(runtime4, config, vars) {
|
|
66649
67190
|
const template = getConfiguredPrompt({
|
|
66650
67191
|
section: "annotate",
|
|
66651
67192
|
key: "fileFeedback",
|
|
66652
|
-
runtime:
|
|
67193
|
+
runtime: runtime4,
|
|
66653
67194
|
config,
|
|
66654
67195
|
fallback: DEFAULT_ANNOTATE_FILE_FEEDBACK_PROMPT
|
|
66655
67196
|
});
|
|
66656
67197
|
return resolveTemplate(template, vars ?? {});
|
|
66657
67198
|
}
|
|
66658
|
-
function getAnnotateMessageFeedbackPrompt(
|
|
67199
|
+
function getAnnotateMessageFeedbackPrompt(runtime4, config, vars) {
|
|
66659
67200
|
const template = getConfiguredPrompt({
|
|
66660
67201
|
section: "annotate",
|
|
66661
67202
|
key: "messageFeedback",
|
|
66662
|
-
runtime:
|
|
67203
|
+
runtime: runtime4,
|
|
66663
67204
|
config,
|
|
66664
67205
|
fallback: DEFAULT_ANNOTATE_MESSAGE_FEEDBACK_PROMPT
|
|
66665
67206
|
});
|
|
@@ -66711,6 +67252,73 @@ function parseAnnotateArgs(raw2) {
|
|
|
66711
67252
|
return { filePath: stripAtPrefix(rawFilePath), rawFilePath, ...flags };
|
|
66712
67253
|
}
|
|
66713
67254
|
|
|
67255
|
+
// ../../packages/shared/review-args.ts
|
|
67256
|
+
function parseReviewArgs(input) {
|
|
67257
|
+
const tokens = Array.isArray(input) ? input.map((token2) => stripWrappingQuotes(token2.trim())).filter(Boolean) : tokenizeReviewArgs(input ?? "");
|
|
67258
|
+
let vcsType;
|
|
67259
|
+
let useLocal = true;
|
|
67260
|
+
const positional = [];
|
|
67261
|
+
for (const token2 of tokens) {
|
|
67262
|
+
switch (token2) {
|
|
67263
|
+
case "--git":
|
|
67264
|
+
vcsType = "git";
|
|
67265
|
+
break;
|
|
67266
|
+
case "--local":
|
|
67267
|
+
useLocal = true;
|
|
67268
|
+
break;
|
|
67269
|
+
case "--no-local":
|
|
67270
|
+
useLocal = false;
|
|
67271
|
+
break;
|
|
67272
|
+
default:
|
|
67273
|
+
positional.push(token2);
|
|
67274
|
+
break;
|
|
67275
|
+
}
|
|
67276
|
+
}
|
|
67277
|
+
const target = positional[0];
|
|
67278
|
+
return {
|
|
67279
|
+
prUrl: target && isReviewUrl(target) ? target : undefined,
|
|
67280
|
+
vcsType,
|
|
67281
|
+
useLocal
|
|
67282
|
+
};
|
|
67283
|
+
}
|
|
67284
|
+
function isReviewUrl(value) {
|
|
67285
|
+
return value.startsWith("http://") || value.startsWith("https://");
|
|
67286
|
+
}
|
|
67287
|
+
function tokenizeReviewArgs(input) {
|
|
67288
|
+
const raw2 = input.trim();
|
|
67289
|
+
if (!raw2)
|
|
67290
|
+
return [];
|
|
67291
|
+
const tokens = [];
|
|
67292
|
+
let current = "";
|
|
67293
|
+
let quote;
|
|
67294
|
+
for (let i4 = 0;i4 < raw2.length; i4++) {
|
|
67295
|
+
const char = raw2[i4];
|
|
67296
|
+
if (quote) {
|
|
67297
|
+
if (char === quote) {
|
|
67298
|
+
quote = undefined;
|
|
67299
|
+
} else {
|
|
67300
|
+
current += char;
|
|
67301
|
+
}
|
|
67302
|
+
continue;
|
|
67303
|
+
}
|
|
67304
|
+
if (char === "'" || char === '"') {
|
|
67305
|
+
quote = char;
|
|
67306
|
+
continue;
|
|
67307
|
+
}
|
|
67308
|
+
if (/\s/.test(char)) {
|
|
67309
|
+
if (current) {
|
|
67310
|
+
tokens.push(current);
|
|
67311
|
+
current = "";
|
|
67312
|
+
}
|
|
67313
|
+
continue;
|
|
67314
|
+
}
|
|
67315
|
+
current += char;
|
|
67316
|
+
}
|
|
67317
|
+
if (current)
|
|
67318
|
+
tokens.push(current);
|
|
67319
|
+
return tokens.map((token2) => stripWrappingQuotes(token2.trim())).filter(Boolean);
|
|
67320
|
+
}
|
|
67321
|
+
|
|
66714
67322
|
// ../../packages/shared/url-to-markdown.ts
|
|
66715
67323
|
var isConvertedSource = (source) => source === "jina" || source === "fetch+turndown";
|
|
66716
67324
|
var FETCH_TIMEOUT_MS = 30000;
|
|
@@ -66950,8 +67558,9 @@ import { statSync as statSync5 } from "fs";
|
|
|
66950
67558
|
import path3 from "path";
|
|
66951
67559
|
async function handleReviewCommand(event, deps) {
|
|
66952
67560
|
const { client: client3, reviewHtmlContent, getSharingEnabled, getShareBaseUrl, directory } = deps;
|
|
66953
|
-
const
|
|
66954
|
-
const
|
|
67561
|
+
const reviewArgs = parseReviewArgs(event.properties?.arguments || "");
|
|
67562
|
+
const urlArg = reviewArgs.prUrl;
|
|
67563
|
+
const isPRMode = urlArg !== undefined;
|
|
66955
67564
|
let rawPatch;
|
|
66956
67565
|
let gitRef;
|
|
66957
67566
|
let diffError;
|
|
@@ -66983,14 +67592,17 @@ async function handleReviewCommand(event, deps) {
|
|
|
66983
67592
|
}
|
|
66984
67593
|
} else {
|
|
66985
67594
|
client3.app.log({ level: "info", message: "Opening code review UI..." });
|
|
66986
|
-
gitContext = await getGitContext2(directory);
|
|
66987
67595
|
const config = loadConfig();
|
|
66988
|
-
|
|
66989
|
-
|
|
67596
|
+
const diffResult = await prepareLocalReviewDiff({
|
|
67597
|
+
cwd: directory,
|
|
67598
|
+
vcsType: reviewArgs.vcsType,
|
|
67599
|
+
configuredDiffType: resolveDefaultDiffType(config),
|
|
66990
67600
|
hideWhitespace: config.diffOptions?.hideWhitespace ?? false
|
|
66991
67601
|
});
|
|
66992
|
-
|
|
66993
|
-
|
|
67602
|
+
gitContext = diffResult.gitContext;
|
|
67603
|
+
userDiffType = diffResult.diffType;
|
|
67604
|
+
rawPatch = diffResult.rawPatch;
|
|
67605
|
+
gitRef = diffResult.gitRef;
|
|
66994
67606
|
diffError = diffResult.error;
|
|
66995
67607
|
}
|
|
66996
67608
|
const server2 = await startReviewServer({
|
|
@@ -67716,14 +68328,14 @@ Use /plannotator-last or /plannotator-annotate for manual review, or set workflo
|
|
|
67716
68328
|
});
|
|
67717
68329
|
const timeoutSeconds = getPlanTimeoutSeconds();
|
|
67718
68330
|
const timeoutMs = timeoutSeconds === null ? null : timeoutSeconds * 1000;
|
|
67719
|
-
const result = timeoutMs === null ? await server2.waitForDecision() : await new Promise((
|
|
67720
|
-
const timeoutId = setTimeout(() =>
|
|
68331
|
+
const result = timeoutMs === null ? await server2.waitForDecision() : await new Promise((resolve6) => {
|
|
68332
|
+
const timeoutId = setTimeout(() => resolve6({
|
|
67721
68333
|
approved: false,
|
|
67722
68334
|
feedback: `[Plannotator] No response within ${timeoutSeconds} seconds. Port released automatically. Please call submit_plan again.`
|
|
67723
68335
|
}), timeoutMs);
|
|
67724
68336
|
server2.waitForDecision().then((r9) => {
|
|
67725
68337
|
clearTimeout(timeoutId);
|
|
67726
|
-
|
|
68338
|
+
resolve6(r9);
|
|
67727
68339
|
});
|
|
67728
68340
|
});
|
|
67729
68341
|
await Bun.sleep(1500);
|