@sideboard-ai/core 0.1.66 → 0.1.68
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agents-EWFD765A.js → agents-JBD7IAGK.js} +10 -6
- package/dist/{agents-MD7SCFYX.js → agents-PE3RHQS5.js} +10 -6
- package/dist/{chunk-BBEH2CJE.js → chunk-47RBLBRK.js} +22 -7
- package/dist/{chunk-IFAU2DEY.js → chunk-6Q7H6SMX.js} +22 -7
- package/dist/{chunk-5AG5BUQN.js → chunk-AE5VBOFE.js} +14 -3
- package/dist/{chunk-DZYMNW2A.js → chunk-BTL7EMGT.js} +4 -4
- package/dist/{chunk-TXQ6K2GR.js → chunk-D4DPQ552.js} +14 -3
- package/dist/{chunk-PESJDZTB.js → chunk-DPDGMMGI.js} +2 -2
- package/dist/{chunk-R7GUDEPY.js → chunk-EEBDVLDK.js} +22 -20
- package/dist/{chunk-LRBRQFBU.js → chunk-N5LMEP65.js} +1 -1
- package/dist/{chunk-DNPP7QMK.js → chunk-OICHV4DH.js} +2 -2
- package/dist/{chunk-HTOTTJJX.js → chunk-QQC2D4MY.js} +2 -2
- package/dist/{chunk-I2KGRAXC.js → chunk-REKGFVUX.js} +22 -20
- package/dist/{chunk-YTNLOJPK.js → chunk-ROXEENBT.js} +2 -2
- package/dist/{chunk-EVD4KNKR.js → chunk-VROPG6QF.js} +1 -1
- package/dist/{chunk-AKPEXIKK.js → chunk-VX6ACNXS.js} +1 -1
- package/dist/{connected-teams-CHXO5FFA.js → connected-teams-35EIRJCP.js} +2 -2
- package/dist/{connected-teams-GJTESSTX.js → connected-teams-ZRS53OAT.js} +2 -2
- package/dist/{coordinator-prompt-ILSULI7C.js → coordinator-prompt-HD6IMCKS.js} +3 -3
- package/dist/{coordinator-prompt-E5UGSJES.js → coordinator-prompt-YZYZ5P6P.js} +3 -3
- package/dist/{global-workspace-44UG64NA.js → global-workspace-7P5NG3JZ.js} +4 -4
- package/dist/{global-workspace-5PM5LA6E.js → global-workspace-Z6GF7D2K.js} +4 -4
- package/dist/index.cjs +401 -163
- package/dist/index.d.cts +33 -3
- package/dist/index.d.ts +33 -3
- package/dist/index.js +368 -157
- package/dist/mcp/run-stdio.cjs +397 -163
- package/dist/mcp/run-stdio.js +363 -156
- package/dist/{run-74S2NZWB.js → run-A4RHY7HH.js} +1 -1
- package/dist/{run-JLN5JK7Q.js → run-V2WZUMJA.js} +1 -1
- package/dist/{workspaces-OVBCSS5Y.js → workspaces-BWJNGEE6.js} +5 -5
- package/dist/{workspaces-RXFXQRRF.js → workspaces-O6EZGKQK.js} +5 -5
- package/dist/{worktree-S2N63FLV.js → worktree-VDXLUOWR.js} +2 -2
- package/dist/{worktree-K2JB53R5.js → worktree-ZPSKEZFE.js} +2 -2
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2163,6 +2163,13 @@ function prependPathDir(env, dir) {
|
|
|
2163
2163
|
}
|
|
2164
2164
|
env.PATH = [dir, ...parts].join(import_node_path5.delimiter);
|
|
2165
2165
|
}
|
|
2166
|
+
function conductorBundledBinDir(home = process.env.HOME || process.env.USERPROFILE || (0, import_node_os4.homedir)()) {
|
|
2167
|
+
return (0, import_node_path5.join)(home, "Library", "Application Support", "com.conductor.app", "bin");
|
|
2168
|
+
}
|
|
2169
|
+
function isConductorBundledCli(filePath) {
|
|
2170
|
+
const p = (filePath ?? "").replace(/\\/g, "/");
|
|
2171
|
+
return p.includes("/com.conductor.app/bin/") || p.endsWith("/com.conductor.app/bin");
|
|
2172
|
+
}
|
|
2166
2173
|
function ensureAgentPath(env = process.env) {
|
|
2167
2174
|
const home = env.HOME || env.USERPROFILE || (0, import_node_os4.homedir)();
|
|
2168
2175
|
const current = env.PATH ?? "";
|
|
@@ -2171,7 +2178,9 @@ function ensureAgentPath(env = process.env) {
|
|
|
2171
2178
|
const extras = [
|
|
2172
2179
|
...EXTRA_BIN_DIRS.map((rel) => (0, import_node_path5.join)(home, rel)),
|
|
2173
2180
|
"/opt/homebrew/bin",
|
|
2174
|
-
"/usr/local/bin"
|
|
2181
|
+
"/usr/local/bin",
|
|
2182
|
+
// Keep after Homebrew/npm so a user-installed CLI still wins.
|
|
2183
|
+
conductorBundledBinDir(home)
|
|
2175
2184
|
];
|
|
2176
2185
|
for (const dir of extras.reverse()) {
|
|
2177
2186
|
if (!dir || seen.has(dir) || !(0, import_node_fs5.existsSync)(dir)) continue;
|
|
@@ -2218,7 +2227,7 @@ function withExportedPath(command, pathValue) {
|
|
|
2218
2227
|
const trimmed = command.trim();
|
|
2219
2228
|
if (!trimmed) return trimmed;
|
|
2220
2229
|
if (/^(export\s+PATH=|PATH=)/.test(trimmed)) return trimmed;
|
|
2221
|
-
return `export PATH=${posixShellSingleQuote(pathValue)}
|
|
2230
|
+
return `export PATH=${posixShellSingleQuote(pathValue)} && ${trimmed}`;
|
|
2222
2231
|
}
|
|
2223
2232
|
var import_node_fs5, import_node_child_process, import_node_os4, import_node_path5, EXTRA_BIN_DIRS;
|
|
2224
2233
|
var init_path = __esm({
|
|
@@ -2286,7 +2295,7 @@ async function git(args, cwd, opts) {
|
|
|
2286
2295
|
prefix.push("-c", `${key}=${value}`);
|
|
2287
2296
|
}
|
|
2288
2297
|
}
|
|
2289
|
-
return run("git", [...prefix, ...args], {
|
|
2298
|
+
return run("git", ["--no-pager", ...prefix, ...args], {
|
|
2290
2299
|
cwd,
|
|
2291
2300
|
reject: opts?.reject,
|
|
2292
2301
|
timeoutMs: opts?.timeoutMs,
|
|
@@ -2789,7 +2798,7 @@ async function originGhRepoEnv(cwd) {
|
|
|
2789
2798
|
const slug = await resolveGithubRepoSlug(cwd);
|
|
2790
2799
|
return slug ? { GH_REPO: slug } : {};
|
|
2791
2800
|
}
|
|
2792
|
-
async function resolveDefaultBranch(repoPath) {
|
|
2801
|
+
async function resolveDefaultBranch(repoPath, opts) {
|
|
2793
2802
|
const viaOrigin = await git(
|
|
2794
2803
|
["symbolic-ref", "refs/remotes/origin/HEAD"],
|
|
2795
2804
|
repoPath,
|
|
@@ -2798,22 +2807,24 @@ async function resolveDefaultBranch(repoPath) {
|
|
|
2798
2807
|
if (viaOrigin.exitCode === 0 && viaOrigin.stdout.trim()) {
|
|
2799
2808
|
return viaOrigin.stdout.trim().replace(/^refs\/remotes\/origin\//, "");
|
|
2800
2809
|
}
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2810
|
+
if (opts?.network !== false) {
|
|
2811
|
+
const slug = await resolveGithubRepoSlug(repoPath);
|
|
2812
|
+
const viaGh = await gh(
|
|
2813
|
+
[
|
|
2814
|
+
"repo",
|
|
2815
|
+
"view",
|
|
2816
|
+
...slug ? ["--repo", slug] : [],
|
|
2817
|
+
"--json",
|
|
2818
|
+
"defaultBranchRef",
|
|
2819
|
+
"--jq",
|
|
2820
|
+
".defaultBranchRef.name"
|
|
2821
|
+
],
|
|
2822
|
+
repoPath,
|
|
2823
|
+
{ reject: false, timeoutMs: 8e3 }
|
|
2824
|
+
);
|
|
2825
|
+
if (viaGh.exitCode === 0 && viaGh.stdout.trim()) {
|
|
2826
|
+
return viaGh.stdout.trim();
|
|
2827
|
+
}
|
|
2817
2828
|
}
|
|
2818
2829
|
for (const candidate of ["main", "master"]) {
|
|
2819
2830
|
const check = await git(
|
|
@@ -3465,11 +3476,11 @@ async function listWorktrees(repoPath) {
|
|
|
3465
3476
|
return entries;
|
|
3466
3477
|
}
|
|
3467
3478
|
async function isDirty(worktreePath) {
|
|
3468
|
-
const { stdout } = await git(["status", "--porcelain"
|
|
3479
|
+
const { stdout } = await git(["status", "--porcelain"], worktreePath);
|
|
3469
3480
|
for (const line of stdout.split("\n")) {
|
|
3470
3481
|
if (!line.trim()) continue;
|
|
3471
3482
|
const rel = porcelainStatusPath(line);
|
|
3472
|
-
if (!rel || isSideboardScratchPath(rel)) continue;
|
|
3483
|
+
if (!rel || isSideboardScratchPath(rel) || rel === ".sideboard") continue;
|
|
3473
3484
|
return true;
|
|
3474
3485
|
}
|
|
3475
3486
|
return false;
|
|
@@ -7078,6 +7089,11 @@ async function openInSystemTerminal(command) {
|
|
|
7078
7089
|
`No terminal found to run: ${trimmed}. Install gnome-terminal (or similar), or run the command manually.`
|
|
7079
7090
|
);
|
|
7080
7091
|
}
|
|
7092
|
+
async function whichCli(bin) {
|
|
7093
|
+
const which = await run("which", [bin], { reject: false, timeoutMs: 3e3 });
|
|
7094
|
+
if (which.exitCode !== 0) return null;
|
|
7095
|
+
return which.stdout.trim().split(/\r?\n/).find(Boolean) ?? null;
|
|
7096
|
+
}
|
|
7081
7097
|
async function installAgent(agent) {
|
|
7082
7098
|
const info = getAgentSetupInfo(agent);
|
|
7083
7099
|
if (info.kind === "bundled-sdk" || info.kind === "api-key") {
|
|
@@ -7099,6 +7115,17 @@ async function installAgent(agent) {
|
|
|
7099
7115
|
};
|
|
7100
7116
|
}
|
|
7101
7117
|
enrichPathWithNpmGlobalBin();
|
|
7118
|
+
const cliBin = agent === "cursor" ? null : CLI_BIN[agent];
|
|
7119
|
+
if (cliBin) {
|
|
7120
|
+
const existing = await whichCli(cliBin);
|
|
7121
|
+
if (existing) {
|
|
7122
|
+
return {
|
|
7123
|
+
ok: true,
|
|
7124
|
+
command: existing,
|
|
7125
|
+
message: isConductorBundledCli(existing) ? `Using Conductor\u2019s ${cliBin} at ${existing}. No extra install \u2014 Log in only if auth is missing.` : `Already on PATH: ${existing}`
|
|
7126
|
+
};
|
|
7127
|
+
}
|
|
7128
|
+
}
|
|
7102
7129
|
const result = await run("npm", ["install", "-g", info.npmPackage], { reject: false });
|
|
7103
7130
|
const ok = result.exitCode === 0;
|
|
7104
7131
|
if (!ok) {
|
|
@@ -7125,11 +7152,9 @@ async function installAgent(agent) {
|
|
|
7125
7152
|
}
|
|
7126
7153
|
}
|
|
7127
7154
|
enrichPathWithNpmGlobalBin();
|
|
7128
|
-
const cliBin = agent === "cursor" ? null : CLI_BIN[agent];
|
|
7129
7155
|
let binPath = null;
|
|
7130
7156
|
if (cliBin) {
|
|
7131
|
-
|
|
7132
|
-
binPath = which.exitCode === 0 ? which.stdout.trim().split(/\r?\n/).find(Boolean) ?? null : null;
|
|
7157
|
+
binPath = await whichCli(cliBin);
|
|
7133
7158
|
}
|
|
7134
7159
|
return {
|
|
7135
7160
|
ok: true,
|
|
@@ -7239,6 +7264,7 @@ __export(agents_exports, {
|
|
|
7239
7264
|
claudeAdapter: () => claudeAdapter,
|
|
7240
7265
|
codexAdapter: () => codexAdapter,
|
|
7241
7266
|
coerceOrchestratorAgent: () => coerceOrchestratorAgent,
|
|
7267
|
+
conductorBundledBinDir: () => conductorBundledBinDir,
|
|
7242
7268
|
cursorAdapter: () => cursorAdapter,
|
|
7243
7269
|
cursorSdkMessageToEvents: () => cursorSdkMessageToEvents,
|
|
7244
7270
|
decodeBrightsyTarget: () => decodeBrightsyTarget,
|
|
@@ -7248,6 +7274,7 @@ __export(agents_exports, {
|
|
|
7248
7274
|
getAdapter: () => getAdapter,
|
|
7249
7275
|
getAgentSetupInfo: () => getAgentSetupInfo,
|
|
7250
7276
|
installAgent: () => installAgent,
|
|
7277
|
+
isConductorBundledCli: () => isConductorBundledCli,
|
|
7251
7278
|
isCursorAutoModel: () => isCursorAutoModel,
|
|
7252
7279
|
isOrchestratorCapableAgent: () => isOrchestratorCapableAgent,
|
|
7253
7280
|
isSessionQuotaLimit: () => isSessionQuotaLimit,
|
|
@@ -7593,6 +7620,7 @@ __export(index_exports, {
|
|
|
7593
7620
|
coerceOrchestratorAgent: () => coerceOrchestratorAgent,
|
|
7594
7621
|
collectTakenTeamSlugs: () => collectTakenTeamSlugs,
|
|
7595
7622
|
commitAll: () => commitAll,
|
|
7623
|
+
conductorBundledBinDir: () => conductorBundledBinDir,
|
|
7596
7624
|
conductorDbPath: () => conductorDbPath,
|
|
7597
7625
|
confirmLand: () => confirmLand,
|
|
7598
7626
|
connectBrightsyTeam: () => connectBrightsyTeam,
|
|
@@ -7704,6 +7732,7 @@ __export(index_exports, {
|
|
|
7704
7732
|
isBrightsyConnected: () => isBrightsyConnected,
|
|
7705
7733
|
isBrightsyNdjsonLine: () => isBrightsyNdjsonLine,
|
|
7706
7734
|
isCloudCoordinatorThread: () => isCloudCoordinatorThread,
|
|
7735
|
+
isConductorBundledCli: () => isConductorBundledCli,
|
|
7707
7736
|
isCursorAutoModel: () => isCursorAutoModel,
|
|
7708
7737
|
isDirty: () => isDirty,
|
|
7709
7738
|
isGhRateLimitError: () => isGhRateLimitError,
|
|
@@ -9154,24 +9183,25 @@ function capPatch(patch, maxHunk) {
|
|
|
9154
9183
|
|
|
9155
9184
|
\u2026 truncated (${patch.length - maxHunk} more chars)`;
|
|
9156
9185
|
}
|
|
9186
|
+
var mergeBaseCache = /* @__PURE__ */ new Map();
|
|
9187
|
+
var MERGE_BASE_TTL_MS = 45e3;
|
|
9157
9188
|
async function resolveMergeBase(worktreePath, base, repoPath) {
|
|
9158
9189
|
const baseRef = await resolveDiffBaseRef(worktreePath, base, repoPath);
|
|
9190
|
+
const cacheKey = `${worktreePath}\0${baseRef}`;
|
|
9191
|
+
const hit = mergeBaseCache.get(cacheKey);
|
|
9192
|
+
if (hit && Date.now() - hit.at < MERGE_BASE_TTL_MS) return hit.value;
|
|
9159
9193
|
const { stdout } = await git(["merge-base", baseRef, "HEAD"], worktreePath, {
|
|
9160
9194
|
reject: false
|
|
9161
9195
|
});
|
|
9162
|
-
const mb = stdout.trim();
|
|
9163
|
-
|
|
9196
|
+
const mb = stdout.trim() || baseRef;
|
|
9197
|
+
mergeBaseCache.set(cacheKey, { at: Date.now(), value: mb });
|
|
9198
|
+
return mb;
|
|
9164
9199
|
}
|
|
9165
9200
|
async function countUnpushedCommits(worktreePath) {
|
|
9166
9201
|
const head = await git(["rev-parse", "--abbrev-ref", "HEAD"], worktreePath, {
|
|
9167
9202
|
reject: false
|
|
9168
9203
|
});
|
|
9169
9204
|
const branch = head.stdout.trim();
|
|
9170
|
-
if (branch && branch !== "HEAD") {
|
|
9171
|
-
await git(["fetch", "origin", branch, "--quiet"], worktreePath, {
|
|
9172
|
-
reject: false
|
|
9173
|
-
});
|
|
9174
|
-
}
|
|
9175
9205
|
const upstream = await git(
|
|
9176
9206
|
["rev-list", "--count", "@{upstream}..HEAD"],
|
|
9177
9207
|
worktreePath,
|
|
@@ -9204,11 +9234,37 @@ function splitCombinedDiff(stdout) {
|
|
|
9204
9234
|
}
|
|
9205
9235
|
return map;
|
|
9206
9236
|
}
|
|
9237
|
+
function syntheticAddPatch(path, content, maxHunk) {
|
|
9238
|
+
const lines = content.split("\n");
|
|
9239
|
+
const body = lines.map((l) => `+${l}`).join("\n");
|
|
9240
|
+
const header = `diff --git a/${path} b/${path}
|
|
9241
|
+
new file mode 100644
|
|
9242
|
+
--- /dev/null
|
|
9243
|
+
+++ b/${path}
|
|
9244
|
+
@@ -0,0 +1,${lines.length} @@
|
|
9245
|
+
`;
|
|
9246
|
+
return {
|
|
9247
|
+
path,
|
|
9248
|
+
status: "A",
|
|
9249
|
+
patch: capPatch(`${header}${body}`, maxHunk),
|
|
9250
|
+
additions: lines.length,
|
|
9251
|
+
deletions: 0
|
|
9252
|
+
};
|
|
9253
|
+
}
|
|
9207
9254
|
async function untrackedPatch(worktreePath, path, maxHunk) {
|
|
9255
|
+
const abs = (0, import_node_path17.join)(worktreePath, path);
|
|
9256
|
+
try {
|
|
9257
|
+
const st = (0, import_node_fs20.statSync)(abs);
|
|
9258
|
+
if (st.isFile() && st.size > maxHunk) {
|
|
9259
|
+
const buf = (0, import_node_fs20.readFileSync)(abs).subarray(0, maxHunk);
|
|
9260
|
+
return syntheticAddPatch(path, buf.toString("utf8"), maxHunk);
|
|
9261
|
+
}
|
|
9262
|
+
} catch {
|
|
9263
|
+
}
|
|
9208
9264
|
const { stdout: patch } = await git(
|
|
9209
|
-
["diff", "--no-index", "--", "/dev/null", path],
|
|
9265
|
+
["diff", "--no-ext-diff", "--no-color", "--no-index", "--", "/dev/null", path],
|
|
9210
9266
|
worktreePath,
|
|
9211
|
-
{ reject: false }
|
|
9267
|
+
{ reject: false, timeoutMs: 4e3 }
|
|
9212
9268
|
);
|
|
9213
9269
|
const normalized = patch.replace(/^diff --git a\/.+? b\/.+?$/m, `diff --git a/${path} b/${path}`).replace(/^--- .*$/m, "--- /dev/null").replace(/^\+\+\+ .*$/m, `+++ b/${path}`);
|
|
9214
9270
|
const addLines = normalized.split("\n").filter((l) => l.startsWith("+") && !l.startsWith("+++")).length;
|
|
@@ -9220,22 +9276,97 @@ async function untrackedPatch(worktreePath, path, maxHunk) {
|
|
|
9220
9276
|
deletions: 0
|
|
9221
9277
|
};
|
|
9222
9278
|
}
|
|
9223
|
-
async function listUntrackedPaths(worktreePath) {
|
|
9224
|
-
const
|
|
9225
|
-
|
|
9226
|
-
|
|
9227
|
-
{ reject: false }
|
|
9228
|
-
);
|
|
9279
|
+
async function listUntrackedPaths(worktreePath, path) {
|
|
9280
|
+
const args = ["ls-files", "-z", "--others", "--exclude-standard"];
|
|
9281
|
+
if (path) args.push("--", path);
|
|
9282
|
+
const { stdout } = await git(args, worktreePath, { reject: false });
|
|
9229
9283
|
return stdout.split("\0").filter(Boolean).filter((p) => !isSideboardScratchPath(p));
|
|
9230
9284
|
}
|
|
9231
|
-
async function listUntrackedFiles(worktreePath, maxHunk) {
|
|
9232
|
-
const
|
|
9233
|
-
if (
|
|
9234
|
-
return Promise.all(
|
|
9285
|
+
async function listUntrackedFiles(worktreePath, maxHunk, paths) {
|
|
9286
|
+
const list = paths ?? await listUntrackedPaths(worktreePath);
|
|
9287
|
+
if (list.length === 0) return [];
|
|
9288
|
+
return Promise.all(list.map((path) => untrackedPatch(worktreePath, path, maxHunk)));
|
|
9289
|
+
}
|
|
9290
|
+
function untrackedStubs(paths) {
|
|
9291
|
+
return paths.map((path) => ({
|
|
9292
|
+
path,
|
|
9293
|
+
status: "A",
|
|
9294
|
+
patch: "",
|
|
9295
|
+
additions: 0,
|
|
9296
|
+
deletions: 0
|
|
9297
|
+
}));
|
|
9298
|
+
}
|
|
9299
|
+
function pathspec(path) {
|
|
9300
|
+
return path ? ["--", path] : [];
|
|
9301
|
+
}
|
|
9302
|
+
function gitDiff(args, cwd, opts) {
|
|
9303
|
+
return git(["diff", "--no-ext-diff", "--no-color", ...args], cwd, {
|
|
9304
|
+
reject: false,
|
|
9305
|
+
timeoutMs: opts?.timeoutMs
|
|
9306
|
+
});
|
|
9307
|
+
}
|
|
9308
|
+
function fileFromPatch(path, patch, maxHunk) {
|
|
9309
|
+
let status = "M";
|
|
9310
|
+
if (/^new file mode /m.test(patch) || /^--- \/dev\/null/m.test(patch)) {
|
|
9311
|
+
status = "A";
|
|
9312
|
+
} else if (/^deleted file mode /m.test(patch) || /^\+\+\+ \/dev\/null/m.test(patch)) {
|
|
9313
|
+
status = "D";
|
|
9314
|
+
} else if (/^rename from /m.test(patch)) {
|
|
9315
|
+
status = "R";
|
|
9316
|
+
}
|
|
9317
|
+
const additions = patch.split("\n").filter((l) => l.startsWith("+") && !l.startsWith("+++")).length;
|
|
9318
|
+
const deletions = patch.split("\n").filter((l) => l.startsWith("-") && !l.startsWith("---")).length;
|
|
9319
|
+
return {
|
|
9320
|
+
path,
|
|
9321
|
+
status,
|
|
9322
|
+
patch: capPatch(patch, maxHunk),
|
|
9323
|
+
additions,
|
|
9324
|
+
deletions
|
|
9325
|
+
};
|
|
9326
|
+
}
|
|
9327
|
+
async function gitDiffParts(worktreePath, diffArgs, includePatches, path) {
|
|
9328
|
+
const extra = pathspec(path);
|
|
9329
|
+
if (includePatches) {
|
|
9330
|
+
const diff = await gitDiff([...diffArgs, ...extra], worktreePath, {
|
|
9331
|
+
timeoutMs: 4e3
|
|
9332
|
+
});
|
|
9333
|
+
return { nameStatus: "", numstat: "", combinedDiff: diff.stdout };
|
|
9334
|
+
}
|
|
9335
|
+
const [ns, num2] = await Promise.all([
|
|
9336
|
+
gitDiff(["--name-status", ...diffArgs, ...extra], worktreePath),
|
|
9337
|
+
gitDiff(["--numstat", ...diffArgs, ...extra], worktreePath)
|
|
9338
|
+
]);
|
|
9339
|
+
return {
|
|
9340
|
+
nameStatus: ns.stdout,
|
|
9341
|
+
numstat: num2.stdout,
|
|
9342
|
+
combinedDiff: ""
|
|
9343
|
+
};
|
|
9344
|
+
}
|
|
9345
|
+
function formatStat(files) {
|
|
9346
|
+
if (files.length === 0) return "(no changes)";
|
|
9347
|
+
const additions = files.reduce((n2, f) => n2 + (f.additions ?? 0), 0);
|
|
9348
|
+
const deletions = files.reduce((n2, f) => n2 + (f.deletions ?? 0), 0);
|
|
9349
|
+
const n = files.length;
|
|
9350
|
+
return `${n} file${n === 1 ? "" : "s"} changed, ${additions} insertions(+), ${deletions} deletions(-)`;
|
|
9351
|
+
}
|
|
9352
|
+
function emptyScopeStats() {
|
|
9353
|
+
const z2 = emptyStat();
|
|
9354
|
+
return {
|
|
9355
|
+
commits: z2,
|
|
9356
|
+
uncommitted: z2,
|
|
9357
|
+
staged: z2,
|
|
9358
|
+
unstaged: z2,
|
|
9359
|
+
last_turn: z2
|
|
9360
|
+
};
|
|
9235
9361
|
}
|
|
9236
9362
|
function filesFromDiff(nameStatus, numstat, combinedDiff, maxHunk) {
|
|
9237
|
-
const counts = parseNumstat(numstat);
|
|
9238
9363
|
const patches = splitCombinedDiff(combinedDiff);
|
|
9364
|
+
if (!nameStatus.trim() && patches.size > 0) {
|
|
9365
|
+
return [...patches.entries()].map(
|
|
9366
|
+
([path, patch]) => fileFromPatch(path, patch, maxHunk)
|
|
9367
|
+
);
|
|
9368
|
+
}
|
|
9369
|
+
const counts = parseNumstat(numstat);
|
|
9239
9370
|
const files = [];
|
|
9240
9371
|
for (const { status, path } of parseNameStatus(nameStatus)) {
|
|
9241
9372
|
const n = counts.get(path);
|
|
@@ -9257,11 +9388,11 @@ async function computeScopeStats(worktreePath, mergeBase, lastTurnBase, untracke
|
|
|
9257
9388
|
{ stdout: unstagedNum },
|
|
9258
9389
|
lastTurnNum
|
|
9259
9390
|
] = await Promise.all([
|
|
9260
|
-
mergeBase ?
|
|
9261
|
-
|
|
9262
|
-
|
|
9263
|
-
|
|
9264
|
-
lastTurnBase ?
|
|
9391
|
+
mergeBase ? gitDiff(["--numstat", mergeBase], worktreePath) : Promise.resolve({ stdout: "" }),
|
|
9392
|
+
gitDiff(["--numstat", "HEAD"], worktreePath),
|
|
9393
|
+
gitDiff(["--numstat", "--cached"], worktreePath),
|
|
9394
|
+
gitDiff(["--numstat"], worktreePath),
|
|
9395
|
+
lastTurnBase ? gitDiff(["--numstat", lastTurnBase], worktreePath) : Promise.resolve({ stdout: "" })
|
|
9265
9396
|
]);
|
|
9266
9397
|
return {
|
|
9267
9398
|
commits: mergeBase ? statFromNumstat(commitsNum, untrackedCount) : emptyStat(),
|
|
@@ -9280,7 +9411,7 @@ async function listBranchCommits(worktreePath, repoPath, opts) {
|
|
|
9280
9411
|
if (head.exitCode !== 0) return [];
|
|
9281
9412
|
let base = opts?.base;
|
|
9282
9413
|
try {
|
|
9283
|
-
base = base ?? await resolveDefaultBranch(repoPath);
|
|
9414
|
+
base = base ?? await resolveDefaultBranch(repoPath, { network: false });
|
|
9284
9415
|
} catch {
|
|
9285
9416
|
base = "HEAD";
|
|
9286
9417
|
}
|
|
@@ -9310,7 +9441,121 @@ async function listBranchCommits(worktreePath, repoPath, opts) {
|
|
|
9310
9441
|
}
|
|
9311
9442
|
return commits;
|
|
9312
9443
|
}
|
|
9444
|
+
var SHA_RE = /^[0-9a-f]{7,40}$/i;
|
|
9445
|
+
function emptyPathDiff(scope, base, hasLastTurnBase, commitSha = null) {
|
|
9446
|
+
return {
|
|
9447
|
+
scope,
|
|
9448
|
+
commitSha: scope === "commits" ? commitSha : null,
|
|
9449
|
+
base,
|
|
9450
|
+
files: [],
|
|
9451
|
+
stat: formatStat([]),
|
|
9452
|
+
dirty: false,
|
|
9453
|
+
unpushed: 0,
|
|
9454
|
+
hasLastTurnBase,
|
|
9455
|
+
commits: [],
|
|
9456
|
+
scopeStats: emptyScopeStats()
|
|
9457
|
+
};
|
|
9458
|
+
}
|
|
9459
|
+
async function getPathDiff(worktreePath, repoPath, opts) {
|
|
9460
|
+
const { path, scope, commitSha, lastTurnBase, hasLastTurnBase, includePatches, maxHunk } = opts;
|
|
9461
|
+
if (scope === "last_turn" && !lastTurnBase) {
|
|
9462
|
+
return emptyPathDiff(scope, "last turn", false);
|
|
9463
|
+
}
|
|
9464
|
+
let diffArgs;
|
|
9465
|
+
let labelBase;
|
|
9466
|
+
if (scope === "staged") {
|
|
9467
|
+
diffArgs = ["--cached"];
|
|
9468
|
+
labelBase = "staged";
|
|
9469
|
+
} else if (scope === "unstaged") {
|
|
9470
|
+
diffArgs = [];
|
|
9471
|
+
labelBase = "unstaged";
|
|
9472
|
+
} else if (scope === "uncommitted") {
|
|
9473
|
+
diffArgs = ["HEAD"];
|
|
9474
|
+
labelBase = "HEAD";
|
|
9475
|
+
} else if (scope === "last_turn") {
|
|
9476
|
+
diffArgs = [lastTurnBase];
|
|
9477
|
+
labelBase = "last turn";
|
|
9478
|
+
} else if (scope === "commits" && commitSha) {
|
|
9479
|
+
diffArgs = [`${commitSha}^!`];
|
|
9480
|
+
labelBase = commitSha.slice(0, 7);
|
|
9481
|
+
} else if (scope === "commits" && opts.base && SHA_RE.test(opts.base)) {
|
|
9482
|
+
diffArgs = [opts.base];
|
|
9483
|
+
labelBase = opts.base.slice(0, 7);
|
|
9484
|
+
} else if (scope === "commits") {
|
|
9485
|
+
let base = opts.base;
|
|
9486
|
+
try {
|
|
9487
|
+
base = base ?? await resolveDefaultBranch(repoPath, { network: false });
|
|
9488
|
+
} catch {
|
|
9489
|
+
base = "HEAD";
|
|
9490
|
+
}
|
|
9491
|
+
const mergeBase = await resolveMergeBase(worktreePath, base, repoPath);
|
|
9492
|
+
diffArgs = [mergeBase];
|
|
9493
|
+
labelBase = mergeBase;
|
|
9494
|
+
} else {
|
|
9495
|
+
diffArgs = ["HEAD"];
|
|
9496
|
+
labelBase = "HEAD";
|
|
9497
|
+
}
|
|
9498
|
+
const diff = await gitDiff(
|
|
9499
|
+
includePatches ? [...diffArgs, "--", path] : ["--name-status", ...diffArgs, "--", path],
|
|
9500
|
+
worktreePath,
|
|
9501
|
+
{ timeoutMs: 4e3 }
|
|
9502
|
+
);
|
|
9503
|
+
const filesMap = /* @__PURE__ */ new Map();
|
|
9504
|
+
if (includePatches) {
|
|
9505
|
+
const parsed = filesFromDiff("", "", diff.stdout, maxHunk);
|
|
9506
|
+
for (const file of parsed) filesMap.set(file.path, file);
|
|
9507
|
+
if (diff.stdout.trim() && !filesMap.has(path)) {
|
|
9508
|
+
filesMap.set(path, fileFromPatch(path, diff.stdout, maxHunk));
|
|
9509
|
+
}
|
|
9510
|
+
} else {
|
|
9511
|
+
for (const file of filesFromDiff(diff.stdout, "", "", maxHunk)) {
|
|
9512
|
+
filesMap.set(file.path, file);
|
|
9513
|
+
}
|
|
9514
|
+
}
|
|
9515
|
+
if (filesMap.size === 0) {
|
|
9516
|
+
const maybe = await listUntrackedPaths(worktreePath, path);
|
|
9517
|
+
if (maybe.length > 0) {
|
|
9518
|
+
const extra = includePatches ? await listUntrackedFiles(worktreePath, maxHunk, maybe) : untrackedStubs(maybe);
|
|
9519
|
+
for (const file of extra) filesMap.set(file.path, file);
|
|
9520
|
+
}
|
|
9521
|
+
}
|
|
9522
|
+
const files = [...filesMap.values()].sort((a, b) => a.path.localeCompare(b.path));
|
|
9523
|
+
return {
|
|
9524
|
+
scope,
|
|
9525
|
+
commitSha: scope === "commits" ? commitSha : null,
|
|
9526
|
+
base: labelBase,
|
|
9527
|
+
files,
|
|
9528
|
+
stat: formatStat(files),
|
|
9529
|
+
dirty: files.length > 0,
|
|
9530
|
+
unpushed: 0,
|
|
9531
|
+
hasLastTurnBase,
|
|
9532
|
+
commits: [],
|
|
9533
|
+
scopeStats: emptyScopeStats(),
|
|
9534
|
+
mergeBase: SHA_RE.test(diffArgs[0] ?? "") ? diffArgs[0] : null
|
|
9535
|
+
};
|
|
9536
|
+
}
|
|
9313
9537
|
async function getDiff(worktreePath, repoPath, opts) {
|
|
9538
|
+
const maxHunk = opts?.maxHunkChars ?? 8e3;
|
|
9539
|
+
const scope = opts?.scope ?? "commits";
|
|
9540
|
+
const lastTurnBase = opts?.lastTurnBase?.trim() || null;
|
|
9541
|
+
const hasLastTurnBase = Boolean(lastTurnBase);
|
|
9542
|
+
const commitSha = opts?.commitSha?.trim() || null;
|
|
9543
|
+
const includePatches = opts?.includePatches ?? true;
|
|
9544
|
+
const pathFilter = opts?.path?.trim() || null;
|
|
9545
|
+
const fileOnly = Boolean(pathFilter);
|
|
9546
|
+
const includeMeta = (opts?.includeMeta ?? true) && !fileOnly;
|
|
9547
|
+
if (fileOnly && pathFilter && !includeMeta) {
|
|
9548
|
+
return getPathDiff(worktreePath, repoPath, {
|
|
9549
|
+
path: pathFilter,
|
|
9550
|
+
scope,
|
|
9551
|
+
commitSha,
|
|
9552
|
+
lastTurnBase,
|
|
9553
|
+
hasLastTurnBase,
|
|
9554
|
+
base: opts?.base,
|
|
9555
|
+
includePatches,
|
|
9556
|
+
maxHunk
|
|
9557
|
+
});
|
|
9558
|
+
}
|
|
9314
9559
|
const status = await inspectGitWorktree(worktreePath);
|
|
9315
9560
|
if (status === "missing_worktree") {
|
|
9316
9561
|
throw new Error("Worktree not found");
|
|
@@ -9318,18 +9563,19 @@ async function getDiff(worktreePath, repoPath, opts) {
|
|
|
9318
9563
|
if (status === "not_git") {
|
|
9319
9564
|
throw new Error("Not a Git repository");
|
|
9320
9565
|
}
|
|
9321
|
-
const
|
|
9322
|
-
const
|
|
9323
|
-
const
|
|
9324
|
-
const hasLastTurnBase = Boolean(lastTurnBase);
|
|
9325
|
-
const commitSha = opts?.commitSha?.trim() || null;
|
|
9326
|
-
const head = await git(["rev-parse", "--verify", "HEAD"], worktreePath, {
|
|
9566
|
+
const wantUntracked = opts?.includeUntracked !== void 0 ? opts.includeUntracked : !fileOnly && (scope === "commits" && !commitSha || scope === "uncommitted" || scope === "unstaged" || scope === "last_turn");
|
|
9567
|
+
const needsMergeBase = scope === "commits" && !commitSha || includeMeta;
|
|
9568
|
+
const headP = git(["rev-parse", "--verify", "HEAD"], worktreePath, {
|
|
9327
9569
|
reject: false
|
|
9328
9570
|
});
|
|
9571
|
+
const untrackedP = wantUntracked ? listUntrackedPaths(worktreePath, pathFilter) : Promise.resolve([]);
|
|
9572
|
+
const head = await headP;
|
|
9329
9573
|
const hasHead = head.exitCode === 0;
|
|
9330
|
-
const untrackedPaths = await listUntrackedPaths(worktreePath);
|
|
9331
9574
|
if (!hasHead) {
|
|
9332
|
-
const
|
|
9575
|
+
const untrackedPaths2 = await untrackedP;
|
|
9576
|
+
const files2 = scope === "staged" ? [] : includePatches ? (await listUntrackedFiles(worktreePath, maxHunk, untrackedPaths2)).sort(
|
|
9577
|
+
(a, b) => a.path.localeCompare(b.path)
|
|
9578
|
+
) : untrackedStubs(untrackedPaths2).sort(
|
|
9333
9579
|
(a, b) => a.path.localeCompare(b.path)
|
|
9334
9580
|
);
|
|
9335
9581
|
const untrackedStat = {
|
|
@@ -9343,7 +9589,7 @@ async function getDiff(worktreePath, repoPath, opts) {
|
|
|
9343
9589
|
commitSha: null,
|
|
9344
9590
|
base: "(no commits)",
|
|
9345
9591
|
files: files2,
|
|
9346
|
-
stat: files2
|
|
9592
|
+
stat: formatStat(files2),
|
|
9347
9593
|
dirty: files2.length > 0,
|
|
9348
9594
|
unpushed: 0,
|
|
9349
9595
|
hasLastTurnBase,
|
|
@@ -9357,137 +9603,122 @@ async function getDiff(worktreePath, repoPath, opts) {
|
|
|
9357
9603
|
}
|
|
9358
9604
|
};
|
|
9359
9605
|
}
|
|
9360
|
-
let
|
|
9361
|
-
|
|
9362
|
-
|
|
9363
|
-
|
|
9364
|
-
|
|
9606
|
+
let mergeBase = "HEAD";
|
|
9607
|
+
let baseLabel = "HEAD";
|
|
9608
|
+
if (needsMergeBase) {
|
|
9609
|
+
let base = opts?.base;
|
|
9610
|
+
try {
|
|
9611
|
+
base = base ?? await resolveDefaultBranch(repoPath, { network: false });
|
|
9612
|
+
} catch {
|
|
9613
|
+
base = "HEAD";
|
|
9614
|
+
}
|
|
9615
|
+
mergeBase = await resolveMergeBase(worktreePath, base, repoPath);
|
|
9616
|
+
baseLabel = await resolveDiffBaseRef(worktreePath, base, repoPath);
|
|
9365
9617
|
}
|
|
9366
|
-
|
|
9367
|
-
|
|
9368
|
-
|
|
9369
|
-
|
|
9370
|
-
|
|
9371
|
-
|
|
9372
|
-
|
|
9618
|
+
const includeUntracked = wantUntracked;
|
|
9619
|
+
const metaPromise = includeMeta ? Promise.all([
|
|
9620
|
+
computeScopeStats(
|
|
9621
|
+
worktreePath,
|
|
9622
|
+
mergeBase,
|
|
9623
|
+
lastTurnBase,
|
|
9624
|
+
// Cheap: don't wait on the untracked walk just to pad the badge.
|
|
9625
|
+
0
|
|
9626
|
+
),
|
|
9627
|
+
listBranchCommits(worktreePath, repoPath, { base: baseLabel }),
|
|
9628
|
+
isDirty(worktreePath),
|
|
9629
|
+
countUnpushedCommits(worktreePath)
|
|
9630
|
+
]).then(([scopeStats, commits, dirty, unpushed]) => ({
|
|
9631
|
+
scopeStats,
|
|
9632
|
+
commits,
|
|
9633
|
+
dirty,
|
|
9634
|
+
unpushed
|
|
9635
|
+
})) : Promise.resolve({
|
|
9636
|
+
scopeStats: emptyScopeStats(),
|
|
9637
|
+
commits: [],
|
|
9638
|
+
dirty: false,
|
|
9639
|
+
unpushed: 0
|
|
9640
|
+
});
|
|
9641
|
+
if (scope === "last_turn" && !lastTurnBase) {
|
|
9642
|
+
const meta2 = await metaPromise;
|
|
9643
|
+
return {
|
|
9644
|
+
scope,
|
|
9645
|
+
commitSha: null,
|
|
9646
|
+
base: "last turn",
|
|
9647
|
+
files: [],
|
|
9648
|
+
stat: "(no last agent turn)",
|
|
9649
|
+
dirty: meta2.dirty,
|
|
9650
|
+
unpushed: meta2.unpushed,
|
|
9651
|
+
hasLastTurnBase: false,
|
|
9652
|
+
commits: meta2.commits,
|
|
9653
|
+
scopeStats: meta2.scopeStats
|
|
9654
|
+
};
|
|
9373
9655
|
}
|
|
9374
|
-
|
|
9375
|
-
|
|
9376
|
-
worktreePath,
|
|
9377
|
-
mergeBase,
|
|
9378
|
-
lastTurnBase,
|
|
9379
|
-
untrackedPaths.length
|
|
9380
|
-
);
|
|
9381
|
-
const includeUntracked = scope === "commits" && !commitSha || scope === "uncommitted" || scope === "unstaged" || scope === "last_turn";
|
|
9382
|
-
let nameStatus = "";
|
|
9383
|
-
let numstat = "";
|
|
9384
|
-
let combinedDiff = "";
|
|
9385
|
-
let labelBase = base;
|
|
9656
|
+
let diffArgs;
|
|
9657
|
+
let labelBase = baseLabel;
|
|
9386
9658
|
if (scope === "staged") {
|
|
9387
|
-
|
|
9388
|
-
git(["diff", "--name-status", "--cached"], worktreePath, { reject: false }),
|
|
9389
|
-
git(["diff", "--numstat", "--cached"], worktreePath, { reject: false }),
|
|
9390
|
-
git(["diff", "--cached"], worktreePath, { reject: false })
|
|
9391
|
-
]);
|
|
9392
|
-
nameStatus = ns.stdout;
|
|
9393
|
-
numstat = num2.stdout;
|
|
9394
|
-
combinedDiff = diff.stdout;
|
|
9659
|
+
diffArgs = ["--cached"];
|
|
9395
9660
|
labelBase = "staged";
|
|
9396
9661
|
} else if (scope === "unstaged") {
|
|
9397
|
-
|
|
9398
|
-
git(["diff", "--name-status"], worktreePath, { reject: false }),
|
|
9399
|
-
git(["diff", "--numstat"], worktreePath, { reject: false }),
|
|
9400
|
-
git(["diff"], worktreePath, { reject: false })
|
|
9401
|
-
]);
|
|
9402
|
-
nameStatus = ns.stdout;
|
|
9403
|
-
numstat = num2.stdout;
|
|
9404
|
-
combinedDiff = diff.stdout;
|
|
9662
|
+
diffArgs = [];
|
|
9405
9663
|
labelBase = "unstaged";
|
|
9406
9664
|
} else if (scope === "uncommitted") {
|
|
9407
|
-
|
|
9408
|
-
git(["diff", "--name-status", "HEAD"], worktreePath, { reject: false }),
|
|
9409
|
-
git(["diff", "--numstat", "HEAD"], worktreePath, { reject: false }),
|
|
9410
|
-
git(["diff", "HEAD"], worktreePath, { reject: false })
|
|
9411
|
-
]);
|
|
9412
|
-
nameStatus = ns.stdout;
|
|
9413
|
-
numstat = num2.stdout;
|
|
9414
|
-
combinedDiff = diff.stdout;
|
|
9665
|
+
diffArgs = ["HEAD"];
|
|
9415
9666
|
labelBase = "HEAD";
|
|
9416
9667
|
} else if (scope === "last_turn") {
|
|
9417
|
-
|
|
9418
|
-
const commits2 = await listBranchCommits(worktreePath, repoPath, { base });
|
|
9419
|
-
return {
|
|
9420
|
-
scope,
|
|
9421
|
-
commitSha: null,
|
|
9422
|
-
base: "last turn",
|
|
9423
|
-
files: [],
|
|
9424
|
-
stat: "(no last agent turn)",
|
|
9425
|
-
dirty: await isDirty(worktreePath),
|
|
9426
|
-
unpushed: await countUnpushedCommits(worktreePath),
|
|
9427
|
-
hasLastTurnBase: false,
|
|
9428
|
-
commits: commits2,
|
|
9429
|
-
scopeStats
|
|
9430
|
-
};
|
|
9431
|
-
}
|
|
9432
|
-
const [ns, num2, diff] = await Promise.all([
|
|
9433
|
-
git(["diff", "--name-status", lastTurnBase], worktreePath, { reject: false }),
|
|
9434
|
-
git(["diff", "--numstat", lastTurnBase], worktreePath, { reject: false }),
|
|
9435
|
-
git(["diff", lastTurnBase], worktreePath, { reject: false })
|
|
9436
|
-
]);
|
|
9437
|
-
nameStatus = ns.stdout;
|
|
9438
|
-
numstat = num2.stdout;
|
|
9439
|
-
combinedDiff = diff.stdout;
|
|
9668
|
+
diffArgs = [lastTurnBase];
|
|
9440
9669
|
labelBase = "last turn";
|
|
9441
9670
|
} else if (scope === "commits" && commitSha) {
|
|
9442
|
-
|
|
9443
|
-
const [ns, num2, diff] = await Promise.all([
|
|
9444
|
-
git(["diff", "--name-status", range], worktreePath, { reject: false }),
|
|
9445
|
-
git(["diff", "--numstat", range], worktreePath, { reject: false }),
|
|
9446
|
-
git(["diff", range], worktreePath, { reject: false })
|
|
9447
|
-
]);
|
|
9448
|
-
nameStatus = ns.stdout;
|
|
9449
|
-
numstat = num2.stdout;
|
|
9450
|
-
combinedDiff = diff.stdout;
|
|
9671
|
+
diffArgs = [`${commitSha}^!`];
|
|
9451
9672
|
labelBase = commitSha.slice(0, 7);
|
|
9452
9673
|
} else {
|
|
9453
|
-
|
|
9454
|
-
|
|
9455
|
-
git(["diff", "--numstat", mergeBase], worktreePath, { reject: false }),
|
|
9456
|
-
git(["diff", mergeBase], worktreePath, { reject: false })
|
|
9457
|
-
]);
|
|
9458
|
-
nameStatus = ns.stdout;
|
|
9459
|
-
numstat = num2.stdout;
|
|
9460
|
-
combinedDiff = diff.stdout;
|
|
9461
|
-
labelBase = base;
|
|
9674
|
+
diffArgs = [mergeBase];
|
|
9675
|
+
labelBase = baseLabel;
|
|
9462
9676
|
}
|
|
9463
|
-
const
|
|
9677
|
+
const partsPromise = gitDiffParts(
|
|
9678
|
+
worktreePath,
|
|
9679
|
+
diffArgs,
|
|
9680
|
+
includePatches,
|
|
9681
|
+
pathFilter
|
|
9682
|
+
);
|
|
9683
|
+
const [parts, meta, untrackedPaths] = await Promise.all([
|
|
9684
|
+
partsPromise,
|
|
9685
|
+
metaPromise,
|
|
9686
|
+
untrackedP
|
|
9687
|
+
]);
|
|
9464
9688
|
const filesMap = /* @__PURE__ */ new Map();
|
|
9465
|
-
for (const file of filesFromDiff(
|
|
9689
|
+
for (const file of filesFromDiff(
|
|
9690
|
+
parts.nameStatus,
|
|
9691
|
+
parts.numstat,
|
|
9692
|
+
parts.combinedDiff,
|
|
9693
|
+
maxHunk
|
|
9694
|
+
)) {
|
|
9466
9695
|
filesMap.set(file.path, file);
|
|
9467
9696
|
}
|
|
9468
9697
|
if (includeUntracked) {
|
|
9469
|
-
const
|
|
9470
|
-
for (const file of
|
|
9698
|
+
const extra = includePatches ? await listUntrackedFiles(worktreePath, maxHunk, untrackedPaths) : untrackedStubs(untrackedPaths);
|
|
9699
|
+
for (const file of extra) {
|
|
9471
9700
|
if (!filesMap.has(file.path)) filesMap.set(file.path, file);
|
|
9472
9701
|
}
|
|
9702
|
+
} else if (fileOnly && pathFilter && !filesMap.has(pathFilter)) {
|
|
9703
|
+
const maybe = await listUntrackedPaths(worktreePath, pathFilter);
|
|
9704
|
+
if (maybe.length > 0) {
|
|
9705
|
+
const extra = includePatches ? await listUntrackedFiles(worktreePath, maxHunk, maybe) : untrackedStubs(maybe);
|
|
9706
|
+
for (const file of extra) filesMap.set(file.path, file);
|
|
9707
|
+
}
|
|
9473
9708
|
}
|
|
9474
9709
|
const files = [...filesMap.values()].sort((a, b) => a.path.localeCompare(b.path));
|
|
9475
|
-
const { stdout: statOut } = await git(
|
|
9476
|
-
scope === "staged" ? ["diff", "--stat", "--cached"] : scope === "unstaged" ? ["diff", "--stat"] : scope === "uncommitted" ? ["diff", "--stat", "HEAD"] : scope === "last_turn" && lastTurnBase ? ["diff", "--stat", lastTurnBase] : scope === "commits" && commitSha ? ["diff", "--stat", `${commitSha}^!`] : ["diff", "--stat", mergeBase],
|
|
9477
|
-
worktreePath,
|
|
9478
|
-
{ reject: false }
|
|
9479
|
-
);
|
|
9480
9710
|
return {
|
|
9481
9711
|
scope,
|
|
9482
9712
|
commitSha: scope === "commits" ? commitSha : null,
|
|
9483
9713
|
base: labelBase,
|
|
9484
9714
|
files,
|
|
9485
|
-
stat:
|
|
9486
|
-
dirty:
|
|
9487
|
-
unpushed:
|
|
9715
|
+
stat: formatStat(files),
|
|
9716
|
+
dirty: fileOnly || !includeMeta ? files.length > 0 : meta.dirty,
|
|
9717
|
+
unpushed: meta.unpushed,
|
|
9488
9718
|
hasLastTurnBase,
|
|
9489
|
-
commits,
|
|
9490
|
-
scopeStats
|
|
9719
|
+
commits: meta.commits,
|
|
9720
|
+
scopeStats: meta.scopeStats,
|
|
9721
|
+
mergeBase: needsMergeBase ? mergeBase : null
|
|
9491
9722
|
};
|
|
9492
9723
|
}
|
|
9493
9724
|
async function listWorktreeFiles(worktreePath, opts) {
|
|
@@ -13183,6 +13414,11 @@ var Orchestrator = class {
|
|
|
13183
13414
|
return getDiff(thread.worktreePath, thread.repoPath, {
|
|
13184
13415
|
scope: opts?.scope,
|
|
13185
13416
|
commitSha: opts?.commitSha,
|
|
13417
|
+
base: opts?.base,
|
|
13418
|
+
includePatches: opts?.includePatches,
|
|
13419
|
+
includeMeta: opts?.includeMeta,
|
|
13420
|
+
includeUntracked: opts?.includeUntracked,
|
|
13421
|
+
path: opts?.path,
|
|
13186
13422
|
lastTurnBase: this.turnBaselines.get(thread.id) ?? null
|
|
13187
13423
|
});
|
|
13188
13424
|
}
|
|
@@ -15235,6 +15471,7 @@ init_injected_mcp();
|
|
|
15235
15471
|
coerceOrchestratorAgent,
|
|
15236
15472
|
collectTakenTeamSlugs,
|
|
15237
15473
|
commitAll,
|
|
15474
|
+
conductorBundledBinDir,
|
|
15238
15475
|
conductorDbPath,
|
|
15239
15476
|
confirmLand,
|
|
15240
15477
|
connectBrightsyTeam,
|
|
@@ -15346,6 +15583,7 @@ init_injected_mcp();
|
|
|
15346
15583
|
isBrightsyConnected,
|
|
15347
15584
|
isBrightsyNdjsonLine,
|
|
15348
15585
|
isCloudCoordinatorThread,
|
|
15586
|
+
isConductorBundledCli,
|
|
15349
15587
|
isCursorAutoModel,
|
|
15350
15588
|
isDirty,
|
|
15351
15589
|
isGhRateLimitError,
|