@buildautomaton/cli 0.1.33 → 0.1.35
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/cli.js +407 -249
- package/dist/cli.js.map +4 -4
- package/dist/index.js +403 -245
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -11857,8 +11857,8 @@ function getElementAtPath(obj, path43) {
|
|
|
11857
11857
|
}
|
|
11858
11858
|
function promiseAllObject(promisesObj) {
|
|
11859
11859
|
const keys = Object.keys(promisesObj);
|
|
11860
|
-
const
|
|
11861
|
-
return Promise.all(
|
|
11860
|
+
const promises5 = keys.map((key) => promisesObj[key]);
|
|
11861
|
+
return Promise.all(promises5).then((results) => {
|
|
11862
11862
|
const resolvedObj = {};
|
|
11863
11863
|
for (let i = 0; i < keys.length; i++) {
|
|
11864
11864
|
resolvedObj[keys[i]] = results[i];
|
|
@@ -25064,7 +25064,7 @@ var {
|
|
|
25064
25064
|
} = import_index.default;
|
|
25065
25065
|
|
|
25066
25066
|
// src/cli-version.ts
|
|
25067
|
-
var CLI_VERSION = "0.1.
|
|
25067
|
+
var CLI_VERSION = "0.1.35".length > 0 ? "0.1.35" : "0.0.0-dev";
|
|
25068
25068
|
|
|
25069
25069
|
// src/cli/defaults.ts
|
|
25070
25070
|
var DEFAULT_API_URL = process.env.BUILDAUTOMATON_API_URL ?? "https://api.buildautomaton.com";
|
|
@@ -25607,20 +25607,22 @@ function createWsBridge(options) {
|
|
|
25607
25607
|
onOpen?.();
|
|
25608
25608
|
});
|
|
25609
25609
|
ws.on("message", (raw) => {
|
|
25610
|
-
|
|
25611
|
-
|
|
25612
|
-
|
|
25613
|
-
|
|
25614
|
-
|
|
25615
|
-
|
|
25616
|
-
|
|
25617
|
-
|
|
25618
|
-
|
|
25610
|
+
setImmediate(() => {
|
|
25611
|
+
try {
|
|
25612
|
+
let data;
|
|
25613
|
+
if (typeof raw === "string") {
|
|
25614
|
+
data = JSON.parse(raw);
|
|
25615
|
+
} else if (Buffer.isBuffer(raw) || raw instanceof ArrayBuffer) {
|
|
25616
|
+
const str = Buffer.isBuffer(raw) ? raw.toString("utf8") : Buffer.from(raw).toString("utf8");
|
|
25617
|
+
data = JSON.parse(str);
|
|
25618
|
+
} else {
|
|
25619
|
+
data = raw;
|
|
25620
|
+
}
|
|
25621
|
+
onMessage?.(data);
|
|
25622
|
+
} catch {
|
|
25623
|
+
onMessage?.(raw);
|
|
25619
25624
|
}
|
|
25620
|
-
|
|
25621
|
-
} catch {
|
|
25622
|
-
onMessage?.(raw);
|
|
25623
|
-
}
|
|
25625
|
+
});
|
|
25624
25626
|
});
|
|
25625
25627
|
ws.on("close", (code, reason) => {
|
|
25626
25628
|
disposeClientPing();
|
|
@@ -27783,17 +27785,13 @@ function getAgentModelFromAgentConfig(config2) {
|
|
|
27783
27785
|
return t !== "" ? t : null;
|
|
27784
27786
|
}
|
|
27785
27787
|
|
|
27786
|
-
// src/git/session-git-queue.ts
|
|
27787
|
-
import { execFile as execFile7 } from "node:child_process";
|
|
27788
|
+
// src/git/snapshot/session-git-queue.ts
|
|
27788
27789
|
import { readFile as readFile2, stat as stat2 } from "node:fs/promises";
|
|
27789
|
-
import { promisify as promisify7 } from "node:util";
|
|
27790
27790
|
import * as path15 from "node:path";
|
|
27791
27791
|
|
|
27792
|
-
// src/git/pre-turn-snapshot.ts
|
|
27792
|
+
// src/git/snapshot/pre-turn-snapshot.ts
|
|
27793
27793
|
import * as fs15 from "node:fs";
|
|
27794
27794
|
import * as path14 from "node:path";
|
|
27795
|
-
import { execFile as execFile6 } from "node:child_process";
|
|
27796
|
-
import { promisify as promisify6 } from "node:util";
|
|
27797
27795
|
|
|
27798
27796
|
// src/git/discover-repos.ts
|
|
27799
27797
|
import * as fs14 from "node:fs";
|
|
@@ -32358,12 +32356,68 @@ function gitInstanceFactory(baseDir, options) {
|
|
|
32358
32356
|
init_git_response_error();
|
|
32359
32357
|
var simpleGit = gitInstanceFactory;
|
|
32360
32358
|
|
|
32359
|
+
// src/git/git-runtime.ts
|
|
32360
|
+
var activeGitChildProcesses = /* @__PURE__ */ new Set();
|
|
32361
|
+
function abortActiveGitChildProcesses() {
|
|
32362
|
+
for (const child of activeGitChildProcesses) {
|
|
32363
|
+
try {
|
|
32364
|
+
child.kill("SIGTERM");
|
|
32365
|
+
} catch {
|
|
32366
|
+
}
|
|
32367
|
+
}
|
|
32368
|
+
}
|
|
32369
|
+
var GitOperationAbortedError = class extends Error {
|
|
32370
|
+
constructor(message = "Git operation aborted") {
|
|
32371
|
+
super(message);
|
|
32372
|
+
this.name = "GitOperationAbortedError";
|
|
32373
|
+
}
|
|
32374
|
+
};
|
|
32375
|
+
function throwIfGitShutdownRequested() {
|
|
32376
|
+
if (isCliImmediateShutdownRequested()) {
|
|
32377
|
+
abortActiveGitChildProcesses();
|
|
32378
|
+
throw new GitOperationAbortedError();
|
|
32379
|
+
}
|
|
32380
|
+
}
|
|
32381
|
+
async function runGitTask(fn) {
|
|
32382
|
+
throwIfGitShutdownRequested();
|
|
32383
|
+
try {
|
|
32384
|
+
const result = await fn();
|
|
32385
|
+
throwIfGitShutdownRequested();
|
|
32386
|
+
return result;
|
|
32387
|
+
} catch (e) {
|
|
32388
|
+
if (isCliImmediateShutdownRequested()) {
|
|
32389
|
+
throw new GitOperationAbortedError();
|
|
32390
|
+
}
|
|
32391
|
+
throw e;
|
|
32392
|
+
}
|
|
32393
|
+
}
|
|
32394
|
+
async function yieldToEventLoop2() {
|
|
32395
|
+
throwIfGitShutdownRequested();
|
|
32396
|
+
await new Promise((resolve20) => {
|
|
32397
|
+
setImmediate(resolve20);
|
|
32398
|
+
});
|
|
32399
|
+
throwIfGitShutdownRequested();
|
|
32400
|
+
}
|
|
32401
|
+
async function forEachWithGitYield(items, fn) {
|
|
32402
|
+
for (let i = 0; i < items.length; i++) {
|
|
32403
|
+
if (i > 0 || items.length > 1) await yieldToEventLoop2();
|
|
32404
|
+
await fn(items[i], i);
|
|
32405
|
+
}
|
|
32406
|
+
}
|
|
32407
|
+
|
|
32361
32408
|
// src/git/cli-simple-git.ts
|
|
32362
32409
|
function cliSimpleGit(baseDir) {
|
|
32363
|
-
const git = simpleGit({
|
|
32410
|
+
const git = simpleGit({
|
|
32411
|
+
baseDir,
|
|
32412
|
+
trimmed: true,
|
|
32413
|
+
spawnOptions: {}
|
|
32414
|
+
});
|
|
32364
32415
|
git.outputHandler((command, stdout, stderr) => {
|
|
32365
32416
|
const trace = isCliTrace();
|
|
32366
32417
|
const onChunk = (label) => (chunk) => {
|
|
32418
|
+
if (isCliImmediateShutdownRequested()) {
|
|
32419
|
+
abortActiveGitChildProcesses();
|
|
32420
|
+
}
|
|
32367
32421
|
const text = typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
32368
32422
|
const line = text.replace(/\s+$/, "");
|
|
32369
32423
|
if (trace && line) {
|
|
@@ -32452,17 +32506,37 @@ async function discoverGitReposUnderRoot(rootPath) {
|
|
|
32452
32506
|
return out;
|
|
32453
32507
|
}
|
|
32454
32508
|
|
|
32455
|
-
// src/git/
|
|
32509
|
+
// src/git/git-exec.ts
|
|
32510
|
+
import { execFile as execFile6, spawn as spawn2 } from "node:child_process";
|
|
32511
|
+
import { promisify as promisify6 } from "node:util";
|
|
32456
32512
|
var execFileAsync5 = promisify6(execFile6);
|
|
32513
|
+
async function execGitFile(args, options) {
|
|
32514
|
+
throwIfGitShutdownRequested();
|
|
32515
|
+
try {
|
|
32516
|
+
const result = await execFileAsync5("git", args, {
|
|
32517
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
32518
|
+
...options
|
|
32519
|
+
});
|
|
32520
|
+
throwIfGitShutdownRequested();
|
|
32521
|
+
return {
|
|
32522
|
+
stdout: String(result.stdout ?? ""),
|
|
32523
|
+
stderr: String(result.stderr ?? "")
|
|
32524
|
+
};
|
|
32525
|
+
} catch (e) {
|
|
32526
|
+
if (isCliImmediateShutdownRequested()) {
|
|
32527
|
+
throw new GitOperationAbortedError();
|
|
32528
|
+
}
|
|
32529
|
+
throw e;
|
|
32530
|
+
}
|
|
32531
|
+
}
|
|
32532
|
+
|
|
32533
|
+
// src/git/snapshot/pre-turn-snapshot.ts
|
|
32457
32534
|
function snapshotsDirForCwd(agentCwd) {
|
|
32458
32535
|
return path14.join(agentCwd, ".buildautomaton", "snapshots");
|
|
32459
32536
|
}
|
|
32460
32537
|
async function gitStashCreate(repoRoot, log2) {
|
|
32461
32538
|
try {
|
|
32462
|
-
const { stdout } = await
|
|
32463
|
-
cwd: repoRoot,
|
|
32464
|
-
maxBuffer: 10 * 1024 * 1024
|
|
32465
|
-
});
|
|
32539
|
+
const { stdout } = await execGitFile(["stash", "create"], { cwd: repoRoot });
|
|
32466
32540
|
return stdout.trim();
|
|
32467
32541
|
} catch (e) {
|
|
32468
32542
|
log2(
|
|
@@ -32473,7 +32547,7 @@ async function gitStashCreate(repoRoot, log2) {
|
|
|
32473
32547
|
}
|
|
32474
32548
|
async function gitRun(repoRoot, args, log2, label) {
|
|
32475
32549
|
try {
|
|
32476
|
-
await
|
|
32550
|
+
await execGitFile(args, { cwd: repoRoot });
|
|
32477
32551
|
return { ok: true };
|
|
32478
32552
|
} catch (e) {
|
|
32479
32553
|
const msg = e instanceof Error ? e.message : String(e);
|
|
@@ -32507,10 +32581,10 @@ async function capturePreTurnSnapshot(options) {
|
|
|
32507
32581
|
return { ok: false, error: "No git repos to snapshot" };
|
|
32508
32582
|
}
|
|
32509
32583
|
const repos = [];
|
|
32510
|
-
|
|
32584
|
+
await forEachWithGitYield(repoRoots, async (root) => {
|
|
32511
32585
|
const stashSha = await gitStashCreate(root, log2);
|
|
32512
32586
|
repos.push({ path: root, stashSha });
|
|
32513
|
-
}
|
|
32587
|
+
});
|
|
32514
32588
|
const dir = snapshotsDirForCwd(agentCwd);
|
|
32515
32589
|
try {
|
|
32516
32590
|
fs15.mkdirSync(dir, { recursive: true });
|
|
@@ -32545,17 +32619,25 @@ async function applyPreTurnSnapshot(filePath, log2) {
|
|
|
32545
32619
|
if (!Array.isArray(data.repos)) {
|
|
32546
32620
|
return { ok: false, error: "Invalid snapshot file" };
|
|
32547
32621
|
}
|
|
32548
|
-
|
|
32549
|
-
|
|
32622
|
+
let applyError = null;
|
|
32623
|
+
await forEachWithGitYield(data.repos, async (r) => {
|
|
32624
|
+
if (applyError || !r.path) return;
|
|
32550
32625
|
const reset = await gitRun(r.path, ["reset", "--hard", "HEAD"], log2, "reset --hard");
|
|
32551
|
-
if (!reset.ok)
|
|
32626
|
+
if (!reset.ok) {
|
|
32627
|
+
applyError = reset;
|
|
32628
|
+
return;
|
|
32629
|
+
}
|
|
32552
32630
|
const clean = await gitRun(r.path, ["clean", "-fd"], log2, "clean -fd");
|
|
32553
|
-
if (!clean.ok)
|
|
32631
|
+
if (!clean.ok) {
|
|
32632
|
+
applyError = clean;
|
|
32633
|
+
return;
|
|
32634
|
+
}
|
|
32554
32635
|
if (r.stashSha) {
|
|
32555
32636
|
const ap = await gitRun(r.path, ["stash", "apply", r.stashSha], log2, "stash apply");
|
|
32556
|
-
if (!ap.ok)
|
|
32637
|
+
if (!ap.ok) applyError = ap;
|
|
32557
32638
|
}
|
|
32558
|
-
}
|
|
32639
|
+
});
|
|
32640
|
+
if (applyError?.ok === false) return applyError;
|
|
32559
32641
|
log2(`[snapshot] Restored pre-turn state for ${data.runId.slice(0, 8)}\u2026`);
|
|
32560
32642
|
return { ok: true };
|
|
32561
32643
|
}
|
|
@@ -32563,8 +32645,7 @@ function snapshotFilePath(agentCwd, runId) {
|
|
|
32563
32645
|
return path14.join(snapshotsDirForCwd(agentCwd), `${runId}.json`);
|
|
32564
32646
|
}
|
|
32565
32647
|
|
|
32566
|
-
// src/git/session-git-queue.ts
|
|
32567
|
-
var execFileAsync6 = promisify7(execFile7);
|
|
32648
|
+
// src/git/snapshot/session-git-queue.ts
|
|
32568
32649
|
var MAX_FULL_FILE_TEXT_BYTES = 512 * 1024;
|
|
32569
32650
|
async function readWorkspaceFileAsUtf8(absPath) {
|
|
32570
32651
|
try {
|
|
@@ -32593,35 +32674,28 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
|
|
|
32593
32674
|
return;
|
|
32594
32675
|
}
|
|
32595
32676
|
const multiRepo = data.repos.length > 1;
|
|
32596
|
-
|
|
32597
|
-
if (!repo.stashSha)
|
|
32677
|
+
await forEachWithGitYield(data.repos, async (repo) => {
|
|
32678
|
+
if (!repo.stashSha) return;
|
|
32598
32679
|
let namesRaw;
|
|
32599
32680
|
try {
|
|
32600
|
-
const { stdout } = await
|
|
32601
|
-
cwd: repo.path,
|
|
32602
|
-
maxBuffer: 10 * 1024 * 1024
|
|
32603
|
-
});
|
|
32681
|
+
const { stdout } = await execGitFile(["diff", "--name-only", repo.stashSha], { cwd: repo.path });
|
|
32604
32682
|
namesRaw = stdout;
|
|
32605
32683
|
} catch (e) {
|
|
32606
32684
|
log2(
|
|
32607
32685
|
`[session-git-queue] Git diff --name-only failed in ${repo.path}: ${e instanceof Error ? e.message : String(e)}`
|
|
32608
32686
|
);
|
|
32609
|
-
|
|
32687
|
+
return;
|
|
32610
32688
|
}
|
|
32611
32689
|
const lines = namesRaw.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
32612
32690
|
const slug = path15.basename(repo.path).replace(/[^\w.-]+/g, "_") || "repo";
|
|
32613
|
-
|
|
32614
|
-
if (rel.includes(".."))
|
|
32691
|
+
await forEachWithGitYield(lines, async (rel) => {
|
|
32692
|
+
if (rel.includes("..")) return;
|
|
32615
32693
|
try {
|
|
32616
|
-
const { stdout: patchContent } = await
|
|
32617
|
-
"git",
|
|
32694
|
+
const { stdout: patchContent } = await execGitFile(
|
|
32618
32695
|
["diff", "--no-color", repo.stashSha, "--", rel],
|
|
32619
|
-
{
|
|
32620
|
-
cwd: repo.path,
|
|
32621
|
-
maxBuffer: 50 * 1024 * 1024
|
|
32622
|
-
}
|
|
32696
|
+
{ cwd: repo.path }
|
|
32623
32697
|
);
|
|
32624
|
-
if (!patchContent.trim())
|
|
32698
|
+
if (!patchContent.trim()) return;
|
|
32625
32699
|
const displayPath = multiRepo ? `${slug}/${rel}` : rel;
|
|
32626
32700
|
const workspaceFilePath = path15.join(repo.path, rel);
|
|
32627
32701
|
const newText = await readWorkspaceFileAsUtf8(workspaceFilePath);
|
|
@@ -32638,8 +32712,8 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
|
|
|
32638
32712
|
`[session-git-queue] Git diff failed for ${rel}: ${e instanceof Error ? e.message : String(e)}`
|
|
32639
32713
|
);
|
|
32640
32714
|
}
|
|
32641
|
-
}
|
|
32642
|
-
}
|
|
32715
|
+
});
|
|
32716
|
+
});
|
|
32643
32717
|
}
|
|
32644
32718
|
|
|
32645
32719
|
// src/agents/acp/put-summarize-change-summaries.ts
|
|
@@ -32981,9 +33055,9 @@ __export(claude_code_acp_client_exports, {
|
|
|
32981
33055
|
});
|
|
32982
33056
|
|
|
32983
33057
|
// src/agents/acp/clients/detect-command-on-path.ts
|
|
32984
|
-
import { execFile as
|
|
32985
|
-
import { promisify as
|
|
32986
|
-
var
|
|
33058
|
+
import { execFile as execFile7 } from "node:child_process";
|
|
33059
|
+
import { promisify as promisify7 } from "node:util";
|
|
33060
|
+
var execFileAsync6 = promisify7(execFile7);
|
|
32987
33061
|
var COMMAND_ON_PATH_PROBE_TIMEOUT_MS = 750;
|
|
32988
33062
|
async function execFileShutdownAware(file2, args, timeoutMs) {
|
|
32989
33063
|
if (isCliImmediateShutdownRequested()) throw new Error("shutdown");
|
|
@@ -32993,7 +33067,7 @@ async function execFileShutdownAware(file2, args, timeoutMs) {
|
|
|
32993
33067
|
}, 50);
|
|
32994
33068
|
shutdownPoll.unref?.();
|
|
32995
33069
|
try {
|
|
32996
|
-
await
|
|
33070
|
+
await execFileAsync6(file2, args, { timeout: timeoutMs, signal: ac.signal });
|
|
32997
33071
|
} finally {
|
|
32998
33072
|
clearInterval(shutdownPoll);
|
|
32999
33073
|
}
|
|
@@ -33018,7 +33092,7 @@ async function execProbeShutdownAware(file2, args, timeoutMs) {
|
|
|
33018
33092
|
}
|
|
33019
33093
|
|
|
33020
33094
|
// src/agents/acp/clients/sdk/sdk-stdio-acp-client.ts
|
|
33021
|
-
import { spawn as
|
|
33095
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
33022
33096
|
import { Readable, Writable } from "node:stream";
|
|
33023
33097
|
|
|
33024
33098
|
// src/agents/acp/clients/agent-stderr-capture.ts
|
|
@@ -33613,7 +33687,7 @@ async function createSdkStdioAcpClient(options) {
|
|
|
33613
33687
|
getActiveConfigOptions
|
|
33614
33688
|
} = options;
|
|
33615
33689
|
const isWindows = process.platform === "win32";
|
|
33616
|
-
const child =
|
|
33690
|
+
const child = spawn3(command[0], command.slice(1), {
|
|
33617
33691
|
cwd,
|
|
33618
33692
|
stdio: ["pipe", "pipe", "pipe"],
|
|
33619
33693
|
env: process.env,
|
|
@@ -33826,7 +33900,7 @@ __export(cursor_acp_client_exports, {
|
|
|
33826
33900
|
createCursorAcpClient: () => createCursorAcpClient,
|
|
33827
33901
|
detectLocalAgentPresence: () => detectLocalAgentPresence3
|
|
33828
33902
|
});
|
|
33829
|
-
import { spawn as
|
|
33903
|
+
import { spawn as spawn4 } from "node:child_process";
|
|
33830
33904
|
import * as readline from "node:readline";
|
|
33831
33905
|
|
|
33832
33906
|
// src/agents/acp/format-session-update-kind-for-log.ts
|
|
@@ -33896,7 +33970,7 @@ async function createCursorAcpClient(options) {
|
|
|
33896
33970
|
} = options;
|
|
33897
33971
|
const dbgFs = process.env.BUILDAUTOMATON_DEBUG_ACP_FS === "1";
|
|
33898
33972
|
const isWindows = process.platform === "win32";
|
|
33899
|
-
const child =
|
|
33973
|
+
const child = spawn4(command[0], command.slice(1), {
|
|
33900
33974
|
cwd,
|
|
33901
33975
|
stdio: ["pipe", "pipe", "pipe"],
|
|
33902
33976
|
env: process.env,
|
|
@@ -35074,7 +35148,7 @@ async function ensureAcpClient(options) {
|
|
|
35074
35148
|
if (!state.acpStartPromise) {
|
|
35075
35149
|
let statOk = false;
|
|
35076
35150
|
try {
|
|
35077
|
-
const st = fs16.
|
|
35151
|
+
const st = await fs16.promises.stat(targetSessionParentPath);
|
|
35078
35152
|
statOk = st.isDirectory();
|
|
35079
35153
|
if (!statOk) {
|
|
35080
35154
|
state.lastAcpStartError = `Agent cwd is not a directory: ${targetSessionParentPath}`;
|
|
@@ -35342,7 +35416,7 @@ import os8 from "node:os";
|
|
|
35342
35416
|
import * as fs18 from "node:fs";
|
|
35343
35417
|
import * as path21 from "node:path";
|
|
35344
35418
|
|
|
35345
|
-
// src/git/worktree-add.ts
|
|
35419
|
+
// src/git/worktrees/worktree-add.ts
|
|
35346
35420
|
async function gitWorktreeAddBranch(mainRepoPath, worktreePath, branch) {
|
|
35347
35421
|
const mainGit = cliSimpleGit(mainRepoPath);
|
|
35348
35422
|
await mainGit.raw(["worktree", "add", "-b", branch, worktreePath, "HEAD"]);
|
|
@@ -35447,7 +35521,7 @@ async function prepareNewSessionWorktrees(options) {
|
|
|
35447
35521
|
};
|
|
35448
35522
|
}
|
|
35449
35523
|
|
|
35450
|
-
// src/git/rename-branch.ts
|
|
35524
|
+
// src/git/branches/rename-branch.ts
|
|
35451
35525
|
async function gitRenameCurrentBranch(repoDir, newName) {
|
|
35452
35526
|
const g = cliSimpleGit(repoDir);
|
|
35453
35527
|
await g.raw(["branch", "-m", newName]);
|
|
@@ -35471,10 +35545,10 @@ async function renameSessionWorktreeBranches(paths, newBranch, log2) {
|
|
|
35471
35545
|
// src/worktrees/remove-session-worktrees.ts
|
|
35472
35546
|
import * as fs21 from "node:fs";
|
|
35473
35547
|
|
|
35474
|
-
// src/git/worktree-remove.ts
|
|
35548
|
+
// src/git/worktrees/worktree-remove.ts
|
|
35475
35549
|
import * as fs20 from "node:fs";
|
|
35476
35550
|
|
|
35477
|
-
// src/git/resolve-main-repo-from-git-file.ts
|
|
35551
|
+
// src/git/worktrees/resolve-main-repo-from-git-file.ts
|
|
35478
35552
|
import * as fs19 from "node:fs";
|
|
35479
35553
|
import * as path22 from "node:path";
|
|
35480
35554
|
function resolveMainRepoFromWorktreeGitFile(wt) {
|
|
@@ -35488,7 +35562,7 @@ function resolveMainRepoFromWorktreeGitFile(wt) {
|
|
|
35488
35562
|
return path22.dirname(gitDir);
|
|
35489
35563
|
}
|
|
35490
35564
|
|
|
35491
|
-
// src/git/worktree-remove.ts
|
|
35565
|
+
// src/git/worktrees/worktree-remove.ts
|
|
35492
35566
|
async function gitWorktreeRemoveForce(worktreePath) {
|
|
35493
35567
|
const mainRepo = resolveMainRepoFromWorktreeGitFile(worktreePath);
|
|
35494
35568
|
if (mainRepo) {
|
|
@@ -35514,7 +35588,88 @@ async function removeSessionWorktrees(paths, log2) {
|
|
|
35514
35588
|
}
|
|
35515
35589
|
}
|
|
35516
35590
|
|
|
35517
|
-
// src/git/
|
|
35591
|
+
// src/git/changes/lib/parse-git-status.ts
|
|
35592
|
+
function parseNameStatusLines(lines) {
|
|
35593
|
+
const m = /* @__PURE__ */ new Map();
|
|
35594
|
+
for (const line of lines) {
|
|
35595
|
+
if (!line.trim()) continue;
|
|
35596
|
+
const tabParts = line.split(" ");
|
|
35597
|
+
if (tabParts.length < 2) continue;
|
|
35598
|
+
const status = tabParts[0].trim();
|
|
35599
|
+
const code = status[0];
|
|
35600
|
+
if (code === "A") {
|
|
35601
|
+
m.set(tabParts[tabParts.length - 1], "added");
|
|
35602
|
+
} else if (code === "D") {
|
|
35603
|
+
m.set(tabParts[tabParts.length - 1], "removed");
|
|
35604
|
+
} else if (code === "R" || code === "C") {
|
|
35605
|
+
if (tabParts.length >= 3) m.set(tabParts[tabParts.length - 1], "modified");
|
|
35606
|
+
} else if (code === "M" || code === "U" || code === "T") {
|
|
35607
|
+
m.set(tabParts[tabParts.length - 1], "modified");
|
|
35608
|
+
}
|
|
35609
|
+
}
|
|
35610
|
+
return m;
|
|
35611
|
+
}
|
|
35612
|
+
function parseNumstatFirstLine(line) {
|
|
35613
|
+
const parts = line.split(" ");
|
|
35614
|
+
if (parts.length < 3) return null;
|
|
35615
|
+
const [a, d] = parts;
|
|
35616
|
+
const additions = a === "-" ? 0 : parseInt(String(a), 10) || 0;
|
|
35617
|
+
const deletions = d === "-" ? 0 : parseInt(String(d), 10) || 0;
|
|
35618
|
+
return { additions, deletions };
|
|
35619
|
+
}
|
|
35620
|
+
function parseNumstat(lines) {
|
|
35621
|
+
const m = /* @__PURE__ */ new Map();
|
|
35622
|
+
for (const line of lines) {
|
|
35623
|
+
if (!line.trim()) continue;
|
|
35624
|
+
const parts = line.split(" ");
|
|
35625
|
+
if (parts.length < 3) continue;
|
|
35626
|
+
const [a, d, p] = parts;
|
|
35627
|
+
const additions = a === "-" ? 0 : parseInt(String(a), 10) || 0;
|
|
35628
|
+
const deletions = d === "-" ? 0 : parseInt(String(d), 10) || 0;
|
|
35629
|
+
m.set(p, { additions, deletions });
|
|
35630
|
+
}
|
|
35631
|
+
return m;
|
|
35632
|
+
}
|
|
35633
|
+
async function numstatFromGitNoIndex(g, pathInRepo) {
|
|
35634
|
+
const devNull = process.platform === "win32" ? "NUL" : "/dev/null";
|
|
35635
|
+
try {
|
|
35636
|
+
const out = await g.raw(["diff", "--numstat", "--no-index", "--", devNull, pathInRepo]);
|
|
35637
|
+
const first2 = String(out).split("\n").find((l) => l.trim()) ?? "";
|
|
35638
|
+
return parseNumstatFirstLine(first2);
|
|
35639
|
+
} catch {
|
|
35640
|
+
return null;
|
|
35641
|
+
}
|
|
35642
|
+
}
|
|
35643
|
+
|
|
35644
|
+
// src/git/changes/lib/working-tree-changed-path-count.ts
|
|
35645
|
+
function workingTreeChangedPathCount(nameStatusLines, numstatLines, untrackedLines) {
|
|
35646
|
+
const kindByPath = parseNameStatusLines(nameStatusLines);
|
|
35647
|
+
const numByPath = parseNumstat(numstatLines);
|
|
35648
|
+
const paths = /* @__PURE__ */ new Set([...kindByPath.keys(), ...numByPath.keys()]);
|
|
35649
|
+
for (const p of untrackedLines.map((s) => s.trim()).filter(Boolean)) {
|
|
35650
|
+
paths.add(p);
|
|
35651
|
+
}
|
|
35652
|
+
return paths.size;
|
|
35653
|
+
}
|
|
35654
|
+
|
|
35655
|
+
// src/git/changes/count-working-tree-changed-files.ts
|
|
35656
|
+
async function countWorkingTreeChangedFilesForRepo(repoGitCwd) {
|
|
35657
|
+
return runGitTask(async () => {
|
|
35658
|
+
const g = cliSimpleGit(repoGitCwd);
|
|
35659
|
+
const [nameStatusRaw, numstatRaw, untrackedRaw] = await Promise.all([
|
|
35660
|
+
g.raw(["diff", "--name-status", "HEAD"]).catch(() => ""),
|
|
35661
|
+
g.raw(["diff", "HEAD", "--numstat"]).catch(() => ""),
|
|
35662
|
+
g.raw(["ls-files", "--others", "--exclude-standard"]).catch(() => "")
|
|
35663
|
+
]);
|
|
35664
|
+
return workingTreeChangedPathCount(
|
|
35665
|
+
String(nameStatusRaw).split("\n"),
|
|
35666
|
+
String(numstatRaw).split("\n"),
|
|
35667
|
+
String(untrackedRaw).split("\n")
|
|
35668
|
+
);
|
|
35669
|
+
});
|
|
35670
|
+
}
|
|
35671
|
+
|
|
35672
|
+
// src/git/commits/resolve-remote-tracking.ts
|
|
35518
35673
|
async function tryConfigGet(g, key) {
|
|
35519
35674
|
try {
|
|
35520
35675
|
const out = await g.raw(["config", "--get", key]);
|
|
@@ -35597,30 +35752,6 @@ async function resolveBaseShaForUnpushedCommits(g) {
|
|
|
35597
35752
|
if (!defaultRef) return null;
|
|
35598
35753
|
return revParseSafe(g, defaultRef);
|
|
35599
35754
|
}
|
|
35600
|
-
function parseLogShaDateSubjectLines(raw) {
|
|
35601
|
-
const out = [];
|
|
35602
|
-
for (const line of String(raw).split("\n")) {
|
|
35603
|
-
const l = line.trimEnd();
|
|
35604
|
-
if (!l.trim()) continue;
|
|
35605
|
-
const parts = l.split(" ");
|
|
35606
|
-
if (parts.length < 3) continue;
|
|
35607
|
-
const sha = parts[0].trim();
|
|
35608
|
-
const committedAt = parts[1].trim();
|
|
35609
|
-
const subject = parts.slice(2).join(" ").trim();
|
|
35610
|
-
if (!/^[0-9a-f]{7,40}$/i.test(sha)) continue;
|
|
35611
|
-
out.push({ sha, shortSha: sha.slice(0, 7), subject, committedAt });
|
|
35612
|
-
}
|
|
35613
|
-
return out;
|
|
35614
|
-
}
|
|
35615
|
-
async function gitLogNotReachableFromBase(g, baseSha, headSha) {
|
|
35616
|
-
if (baseSha === headSha) return [];
|
|
35617
|
-
try {
|
|
35618
|
-
const logOut = await g.raw(["log", "--format=%H %cI %s", `${baseSha}..${headSha}`]);
|
|
35619
|
-
return parseLogShaDateSubjectLines(logOut);
|
|
35620
|
-
} catch {
|
|
35621
|
-
return [];
|
|
35622
|
-
}
|
|
35623
|
-
}
|
|
35624
35755
|
async function commitsAheadOfRemoteTracking(repoDir) {
|
|
35625
35756
|
const g = cliSimpleGit(repoDir);
|
|
35626
35757
|
const headSha = await revParseSafe(g, "HEAD");
|
|
@@ -35635,44 +35766,41 @@ async function commitsAheadOfRemoteTracking(repoDir) {
|
|
|
35635
35766
|
return 0;
|
|
35636
35767
|
}
|
|
35637
35768
|
}
|
|
35769
|
+
|
|
35770
|
+
// src/git/status/working-tree-status.ts
|
|
35638
35771
|
async function getRepoWorkingTreeStatus(repoDir) {
|
|
35639
|
-
|
|
35640
|
-
|
|
35641
|
-
|
|
35642
|
-
|
|
35643
|
-
|
|
35644
|
-
}
|
|
35645
|
-
async function listUnpushedCommits(repoDir) {
|
|
35646
|
-
const g = cliSimpleGit(repoDir);
|
|
35647
|
-
const headSha = await revParseSafe(g, "HEAD");
|
|
35648
|
-
if (!headSha) return [];
|
|
35649
|
-
const baseSha = await resolveBaseShaForUnpushedCommits(g);
|
|
35650
|
-
if (!baseSha) return [];
|
|
35651
|
-
return gitLogNotReachableFromBase(g, baseSha, headSha);
|
|
35772
|
+
return runGitTask(async () => {
|
|
35773
|
+
const uncommittedFileCount = await countWorkingTreeChangedFilesForRepo(repoDir);
|
|
35774
|
+
const hasUncommittedChanges = uncommittedFileCount > 0;
|
|
35775
|
+
const ahead = await commitsAheadOfRemoteTracking(repoDir);
|
|
35776
|
+
return { hasUncommittedChanges, hasUnpushedCommits: ahead > 0, uncommittedFileCount };
|
|
35777
|
+
});
|
|
35652
35778
|
}
|
|
35653
35779
|
async function aggregateSessionPathsWorkingTreeStatus(paths) {
|
|
35654
35780
|
let hasUncommittedChanges = false;
|
|
35655
35781
|
let hasUnpushedCommits = false;
|
|
35656
|
-
|
|
35782
|
+
let uncommittedFileCount = 0;
|
|
35783
|
+
await forEachWithGitYield(paths, async (p) => {
|
|
35657
35784
|
const s = await getRepoWorkingTreeStatus(p);
|
|
35785
|
+
uncommittedFileCount += s.uncommittedFileCount;
|
|
35658
35786
|
if (s.hasUncommittedChanges) hasUncommittedChanges = true;
|
|
35659
35787
|
if (s.hasUnpushedCommits) hasUnpushedCommits = true;
|
|
35660
|
-
}
|
|
35661
|
-
return { hasUncommittedChanges, hasUnpushedCommits };
|
|
35788
|
+
});
|
|
35789
|
+
return { hasUncommittedChanges, hasUnpushedCommits, uncommittedFileCount };
|
|
35662
35790
|
}
|
|
35663
35791
|
async function pushAheadOfUpstreamForPaths(paths) {
|
|
35664
|
-
|
|
35792
|
+
await forEachWithGitYield(paths, async (p) => {
|
|
35665
35793
|
const g = cliSimpleGit(p);
|
|
35666
35794
|
const ahead = await commitsAheadOfRemoteTracking(p);
|
|
35667
|
-
if (ahead <= 0)
|
|
35795
|
+
if (ahead <= 0) return;
|
|
35668
35796
|
await g.push();
|
|
35669
|
-
}
|
|
35797
|
+
});
|
|
35670
35798
|
}
|
|
35671
35799
|
|
|
35672
|
-
// src/git/
|
|
35800
|
+
// src/git/changes/types.ts
|
|
35673
35801
|
var MAX_PATCH_CHARS = 35e4;
|
|
35674
35802
|
|
|
35675
|
-
// src/git/
|
|
35803
|
+
// src/git/changes/lib/repo-format.ts
|
|
35676
35804
|
function posixJoinDirFile(dir, file2) {
|
|
35677
35805
|
const d = dir === "." || dir === "" ? "" : dir.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
35678
35806
|
const f = file2.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
@@ -35726,63 +35854,80 @@ function formatRemoteDisplayLabel(remoteUrl) {
|
|
|
35726
35854
|
return `origin \xB7 ${hostPath}`;
|
|
35727
35855
|
}
|
|
35728
35856
|
|
|
35729
|
-
// src/git/
|
|
35857
|
+
// src/git/changes/get-working-tree-change-repo-details.ts
|
|
35730
35858
|
import * as path24 from "node:path";
|
|
35731
35859
|
|
|
35732
|
-
// src/git/
|
|
35733
|
-
function
|
|
35734
|
-
const
|
|
35735
|
-
for (const line of
|
|
35736
|
-
|
|
35737
|
-
|
|
35738
|
-
|
|
35739
|
-
|
|
35740
|
-
const
|
|
35741
|
-
|
|
35742
|
-
|
|
35743
|
-
|
|
35744
|
-
|
|
35745
|
-
} else if (code === "R" || code === "C") {
|
|
35746
|
-
if (tabParts.length >= 3) m.set(tabParts[tabParts.length - 1], "modified");
|
|
35747
|
-
} else if (code === "M" || code === "U" || code === "T") {
|
|
35748
|
-
m.set(tabParts[tabParts.length - 1], "modified");
|
|
35749
|
-
}
|
|
35860
|
+
// src/git/commits/lib/parse-log-lines.ts
|
|
35861
|
+
function parseLogShaDateSubjectLines(raw) {
|
|
35862
|
+
const out = [];
|
|
35863
|
+
for (const line of String(raw).split("\n")) {
|
|
35864
|
+
const l = line.trimEnd();
|
|
35865
|
+
if (!l.trim()) continue;
|
|
35866
|
+
const parts = l.split(" ");
|
|
35867
|
+
if (parts.length < 3) continue;
|
|
35868
|
+
const sha = parts[0].trim();
|
|
35869
|
+
const committedAt = parts[1].trim();
|
|
35870
|
+
const subject = parts.slice(2).join(" ").trim();
|
|
35871
|
+
if (!/^[0-9a-f]{7,40}$/i.test(sha)) continue;
|
|
35872
|
+
out.push({ sha, shortSha: sha.slice(0, 7), subject, committedAt });
|
|
35750
35873
|
}
|
|
35751
|
-
return
|
|
35752
|
-
}
|
|
35753
|
-
function parseNumstatFirstLine(line) {
|
|
35754
|
-
const parts = line.split(" ");
|
|
35755
|
-
if (parts.length < 3) return null;
|
|
35756
|
-
const [a, d] = parts;
|
|
35757
|
-
const additions = a === "-" ? 0 : parseInt(String(a), 10) || 0;
|
|
35758
|
-
const deletions = d === "-" ? 0 : parseInt(String(d), 10) || 0;
|
|
35759
|
-
return { additions, deletions };
|
|
35874
|
+
return out;
|
|
35760
35875
|
}
|
|
35761
|
-
|
|
35762
|
-
|
|
35763
|
-
|
|
35764
|
-
|
|
35765
|
-
|
|
35766
|
-
|
|
35767
|
-
|
|
35768
|
-
|
|
35769
|
-
|
|
35770
|
-
m.set(p, { additions, deletions });
|
|
35876
|
+
|
|
35877
|
+
// src/git/commits/list-unpushed-commits.ts
|
|
35878
|
+
async function gitLogNotReachableFromBase(g, baseSha, headSha) {
|
|
35879
|
+
if (baseSha === headSha) return [];
|
|
35880
|
+
try {
|
|
35881
|
+
const logOut = await g.raw(["log", "--format=%H %cI %s", `${baseSha}..${headSha}`]);
|
|
35882
|
+
return parseLogShaDateSubjectLines(logOut);
|
|
35883
|
+
} catch {
|
|
35884
|
+
return [];
|
|
35771
35885
|
}
|
|
35772
|
-
return m;
|
|
35773
35886
|
}
|
|
35774
|
-
async function
|
|
35775
|
-
const
|
|
35887
|
+
async function listUnpushedCommits(repoDir) {
|
|
35888
|
+
const g = cliSimpleGit(repoDir);
|
|
35889
|
+
const headSha = await revParseSafe(g, "HEAD");
|
|
35890
|
+
if (!headSha) return [];
|
|
35891
|
+
const baseSha = await resolveBaseShaForUnpushedCommits(g);
|
|
35892
|
+
if (!baseSha) return [];
|
|
35893
|
+
return gitLogNotReachableFromBase(g, baseSha, headSha);
|
|
35894
|
+
}
|
|
35895
|
+
|
|
35896
|
+
// src/git/commits/lib/sanitize-recent-commits-limit.ts
|
|
35897
|
+
var RECENT_COMMITS_LIMIT_MIN = 1;
|
|
35898
|
+
var RECENT_COMMITS_LIMIT_MAX = 50;
|
|
35899
|
+
var RECENT_COMMITS_LIMIT_DEFAULT = 2;
|
|
35900
|
+
function sanitizeRecentCommitsLimit(value) {
|
|
35901
|
+
const n = typeof value === "number" ? value : typeof value === "string" ? Number.parseInt(value.trim(), 10) : Number.NaN;
|
|
35902
|
+
if (!Number.isFinite(n)) return RECENT_COMMITS_LIMIT_DEFAULT;
|
|
35903
|
+
return Math.min(RECENT_COMMITS_LIMIT_MAX, Math.max(RECENT_COMMITS_LIMIT_MIN, Math.trunc(n)));
|
|
35904
|
+
}
|
|
35905
|
+
|
|
35906
|
+
// src/git/commits/list-recent-commits.ts
|
|
35907
|
+
async function listRecentCommits(repoDir, limitInput) {
|
|
35908
|
+
const limit = sanitizeRecentCommitsLimit(limitInput);
|
|
35909
|
+
const g = cliSimpleGit(repoDir);
|
|
35910
|
+
const headSha = await revParseSafe(g, "HEAD");
|
|
35911
|
+
if (!headSha) return { commits: [], hasMore: false };
|
|
35912
|
+
const unpushedSet = new Set((await listUnpushedCommits(repoDir)).map((c) => c.sha));
|
|
35776
35913
|
try {
|
|
35777
|
-
const
|
|
35778
|
-
const
|
|
35779
|
-
|
|
35914
|
+
const logOut = await g.raw(["log", "--format=%H %cI %s", `-n`, String(limit), "HEAD"]);
|
|
35915
|
+
const commits = parseLogShaDateSubjectLines(logOut).map((c) => ({
|
|
35916
|
+
...c,
|
|
35917
|
+
needsPush: unpushedSet.has(c.sha)
|
|
35918
|
+
}));
|
|
35919
|
+
let hasMore = false;
|
|
35920
|
+
if (commits.length === limit) {
|
|
35921
|
+
const nextOut = await g.raw(["log", "-n", "1", `--skip=${limit}`, "--format=%H", "HEAD"]);
|
|
35922
|
+
hasMore = /^[0-9a-f]{7,40}$/i.test(String(nextOut).trim());
|
|
35923
|
+
}
|
|
35924
|
+
return { commits, hasMore };
|
|
35780
35925
|
} catch {
|
|
35781
|
-
return
|
|
35926
|
+
return { commits: [], hasMore: false };
|
|
35782
35927
|
}
|
|
35783
35928
|
}
|
|
35784
35929
|
|
|
35785
|
-
// src/git/
|
|
35930
|
+
// src/git/changes/lib/patch-truncate.ts
|
|
35786
35931
|
function truncatePatch(s) {
|
|
35787
35932
|
if (s.length <= MAX_PATCH_CHARS) return s;
|
|
35788
35933
|
return `${s.slice(0, MAX_PATCH_CHARS)}
|
|
@@ -35790,7 +35935,7 @@ function truncatePatch(s) {
|
|
|
35790
35935
|
\u2026 (diff truncated)`;
|
|
35791
35936
|
}
|
|
35792
35937
|
|
|
35793
|
-
// src/git/
|
|
35938
|
+
// src/git/commits/list-changed-files-for-commit.ts
|
|
35794
35939
|
var EMPTY_TREE = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
|
|
35795
35940
|
async function parentForCommitDiff(g, sha) {
|
|
35796
35941
|
try {
|
|
@@ -35816,7 +35961,7 @@ async function listChangedFilesForCommit(repoGitCwd, repoRelPath, commitSha) {
|
|
|
35816
35961
|
const paths = new Set([...kindByPath.keys(), ...numByPath.keys()].filter(Boolean));
|
|
35817
35962
|
const rows = [];
|
|
35818
35963
|
const normRel = repoRelPath === "." || repoRelPath === "" ? "." : repoRelPath;
|
|
35819
|
-
|
|
35964
|
+
await forEachWithGitYield([...paths], async (pathInRepo) => {
|
|
35820
35965
|
const relLauncher = posixJoinDirFile(normRel, pathInRepo.replace(/\\/g, "/"));
|
|
35821
35966
|
const nums = numByPath.get(pathInRepo);
|
|
35822
35967
|
let additions = nums?.additions ?? 0;
|
|
@@ -35828,8 +35973,8 @@ async function listChangedFilesForCommit(repoGitCwd, repoRelPath, commitSha) {
|
|
|
35828
35973
|
else change = "modified";
|
|
35829
35974
|
}
|
|
35830
35975
|
rows.push({ pathRelLauncher: relLauncher, additions, deletions, change });
|
|
35831
|
-
}
|
|
35832
|
-
|
|
35976
|
+
});
|
|
35977
|
+
await forEachWithGitYield(rows, async (row) => {
|
|
35833
35978
|
let pathInRepo;
|
|
35834
35979
|
if (normRel === ".") {
|
|
35835
35980
|
pathInRepo = row.pathRelLauncher;
|
|
@@ -35841,16 +35986,16 @@ async function listChangedFilesForCommit(repoGitCwd, repoRelPath, commitSha) {
|
|
|
35841
35986
|
const raw = await g.raw(["diff", "-U20000", range, "--", pathInRepo]).catch(() => "");
|
|
35842
35987
|
const t = String(raw).trim();
|
|
35843
35988
|
row.patchContent = t ? truncatePatch(t) : void 0;
|
|
35844
|
-
}
|
|
35989
|
+
});
|
|
35845
35990
|
rows.sort((a, b) => a.pathRelLauncher.localeCompare(b.pathRelLauncher));
|
|
35846
35991
|
return rows;
|
|
35847
35992
|
}
|
|
35848
35993
|
|
|
35849
|
-
// src/git/
|
|
35994
|
+
// src/git/changes/list-changed-files-for-repo.ts
|
|
35850
35995
|
import * as fs23 from "node:fs";
|
|
35851
35996
|
import * as path23 from "node:path";
|
|
35852
35997
|
|
|
35853
|
-
// src/git/
|
|
35998
|
+
// src/git/changes/lib/count-lines.ts
|
|
35854
35999
|
import { createReadStream } from "node:fs";
|
|
35855
36000
|
import * as readline2 from "node:readline";
|
|
35856
36001
|
async function countTextFileLines(filePath) {
|
|
@@ -35871,7 +36016,7 @@ async function countTextFileLines(filePath) {
|
|
|
35871
36016
|
return lines;
|
|
35872
36017
|
}
|
|
35873
36018
|
|
|
35874
|
-
// src/git/
|
|
36019
|
+
// src/git/changes/hydrate-patch.ts
|
|
35875
36020
|
import * as fs22 from "node:fs";
|
|
35876
36021
|
var UNIFIED_HUNK_HEADER_RE = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/;
|
|
35877
36022
|
var MAX_HYDRATE_LINES_PER_GAP = 8e3;
|
|
@@ -35987,26 +36132,16 @@ async function hydrateUnifiedPatchWithFileContext(patch, filePath, repoGitCwd, p
|
|
|
35987
36132
|
return truncatePatch(out.join("\n"));
|
|
35988
36133
|
}
|
|
35989
36134
|
|
|
35990
|
-
// src/git/
|
|
36135
|
+
// src/git/changes/unified-diff-for-file.ts
|
|
35991
36136
|
async function unifiedDiffForFile(repoCwd, pathInRepo, change) {
|
|
35992
36137
|
const g = cliSimpleGit(repoCwd);
|
|
35993
|
-
|
|
35994
|
-
|
|
35995
|
-
|
|
35996
|
-
|
|
35997
|
-
raw = await g.raw(["diff", "--no-index", "--", devNull, pathInRepo]);
|
|
35998
|
-
} else {
|
|
35999
|
-
raw = await g.raw(["diff", "HEAD", "--", pathInRepo]);
|
|
36000
|
-
}
|
|
36001
|
-
const t = String(raw).trim();
|
|
36002
|
-
if (!t) return void 0;
|
|
36003
|
-
return truncatePatch(t);
|
|
36004
|
-
} catch {
|
|
36005
|
-
return void 0;
|
|
36006
|
-
}
|
|
36138
|
+
const args = change === "added" ? ["diff", "--no-color", "HEAD", "--", pathInRepo] : change === "removed" ? ["diff", "--no-color", "HEAD", "--", pathInRepo] : ["diff", "--no-color", "HEAD", "--", pathInRepo];
|
|
36139
|
+
const raw = await g.raw([...args]).catch(() => "");
|
|
36140
|
+
const t = String(raw).trim();
|
|
36141
|
+
return t ? truncatePatch(t) : void 0;
|
|
36007
36142
|
}
|
|
36008
36143
|
|
|
36009
|
-
// src/git/
|
|
36144
|
+
// src/git/changes/list-changed-files-for-repo.ts
|
|
36010
36145
|
async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
|
|
36011
36146
|
const g = cliSimpleGit(repoGitCwd);
|
|
36012
36147
|
const [nameStatusRaw, numstatRaw, untrackedRaw] = await Promise.all([
|
|
@@ -36020,7 +36155,7 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
|
|
|
36020
36155
|
const untracked = String(untrackedRaw).split("\n").map((s) => s.trim()).filter(Boolean);
|
|
36021
36156
|
for (const p of untracked) paths.add(p);
|
|
36022
36157
|
const rows = [];
|
|
36023
|
-
|
|
36158
|
+
await forEachWithGitYield([...paths], async (pathInRepo) => {
|
|
36024
36159
|
const relLauncher = posixJoinDirFile(repoRelPath, pathInRepo.replace(/\\/g, "/"));
|
|
36025
36160
|
const repoFilePath = path23.join(repoGitCwd, pathInRepo);
|
|
36026
36161
|
const nums = numByPath.get(pathInRepo);
|
|
@@ -36050,9 +36185,9 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
|
|
|
36050
36185
|
else change = "modified";
|
|
36051
36186
|
}
|
|
36052
36187
|
rows.push({ pathRelLauncher: relLauncher, additions, deletions, change });
|
|
36053
|
-
}
|
|
36188
|
+
});
|
|
36054
36189
|
const normRel = repoRelPath === "." || repoRelPath === "" ? "." : repoRelPath;
|
|
36055
|
-
|
|
36190
|
+
await forEachWithGitYield(rows, async (row) => {
|
|
36056
36191
|
let pathInRepo;
|
|
36057
36192
|
if (normRel === ".") {
|
|
36058
36193
|
pathInRepo = row.pathRelLauncher;
|
|
@@ -36067,11 +36202,11 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
|
|
|
36067
36202
|
patch = await hydrateUnifiedPatchWithFileContext(patch, filePath, repoGitCwd, pathInRepo, row.change);
|
|
36068
36203
|
}
|
|
36069
36204
|
row.patchContent = patch;
|
|
36070
|
-
}
|
|
36205
|
+
});
|
|
36071
36206
|
return rows;
|
|
36072
36207
|
}
|
|
36073
36208
|
|
|
36074
|
-
// src/git/
|
|
36209
|
+
// src/git/changes/get-working-tree-change-repo-details.ts
|
|
36075
36210
|
function normRepoRel(p) {
|
|
36076
36211
|
const x = p.replace(/\\/g, "/").trim();
|
|
36077
36212
|
return x === "" ? "." : x;
|
|
@@ -36090,7 +36225,9 @@ async function getWorkingTreeChangeRepoDetails(options) {
|
|
|
36090
36225
|
throw new Error("commit sha is required for commit changes");
|
|
36091
36226
|
}
|
|
36092
36227
|
const basis = filter == null && basisInput.kind === "commit" ? { kind: "working" } : basisInput;
|
|
36093
|
-
for (
|
|
36228
|
+
for (let i = 0; i < options.commitTargetPaths.length; i++) {
|
|
36229
|
+
if (i > 0) await yieldToEventLoop2();
|
|
36230
|
+
const target = options.commitTargetPaths[i];
|
|
36094
36231
|
const t = path24.resolve(target);
|
|
36095
36232
|
if (!await isGitRepoDirectory(t)) continue;
|
|
36096
36233
|
const g = cliSimpleGit(t);
|
|
@@ -36124,7 +36261,10 @@ async function getWorkingTreeChangeRepoDetails(options) {
|
|
|
36124
36261
|
const files = basis.kind === "commit" ? await listChangedFilesForCommit(t, relForList, basis.sha.trim()) : await listChangedFilesForRepo(t, relForList);
|
|
36125
36262
|
const st = await g.status();
|
|
36126
36263
|
const hasUncommittedChanges = (st.files?.length ?? 0) > 0;
|
|
36127
|
-
const unpushedCommits = await
|
|
36264
|
+
const [unpushedCommits, recentCommitList] = await Promise.all([
|
|
36265
|
+
listUnpushedCommits(t),
|
|
36266
|
+
listRecentCommits(t, options.recentCommitsLimit)
|
|
36267
|
+
]);
|
|
36128
36268
|
out.push({
|
|
36129
36269
|
repoRelPath: norm,
|
|
36130
36270
|
repoDisplayName,
|
|
@@ -36134,6 +36274,8 @@ async function getWorkingTreeChangeRepoDetails(options) {
|
|
|
36134
36274
|
files,
|
|
36135
36275
|
hasUncommittedChanges,
|
|
36136
36276
|
unpushedCommits,
|
|
36277
|
+
recentCommits: recentCommitList.commits,
|
|
36278
|
+
recentCommitsHasMore: recentCommitList.hasMore,
|
|
36137
36279
|
changesView: basis.kind === "commit" ? "commit" : "working",
|
|
36138
36280
|
changesCommitSha: basis.kind === "commit" ? basis.sha.trim() : null
|
|
36139
36281
|
});
|
|
@@ -36142,7 +36284,7 @@ async function getWorkingTreeChangeRepoDetails(options) {
|
|
|
36142
36284
|
return out;
|
|
36143
36285
|
}
|
|
36144
36286
|
|
|
36145
|
-
// src/git/commit-and-push.ts
|
|
36287
|
+
// src/git/branches/commit-and-push.ts
|
|
36146
36288
|
async function gitCommitAllIfDirty(repoDir, message, options) {
|
|
36147
36289
|
const g = cliSimpleGit(repoDir);
|
|
36148
36290
|
const st = await g.status();
|
|
@@ -36566,7 +36708,8 @@ var SessionWorktreeManager = class {
|
|
|
36566
36708
|
sessionWorktreeRootPath: sessionWorkingTreeRelRoot,
|
|
36567
36709
|
legacyRepoNestedSessionLayout: legacyNested,
|
|
36568
36710
|
repoFilterRelPath: opts?.repoRelPath?.trim() ? opts.repoRelPath.trim() : null,
|
|
36569
|
-
basis: opts?.basis
|
|
36711
|
+
basis: opts?.basis,
|
|
36712
|
+
recentCommitsLimit: opts?.recentCommitsLimit
|
|
36570
36713
|
});
|
|
36571
36714
|
}
|
|
36572
36715
|
async pushSessionUpstream(sessionId) {
|
|
@@ -37096,7 +37239,7 @@ function pipedStdoutStderrFor(attemptStdio) {
|
|
|
37096
37239
|
}
|
|
37097
37240
|
|
|
37098
37241
|
// src/dev-servers/manager/shell-spawn/try-spawn-piped-via-sh.ts
|
|
37099
|
-
import { spawn as
|
|
37242
|
+
import { spawn as spawn5 } from "node:child_process";
|
|
37100
37243
|
function trySpawnPipedViaSh(command, env, cwd, signal) {
|
|
37101
37244
|
const attempts = [
|
|
37102
37245
|
{ stdio: [devNullReadFd(), "pipe", "pipe"], endStdin: false },
|
|
@@ -37117,9 +37260,9 @@ function trySpawnPipedViaSh(command, env, cwd, signal) {
|
|
|
37117
37260
|
if (process.platform === "win32") {
|
|
37118
37261
|
opts.windowsHide = true;
|
|
37119
37262
|
const com = process.env.ComSpec || "cmd.exe";
|
|
37120
|
-
proc =
|
|
37263
|
+
proc = spawn5(com, ["/d", "/s", "/c", command], opts);
|
|
37121
37264
|
} else {
|
|
37122
|
-
proc =
|
|
37265
|
+
proc = spawn5("/bin/sh", ["-c", command], opts);
|
|
37123
37266
|
}
|
|
37124
37267
|
if (attempt.endStdin) {
|
|
37125
37268
|
proc.stdin?.end();
|
|
@@ -37139,7 +37282,7 @@ function trySpawnPipedViaSh(command, env, cwd, signal) {
|
|
|
37139
37282
|
}
|
|
37140
37283
|
|
|
37141
37284
|
// src/dev-servers/manager/shell-spawn/try-spawn-shell-true-piped.ts
|
|
37142
|
-
import { spawn as
|
|
37285
|
+
import { spawn as spawn6 } from "node:child_process";
|
|
37143
37286
|
function trySpawnShellTruePiped(command, env, cwd, devNullFd, signal) {
|
|
37144
37287
|
try {
|
|
37145
37288
|
const opts = {
|
|
@@ -37152,7 +37295,7 @@ function trySpawnShellTruePiped(command, env, cwd, devNullFd, signal) {
|
|
|
37152
37295
|
if (process.platform === "win32") {
|
|
37153
37296
|
opts.windowsHide = true;
|
|
37154
37297
|
}
|
|
37155
|
-
return
|
|
37298
|
+
return spawn6(command, opts);
|
|
37156
37299
|
} catch (e) {
|
|
37157
37300
|
if (isSpawnEbadf(e)) return null;
|
|
37158
37301
|
throw e;
|
|
@@ -37160,7 +37303,7 @@ function trySpawnShellTruePiped(command, env, cwd, devNullFd, signal) {
|
|
|
37160
37303
|
}
|
|
37161
37304
|
|
|
37162
37305
|
// src/dev-servers/manager/shell-spawn/try-spawn-merged-log-file.ts
|
|
37163
|
-
import { spawn as
|
|
37306
|
+
import { spawn as spawn7 } from "node:child_process";
|
|
37164
37307
|
import fs29 from "node:fs";
|
|
37165
37308
|
import { tmpdir } from "node:os";
|
|
37166
37309
|
import path32 from "node:path";
|
|
@@ -37178,7 +37321,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
37178
37321
|
try {
|
|
37179
37322
|
let proc;
|
|
37180
37323
|
if (process.platform === "win32") {
|
|
37181
|
-
proc =
|
|
37324
|
+
proc = spawn7(process.env.ComSpec || "cmd.exe", ["/d", "/s", "/c", command], {
|
|
37182
37325
|
env,
|
|
37183
37326
|
cwd,
|
|
37184
37327
|
stdio,
|
|
@@ -37186,7 +37329,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
37186
37329
|
...signal ? { signal } : {}
|
|
37187
37330
|
});
|
|
37188
37331
|
} else {
|
|
37189
|
-
proc =
|
|
37332
|
+
proc = spawn7("/bin/sh", ["-c", command], { env, cwd, stdio, ...signal ? { signal } : {} });
|
|
37190
37333
|
}
|
|
37191
37334
|
fs29.closeSync(logFd);
|
|
37192
37335
|
return {
|
|
@@ -37207,7 +37350,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
37207
37350
|
}
|
|
37208
37351
|
|
|
37209
37352
|
// src/dev-servers/manager/shell-spawn/try-spawn-shell-script-log-redirect.ts
|
|
37210
|
-
import { spawn as
|
|
37353
|
+
import { spawn as spawn8 } from "node:child_process";
|
|
37211
37354
|
import fs30 from "node:fs";
|
|
37212
37355
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
37213
37356
|
import path33 from "node:path";
|
|
@@ -37230,7 +37373,7 @@ cd ${shSingleQuote(cwd)}
|
|
|
37230
37373
|
/bin/sh ${shSingleQuote(innerPath)} >>${shSingleQuote(logPath)} 2>&1
|
|
37231
37374
|
`
|
|
37232
37375
|
);
|
|
37233
|
-
const proc =
|
|
37376
|
+
const proc = spawn8("/bin/sh", [runnerPath], {
|
|
37234
37377
|
env,
|
|
37235
37378
|
cwd: tmpRoot,
|
|
37236
37379
|
stdio: "ignore",
|
|
@@ -37262,7 +37405,7 @@ CD /D ${q(cwd)}\r
|
|
|
37262
37405
|
${command} >> ${q(logPath)} 2>&1\r
|
|
37263
37406
|
`
|
|
37264
37407
|
);
|
|
37265
|
-
const proc =
|
|
37408
|
+
const proc = spawn8(com, ["/d", "/s", "/c", q(runnerPath)], {
|
|
37266
37409
|
env,
|
|
37267
37410
|
cwd: tmpRoot,
|
|
37268
37411
|
stdio: "ignore",
|
|
@@ -37283,7 +37426,7 @@ ${command} >> ${q(logPath)} 2>&1\r
|
|
|
37283
37426
|
}
|
|
37284
37427
|
|
|
37285
37428
|
// src/dev-servers/manager/shell-spawn/try-spawn-inherit.ts
|
|
37286
|
-
import { spawn as
|
|
37429
|
+
import { spawn as spawn9 } from "node:child_process";
|
|
37287
37430
|
function trySpawnInheritStdio(command, env, cwd, signal) {
|
|
37288
37431
|
const opts = {
|
|
37289
37432
|
env,
|
|
@@ -37295,9 +37438,9 @@ function trySpawnInheritStdio(command, env, cwd, signal) {
|
|
|
37295
37438
|
if (process.platform === "win32") {
|
|
37296
37439
|
opts.windowsHide = true;
|
|
37297
37440
|
const com = process.env.ComSpec || "cmd.exe";
|
|
37298
|
-
proc =
|
|
37441
|
+
proc = spawn9(com, ["/d", "/s", "/c", command], opts);
|
|
37299
37442
|
} else {
|
|
37300
|
-
proc =
|
|
37443
|
+
proc = spawn9("/bin/sh", ["-c", command], opts);
|
|
37301
37444
|
}
|
|
37302
37445
|
return { proc, pipedStdoutStderr: false };
|
|
37303
37446
|
}
|
|
@@ -38027,11 +38170,13 @@ function connectFirehose(options) {
|
|
|
38027
38170
|
if (Buffer.isBuffer(raw) && tryConsumeBinaryProxyBody(raw, deps)) {
|
|
38028
38171
|
return;
|
|
38029
38172
|
}
|
|
38030
|
-
|
|
38031
|
-
|
|
38032
|
-
|
|
38033
|
-
|
|
38034
|
-
|
|
38173
|
+
setImmediate(() => {
|
|
38174
|
+
try {
|
|
38175
|
+
const text = Buffer.isBuffer(raw) ? raw.toString("utf8") : String(raw);
|
|
38176
|
+
dispatchFirehoseJsonMessage(JSON.parse(text), deps);
|
|
38177
|
+
} catch {
|
|
38178
|
+
}
|
|
38179
|
+
});
|
|
38035
38180
|
});
|
|
38036
38181
|
ws.on("close", (code, reason) => {
|
|
38037
38182
|
disposeClientPing();
|
|
@@ -38547,7 +38692,9 @@ async function runLocalRevertBeforeQueuedPrompt(next, deps) {
|
|
|
38547
38692
|
const tid = typeof pl.snapshotRevertTurnId === "string" && pl.snapshotRevertTurnId.trim() !== "" ? pl.snapshotRevertTurnId.trim() : next.turnId;
|
|
38548
38693
|
const agentBase = deps.sessionWorktreeManager.getSessionWorktreeRootForSession(sid) ?? getBridgeRoot();
|
|
38549
38694
|
const file2 = snapshotFilePath(agentBase, tid);
|
|
38550
|
-
|
|
38695
|
+
try {
|
|
38696
|
+
await fs32.promises.access(file2, fs32.constants.F_OK);
|
|
38697
|
+
} catch {
|
|
38551
38698
|
deps.log(
|
|
38552
38699
|
`[Queue] requeued_with_revert: no pre-turn snapshot for ${tid.slice(0, 8)}\u2026; continuing without revert.`
|
|
38553
38700
|
);
|
|
@@ -38721,12 +38868,12 @@ function createBridgePromptSenders(deps, getWs) {
|
|
|
38721
38868
|
}
|
|
38722
38869
|
|
|
38723
38870
|
// src/agents/acp/from-bridge/bridge-prompt-preamble.ts
|
|
38724
|
-
import { execFile as
|
|
38725
|
-
import { promisify as
|
|
38726
|
-
var
|
|
38871
|
+
import { execFile as execFile8 } from "node:child_process";
|
|
38872
|
+
import { promisify as promisify8 } from "node:util";
|
|
38873
|
+
var execFileAsync7 = promisify8(execFile8);
|
|
38727
38874
|
async function readGitBranch(cwd) {
|
|
38728
38875
|
try {
|
|
38729
|
-
const { stdout } = await
|
|
38876
|
+
const { stdout } = await execFileAsync7("git", ["branch", "--show-current"], { cwd, maxBuffer: 64 * 1024 });
|
|
38730
38877
|
const b = stdout.trim();
|
|
38731
38878
|
return b || null;
|
|
38732
38879
|
} catch {
|
|
@@ -38974,7 +39121,7 @@ var handleSessionRequestResponseMessage = (msg, deps) => {
|
|
|
38974
39121
|
};
|
|
38975
39122
|
|
|
38976
39123
|
// src/skills/preview.ts
|
|
38977
|
-
import { spawn as
|
|
39124
|
+
import { spawn as spawn10 } from "node:child_process";
|
|
38978
39125
|
var PREVIEW_API_BASE_PATH = "/__preview";
|
|
38979
39126
|
var PREVIEW_SECRET_HEADER = "X-Preview-Secret";
|
|
38980
39127
|
var DEFAULT_PORT = 3e3;
|
|
@@ -39053,7 +39200,7 @@ var previewSkill = {
|
|
|
39053
39200
|
const parts = command.split(/\s+/);
|
|
39054
39201
|
const exe = parts[0];
|
|
39055
39202
|
const args = parts.slice(1);
|
|
39056
|
-
previewProcess =
|
|
39203
|
+
previewProcess = spawn10(isWindows && exe === "npm" ? "npm.cmd" : exe, args, {
|
|
39057
39204
|
cwd: getBridgeRoot(),
|
|
39058
39205
|
stdio: ["ignore", "pipe", "pipe"],
|
|
39059
39206
|
env: {
|
|
@@ -39610,7 +39757,8 @@ var handleSessionGitRequestMessage = (msg, deps) => {
|
|
|
39610
39757
|
reply({
|
|
39611
39758
|
ok: true,
|
|
39612
39759
|
hasUncommittedChanges: r.hasUncommittedChanges,
|
|
39613
|
-
hasUnpushedCommits: r.hasUnpushedCommits
|
|
39760
|
+
hasUnpushedCommits: r.hasUnpushedCommits,
|
|
39761
|
+
uncommittedFileCount: r.uncommittedFileCount
|
|
39614
39762
|
});
|
|
39615
39763
|
return;
|
|
39616
39764
|
}
|
|
@@ -39624,7 +39772,12 @@ var handleSessionGitRequestMessage = (msg, deps) => {
|
|
|
39624
39772
|
return;
|
|
39625
39773
|
}
|
|
39626
39774
|
}
|
|
39627
|
-
const
|
|
39775
|
+
const recentCommitsLimit = typeof msg.changesRecentCommitsLimit === "number" || typeof msg.changesRecentCommitsLimit === "string" ? msg.changesRecentCommitsLimit : void 0;
|
|
39776
|
+
const opts = repoRel && view === "commit" && commitSha ? {
|
|
39777
|
+
repoRelPath: repoRel,
|
|
39778
|
+
basis: { kind: "commit", sha: commitSha },
|
|
39779
|
+
recentCommitsLimit
|
|
39780
|
+
} : repoRel ? { repoRelPath: repoRel, basis: { kind: "working" }, recentCommitsLimit } : recentCommitsLimit !== void 0 ? { recentCommitsLimit } : void 0;
|
|
39628
39781
|
const repos = await deps.sessionWorktreeManager.getSessionWorkingTreeChangeDetails(sessionId, opts);
|
|
39629
39782
|
reply({
|
|
39630
39783
|
ok: true,
|
|
@@ -39642,7 +39795,8 @@ var handleSessionGitRequestMessage = (msg, deps) => {
|
|
|
39642
39795
|
reply({
|
|
39643
39796
|
ok: true,
|
|
39644
39797
|
hasUncommittedChanges: st2.hasUncommittedChanges,
|
|
39645
|
-
hasUnpushedCommits: st2.hasUnpushedCommits
|
|
39798
|
+
hasUnpushedCommits: st2.hasUnpushedCommits,
|
|
39799
|
+
uncommittedFileCount: st2.uncommittedFileCount
|
|
39646
39800
|
});
|
|
39647
39801
|
return;
|
|
39648
39802
|
}
|
|
@@ -39667,7 +39821,8 @@ var handleSessionGitRequestMessage = (msg, deps) => {
|
|
|
39667
39821
|
reply({
|
|
39668
39822
|
ok: true,
|
|
39669
39823
|
hasUncommittedChanges: st.hasUncommittedChanges,
|
|
39670
|
-
hasUnpushedCommits: st.hasUnpushedCommits
|
|
39824
|
+
hasUnpushedCommits: st.hasUnpushedCommits,
|
|
39825
|
+
uncommittedFileCount: st.uncommittedFileCount
|
|
39671
39826
|
});
|
|
39672
39827
|
} catch (e) {
|
|
39673
39828
|
reply({ ok: false, error: e instanceof Error ? e.message : String(e) });
|
|
@@ -39710,7 +39865,9 @@ var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
|
39710
39865
|
if (!s) return;
|
|
39711
39866
|
const agentBase = sessionWorktreeManager.getSessionWorktreeRootForSession(sessionId) ?? getBridgeRoot();
|
|
39712
39867
|
const file2 = snapshotFilePath(agentBase, turnId);
|
|
39713
|
-
|
|
39868
|
+
try {
|
|
39869
|
+
await fs36.promises.access(file2, fs36.constants.F_OK);
|
|
39870
|
+
} catch {
|
|
39714
39871
|
sendWsMessage(s, {
|
|
39715
39872
|
type: "revert_turn_snapshot_result",
|
|
39716
39873
|
id,
|
|
@@ -39829,9 +39986,7 @@ function handleBridgeMessage(data, deps) {
|
|
|
39829
39986
|
if (!deps.getWs()) return;
|
|
39830
39987
|
const msg = parseApiToBridgeMessage(normalizeInboundBridgeWebSocketJson(data), deps.log);
|
|
39831
39988
|
if (!msg) return;
|
|
39832
|
-
|
|
39833
|
-
dispatchBridgeMessage(msg, deps);
|
|
39834
|
-
});
|
|
39989
|
+
dispatchBridgeMessage(msg, deps);
|
|
39835
39990
|
}
|
|
39836
39991
|
|
|
39837
39992
|
// src/auth/refresh-bridge-tokens.ts
|
|
@@ -40397,25 +40552,27 @@ async function createBridgeConnection(options) {
|
|
|
40397
40552
|
}
|
|
40398
40553
|
function sendAgentCapabilitiesToBridge(info) {
|
|
40399
40554
|
if (!Array.isArray(info.configOptions) || info.configOptions.length === 0) return;
|
|
40400
|
-
|
|
40401
|
-
|
|
40402
|
-
|
|
40403
|
-
|
|
40404
|
-
|
|
40405
|
-
|
|
40406
|
-
|
|
40407
|
-
|
|
40408
|
-
|
|
40409
|
-
|
|
40410
|
-
|
|
40411
|
-
|
|
40412
|
-
|
|
40413
|
-
|
|
40414
|
-
|
|
40415
|
-
|
|
40416
|
-
|
|
40417
|
-
|
|
40418
|
-
|
|
40555
|
+
setImmediate(() => {
|
|
40556
|
+
let changed = false;
|
|
40557
|
+
try {
|
|
40558
|
+
changed = withCliSqliteSync(
|
|
40559
|
+
(db) => upsertCliAgentCapabilityCache(db, {
|
|
40560
|
+
workspaceId,
|
|
40561
|
+
agentType: info.agentType,
|
|
40562
|
+
configOptions: info.configOptions
|
|
40563
|
+
})
|
|
40564
|
+
);
|
|
40565
|
+
} catch (e) {
|
|
40566
|
+
if (e instanceof CliSqliteInterrupted) return;
|
|
40567
|
+
}
|
|
40568
|
+
if (!changed) return;
|
|
40569
|
+
const socket = getWs();
|
|
40570
|
+
if (!socket || socket.readyState !== wrapper_default.OPEN) return;
|
|
40571
|
+
sendWsMessage(socket, {
|
|
40572
|
+
type: "agent_capabilities",
|
|
40573
|
+
agentType: info.agentType,
|
|
40574
|
+
configOptions: info.configOptions
|
|
40575
|
+
});
|
|
40419
40576
|
});
|
|
40420
40577
|
}
|
|
40421
40578
|
const worktreesRootPath = options.worktreesRootPath ?? defaultWorktreesRootPath();
|
|
@@ -40567,6 +40724,7 @@ async function runConnectedBridge(options, restartWithoutAuth) {
|
|
|
40567
40724
|
let bridgeClose = null;
|
|
40568
40725
|
const onSignal = (kind) => {
|
|
40569
40726
|
requestCliImmediateShutdown();
|
|
40727
|
+
abortActiveGitChildProcesses();
|
|
40570
40728
|
cleanupKeyCommand?.();
|
|
40571
40729
|
logImmediate(
|
|
40572
40730
|
kind === "interrupt" ? "Keyboard interrupt (Ctrl+C) \u2014 stopping\u2026" : "Stop requested \u2014 shutting down\u2026"
|