@buildautomaton/cli 0.1.24 → 0.1.25
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 +867 -600
- package/dist/cli.js.map +4 -4
- package/dist/index.js +1009 -747
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4065,8 +4065,8 @@ var init_parseUtil = __esm({
|
|
|
4065
4065
|
init_errors();
|
|
4066
4066
|
init_en();
|
|
4067
4067
|
makeIssue = (params) => {
|
|
4068
|
-
const { data, path:
|
|
4069
|
-
const fullPath = [...
|
|
4068
|
+
const { data, path: path35, errorMaps, issueData } = params;
|
|
4069
|
+
const fullPath = [...path35, ...issueData.path || []];
|
|
4070
4070
|
const fullIssue = {
|
|
4071
4071
|
...issueData,
|
|
4072
4072
|
path: fullPath
|
|
@@ -4374,11 +4374,11 @@ var init_types = __esm({
|
|
|
4374
4374
|
init_parseUtil();
|
|
4375
4375
|
init_util();
|
|
4376
4376
|
ParseInputLazyPath = class {
|
|
4377
|
-
constructor(parent, value,
|
|
4377
|
+
constructor(parent, value, path35, key) {
|
|
4378
4378
|
this._cachedPath = [];
|
|
4379
4379
|
this.parent = parent;
|
|
4380
4380
|
this.data = value;
|
|
4381
|
-
this._path =
|
|
4381
|
+
this._path = path35;
|
|
4382
4382
|
this._key = key;
|
|
4383
4383
|
}
|
|
4384
4384
|
get path() {
|
|
@@ -7993,10 +7993,10 @@ function assignProp(target, prop, value) {
|
|
|
7993
7993
|
configurable: true
|
|
7994
7994
|
});
|
|
7995
7995
|
}
|
|
7996
|
-
function getElementAtPath(obj,
|
|
7997
|
-
if (!
|
|
7996
|
+
function getElementAtPath(obj, path35) {
|
|
7997
|
+
if (!path35)
|
|
7998
7998
|
return obj;
|
|
7999
|
-
return
|
|
7999
|
+
return path35.reduce((acc, key) => acc?.[key], obj);
|
|
8000
8000
|
}
|
|
8001
8001
|
function promiseAllObject(promisesObj) {
|
|
8002
8002
|
const keys = Object.keys(promisesObj);
|
|
@@ -8245,11 +8245,11 @@ function aborted(x, startIndex = 0) {
|
|
|
8245
8245
|
}
|
|
8246
8246
|
return false;
|
|
8247
8247
|
}
|
|
8248
|
-
function prefixIssues(
|
|
8248
|
+
function prefixIssues(path35, issues) {
|
|
8249
8249
|
return issues.map((iss) => {
|
|
8250
8250
|
var _a2;
|
|
8251
8251
|
(_a2 = iss).path ?? (_a2.path = []);
|
|
8252
|
-
iss.path.unshift(
|
|
8252
|
+
iss.path.unshift(path35);
|
|
8253
8253
|
return iss;
|
|
8254
8254
|
});
|
|
8255
8255
|
}
|
|
@@ -8438,7 +8438,7 @@ function treeifyError(error40, _mapper) {
|
|
|
8438
8438
|
return issue2.message;
|
|
8439
8439
|
};
|
|
8440
8440
|
const result = { errors: [] };
|
|
8441
|
-
const processError = (error41,
|
|
8441
|
+
const processError = (error41, path35 = []) => {
|
|
8442
8442
|
var _a2, _b;
|
|
8443
8443
|
for (const issue2 of error41.issues) {
|
|
8444
8444
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -8448,7 +8448,7 @@ function treeifyError(error40, _mapper) {
|
|
|
8448
8448
|
} else if (issue2.code === "invalid_element") {
|
|
8449
8449
|
processError({ issues: issue2.issues }, issue2.path);
|
|
8450
8450
|
} else {
|
|
8451
|
-
const fullpath = [...
|
|
8451
|
+
const fullpath = [...path35, ...issue2.path];
|
|
8452
8452
|
if (fullpath.length === 0) {
|
|
8453
8453
|
result.errors.push(mapper(issue2));
|
|
8454
8454
|
continue;
|
|
@@ -8478,9 +8478,9 @@ function treeifyError(error40, _mapper) {
|
|
|
8478
8478
|
processError(error40);
|
|
8479
8479
|
return result;
|
|
8480
8480
|
}
|
|
8481
|
-
function toDotPath(
|
|
8481
|
+
function toDotPath(path35) {
|
|
8482
8482
|
const segs = [];
|
|
8483
|
-
for (const seg of
|
|
8483
|
+
for (const seg of path35) {
|
|
8484
8484
|
if (typeof seg === "number")
|
|
8485
8485
|
segs.push(`[${seg}]`);
|
|
8486
8486
|
else if (typeof seg === "symbol")
|
|
@@ -21669,7 +21669,7 @@ var require_has_flag = __commonJS({
|
|
|
21669
21669
|
var require_supports_color = __commonJS({
|
|
21670
21670
|
"../../node_modules/.pnpm/supports-color@7.2.0/node_modules/supports-color/index.js"(exports, module) {
|
|
21671
21671
|
"use strict";
|
|
21672
|
-
var
|
|
21672
|
+
var os8 = __require("os");
|
|
21673
21673
|
var tty = __require("tty");
|
|
21674
21674
|
var hasFlag = require_has_flag();
|
|
21675
21675
|
var { env } = process;
|
|
@@ -21717,7 +21717,7 @@ var require_supports_color = __commonJS({
|
|
|
21717
21717
|
return min;
|
|
21718
21718
|
}
|
|
21719
21719
|
if (process.platform === "win32") {
|
|
21720
|
-
const osRelease =
|
|
21720
|
+
const osRelease = os8.release().split(".");
|
|
21721
21721
|
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
|
|
21722
21722
|
return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
21723
21723
|
}
|
|
@@ -21963,10 +21963,10 @@ var require_src2 = __commonJS({
|
|
|
21963
21963
|
var fs_1 = __require("fs");
|
|
21964
21964
|
var debug_1 = __importDefault(require_src());
|
|
21965
21965
|
var log2 = debug_1.default("@kwsites/file-exists");
|
|
21966
|
-
function check2(
|
|
21967
|
-
log2(`checking %s`,
|
|
21966
|
+
function check2(path35, isFile, isDirectory) {
|
|
21967
|
+
log2(`checking %s`, path35);
|
|
21968
21968
|
try {
|
|
21969
|
-
const stat2 = fs_1.statSync(
|
|
21969
|
+
const stat2 = fs_1.statSync(path35);
|
|
21970
21970
|
if (stat2.isFile() && isFile) {
|
|
21971
21971
|
log2(`[OK] path represents a file`);
|
|
21972
21972
|
return true;
|
|
@@ -21986,8 +21986,8 @@ var require_src2 = __commonJS({
|
|
|
21986
21986
|
throw e;
|
|
21987
21987
|
}
|
|
21988
21988
|
}
|
|
21989
|
-
function exists2(
|
|
21990
|
-
return check2(
|
|
21989
|
+
function exists2(path35, type = exports.READABLE) {
|
|
21990
|
+
return check2(path35, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
|
|
21991
21991
|
}
|
|
21992
21992
|
exports.exists = exists2;
|
|
21993
21993
|
exports.FILE = 1;
|
|
@@ -22189,6 +22189,309 @@ function sendWsMessage(ws, payload) {
|
|
|
22189
22189
|
}
|
|
22190
22190
|
}
|
|
22191
22191
|
|
|
22192
|
+
// src/lib/local-agent-auth.ts
|
|
22193
|
+
var LOCAL_AGENT_AUTH_ERROR_HINTS = {
|
|
22194
|
+
"kiro-acp": [/not logged in/i, /kiro-cli\s+login/i, /log in with kiro-cli/i],
|
|
22195
|
+
"cursor-cli": [/cursor_login/i, /authenticate.*cursor/i, /not logged in.*cursor/i, /run:\s*agent\s+login/i],
|
|
22196
|
+
"codex-acp": [
|
|
22197
|
+
/authentication failed/i,
|
|
22198
|
+
/not authenticated/i,
|
|
22199
|
+
/invalid.*api key/i,
|
|
22200
|
+
/sign in.*openai/i,
|
|
22201
|
+
/login.*openai/i,
|
|
22202
|
+
/unauthorized/i
|
|
22203
|
+
],
|
|
22204
|
+
"claude-code": [
|
|
22205
|
+
/ANTHROPIC_API_KEY/i,
|
|
22206
|
+
/not authenticated/i,
|
|
22207
|
+
/authentication failed/i,
|
|
22208
|
+
/claude\s+login/i,
|
|
22209
|
+
/please run.*claude.*login/i
|
|
22210
|
+
]
|
|
22211
|
+
};
|
|
22212
|
+
function localAgentErrorSuggestsAuth(agentType, errorText) {
|
|
22213
|
+
if (agentType == null || agentType === "" || errorText == null || !String(errorText).trim()) return false;
|
|
22214
|
+
const hints = LOCAL_AGENT_AUTH_ERROR_HINTS[agentType];
|
|
22215
|
+
if (!hints?.length) return false;
|
|
22216
|
+
return hints.some((re) => re.test(String(errorText)));
|
|
22217
|
+
}
|
|
22218
|
+
|
|
22219
|
+
// src/agents/acp/clients/sdk/sdk-stdio-acp-client.ts
|
|
22220
|
+
import { spawn } from "node:child_process";
|
|
22221
|
+
import { Readable, Writable } from "node:stream";
|
|
22222
|
+
|
|
22223
|
+
// src/files/cwd/bridge-root.ts
|
|
22224
|
+
import * as path from "node:path";
|
|
22225
|
+
var bridgeRootPath = null;
|
|
22226
|
+
function getBridgeRoot() {
|
|
22227
|
+
if (bridgeRootPath == null) {
|
|
22228
|
+
bridgeRootPath = path.resolve(process.cwd());
|
|
22229
|
+
}
|
|
22230
|
+
return bridgeRootPath;
|
|
22231
|
+
}
|
|
22232
|
+
|
|
22233
|
+
// src/agents/acp/clients/agent-stderr-capture.ts
|
|
22234
|
+
var STDERR_CAPTURE_MAX = 48e3;
|
|
22235
|
+
function createStderrCapture(child) {
|
|
22236
|
+
const chunks = [];
|
|
22237
|
+
let total = 0;
|
|
22238
|
+
return {
|
|
22239
|
+
append(chunk) {
|
|
22240
|
+
try {
|
|
22241
|
+
process.stderr.write(chunk);
|
|
22242
|
+
} catch {
|
|
22243
|
+
}
|
|
22244
|
+
if (total >= STDERR_CAPTURE_MAX) return;
|
|
22245
|
+
const n = Math.min(chunk.length, STDERR_CAPTURE_MAX - total);
|
|
22246
|
+
if (n <= 0) return;
|
|
22247
|
+
chunks.push(n === chunk.length ? chunk : chunk.subarray(0, n));
|
|
22248
|
+
total += n;
|
|
22249
|
+
},
|
|
22250
|
+
getText() {
|
|
22251
|
+
return Buffer.concat(chunks).toString("utf8").trim();
|
|
22252
|
+
}
|
|
22253
|
+
};
|
|
22254
|
+
}
|
|
22255
|
+
function formatJsonRpcStyleError(err) {
|
|
22256
|
+
if (err instanceof Error) return err.message;
|
|
22257
|
+
if (err != null && typeof err === "object") {
|
|
22258
|
+
const o = err;
|
|
22259
|
+
const msg = typeof o.message === "string" ? o.message : null;
|
|
22260
|
+
const code = o.code != null ? String(o.code) : "";
|
|
22261
|
+
if (msg) return code ? `[${code}] ${msg}` : msg;
|
|
22262
|
+
}
|
|
22263
|
+
if (typeof err === "string") return err;
|
|
22264
|
+
try {
|
|
22265
|
+
return JSON.stringify(err);
|
|
22266
|
+
} catch {
|
|
22267
|
+
return String(err);
|
|
22268
|
+
}
|
|
22269
|
+
}
|
|
22270
|
+
function mergeErrorWithStderr(primary, stderrText) {
|
|
22271
|
+
const s = stderrText.trim();
|
|
22272
|
+
const p = (primary ?? "").trim();
|
|
22273
|
+
if (!s) return p;
|
|
22274
|
+
if (!p) return s;
|
|
22275
|
+
if (p.includes(s) || s.includes(p)) return p.length >= s.length ? p : s;
|
|
22276
|
+
return `${p}
|
|
22277
|
+
${s}`;
|
|
22278
|
+
}
|
|
22279
|
+
|
|
22280
|
+
// src/agents/acp/clients/kiro-sdk-ext-notifications.ts
|
|
22281
|
+
function createKiroSdkExtNotificationHandler(options) {
|
|
22282
|
+
const { onSessionUpdate } = options;
|
|
22283
|
+
return async (method, params) => {
|
|
22284
|
+
if (method === "_kiro.dev/metadata") {
|
|
22285
|
+
const p = params && typeof params === "object" ? params : {};
|
|
22286
|
+
const pct = p.contextUsagePercentage;
|
|
22287
|
+
if (typeof pct !== "number" || !Number.isFinite(pct) || !onSessionUpdate) return;
|
|
22288
|
+
onSessionUpdate({
|
|
22289
|
+
sessionUpdate: "context_usage",
|
|
22290
|
+
contextUsagePercentage: pct
|
|
22291
|
+
});
|
|
22292
|
+
return;
|
|
22293
|
+
}
|
|
22294
|
+
};
|
|
22295
|
+
}
|
|
22296
|
+
|
|
22297
|
+
// src/agents/acp/clients/sdk/sdk-stdio-ext-notifications.ts
|
|
22298
|
+
var noopExtNotification = async () => {
|
|
22299
|
+
};
|
|
22300
|
+
function createSdkStdioExtNotificationHandler(options) {
|
|
22301
|
+
const { backendAgentType, onSessionUpdate } = options;
|
|
22302
|
+
switch (backendAgentType) {
|
|
22303
|
+
case "kiro-acp":
|
|
22304
|
+
return createKiroSdkExtNotificationHandler({ onSessionUpdate });
|
|
22305
|
+
default:
|
|
22306
|
+
return noopExtNotification;
|
|
22307
|
+
}
|
|
22308
|
+
}
|
|
22309
|
+
|
|
22310
|
+
// src/agents/acp/enrich-acp-permission-rpc-result.ts
|
|
22311
|
+
var META_KEY = "permissionOptionKind";
|
|
22312
|
+
function optionRecordId(rec) {
|
|
22313
|
+
const raw = rec.optionId ?? rec.id;
|
|
22314
|
+
if (typeof raw === "string" && raw.trim() !== "") return raw.trim();
|
|
22315
|
+
if (typeof raw === "number" && Number.isFinite(raw)) return String(raw);
|
|
22316
|
+
return "";
|
|
22317
|
+
}
|
|
22318
|
+
function enrichAcpPermissionRpcResultFromRequestParams(result, params) {
|
|
22319
|
+
if (params == null || result == null || typeof result !== "object" || Array.isArray(result)) {
|
|
22320
|
+
return result;
|
|
22321
|
+
}
|
|
22322
|
+
const root = result;
|
|
22323
|
+
const outcome = root.outcome;
|
|
22324
|
+
if (outcome == null || typeof outcome !== "object" || Array.isArray(outcome)) return result;
|
|
22325
|
+
const o = outcome;
|
|
22326
|
+
if (o.outcome !== "selected" || typeof o.optionId !== "string" || o.optionId.trim() === "") {
|
|
22327
|
+
return result;
|
|
22328
|
+
}
|
|
22329
|
+
const selectedId = o.optionId.trim();
|
|
22330
|
+
const prevMeta = o._meta != null && typeof o._meta === "object" && !Array.isArray(o._meta) ? o._meta : {};
|
|
22331
|
+
if (typeof prevMeta[META_KEY] === "string" && prevMeta[META_KEY].trim() !== "") {
|
|
22332
|
+
return result;
|
|
22333
|
+
}
|
|
22334
|
+
const rawOpts = Array.isArray(params.options) ? params.options : [];
|
|
22335
|
+
let matchedKind;
|
|
22336
|
+
for (const item of rawOpts) {
|
|
22337
|
+
if (item == null || typeof item !== "object" || Array.isArray(item)) continue;
|
|
22338
|
+
const rec = item;
|
|
22339
|
+
const id = optionRecordId(rec);
|
|
22340
|
+
if (!id || id !== selectedId) continue;
|
|
22341
|
+
if (typeof rec.kind === "string" && rec.kind.trim() !== "") {
|
|
22342
|
+
matchedKind = rec.kind.trim();
|
|
22343
|
+
break;
|
|
22344
|
+
}
|
|
22345
|
+
}
|
|
22346
|
+
if (!matchedKind) return result;
|
|
22347
|
+
return {
|
|
22348
|
+
...root,
|
|
22349
|
+
outcome: {
|
|
22350
|
+
...o,
|
|
22351
|
+
_meta: { ...prevMeta, [META_KEY]: matchedKind }
|
|
22352
|
+
}
|
|
22353
|
+
};
|
|
22354
|
+
}
|
|
22355
|
+
|
|
22356
|
+
// src/cli-log-level.ts
|
|
22357
|
+
var verbosity = "info";
|
|
22358
|
+
function setCliLogVerbosity(level) {
|
|
22359
|
+
verbosity = level;
|
|
22360
|
+
}
|
|
22361
|
+
function getCliLogVerbosity() {
|
|
22362
|
+
return verbosity;
|
|
22363
|
+
}
|
|
22364
|
+
function isCliTrace() {
|
|
22365
|
+
return verbosity === "trace";
|
|
22366
|
+
}
|
|
22367
|
+
|
|
22368
|
+
// src/log.ts
|
|
22369
|
+
function timestampPrefix() {
|
|
22370
|
+
const time3 = (/* @__PURE__ */ new Date()).toISOString().slice(11, 19);
|
|
22371
|
+
return `[${time3}]`;
|
|
22372
|
+
}
|
|
22373
|
+
function log(line) {
|
|
22374
|
+
console.log(`${timestampPrefix()} ${line}`);
|
|
22375
|
+
}
|
|
22376
|
+
function logImmediate(line) {
|
|
22377
|
+
process.stdout.write(`${timestampPrefix()} ${line}
|
|
22378
|
+
`);
|
|
22379
|
+
}
|
|
22380
|
+
function logDebug(line) {
|
|
22381
|
+
const v = getCliLogVerbosity();
|
|
22382
|
+
if (v !== "debug" && v !== "trace") return;
|
|
22383
|
+
console.log(`${timestampPrefix()} [debug] ${line}`);
|
|
22384
|
+
}
|
|
22385
|
+
function logTrace(line) {
|
|
22386
|
+
if (getCliLogVerbosity() !== "trace") return;
|
|
22387
|
+
console.log(`${timestampPrefix()} [trace] ${line}`);
|
|
22388
|
+
}
|
|
22389
|
+
|
|
22390
|
+
// src/agents/acp/clients/shared/acp-fs-read-write.ts
|
|
22391
|
+
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
22392
|
+
import { dirname } from "node:path";
|
|
22393
|
+
|
|
22394
|
+
// src/files/diff/unified-diff.ts
|
|
22395
|
+
function computeLineDiff(oldText, newText) {
|
|
22396
|
+
const oldLines = oldText.split("\n");
|
|
22397
|
+
const newLines = newText.split("\n");
|
|
22398
|
+
const m = oldLines.length;
|
|
22399
|
+
const n = newLines.length;
|
|
22400
|
+
const dp = Array(m + 1);
|
|
22401
|
+
for (let i2 = 0; i2 <= m; i2++) dp[i2] = Array(n + 1).fill(0);
|
|
22402
|
+
for (let i2 = 1; i2 <= m; i2++) {
|
|
22403
|
+
for (let j2 = 1; j2 <= n; j2++) {
|
|
22404
|
+
if (oldLines[i2 - 1] === newLines[j2 - 1]) {
|
|
22405
|
+
dp[i2][j2] = dp[i2 - 1][j2 - 1] + 1;
|
|
22406
|
+
} else {
|
|
22407
|
+
dp[i2][j2] = Math.max(dp[i2 - 1][j2], dp[i2][j2 - 1]);
|
|
22408
|
+
}
|
|
22409
|
+
}
|
|
22410
|
+
}
|
|
22411
|
+
const result = [];
|
|
22412
|
+
let i = m;
|
|
22413
|
+
let j = n;
|
|
22414
|
+
while (i > 0 || j > 0) {
|
|
22415
|
+
if (i > 0 && j > 0 && oldLines[i - 1] === newLines[j - 1]) {
|
|
22416
|
+
result.unshift({ type: "context", line: oldLines[i - 1] });
|
|
22417
|
+
i--;
|
|
22418
|
+
j--;
|
|
22419
|
+
} else if (j > 0 && (i === 0 || dp[i][j - 1] >= dp[i - 1][j])) {
|
|
22420
|
+
result.unshift({ type: "add", line: newLines[j - 1] });
|
|
22421
|
+
j--;
|
|
22422
|
+
} else {
|
|
22423
|
+
result.unshift({ type: "remove", line: oldLines[i - 1] });
|
|
22424
|
+
i--;
|
|
22425
|
+
}
|
|
22426
|
+
}
|
|
22427
|
+
return result;
|
|
22428
|
+
}
|
|
22429
|
+
function editSnippetToUnifiedDiff(filePath, oldText, newText) {
|
|
22430
|
+
const lines = computeLineDiff(oldText, newText);
|
|
22431
|
+
const out = [`--- ${filePath}`, `+++ ${filePath}`];
|
|
22432
|
+
for (const d of lines) {
|
|
22433
|
+
if (d.type === "add") out.push(`+${d.line}`);
|
|
22434
|
+
else if (d.type === "remove") out.push(`-${d.line}`);
|
|
22435
|
+
else out.push(` ${d.line}`);
|
|
22436
|
+
}
|
|
22437
|
+
return out.join("\n");
|
|
22438
|
+
}
|
|
22439
|
+
|
|
22440
|
+
// src/agents/acp/safe-fs-path.ts
|
|
22441
|
+
import * as path2 from "node:path";
|
|
22442
|
+
function resolveSafePathUnderCwd(cwd, filePath) {
|
|
22443
|
+
const trimmed2 = filePath.trim();
|
|
22444
|
+
if (!trimmed2) return null;
|
|
22445
|
+
const normalizedCwd = path2.resolve(cwd);
|
|
22446
|
+
const resolved = path2.isAbsolute(trimmed2) ? path2.normalize(trimmed2) : path2.resolve(normalizedCwd, trimmed2);
|
|
22447
|
+
const rel = path2.relative(normalizedCwd, resolved);
|
|
22448
|
+
if (rel.startsWith("..") || path2.isAbsolute(rel)) return null;
|
|
22449
|
+
return resolved;
|
|
22450
|
+
}
|
|
22451
|
+
function toDisplayPathRelativeToCwd(cwd, absolutePath) {
|
|
22452
|
+
const normalizedCwd = path2.resolve(cwd);
|
|
22453
|
+
const rel = path2.relative(normalizedCwd, path2.resolve(absolutePath));
|
|
22454
|
+
if (!rel || rel === "") return path2.basename(absolutePath);
|
|
22455
|
+
return rel.split(path2.sep).join("/");
|
|
22456
|
+
}
|
|
22457
|
+
|
|
22458
|
+
// src/agents/acp/clients/shared/acp-fs-read-write.ts
|
|
22459
|
+
function sliceFileContentForAcp(content, line, limit) {
|
|
22460
|
+
if (line == null && limit == null) return content;
|
|
22461
|
+
const lines = content.split("\n");
|
|
22462
|
+
const start = line != null && line > 0 ? line - 1 : 0;
|
|
22463
|
+
const end = limit != null && limit > 0 ? start + limit : lines.length;
|
|
22464
|
+
return lines.slice(start, end).join("\n");
|
|
22465
|
+
}
|
|
22466
|
+
function acpReadTextFileInProcess(ctx, filePath, line, limit) {
|
|
22467
|
+
const resolvedPath = resolveSafePathUnderCwd(ctx.cwd, filePath);
|
|
22468
|
+
if (!resolvedPath) throw new Error("Invalid or disallowed path");
|
|
22469
|
+
try {
|
|
22470
|
+
let content = readFileSync(resolvedPath, "utf8");
|
|
22471
|
+
content = sliceFileContentForAcp(content, line, limit);
|
|
22472
|
+
return { content };
|
|
22473
|
+
} catch (e) {
|
|
22474
|
+
if (e.code === "ENOENT") return { content: "" };
|
|
22475
|
+
throw e;
|
|
22476
|
+
}
|
|
22477
|
+
}
|
|
22478
|
+
function acpWriteTextFileInProcess(ctx, filePath, newText) {
|
|
22479
|
+
const resolvedPath = resolveSafePathUnderCwd(ctx.cwd, filePath);
|
|
22480
|
+
if (!resolvedPath) throw new Error("Invalid or disallowed path");
|
|
22481
|
+
let oldText = "";
|
|
22482
|
+
try {
|
|
22483
|
+
oldText = readFileSync(resolvedPath, "utf8");
|
|
22484
|
+
} catch (e) {
|
|
22485
|
+
if (e.code !== "ENOENT") throw e;
|
|
22486
|
+
}
|
|
22487
|
+
mkdirSync(dirname(resolvedPath), { recursive: true });
|
|
22488
|
+
writeFileSync(resolvedPath, newText, "utf8");
|
|
22489
|
+
const displayPath = toDisplayPathRelativeToCwd(ctx.cwd, resolvedPath);
|
|
22490
|
+
const patchContent = editSnippetToUnifiedDiff(displayPath, oldText, newText);
|
|
22491
|
+
ctx.onFileChange?.({ path: displayPath, oldText, newText, patchContent });
|
|
22492
|
+
return {};
|
|
22493
|
+
}
|
|
22494
|
+
|
|
22192
22495
|
// ../types/src/work-items.ts
|
|
22193
22496
|
init_zod();
|
|
22194
22497
|
var WorkItemStatusSchema = external_exports.enum(["backlog", "in-progress", "completed"]);
|
|
@@ -22489,9 +22792,9 @@ function parseChangeSummaryJson(raw, allowedPaths, options) {
|
|
|
22489
22792
|
const rawPath = typeof o.path === "string" ? o.path.trim() : "";
|
|
22490
22793
|
const summary = typeof o.summary === "string" ? o.summary.trim() : "";
|
|
22491
22794
|
if (!rawPath || !summary) continue;
|
|
22492
|
-
const
|
|
22493
|
-
if (!
|
|
22494
|
-
rows.push({ path:
|
|
22795
|
+
const path35 = skip ? normalizeRepoRelativePath(rawPath) || rawPath : resolveChangeSummaryPathAgainstAllowed(rawPath, allowedPaths);
|
|
22796
|
+
if (!path35) continue;
|
|
22797
|
+
rows.push({ path: path35, summary: clampSummaryToAtMostTwoLines(summary) });
|
|
22495
22798
|
}
|
|
22496
22799
|
return rows;
|
|
22497
22800
|
}
|
|
@@ -22640,253 +22943,259 @@ function getClaudePermissionModeFromAgentConfig(config2) {
|
|
|
22640
22943
|
return isClaudeCodePermissionMode(t) ? t : null;
|
|
22641
22944
|
}
|
|
22642
22945
|
|
|
22643
|
-
// src/
|
|
22644
|
-
|
|
22645
|
-
|
|
22646
|
-
|
|
22647
|
-
"
|
|
22648
|
-
|
|
22649
|
-
|
|
22650
|
-
|
|
22651
|
-
|
|
22652
|
-
|
|
22653
|
-
|
|
22654
|
-
|
|
22655
|
-
|
|
22656
|
-
|
|
22657
|
-
|
|
22658
|
-
|
|
22659
|
-
|
|
22660
|
-
|
|
22661
|
-
|
|
22662
|
-
|
|
22663
|
-
|
|
22664
|
-
|
|
22665
|
-
|
|
22666
|
-
|
|
22667
|
-
|
|
22668
|
-
|
|
22669
|
-
|
|
22670
|
-
|
|
22671
|
-
|
|
22672
|
-
|
|
22673
|
-
|
|
22674
|
-
|
|
22675
|
-
|
|
22676
|
-
|
|
22677
|
-
|
|
22678
|
-
const oldLines = oldText.split("\n");
|
|
22679
|
-
const newLines = newText.split("\n");
|
|
22680
|
-
const m = oldLines.length;
|
|
22681
|
-
const n = newLines.length;
|
|
22682
|
-
const dp = Array(m + 1);
|
|
22683
|
-
for (let i2 = 0; i2 <= m; i2++) dp[i2] = Array(n + 1).fill(0);
|
|
22684
|
-
for (let i2 = 1; i2 <= m; i2++) {
|
|
22685
|
-
for (let j2 = 1; j2 <= n; j2++) {
|
|
22686
|
-
if (oldLines[i2 - 1] === newLines[j2 - 1]) {
|
|
22687
|
-
dp[i2][j2] = dp[i2 - 1][j2 - 1] + 1;
|
|
22688
|
-
} else {
|
|
22689
|
-
dp[i2][j2] = Math.max(dp[i2 - 1][j2], dp[i2][j2 - 1]);
|
|
22946
|
+
// src/agents/acp/claude-acp-permission-from-session.ts
|
|
22947
|
+
function flattenSelectOptions(options) {
|
|
22948
|
+
if (options == null || options.length === 0) return [];
|
|
22949
|
+
const first2 = options[0];
|
|
22950
|
+
if (first2 != null && typeof first2 === "object" && "group" in first2 && first2.group != null) {
|
|
22951
|
+
return options.flatMap(
|
|
22952
|
+
(g) => Array.isArray(g.options) ? g.options : []
|
|
22953
|
+
);
|
|
22954
|
+
}
|
|
22955
|
+
return options;
|
|
22956
|
+
}
|
|
22957
|
+
function pickModeConfigOption(configOptions) {
|
|
22958
|
+
if (configOptions == null || configOptions.length === 0) return null;
|
|
22959
|
+
const byCategory = configOptions.find((o) => o.category === "mode");
|
|
22960
|
+
if (byCategory) return byCategory;
|
|
22961
|
+
return configOptions.find((o) => o.id === "mode") ?? null;
|
|
22962
|
+
}
|
|
22963
|
+
async function applyClaudePermissionFromAcpSession(params) {
|
|
22964
|
+
const { sessionId, agentConfig, configOptions, modes, setSessionConfigOption, setSessionMode, logDebug: logDebug2 } = params;
|
|
22965
|
+
const desiredMode = getClaudePermissionModeFromAgentConfig(agentConfig);
|
|
22966
|
+
if (desiredMode == null) return;
|
|
22967
|
+
const modeOpt = pickModeConfigOption(configOptions ?? null);
|
|
22968
|
+
if (modeOpt != null) {
|
|
22969
|
+
const flat = flattenSelectOptions(modeOpt.options);
|
|
22970
|
+
const allowed = flat.some((o) => o.value === desiredMode);
|
|
22971
|
+
if (allowed && modeOpt.currentValue !== desiredMode) {
|
|
22972
|
+
try {
|
|
22973
|
+
logDebug2(
|
|
22974
|
+
`[Agent] Claude Code: sending ACP session/set_config_option (permission mode) configId=${JSON.stringify(modeOpt.id)} value=${JSON.stringify(desiredMode)} was=${JSON.stringify(modeOpt.currentValue)} sessionId=${sessionId.slice(0, 8)}\u2026`
|
|
22975
|
+
);
|
|
22976
|
+
await setSessionConfigOption({ sessionId, configId: modeOpt.id, value: desiredMode });
|
|
22977
|
+
} catch (e) {
|
|
22978
|
+
logDebug2(
|
|
22979
|
+
`[Agent] Claude Code: session/set_config_option failed: ${e instanceof Error ? e.message : String(e)}`
|
|
22980
|
+
);
|
|
22690
22981
|
}
|
|
22691
22982
|
}
|
|
22983
|
+
return;
|
|
22692
22984
|
}
|
|
22693
|
-
|
|
22694
|
-
|
|
22695
|
-
|
|
22696
|
-
|
|
22697
|
-
|
|
22698
|
-
|
|
22699
|
-
|
|
22700
|
-
|
|
22701
|
-
|
|
22702
|
-
|
|
22703
|
-
|
|
22704
|
-
} else {
|
|
22705
|
-
result.unshift({ type: "remove", line: oldLines[i - 1] });
|
|
22706
|
-
i--;
|
|
22985
|
+
if (modes?.availableModes?.length) {
|
|
22986
|
+
const allowed = modes.availableModes.some((m) => m.id === desiredMode);
|
|
22987
|
+
if (allowed && desiredMode !== modes.currentModeId) {
|
|
22988
|
+
try {
|
|
22989
|
+
logDebug2(
|
|
22990
|
+
`[Agent] Claude Code: sending ACP session/set_mode (permission mode) modeId=${JSON.stringify(desiredMode)} was=${JSON.stringify(modes.currentModeId ?? null)} sessionId=${sessionId.slice(0, 8)}\u2026`
|
|
22991
|
+
);
|
|
22992
|
+
await setSessionMode({ sessionId, modeId: desiredMode });
|
|
22993
|
+
} catch (e) {
|
|
22994
|
+
logDebug2(`[Agent] Claude Code: session/set_mode failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
22995
|
+
}
|
|
22707
22996
|
}
|
|
22708
22997
|
}
|
|
22709
|
-
return result;
|
|
22710
|
-
}
|
|
22711
|
-
function editSnippetToUnifiedDiff(filePath, oldText, newText) {
|
|
22712
|
-
const lines = computeLineDiff(oldText, newText);
|
|
22713
|
-
const out = [`--- ${filePath}`, `+++ ${filePath}`];
|
|
22714
|
-
for (const d of lines) {
|
|
22715
|
-
if (d.type === "add") out.push(`+${d.line}`);
|
|
22716
|
-
else if (d.type === "remove") out.push(`-${d.line}`);
|
|
22717
|
-
else out.push(` ${d.line}`);
|
|
22718
|
-
}
|
|
22719
|
-
return out.join("\n");
|
|
22720
22998
|
}
|
|
22721
22999
|
|
|
22722
|
-
// src/
|
|
22723
|
-
|
|
22724
|
-
|
|
22725
|
-
|
|
22726
|
-
|
|
22727
|
-
bridgeRootPath = path.resolve(process.cwd());
|
|
22728
|
-
}
|
|
22729
|
-
return bridgeRootPath;
|
|
23000
|
+
// src/agents/acp/clients/shared/config-options-for-permission.ts
|
|
23001
|
+
function configOptionsForPermission(getActive, established) {
|
|
23002
|
+
const mem = getActive?.();
|
|
23003
|
+
if (Array.isArray(mem) && mem.length > 0) return mem;
|
|
23004
|
+
return established ?? void 0;
|
|
22730
23005
|
}
|
|
22731
23006
|
|
|
22732
|
-
// src/agents/acp/
|
|
22733
|
-
|
|
22734
|
-
|
|
22735
|
-
|
|
22736
|
-
|
|
22737
|
-
|
|
22738
|
-
|
|
22739
|
-
|
|
22740
|
-
if (rel.startsWith("..") || path2.isAbsolute(rel)) return null;
|
|
22741
|
-
return resolved;
|
|
23007
|
+
// src/agents/acp/clients/shared/establish-acp-session.ts
|
|
23008
|
+
function establishedFromResult(raw, sessionId) {
|
|
23009
|
+
const r = raw && typeof raw === "object" ? raw : {};
|
|
23010
|
+
return {
|
|
23011
|
+
sessionId,
|
|
23012
|
+
configOptions: Array.isArray(r.configOptions) ? r.configOptions : null,
|
|
23013
|
+
modes: r.modes ?? null
|
|
23014
|
+
};
|
|
22742
23015
|
}
|
|
22743
|
-
function
|
|
22744
|
-
const
|
|
22745
|
-
|
|
22746
|
-
if (!rel || rel === "") return path2.basename(absolutePath);
|
|
22747
|
-
return rel.split(path2.sep).join("/");
|
|
23016
|
+
function sessionIdFromNewSessionResult(raw) {
|
|
23017
|
+
const r = raw && typeof raw === "object" ? raw : {};
|
|
23018
|
+
return typeof r.sessionId === "string" ? r.sessionId : "";
|
|
22748
23019
|
}
|
|
22749
|
-
|
|
22750
|
-
|
|
22751
|
-
|
|
22752
|
-
|
|
22753
|
-
|
|
22754
|
-
let total = 0;
|
|
22755
|
-
return {
|
|
22756
|
-
append(chunk) {
|
|
23020
|
+
async function establishAcpSessionWithTransport(transport, ctx, canResume, canLoad) {
|
|
23021
|
+
const { cwd, mcpServers, persistedAcpSessionId, agentLabel, suppressLoadReplay } = ctx;
|
|
23022
|
+
const prev = typeof persistedAcpSessionId === "string" && persistedAcpSessionId.trim() !== "" ? persistedAcpSessionId.trim() : "";
|
|
23023
|
+
if (prev) {
|
|
23024
|
+
if (canResume) {
|
|
22757
23025
|
try {
|
|
22758
|
-
|
|
22759
|
-
|
|
23026
|
+
logDebug(`[Agent] ${agentLabel} ACP session/resume for stored session ${prev.slice(0, 8)}\u2026`);
|
|
23027
|
+
const result2 = await transport.resumeSession({ sessionId: prev, cwd, mcpServers });
|
|
23028
|
+
return establishedFromResult(result2, prev);
|
|
23029
|
+
} catch (e) {
|
|
23030
|
+
logDebug(`[Agent] ${agentLabel} ACP session/resume failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
23031
|
+
}
|
|
23032
|
+
}
|
|
23033
|
+
if (canLoad) {
|
|
23034
|
+
suppressLoadReplay.value = true;
|
|
23035
|
+
try {
|
|
23036
|
+
logDebug(`[Agent] ${agentLabel} ACP session/load for stored session ${prev.slice(0, 8)}\u2026`);
|
|
23037
|
+
const result2 = await transport.loadSession({ sessionId: prev, cwd, mcpServers });
|
|
23038
|
+
return establishedFromResult(result2, prev);
|
|
23039
|
+
} catch (e) {
|
|
23040
|
+
logDebug(`[Agent] ${agentLabel} ACP session/load failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
23041
|
+
} finally {
|
|
23042
|
+
suppressLoadReplay.value = false;
|
|
22760
23043
|
}
|
|
22761
|
-
if (total >= STDERR_CAPTURE_MAX) return;
|
|
22762
|
-
const n = Math.min(chunk.length, STDERR_CAPTURE_MAX - total);
|
|
22763
|
-
if (n <= 0) return;
|
|
22764
|
-
chunks.push(n === chunk.length ? chunk : chunk.subarray(0, n));
|
|
22765
|
-
total += n;
|
|
22766
|
-
},
|
|
22767
|
-
getText() {
|
|
22768
|
-
return Buffer.concat(chunks).toString("utf8").trim();
|
|
22769
23044
|
}
|
|
22770
|
-
};
|
|
22771
|
-
}
|
|
22772
|
-
function formatJsonRpcStyleError(err) {
|
|
22773
|
-
if (err instanceof Error) return err.message;
|
|
22774
|
-
if (err != null && typeof err === "object") {
|
|
22775
|
-
const o = err;
|
|
22776
|
-
const msg = typeof o.message === "string" ? o.message : null;
|
|
22777
|
-
const code = o.code != null ? String(o.code) : "";
|
|
22778
|
-
if (msg) return code ? `[${code}] ${msg}` : msg;
|
|
22779
|
-
}
|
|
22780
|
-
if (typeof err === "string") return err;
|
|
22781
|
-
try {
|
|
22782
|
-
return JSON.stringify(err);
|
|
22783
|
-
} catch {
|
|
22784
|
-
return String(err);
|
|
22785
23045
|
}
|
|
23046
|
+
const result = await transport.newSession({ cwd, mcpServers });
|
|
23047
|
+
const sid = sessionIdFromNewSessionResult(result);
|
|
23048
|
+
if (!sid) throw new Error(`${agentLabel} ACP session/new did not return sessionId`);
|
|
23049
|
+
return establishedFromResult(result, sid);
|
|
22786
23050
|
}
|
|
22787
|
-
|
|
22788
|
-
|
|
22789
|
-
|
|
22790
|
-
|
|
22791
|
-
|
|
22792
|
-
|
|
22793
|
-
|
|
22794
|
-
|
|
23051
|
+
|
|
23052
|
+
// src/agents/acp/clients/shared/parse-acp-init-capabilities.ts
|
|
23053
|
+
function parseAcpInitAgentCapabilities(initResult) {
|
|
23054
|
+
const agentCapabilities = initResult?.agentCapabilities;
|
|
23055
|
+
const canLoad = agentCapabilities?.loadSession === true;
|
|
23056
|
+
const sessionCaps = agentCapabilities?.sessionCapabilities;
|
|
23057
|
+
const canResume = Boolean(sessionCaps?.resume);
|
|
23058
|
+
return { canResume, canLoad };
|
|
22795
23059
|
}
|
|
22796
23060
|
|
|
22797
|
-
// src/agents/acp/clients/
|
|
22798
|
-
function
|
|
22799
|
-
const
|
|
22800
|
-
|
|
22801
|
-
|
|
22802
|
-
|
|
22803
|
-
|
|
22804
|
-
|
|
22805
|
-
|
|
22806
|
-
|
|
22807
|
-
|
|
22808
|
-
|
|
22809
|
-
|
|
22810
|
-
|
|
22811
|
-
|
|
23061
|
+
// src/agents/acp/clients/shared/bootstrap-acp-wire-session.ts
|
|
23062
|
+
async function bootstrapAcpWireSession(transport, ctx, initializeRequest) {
|
|
23063
|
+
const initResult = await transport.initialize(initializeRequest);
|
|
23064
|
+
const { canResume, canLoad } = parseAcpInitAgentCapabilities(initResult);
|
|
23065
|
+
await transport.afterInitialize?.();
|
|
23066
|
+
const established = await establishAcpSessionWithTransport(transport, ctx, canResume, canLoad);
|
|
23067
|
+
const sessionId = established.sessionId;
|
|
23068
|
+
ctx.onAcpSessionEstablished?.({
|
|
23069
|
+
acpSessionId: sessionId,
|
|
23070
|
+
configOptions: established.configOptions,
|
|
23071
|
+
modes: established.modes
|
|
23072
|
+
});
|
|
23073
|
+
if (ctx.backendAgentType === "claude-code") {
|
|
23074
|
+
const cfg = ctx.agentConfig != null && typeof ctx.agentConfig === "object" && !Array.isArray(ctx.agentConfig) ? ctx.agentConfig : null;
|
|
23075
|
+
const configOptionsTyped = established.configOptions;
|
|
23076
|
+
const modesTyped = established.modes;
|
|
23077
|
+
await applyClaudePermissionFromAcpSession({
|
|
23078
|
+
sessionId,
|
|
23079
|
+
agentConfig: cfg,
|
|
23080
|
+
configOptions: configOptionsForPermission(ctx.getActiveConfigOptions, configOptionsTyped),
|
|
23081
|
+
modes: modesTyped,
|
|
23082
|
+
setSessionConfigOption: transport.setSessionConfigOption ? (p) => transport.setSessionConfigOption(p) : async () => {
|
|
23083
|
+
},
|
|
23084
|
+
setSessionMode: transport.setSessionMode ? (p) => transport.setSessionMode(p) : async () => {
|
|
23085
|
+
},
|
|
23086
|
+
logDebug: ctx.logDebug
|
|
23087
|
+
});
|
|
23088
|
+
}
|
|
23089
|
+
return established;
|
|
22812
23090
|
}
|
|
22813
23091
|
|
|
22814
|
-
// src/agents/acp/clients/
|
|
22815
|
-
|
|
22816
|
-
};
|
|
22817
|
-
|
|
22818
|
-
|
|
22819
|
-
|
|
22820
|
-
|
|
22821
|
-
|
|
22822
|
-
default:
|
|
22823
|
-
return noopExtNotification;
|
|
23092
|
+
// src/agents/acp/clients/shared/dispatch-session-update.ts
|
|
23093
|
+
function dispatchAcpSessionUpdate(opts) {
|
|
23094
|
+
const { flatPayload, onAcpConfigOptionsUpdated, onSessionUpdate, suppressLoadReplay } = opts;
|
|
23095
|
+
const su = flatPayload.sessionUpdate ?? flatPayload.session_update;
|
|
23096
|
+
if (su === "config_option_update") {
|
|
23097
|
+
const co = flatPayload.configOptions;
|
|
23098
|
+
if (Array.isArray(co)) onAcpConfigOptionsUpdated?.(co);
|
|
23099
|
+
return;
|
|
22824
23100
|
}
|
|
23101
|
+
if (suppressLoadReplay()) return;
|
|
23102
|
+
onSessionUpdate?.(flatPayload);
|
|
22825
23103
|
}
|
|
22826
23104
|
|
|
22827
|
-
// src/agents/acp/
|
|
22828
|
-
|
|
22829
|
-
|
|
22830
|
-
const raw = rec.optionId ?? rec.id;
|
|
22831
|
-
if (typeof raw === "string" && raw.trim() !== "") return raw.trim();
|
|
22832
|
-
if (typeof raw === "number" && Number.isFinite(raw)) return String(raw);
|
|
22833
|
-
return "";
|
|
23105
|
+
// src/agents/acp/clients/shared/flatten-sdk-session-notification.ts
|
|
23106
|
+
function flattenSdkSessionNotificationParams(params) {
|
|
23107
|
+
return { sessionId: params.sessionId, ...params.update };
|
|
22834
23108
|
}
|
|
22835
|
-
|
|
22836
|
-
|
|
22837
|
-
|
|
23109
|
+
|
|
23110
|
+
// src/agents/acp/clients/shared/normalize-acp-prompt-result.ts
|
|
23111
|
+
function normalizeAcpPromptTurnSuccess(opts) {
|
|
23112
|
+
const { stopReason, output, stderrCaptureText, backendAgentType } = opts;
|
|
23113
|
+
const mergedOutput = output || void 0;
|
|
23114
|
+
const stop = (stopReason ?? "").toLowerCase();
|
|
23115
|
+
const cancelled = stop === "cancelled";
|
|
23116
|
+
const refusal = stop === "refusal";
|
|
23117
|
+
const stderrEvaluated = Boolean(stderrCaptureText && backendAgentType);
|
|
23118
|
+
const stderrSuggestsAuth = stderrEvaluated ? localAgentErrorSuggestsAuth(backendAgentType, stderrCaptureText) : false;
|
|
23119
|
+
if (cancelled) {
|
|
23120
|
+
return {
|
|
23121
|
+
success: false,
|
|
23122
|
+
stopReason,
|
|
23123
|
+
output: mergedOutput,
|
|
23124
|
+
error: mergeErrorWithStderr("Stopped by user", stderrCaptureText)
|
|
23125
|
+
};
|
|
22838
23126
|
}
|
|
22839
|
-
|
|
22840
|
-
|
|
22841
|
-
|
|
22842
|
-
|
|
22843
|
-
|
|
22844
|
-
|
|
23127
|
+
if (refusal) {
|
|
23128
|
+
return {
|
|
23129
|
+
success: false,
|
|
23130
|
+
stopReason,
|
|
23131
|
+
output: mergedOutput,
|
|
23132
|
+
error: mergeErrorWithStderr("The agent refused the request.", stderrCaptureText)
|
|
23133
|
+
};
|
|
22845
23134
|
}
|
|
22846
|
-
|
|
22847
|
-
|
|
22848
|
-
|
|
22849
|
-
|
|
23135
|
+
if (stderrSuggestsAuth) {
|
|
23136
|
+
return {
|
|
23137
|
+
success: false,
|
|
23138
|
+
stopReason,
|
|
23139
|
+
output: mergedOutput,
|
|
23140
|
+
error: stderrCaptureText
|
|
23141
|
+
};
|
|
22850
23142
|
}
|
|
22851
|
-
|
|
22852
|
-
|
|
22853
|
-
|
|
22854
|
-
|
|
22855
|
-
|
|
22856
|
-
|
|
22857
|
-
|
|
22858
|
-
|
|
22859
|
-
|
|
22860
|
-
|
|
22861
|
-
|
|
23143
|
+
return {
|
|
23144
|
+
success: true,
|
|
23145
|
+
stopReason,
|
|
23146
|
+
output: mergedOutput
|
|
23147
|
+
};
|
|
23148
|
+
}
|
|
23149
|
+
function normalizeAcpPromptTurnFailure(err, stderrCaptureText) {
|
|
23150
|
+
const merged = mergeErrorWithStderr(formatJsonRpcStyleError(err), stderrCaptureText);
|
|
23151
|
+
return { success: false, error: merged };
|
|
23152
|
+
}
|
|
23153
|
+
|
|
23154
|
+
// src/agents/acp/clients/shared/send-acp-prompt-via-transport.ts
|
|
23155
|
+
async function sendAcpPromptViaTransport(transport, ctx, sessionId, promptText) {
|
|
23156
|
+
try {
|
|
23157
|
+
const response = await transport.prompt({
|
|
23158
|
+
sessionId,
|
|
23159
|
+
prompt: [{ type: "text", text: promptText }]
|
|
23160
|
+
});
|
|
23161
|
+
await new Promise((r2) => setImmediate(r2));
|
|
23162
|
+
const r = response;
|
|
23163
|
+
return normalizeAcpPromptTurnSuccess({
|
|
23164
|
+
stopReason: r?.stopReason,
|
|
23165
|
+
output: r?.output,
|
|
23166
|
+
stderrCaptureText: ctx.getStderrText(),
|
|
23167
|
+
backendAgentType: ctx.backendAgentType
|
|
23168
|
+
});
|
|
23169
|
+
} catch (err) {
|
|
23170
|
+
await new Promise((r) => setImmediate(r));
|
|
23171
|
+
return normalizeAcpPromptTurnFailure(err, ctx.getStderrText());
|
|
22862
23172
|
}
|
|
22863
|
-
|
|
23173
|
+
}
|
|
23174
|
+
|
|
23175
|
+
// src/agents/acp/clients/sdk/sdk-acp-session-transport.ts
|
|
23176
|
+
function createSdkAcpSessionTransport(connection) {
|
|
23177
|
+
const c = connection;
|
|
22864
23178
|
return {
|
|
22865
|
-
|
|
22866
|
-
|
|
22867
|
-
|
|
22868
|
-
|
|
22869
|
-
|
|
23179
|
+
initialize: (request) => c.initialize(request),
|
|
23180
|
+
resumeSession: (p) => c.unstable_resumeSession(p),
|
|
23181
|
+
loadSession: (p) => c.loadSession(p),
|
|
23182
|
+
newSession: (p) => c.newSession(p),
|
|
23183
|
+
prompt: (p) => c.prompt(p),
|
|
23184
|
+
cancelSession: async (sessionId) => {
|
|
23185
|
+
await c.cancel({ sessionId });
|
|
23186
|
+
},
|
|
23187
|
+
setSessionConfigOption: c.setSessionConfigOption ? (p) => c.setSessionConfigOption(p) : void 0,
|
|
23188
|
+
setSessionMode: c.setSessionMode ? (p) => c.setSessionMode(p) : void 0
|
|
22870
23189
|
};
|
|
22871
23190
|
}
|
|
22872
23191
|
|
|
22873
|
-
// src/agents/acp/clients/sdk-stdio-acp-client.ts
|
|
23192
|
+
// src/agents/acp/clients/sdk/sdk-stdio-acp-client.ts
|
|
22874
23193
|
function formatSpawnError(err, command) {
|
|
22875
23194
|
if (err.code === "ENOENT") {
|
|
22876
23195
|
return `Command "${command}" not found. Install the agent (e.g. Cursor CLI) or add it to PATH.`;
|
|
22877
23196
|
}
|
|
22878
23197
|
return err.message || String(err);
|
|
22879
23198
|
}
|
|
22880
|
-
function sliceFileContentRange(content, line, limit) {
|
|
22881
|
-
if (line == null && limit == null) return content;
|
|
22882
|
-
const lines = content.split("\n");
|
|
22883
|
-
const start = line != null && line > 0 ? line - 1 : 0;
|
|
22884
|
-
const end = limit != null && limit > 0 ? start + limit : lines.length;
|
|
22885
|
-
return lines.slice(start, end).join("\n");
|
|
22886
|
-
}
|
|
22887
|
-
function bridgePayloadFromSdkSessionNotification(params) {
|
|
22888
|
-
return { sessionId: params.sessionId, ...params.update };
|
|
22889
|
-
}
|
|
22890
23199
|
async function createSdkStdioAcpClient(options) {
|
|
22891
23200
|
const { ClientSideConnection: ClientSideConnection2, ndJsonStream: ndJsonStream2, PROTOCOL_VERSION: PROTOCOL_VERSION2 } = await Promise.resolve().then(() => (init_acp(), acp_exports));
|
|
22892
23201
|
const {
|
|
@@ -22898,7 +23207,11 @@ async function createSdkStdioAcpClient(options) {
|
|
|
22898
23207
|
onFileChange,
|
|
22899
23208
|
killSubprocessAfterCancelMs,
|
|
22900
23209
|
onAgentSubprocessExit,
|
|
22901
|
-
agentConfig
|
|
23210
|
+
agentConfig,
|
|
23211
|
+
persistedAcpSessionId,
|
|
23212
|
+
onAcpSessionEstablished,
|
|
23213
|
+
onAcpConfigOptionsUpdated,
|
|
23214
|
+
getActiveConfigOptions
|
|
22902
23215
|
} = options;
|
|
22903
23216
|
const isWindows = process.platform === "win32";
|
|
22904
23217
|
const child = spawn(command[0], command.slice(1), {
|
|
@@ -22947,6 +23260,22 @@ async function createSdkStdioAcpClient(options) {
|
|
|
22947
23260
|
backendAgentType,
|
|
22948
23261
|
onSessionUpdate
|
|
22949
23262
|
});
|
|
23263
|
+
const suppressLoadReplayRef = { value: false };
|
|
23264
|
+
const sessionCtx = {
|
|
23265
|
+
cwd,
|
|
23266
|
+
onFileChange,
|
|
23267
|
+
mcpServers: [],
|
|
23268
|
+
persistedAcpSessionId,
|
|
23269
|
+
agentLabel: "ACP",
|
|
23270
|
+
suppressLoadReplay: suppressLoadReplayRef,
|
|
23271
|
+
backendAgentType: backendAgentType ?? null,
|
|
23272
|
+
agentConfig,
|
|
23273
|
+
getActiveConfigOptions,
|
|
23274
|
+
onAcpSessionEstablished,
|
|
23275
|
+
onAcpConfigOptionsUpdated,
|
|
23276
|
+
logDebug,
|
|
23277
|
+
getStderrText: () => stderrCapture.getText()
|
|
23278
|
+
};
|
|
22950
23279
|
let permissionSeq = 0;
|
|
22951
23280
|
const pendingPermissionReplies = /* @__PURE__ */ new Map();
|
|
22952
23281
|
const client = (_agent) => ({
|
|
@@ -22966,35 +23295,19 @@ async function createSdkStdioAcpClient(options) {
|
|
|
22966
23295
|
});
|
|
22967
23296
|
},
|
|
22968
23297
|
async readTextFile(params) {
|
|
22969
|
-
|
|
22970
|
-
if (!resolvedPath) throw new Error("Invalid or disallowed path");
|
|
22971
|
-
try {
|
|
22972
|
-
let content = readFileSync(resolvedPath, "utf8");
|
|
22973
|
-
content = sliceFileContentRange(content, params.line, params.limit);
|
|
22974
|
-
return { content };
|
|
22975
|
-
} catch (e) {
|
|
22976
|
-
if (e.code === "ENOENT") return { content: "" };
|
|
22977
|
-
throw e;
|
|
22978
|
-
}
|
|
23298
|
+
return acpReadTextFileInProcess(sessionCtx, params.path, params.line, params.limit);
|
|
22979
23299
|
},
|
|
22980
23300
|
async writeTextFile(params) {
|
|
22981
|
-
|
|
22982
|
-
if (!resolvedPath) throw new Error("Invalid or disallowed path");
|
|
22983
|
-
let oldText = "";
|
|
22984
|
-
try {
|
|
22985
|
-
oldText = readFileSync(resolvedPath, "utf8");
|
|
22986
|
-
} catch (e) {
|
|
22987
|
-
if (e.code !== "ENOENT") throw e;
|
|
22988
|
-
}
|
|
22989
|
-
mkdirSync(dirname(resolvedPath), { recursive: true });
|
|
22990
|
-
writeFileSync(resolvedPath, params.content, "utf8");
|
|
22991
|
-
const displayPath = toDisplayPathRelativeToCwd(cwd, resolvedPath);
|
|
22992
|
-
const patchContent = editSnippetToUnifiedDiff(displayPath, oldText, params.content);
|
|
22993
|
-
onFileChange?.({ path: displayPath, oldText, newText: params.content, patchContent });
|
|
22994
|
-
return {};
|
|
23301
|
+
return acpWriteTextFileInProcess(sessionCtx, params.path, params.content);
|
|
22995
23302
|
},
|
|
22996
23303
|
async sessionUpdate(params) {
|
|
22997
|
-
|
|
23304
|
+
const bridged = flattenSdkSessionNotificationParams(params);
|
|
23305
|
+
dispatchAcpSessionUpdate({
|
|
23306
|
+
flatPayload: bridged,
|
|
23307
|
+
onAcpConfigOptionsUpdated: sessionCtx.onAcpConfigOptionsUpdated,
|
|
23308
|
+
onSessionUpdate,
|
|
23309
|
+
suppressLoadReplay: () => sessionCtx.suppressLoadReplay.value
|
|
23310
|
+
});
|
|
22998
23311
|
},
|
|
22999
23312
|
async extNotification(method, params) {
|
|
23000
23313
|
await extNotification(method, params);
|
|
@@ -23004,84 +23317,19 @@ async function createSdkStdioAcpClient(options) {
|
|
|
23004
23317
|
connection.signal.addEventListener("abort", () => {
|
|
23005
23318
|
child.kill();
|
|
23006
23319
|
});
|
|
23007
|
-
|
|
23320
|
+
const transport = createSdkAcpSessionTransport(connection);
|
|
23321
|
+
const established = await bootstrapAcpWireSession(transport, sessionCtx, {
|
|
23008
23322
|
protocolVersion: PROTOCOL_VERSION2,
|
|
23009
23323
|
clientCapabilities: {
|
|
23010
23324
|
fs: { readTextFile: true, writeTextFile: true }
|
|
23011
23325
|
},
|
|
23012
23326
|
clientInfo: { name: "buildautomaton-cli", version: "0.1.0" }
|
|
23013
23327
|
});
|
|
23014
|
-
const
|
|
23015
|
-
const sessionId = newSessionRes.sessionId;
|
|
23016
|
-
if (backendAgentType === "claude-code") {
|
|
23017
|
-
const cfg = agentConfig != null && typeof agentConfig === "object" && !Array.isArray(agentConfig) ? agentConfig : null;
|
|
23018
|
-
const desiredMode = getClaudePermissionModeFromAgentConfig(cfg);
|
|
23019
|
-
const modes = newSessionRes.modes;
|
|
23020
|
-
if (desiredMode != null && modes?.availableModes?.length) {
|
|
23021
|
-
const allowed = modes.availableModes.some((m) => m.id === desiredMode);
|
|
23022
|
-
if (allowed && desiredMode !== modes.currentModeId) {
|
|
23023
|
-
try {
|
|
23024
|
-
await connection.setSessionMode({ sessionId, modeId: desiredMode });
|
|
23025
|
-
} catch {
|
|
23026
|
-
}
|
|
23027
|
-
}
|
|
23028
|
-
}
|
|
23029
|
-
}
|
|
23328
|
+
const sessionId = established.sessionId;
|
|
23030
23329
|
settleResolve({
|
|
23031
23330
|
sessionId,
|
|
23032
23331
|
async sendPrompt(prompt, _options) {
|
|
23033
|
-
|
|
23034
|
-
const response = await connection.prompt({
|
|
23035
|
-
sessionId,
|
|
23036
|
-
prompt: [{ type: "text", text: prompt }]
|
|
23037
|
-
});
|
|
23038
|
-
await new Promise((r2) => setImmediate(r2));
|
|
23039
|
-
const r = response;
|
|
23040
|
-
const stopReason = (r?.stopReason ?? "").toLowerCase();
|
|
23041
|
-
const cancelled = stopReason === "cancelled";
|
|
23042
|
-
const refusal = stopReason === "refusal";
|
|
23043
|
-
const stderrAfter = stderrCapture.getText();
|
|
23044
|
-
const agentType = backendAgentType ?? null;
|
|
23045
|
-
const stderrEvaluated = Boolean(stderrAfter && agentType);
|
|
23046
|
-
const stderrSuggestsAuth = stderrEvaluated ? localAgentErrorSuggestsAuth(agentType, stderrAfter) : false;
|
|
23047
|
-
if (cancelled) {
|
|
23048
|
-
return {
|
|
23049
|
-
success: false,
|
|
23050
|
-
stopReason: r?.stopReason,
|
|
23051
|
-
output: r?.output,
|
|
23052
|
-
error: mergeErrorWithStderr("Stopped by user", stderrAfter)
|
|
23053
|
-
};
|
|
23054
|
-
}
|
|
23055
|
-
if (refusal) {
|
|
23056
|
-
return {
|
|
23057
|
-
success: false,
|
|
23058
|
-
stopReason: r?.stopReason,
|
|
23059
|
-
output: r?.output,
|
|
23060
|
-
error: mergeErrorWithStderr("The agent refused the request.", stderrAfter)
|
|
23061
|
-
};
|
|
23062
|
-
}
|
|
23063
|
-
if (stderrSuggestsAuth) {
|
|
23064
|
-
return {
|
|
23065
|
-
success: false,
|
|
23066
|
-
stopReason: r?.stopReason,
|
|
23067
|
-
output: r?.output,
|
|
23068
|
-
error: stderrAfter
|
|
23069
|
-
};
|
|
23070
|
-
}
|
|
23071
|
-
return {
|
|
23072
|
-
success: true,
|
|
23073
|
-
stopReason: r?.stopReason,
|
|
23074
|
-
output: r?.output
|
|
23075
|
-
};
|
|
23076
|
-
} catch (err) {
|
|
23077
|
-
await new Promise((r) => setImmediate(r));
|
|
23078
|
-
const stderrAfter = stderrCapture.getText();
|
|
23079
|
-
const merged = mergeErrorWithStderr(formatJsonRpcStyleError(err), stderrAfter);
|
|
23080
|
-
return {
|
|
23081
|
-
success: false,
|
|
23082
|
-
error: merged
|
|
23083
|
-
};
|
|
23084
|
-
}
|
|
23332
|
+
return sendAcpPromptViaTransport(transport, sessionCtx, sessionId, prompt);
|
|
23085
23333
|
},
|
|
23086
23334
|
async cancel() {
|
|
23087
23335
|
for (const [id, entry] of [...pendingPermissionReplies.entries()]) {
|
|
@@ -23089,7 +23337,7 @@ async function createSdkStdioAcpClient(options) {
|
|
|
23089
23337
|
entry.resolve({ outcome: { outcome: "cancelled" } });
|
|
23090
23338
|
}
|
|
23091
23339
|
try {
|
|
23092
|
-
await
|
|
23340
|
+
await transport.cancelSession(sessionId);
|
|
23093
23341
|
} catch {
|
|
23094
23342
|
}
|
|
23095
23343
|
if (killSubprocessAfterCancelMs != null && killSubprocessAfterCancelMs >= 0) {
|
|
@@ -23315,8 +23563,8 @@ function randomSecret() {
|
|
|
23315
23563
|
}
|
|
23316
23564
|
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
23317
23565
|
}
|
|
23318
|
-
async function requestPreviewApi(port, secret, method,
|
|
23319
|
-
const url2 = `http://127.0.0.1:${port}${
|
|
23566
|
+
async function requestPreviewApi(port, secret, method, path35, body) {
|
|
23567
|
+
const url2 = `http://127.0.0.1:${port}${path35}`;
|
|
23320
23568
|
const headers = {
|
|
23321
23569
|
[PREVIEW_SECRET_HEADER]: secret,
|
|
23322
23570
|
"Content-Type": "application/json"
|
|
@@ -23328,7 +23576,7 @@ async function requestPreviewApi(port, secret, method, path34, body) {
|
|
|
23328
23576
|
});
|
|
23329
23577
|
const data = await res.json().catch(() => ({}));
|
|
23330
23578
|
if (!res.ok) {
|
|
23331
|
-
throw new Error(data?.error ?? `Preview API ${method} ${
|
|
23579
|
+
throw new Error(data?.error ?? `Preview API ${method} ${path35}: ${res.status}`);
|
|
23332
23580
|
}
|
|
23333
23581
|
return data;
|
|
23334
23582
|
}
|
|
@@ -23471,40 +23719,6 @@ async function callSkill(skillId, operationId, params) {
|
|
|
23471
23719
|
return skill.execute(operationId, params);
|
|
23472
23720
|
}
|
|
23473
23721
|
|
|
23474
|
-
// src/cli-log-level.ts
|
|
23475
|
-
var verbosity = "info";
|
|
23476
|
-
function setCliLogVerbosity(level) {
|
|
23477
|
-
verbosity = level;
|
|
23478
|
-
}
|
|
23479
|
-
function getCliLogVerbosity() {
|
|
23480
|
-
return verbosity;
|
|
23481
|
-
}
|
|
23482
|
-
function isCliTrace() {
|
|
23483
|
-
return verbosity === "trace";
|
|
23484
|
-
}
|
|
23485
|
-
|
|
23486
|
-
// src/log.ts
|
|
23487
|
-
function timestampPrefix() {
|
|
23488
|
-
const time3 = (/* @__PURE__ */ new Date()).toISOString().slice(11, 19);
|
|
23489
|
-
return `[${time3}]`;
|
|
23490
|
-
}
|
|
23491
|
-
function log(line) {
|
|
23492
|
-
console.log(`${timestampPrefix()} ${line}`);
|
|
23493
|
-
}
|
|
23494
|
-
function logImmediate(line) {
|
|
23495
|
-
process.stdout.write(`${timestampPrefix()} ${line}
|
|
23496
|
-
`);
|
|
23497
|
-
}
|
|
23498
|
-
function logDebug(line) {
|
|
23499
|
-
const v = getCliLogVerbosity();
|
|
23500
|
-
if (v !== "debug" && v !== "trace") return;
|
|
23501
|
-
console.log(`${timestampPrefix()} [debug] ${line}`);
|
|
23502
|
-
}
|
|
23503
|
-
function logTrace(line) {
|
|
23504
|
-
if (getCliLogVerbosity() !== "trace") return;
|
|
23505
|
-
console.log(`${timestampPrefix()} [trace] ${line}`);
|
|
23506
|
-
}
|
|
23507
|
-
|
|
23508
23722
|
// src/config.ts
|
|
23509
23723
|
import fs from "node:fs";
|
|
23510
23724
|
import path3 from "node:path";
|
|
@@ -23577,7 +23791,7 @@ function installBridgeProcessResilience() {
|
|
|
23577
23791
|
}
|
|
23578
23792
|
|
|
23579
23793
|
// src/cli-version.ts
|
|
23580
|
-
var CLI_VERSION = "0.1.
|
|
23794
|
+
var CLI_VERSION = "0.1.25".length > 0 ? "0.1.25" : "0.0.0-dev";
|
|
23581
23795
|
|
|
23582
23796
|
// ../../node_modules/.pnpm/open@10.2.0/node_modules/open/index.js
|
|
23583
23797
|
import process7 from "node:process";
|
|
@@ -24741,8 +24955,8 @@ function pathspec(...paths) {
|
|
|
24741
24955
|
cache.set(key, paths);
|
|
24742
24956
|
return key;
|
|
24743
24957
|
}
|
|
24744
|
-
function isPathSpec(
|
|
24745
|
-
return
|
|
24958
|
+
function isPathSpec(path35) {
|
|
24959
|
+
return path35 instanceof String && cache.has(path35);
|
|
24746
24960
|
}
|
|
24747
24961
|
function toPaths(pathSpec) {
|
|
24748
24962
|
return cache.get(pathSpec) || [];
|
|
@@ -24831,8 +25045,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
|
|
|
24831
25045
|
function forEachLineWithContent(input, callback) {
|
|
24832
25046
|
return toLinesWithContent(input, true).map((line) => callback(line));
|
|
24833
25047
|
}
|
|
24834
|
-
function folderExists(
|
|
24835
|
-
return (0, import_file_exists.exists)(
|
|
25048
|
+
function folderExists(path35) {
|
|
25049
|
+
return (0, import_file_exists.exists)(path35, import_file_exists.FOLDER);
|
|
24836
25050
|
}
|
|
24837
25051
|
function append(target, item) {
|
|
24838
25052
|
if (Array.isArray(target)) {
|
|
@@ -25236,8 +25450,8 @@ function checkIsRepoRootTask() {
|
|
|
25236
25450
|
commands,
|
|
25237
25451
|
format: "utf-8",
|
|
25238
25452
|
onError,
|
|
25239
|
-
parser(
|
|
25240
|
-
return /^\.(git)?$/.test(
|
|
25453
|
+
parser(path35) {
|
|
25454
|
+
return /^\.(git)?$/.test(path35.trim());
|
|
25241
25455
|
}
|
|
25242
25456
|
};
|
|
25243
25457
|
}
|
|
@@ -25671,11 +25885,11 @@ function parseGrep(grep) {
|
|
|
25671
25885
|
const paths = /* @__PURE__ */ new Set();
|
|
25672
25886
|
const results = {};
|
|
25673
25887
|
forEachLineWithContent(grep, (input) => {
|
|
25674
|
-
const [
|
|
25675
|
-
paths.add(
|
|
25676
|
-
(results[
|
|
25888
|
+
const [path35, line, preview] = input.split(NULL);
|
|
25889
|
+
paths.add(path35);
|
|
25890
|
+
(results[path35] = results[path35] || []).push({
|
|
25677
25891
|
line: asNumber(line),
|
|
25678
|
-
path:
|
|
25892
|
+
path: path35,
|
|
25679
25893
|
preview
|
|
25680
25894
|
});
|
|
25681
25895
|
});
|
|
@@ -26440,14 +26654,14 @@ var init_hash_object = __esm2({
|
|
|
26440
26654
|
init_task();
|
|
26441
26655
|
}
|
|
26442
26656
|
});
|
|
26443
|
-
function parseInit(bare,
|
|
26657
|
+
function parseInit(bare, path35, text) {
|
|
26444
26658
|
const response = String(text).trim();
|
|
26445
26659
|
let result;
|
|
26446
26660
|
if (result = initResponseRegex.exec(response)) {
|
|
26447
|
-
return new InitSummary(bare,
|
|
26661
|
+
return new InitSummary(bare, path35, false, result[1]);
|
|
26448
26662
|
}
|
|
26449
26663
|
if (result = reInitResponseRegex.exec(response)) {
|
|
26450
|
-
return new InitSummary(bare,
|
|
26664
|
+
return new InitSummary(bare, path35, true, result[1]);
|
|
26451
26665
|
}
|
|
26452
26666
|
let gitDir = "";
|
|
26453
26667
|
const tokens = response.split(" ");
|
|
@@ -26458,7 +26672,7 @@ function parseInit(bare, path34, text) {
|
|
|
26458
26672
|
break;
|
|
26459
26673
|
}
|
|
26460
26674
|
}
|
|
26461
|
-
return new InitSummary(bare,
|
|
26675
|
+
return new InitSummary(bare, path35, /^re/i.test(response), gitDir);
|
|
26462
26676
|
}
|
|
26463
26677
|
var InitSummary;
|
|
26464
26678
|
var initResponseRegex;
|
|
@@ -26467,9 +26681,9 @@ var init_InitSummary = __esm2({
|
|
|
26467
26681
|
"src/lib/responses/InitSummary.ts"() {
|
|
26468
26682
|
"use strict";
|
|
26469
26683
|
InitSummary = class {
|
|
26470
|
-
constructor(bare,
|
|
26684
|
+
constructor(bare, path35, existing, gitDir) {
|
|
26471
26685
|
this.bare = bare;
|
|
26472
|
-
this.path =
|
|
26686
|
+
this.path = path35;
|
|
26473
26687
|
this.existing = existing;
|
|
26474
26688
|
this.gitDir = gitDir;
|
|
26475
26689
|
}
|
|
@@ -26481,7 +26695,7 @@ var init_InitSummary = __esm2({
|
|
|
26481
26695
|
function hasBareCommand(command) {
|
|
26482
26696
|
return command.includes(bareCommand);
|
|
26483
26697
|
}
|
|
26484
|
-
function initTask(bare = false,
|
|
26698
|
+
function initTask(bare = false, path35, customArgs) {
|
|
26485
26699
|
const commands = ["init", ...customArgs];
|
|
26486
26700
|
if (bare && !hasBareCommand(commands)) {
|
|
26487
26701
|
commands.splice(1, 0, bareCommand);
|
|
@@ -26490,7 +26704,7 @@ function initTask(bare = false, path34, customArgs) {
|
|
|
26490
26704
|
commands,
|
|
26491
26705
|
format: "utf-8",
|
|
26492
26706
|
parser(text) {
|
|
26493
|
-
return parseInit(commands.includes("--bare"),
|
|
26707
|
+
return parseInit(commands.includes("--bare"), path35, text);
|
|
26494
26708
|
}
|
|
26495
26709
|
};
|
|
26496
26710
|
}
|
|
@@ -27306,12 +27520,12 @@ var init_FileStatusSummary = __esm2({
|
|
|
27306
27520
|
"use strict";
|
|
27307
27521
|
fromPathRegex = /^(.+)\0(.+)$/;
|
|
27308
27522
|
FileStatusSummary = class {
|
|
27309
|
-
constructor(
|
|
27310
|
-
this.path =
|
|
27523
|
+
constructor(path35, index, working_dir) {
|
|
27524
|
+
this.path = path35;
|
|
27311
27525
|
this.index = index;
|
|
27312
27526
|
this.working_dir = working_dir;
|
|
27313
27527
|
if (index === "R" || working_dir === "R") {
|
|
27314
|
-
const detail = fromPathRegex.exec(
|
|
27528
|
+
const detail = fromPathRegex.exec(path35) || [null, path35, path35];
|
|
27315
27529
|
this.from = detail[2] || "";
|
|
27316
27530
|
this.path = detail[1] || "";
|
|
27317
27531
|
}
|
|
@@ -27342,14 +27556,14 @@ function splitLine(result, lineStr) {
|
|
|
27342
27556
|
default:
|
|
27343
27557
|
return;
|
|
27344
27558
|
}
|
|
27345
|
-
function data(index, workingDir,
|
|
27559
|
+
function data(index, workingDir, path35) {
|
|
27346
27560
|
const raw = `${index}${workingDir}`;
|
|
27347
27561
|
const handler = parsers6.get(raw);
|
|
27348
27562
|
if (handler) {
|
|
27349
|
-
handler(result,
|
|
27563
|
+
handler(result, path35);
|
|
27350
27564
|
}
|
|
27351
27565
|
if (raw !== "##" && raw !== "!!") {
|
|
27352
|
-
result.files.push(new FileStatusSummary(
|
|
27566
|
+
result.files.push(new FileStatusSummary(path35, index, workingDir));
|
|
27353
27567
|
}
|
|
27354
27568
|
}
|
|
27355
27569
|
}
|
|
@@ -27658,9 +27872,9 @@ var init_simple_git_api = __esm2({
|
|
|
27658
27872
|
next
|
|
27659
27873
|
);
|
|
27660
27874
|
}
|
|
27661
|
-
hashObject(
|
|
27875
|
+
hashObject(path35, write) {
|
|
27662
27876
|
return this._runTask(
|
|
27663
|
-
hashObjectTask(
|
|
27877
|
+
hashObjectTask(path35, write === true),
|
|
27664
27878
|
trailingFunctionArgument(arguments)
|
|
27665
27879
|
);
|
|
27666
27880
|
}
|
|
@@ -28013,8 +28227,8 @@ var init_branch = __esm2({
|
|
|
28013
28227
|
}
|
|
28014
28228
|
});
|
|
28015
28229
|
function toPath(input) {
|
|
28016
|
-
const
|
|
28017
|
-
return
|
|
28230
|
+
const path35 = input.trim().replace(/^["']|["']$/g, "");
|
|
28231
|
+
return path35 && normalize2(path35);
|
|
28018
28232
|
}
|
|
28019
28233
|
var parseCheckIgnore;
|
|
28020
28234
|
var init_CheckIgnore = __esm2({
|
|
@@ -28328,8 +28542,8 @@ __export2(sub_module_exports, {
|
|
|
28328
28542
|
subModuleTask: () => subModuleTask,
|
|
28329
28543
|
updateSubModuleTask: () => updateSubModuleTask
|
|
28330
28544
|
});
|
|
28331
|
-
function addSubModuleTask(repo,
|
|
28332
|
-
return subModuleTask(["add", repo,
|
|
28545
|
+
function addSubModuleTask(repo, path35) {
|
|
28546
|
+
return subModuleTask(["add", repo, path35]);
|
|
28333
28547
|
}
|
|
28334
28548
|
function initSubModuleTask(customArgs) {
|
|
28335
28549
|
return subModuleTask(["init", ...customArgs]);
|
|
@@ -28662,8 +28876,8 @@ var require_git = __commonJS2({
|
|
|
28662
28876
|
}
|
|
28663
28877
|
return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
|
|
28664
28878
|
};
|
|
28665
|
-
Git2.prototype.submoduleAdd = function(repo,
|
|
28666
|
-
return this._runTask(addSubModuleTask2(repo,
|
|
28879
|
+
Git2.prototype.submoduleAdd = function(repo, path35, then) {
|
|
28880
|
+
return this._runTask(addSubModuleTask2(repo, path35), trailingFunctionArgument2(arguments));
|
|
28667
28881
|
};
|
|
28668
28882
|
Git2.prototype.submoduleUpdate = function(args, then) {
|
|
28669
28883
|
return this._runTask(
|
|
@@ -29550,9 +29764,9 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
|
|
|
29550
29764
|
// src/agents/acp/put-summarize-change-summaries.ts
|
|
29551
29765
|
async function putEncryptedChangeSummaryRows(params) {
|
|
29552
29766
|
const base = params.apiBaseUrl.replace(/\/+$/, "");
|
|
29553
|
-
const entries = params.rows.map(({ path:
|
|
29767
|
+
const entries = params.rows.map(({ path: path35, summary }) => {
|
|
29554
29768
|
const enc = params.e2ee.encryptFields({ summary }, ["summary"]);
|
|
29555
|
-
return { path:
|
|
29769
|
+
return { path: path35, summary: JSON.stringify(enc) };
|
|
29556
29770
|
});
|
|
29557
29771
|
const res = await fetch(
|
|
29558
29772
|
`${base}/api/sessions/${encodeURIComponent(params.sessionId)}/follow-ups/summarize-changes`,
|
|
@@ -29734,8 +29948,8 @@ async function sendPromptToAgent(options) {
|
|
|
29734
29948
|
}
|
|
29735
29949
|
|
|
29736
29950
|
// src/agents/acp/ensure-acp-client.ts
|
|
29737
|
-
import * as
|
|
29738
|
-
import * as
|
|
29951
|
+
import * as fs10 from "node:fs";
|
|
29952
|
+
import * as path12 from "node:path";
|
|
29739
29953
|
|
|
29740
29954
|
// src/error-message.ts
|
|
29741
29955
|
function errorMessage(err) {
|
|
@@ -29825,7 +30039,7 @@ async function createCodexAcpClient(options) {
|
|
|
29825
30039
|
return createSdkStdioAcpClient({ ...options, command });
|
|
29826
30040
|
}
|
|
29827
30041
|
|
|
29828
|
-
// src/agents/acp/clients/cursor-acp-client.ts
|
|
30042
|
+
// src/agents/acp/clients/cursor/cursor-acp-client.ts
|
|
29829
30043
|
var cursor_acp_client_exports = {};
|
|
29830
30044
|
__export(cursor_acp_client_exports, {
|
|
29831
30045
|
BACKEND_LOCAL_AGENT_TYPE: () => BACKEND_LOCAL_AGENT_TYPE3,
|
|
@@ -29833,8 +30047,6 @@ __export(cursor_acp_client_exports, {
|
|
|
29833
30047
|
createCursorAcpClient: () => createCursorAcpClient,
|
|
29834
30048
|
detectLocalAgentPresence: () => detectLocalAgentPresence3
|
|
29835
30049
|
});
|
|
29836
|
-
import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "node:fs";
|
|
29837
|
-
import { dirname as dirname3 } from "node:path";
|
|
29838
30050
|
import { spawn as spawn4 } from "node:child_process";
|
|
29839
30051
|
import * as readline from "node:readline";
|
|
29840
30052
|
|
|
@@ -29851,7 +30063,23 @@ function formatSessionUpdateKindForLog(kind) {
|
|
|
29851
30063
|
return kind.split("_").filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join(" ");
|
|
29852
30064
|
}
|
|
29853
30065
|
|
|
29854
|
-
// src/agents/acp/clients/cursor-acp-
|
|
30066
|
+
// src/agents/acp/clients/cursor/cursor-json-rpc-acp-transport.ts
|
|
30067
|
+
function createCursorJsonRpcAcpTransport(deps) {
|
|
30068
|
+
const { send, cancelSessionNotification } = deps;
|
|
30069
|
+
return {
|
|
30070
|
+
initialize: (request) => send("initialize", request),
|
|
30071
|
+
afterInitialize: async () => {
|
|
30072
|
+
await send("authenticate", { methodId: "cursor_login" });
|
|
30073
|
+
},
|
|
30074
|
+
resumeSession: (p) => send("session/resume", p),
|
|
30075
|
+
loadSession: (p) => send("session/load", p),
|
|
30076
|
+
newSession: (p) => send("session/new", p),
|
|
30077
|
+
prompt: (p) => send("session/prompt", p),
|
|
30078
|
+
cancelSession: (sessionId) => cancelSessionNotification(sessionId)
|
|
30079
|
+
};
|
|
30080
|
+
}
|
|
30081
|
+
|
|
30082
|
+
// src/agents/acp/clients/cursor/cursor-acp-client.ts
|
|
29855
30083
|
var FS_READ_METHODS = /* @__PURE__ */ new Set(["fs/read_text_file", "fs/readTextFile"]);
|
|
29856
30084
|
var FS_WRITE_METHODS = /* @__PURE__ */ new Set(["fs/write_text_file", "fs/writeTextFile"]);
|
|
29857
30085
|
function formatSpawnError2(err, command) {
|
|
@@ -29868,13 +30096,6 @@ function safeJsonParse(value) {
|
|
|
29868
30096
|
return null;
|
|
29869
30097
|
}
|
|
29870
30098
|
}
|
|
29871
|
-
function sliceLinesByRange(content, line, limit) {
|
|
29872
|
-
if (line == null && limit == null) return content;
|
|
29873
|
-
const lines = content.split("\n");
|
|
29874
|
-
const start = line != null && line > 0 ? line - 1 : 0;
|
|
29875
|
-
const end = limit != null && limit > 0 ? start + limit : lines.length;
|
|
29876
|
-
return lines.slice(start, end).join("\n");
|
|
29877
|
-
}
|
|
29878
30099
|
function buildCursorAcpSpawnCommand(base, sessionMode) {
|
|
29879
30100
|
if (!sessionMode) return [...base];
|
|
29880
30101
|
const m = sessionMode.trim();
|
|
@@ -29888,7 +30109,11 @@ async function createCursorAcpClient(options) {
|
|
|
29888
30109
|
backendAgentType,
|
|
29889
30110
|
onSessionUpdate,
|
|
29890
30111
|
onRequest,
|
|
29891
|
-
onFileChange
|
|
30112
|
+
onFileChange,
|
|
30113
|
+
persistedAcpSessionId,
|
|
30114
|
+
onAcpSessionEstablished,
|
|
30115
|
+
onAcpConfigOptionsUpdated,
|
|
30116
|
+
onAgentSubprocessExit
|
|
29892
30117
|
} = options;
|
|
29893
30118
|
const dbgFs = process.env.BUILDAUTOMATON_DEBUG_ACP_FS === "1";
|
|
29894
30119
|
const isWindows = process.platform === "win32";
|
|
@@ -29900,6 +30125,25 @@ async function createCursorAcpClient(options) {
|
|
|
29900
30125
|
});
|
|
29901
30126
|
const stderrCapture = createStderrCapture(child);
|
|
29902
30127
|
child.stderr?.on("data", (chunk) => stderrCapture.append(chunk));
|
|
30128
|
+
child.once("close", (code, signal) => {
|
|
30129
|
+
onAgentSubprocessExit?.({ code, signal });
|
|
30130
|
+
});
|
|
30131
|
+
const suppressLoadReplayRef = { value: false };
|
|
30132
|
+
const sessionCtx = {
|
|
30133
|
+
cwd,
|
|
30134
|
+
onFileChange,
|
|
30135
|
+
mcpServers: [],
|
|
30136
|
+
persistedAcpSessionId,
|
|
30137
|
+
agentLabel: "Cursor",
|
|
30138
|
+
suppressLoadReplay: suppressLoadReplayRef,
|
|
30139
|
+
backendAgentType: backendAgentType ?? null,
|
|
30140
|
+
agentConfig: options.agentConfig,
|
|
30141
|
+
getActiveConfigOptions: options.getActiveConfigOptions,
|
|
30142
|
+
onAcpSessionEstablished,
|
|
30143
|
+
onAcpConfigOptionsUpdated,
|
|
30144
|
+
logDebug,
|
|
30145
|
+
getStderrText: () => stderrCapture.getText()
|
|
30146
|
+
};
|
|
29903
30147
|
return new Promise((resolve16, reject) => {
|
|
29904
30148
|
child.on("error", (err) => {
|
|
29905
30149
|
child.kill();
|
|
@@ -29908,6 +30152,16 @@ async function createCursorAcpClient(options) {
|
|
|
29908
30152
|
let nextId = 1;
|
|
29909
30153
|
const pending = /* @__PURE__ */ new Map();
|
|
29910
30154
|
const pendingRequests = /* @__PURE__ */ new Map();
|
|
30155
|
+
function cancelSessionNotification(sessionId) {
|
|
30156
|
+
const line = JSON.stringify({
|
|
30157
|
+
jsonrpc: "2.0",
|
|
30158
|
+
method: "session/cancel",
|
|
30159
|
+
params: { sessionId }
|
|
30160
|
+
}) + "\n";
|
|
30161
|
+
return new Promise((res, rej) => {
|
|
30162
|
+
child.stdin.write(line, (err) => err ? rej(err) : res());
|
|
30163
|
+
});
|
|
30164
|
+
}
|
|
29911
30165
|
function send(method, params) {
|
|
29912
30166
|
const id = nextId++;
|
|
29913
30167
|
const line = JSON.stringify({ jsonrpc: "2.0", id, method, params }) + "\n";
|
|
@@ -29931,7 +30185,6 @@ async function createCursorAcpClient(options) {
|
|
|
29931
30185
|
respond(requestId, payload);
|
|
29932
30186
|
pendingRequests.delete(requestId);
|
|
29933
30187
|
}
|
|
29934
|
-
let promptOutputBuffer = "";
|
|
29935
30188
|
const rl = readline.createInterface({ input: child.stdout });
|
|
29936
30189
|
rl.on("line", (line) => {
|
|
29937
30190
|
const msg = safeJsonParse(line);
|
|
@@ -29960,11 +30213,12 @@ async function createCursorAcpClient(options) {
|
|
|
29960
30213
|
`[acp] Received session update (${kindLabel}) tool=${toolName || "(none)"}`
|
|
29961
30214
|
);
|
|
29962
30215
|
}
|
|
29963
|
-
|
|
29964
|
-
|
|
29965
|
-
|
|
29966
|
-
|
|
29967
|
-
|
|
30216
|
+
dispatchAcpSessionUpdate({
|
|
30217
|
+
flatPayload: update,
|
|
30218
|
+
onAcpConfigOptionsUpdated: sessionCtx.onAcpConfigOptionsUpdated,
|
|
30219
|
+
onSessionUpdate,
|
|
30220
|
+
suppressLoadReplay: () => sessionCtx.suppressLoadReplay.value
|
|
30221
|
+
});
|
|
29968
30222
|
return;
|
|
29969
30223
|
}
|
|
29970
30224
|
if (method === "session/request_permission" && typeof id === "number") {
|
|
@@ -29984,21 +30238,13 @@ async function createCursorAcpClient(options) {
|
|
|
29984
30238
|
if (dbgFs) {
|
|
29985
30239
|
console.error(`[acp-fs] ${method} path=${filePath.slice(0, 200)}${filePath.length > 200 ? "\u2026" : ""}`);
|
|
29986
30240
|
}
|
|
29987
|
-
const resolvedPath = resolveSafePathUnderCwd(cwd, filePath);
|
|
29988
|
-
if (!resolvedPath) {
|
|
29989
|
-
if (dbgFs) console.error(`[acp-fs] ${method} rejected path (outside cwd or empty)`);
|
|
29990
|
-
respondJsonRpcError(id, -32602, "Invalid or disallowed path");
|
|
29991
|
-
return;
|
|
29992
|
-
}
|
|
29993
30241
|
try {
|
|
29994
|
-
|
|
29995
|
-
const
|
|
29996
|
-
const
|
|
29997
|
-
|
|
29998
|
-
respond(id, { content });
|
|
30242
|
+
const lineNum = typeof params.line === "number" ? params.line : void 0;
|
|
30243
|
+
const limitNum = typeof params.limit === "number" ? params.limit : void 0;
|
|
30244
|
+
const out = acpReadTextFileInProcess(sessionCtx, filePath, lineNum, limitNum);
|
|
30245
|
+
respond(id, out);
|
|
29999
30246
|
} catch (e) {
|
|
30000
|
-
|
|
30001
|
-
if (code === "ENOENT") {
|
|
30247
|
+
if (e?.code === "ENOENT") {
|
|
30002
30248
|
respond(id, { content: "" });
|
|
30003
30249
|
} else {
|
|
30004
30250
|
respondJsonRpcError(id, -32e3, e instanceof Error ? e.message : String(e));
|
|
@@ -30015,32 +30261,17 @@ async function createCursorAcpClient(options) {
|
|
|
30015
30261
|
`[acp-fs] ${method} path=${filePath.slice(0, 200)}${filePath.length > 200 ? "\u2026" : ""} newBytes=${newText.length}`
|
|
30016
30262
|
);
|
|
30017
30263
|
}
|
|
30018
|
-
const resolvedPath = resolveSafePathUnderCwd(cwd, filePath);
|
|
30019
|
-
if (!resolvedPath) {
|
|
30020
|
-
if (dbgFs) console.error(`[acp-fs] ${method} rejected path (outside cwd or empty): ${filePath.slice(0, 120)}`);
|
|
30021
|
-
respondJsonRpcError(id, -32602, "Invalid or disallowed path");
|
|
30022
|
-
return;
|
|
30023
|
-
}
|
|
30024
|
-
let oldText = "";
|
|
30025
30264
|
try {
|
|
30026
|
-
|
|
30265
|
+
acpWriteTextFileInProcess(sessionCtx, filePath, newText);
|
|
30266
|
+
respond(id, null);
|
|
30027
30267
|
} catch (e) {
|
|
30028
|
-
if (e.
|
|
30268
|
+
if (e.message === "Invalid or disallowed path") {
|
|
30269
|
+
if (dbgFs) console.error(`[acp-fs] ${method} rejected path (outside cwd or empty): ${filePath.slice(0, 120)}`);
|
|
30270
|
+
respondJsonRpcError(id, -32602, "Invalid or disallowed path");
|
|
30271
|
+
} else {
|
|
30029
30272
|
respondJsonRpcError(id, -32e3, e instanceof Error ? e.message : String(e));
|
|
30030
|
-
return;
|
|
30031
30273
|
}
|
|
30032
30274
|
}
|
|
30033
|
-
try {
|
|
30034
|
-
mkdirSync3(dirname3(resolvedPath), { recursive: true });
|
|
30035
|
-
writeFileSync3(resolvedPath, newText, "utf8");
|
|
30036
|
-
} catch (e) {
|
|
30037
|
-
respondJsonRpcError(id, -32e3, e instanceof Error ? e.message : String(e));
|
|
30038
|
-
return;
|
|
30039
|
-
}
|
|
30040
|
-
const displayPath = toDisplayPathRelativeToCwd(cwd, resolvedPath);
|
|
30041
|
-
const patchContent = editSnippetToUnifiedDiff(displayPath, oldText, newText);
|
|
30042
|
-
onFileChange?.({ path: displayPath, oldText, newText, patchContent });
|
|
30043
|
-
respond(id, null);
|
|
30044
30275
|
return;
|
|
30045
30276
|
}
|
|
30046
30277
|
if (method === "cursor/create_plan" || method === "cursor/ask_question") {
|
|
@@ -30062,16 +30293,7 @@ async function createCursorAcpClient(options) {
|
|
|
30062
30293
|
});
|
|
30063
30294
|
(async () => {
|
|
30064
30295
|
try {
|
|
30065
|
-
let
|
|
30066
|
-
const line = JSON.stringify({
|
|
30067
|
-
jsonrpc: "2.0",
|
|
30068
|
-
method: "session/cancel",
|
|
30069
|
-
params: { sessionId }
|
|
30070
|
-
}) + "\n";
|
|
30071
|
-
return new Promise((res, rej) => {
|
|
30072
|
-
child.stdin.write(line, (err) => err ? rej(err) : res());
|
|
30073
|
-
});
|
|
30074
|
-
}, cancelPendingPermissionRequests2 = function() {
|
|
30296
|
+
let cancelPendingPermissionRequests2 = function() {
|
|
30075
30297
|
for (const [reqId, pending2] of [...pendingRequests.entries()]) {
|
|
30076
30298
|
if (pending2.method === "session/request_permission") {
|
|
30077
30299
|
respond(reqId, { outcome: { outcome: "cancelled" } });
|
|
@@ -30079,76 +30301,25 @@ async function createCursorAcpClient(options) {
|
|
|
30079
30301
|
}
|
|
30080
30302
|
}
|
|
30081
30303
|
};
|
|
30082
|
-
var
|
|
30083
|
-
|
|
30304
|
+
var cancelPendingPermissionRequests = cancelPendingPermissionRequests2;
|
|
30305
|
+
const transport = createCursorJsonRpcAcpTransport({
|
|
30306
|
+
send,
|
|
30307
|
+
cancelSessionNotification
|
|
30308
|
+
});
|
|
30309
|
+
const established = await bootstrapAcpWireSession(transport, sessionCtx, {
|
|
30084
30310
|
protocolVersion: 1,
|
|
30085
30311
|
clientCapabilities: { fs: { readTextFile: true, writeTextFile: true }, terminal: false },
|
|
30086
30312
|
clientInfo: { name: "buildautomaton-cli", version: "0.1.0" }
|
|
30087
30313
|
});
|
|
30088
|
-
|
|
30089
|
-
const newResult = await send("session/new", { cwd, mcpServers: [] });
|
|
30090
|
-
const sessionId = newResult?.sessionId ?? "";
|
|
30091
|
-
if (!sessionId) throw new Error("Cursor ACP session/new did not return sessionId");
|
|
30314
|
+
const sessionId = established.sessionId;
|
|
30092
30315
|
resolve16({
|
|
30093
30316
|
sessionId,
|
|
30094
30317
|
async sendPrompt(prompt, _options) {
|
|
30095
|
-
|
|
30096
|
-
try {
|
|
30097
|
-
const result = await send("session/prompt", {
|
|
30098
|
-
sessionId,
|
|
30099
|
-
prompt: [{ type: "text", text: prompt }]
|
|
30100
|
-
});
|
|
30101
|
-
await new Promise((r) => setImmediate(r));
|
|
30102
|
-
const output = (result?.output ?? promptOutputBuffer) || void 0;
|
|
30103
|
-
const stopReason = (result?.stopReason ?? "").toLowerCase();
|
|
30104
|
-
const cancelled = stopReason === "cancelled";
|
|
30105
|
-
const refusal = stopReason === "refusal";
|
|
30106
|
-
const stderrAfter = stderrCapture.getText();
|
|
30107
|
-
const agentType = backendAgentType ?? null;
|
|
30108
|
-
const stderrEvaluated = Boolean(stderrAfter && agentType);
|
|
30109
|
-
const stderrSuggestsAuth = stderrEvaluated ? localAgentErrorSuggestsAuth(agentType, stderrAfter) : false;
|
|
30110
|
-
if (cancelled) {
|
|
30111
|
-
return {
|
|
30112
|
-
success: false,
|
|
30113
|
-
stopReason: result?.stopReason,
|
|
30114
|
-
output: output || void 0,
|
|
30115
|
-
error: mergeErrorWithStderr("Stopped by user", stderrAfter)
|
|
30116
|
-
};
|
|
30117
|
-
}
|
|
30118
|
-
if (refusal) {
|
|
30119
|
-
return {
|
|
30120
|
-
success: false,
|
|
30121
|
-
stopReason: result?.stopReason,
|
|
30122
|
-
output: output || void 0,
|
|
30123
|
-
error: mergeErrorWithStderr("The agent refused the request.", stderrAfter)
|
|
30124
|
-
};
|
|
30125
|
-
}
|
|
30126
|
-
if (stderrSuggestsAuth) {
|
|
30127
|
-
return {
|
|
30128
|
-
success: false,
|
|
30129
|
-
stopReason: result?.stopReason,
|
|
30130
|
-
output: output || void 0,
|
|
30131
|
-
error: stderrAfter
|
|
30132
|
-
};
|
|
30133
|
-
}
|
|
30134
|
-
return {
|
|
30135
|
-
success: true,
|
|
30136
|
-
stopReason: result?.stopReason,
|
|
30137
|
-
output: output || void 0
|
|
30138
|
-
};
|
|
30139
|
-
} catch (err) {
|
|
30140
|
-
await new Promise((r) => setImmediate(r));
|
|
30141
|
-
const stderrAfter = stderrCapture.getText();
|
|
30142
|
-
const merged = mergeErrorWithStderr(formatJsonRpcStyleError(err), stderrAfter);
|
|
30143
|
-
return {
|
|
30144
|
-
success: false,
|
|
30145
|
-
error: merged
|
|
30146
|
-
};
|
|
30147
|
-
}
|
|
30318
|
+
return sendAcpPromptViaTransport(transport, sessionCtx, sessionId, prompt);
|
|
30148
30319
|
},
|
|
30149
30320
|
async cancel() {
|
|
30150
30321
|
cancelPendingPermissionRequests2();
|
|
30151
|
-
await
|
|
30322
|
+
await transport.cancelSession(sessionId);
|
|
30152
30323
|
},
|
|
30153
30324
|
resolveRequest(requestId, result) {
|
|
30154
30325
|
const numericId = Number(requestId);
|
|
@@ -30296,7 +30467,7 @@ function getGitRepoRootSync(startDir) {
|
|
|
30296
30467
|
|
|
30297
30468
|
// src/agents/acp/workspace-files.ts
|
|
30298
30469
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
30299
|
-
import { readFileSync as
|
|
30470
|
+
import { readFileSync as readFileSync3 } from "node:fs";
|
|
30300
30471
|
import * as path10 from "node:path";
|
|
30301
30472
|
function resolveWorkspaceFilePath(sessionParentPath, rawPath) {
|
|
30302
30473
|
const trimmed2 = rawPath.trim();
|
|
@@ -30328,7 +30499,7 @@ function readUtf8WorkspaceFile(sessionParentPath, displayPath) {
|
|
|
30328
30499
|
const rel = path10.relative(gitRoot, resolvedPath2);
|
|
30329
30500
|
if (!rel.startsWith("..") && !path10.isAbsolute(rel)) {
|
|
30330
30501
|
try {
|
|
30331
|
-
return
|
|
30502
|
+
return readFileSync3(resolvedPath2, "utf8");
|
|
30332
30503
|
} catch {
|
|
30333
30504
|
}
|
|
30334
30505
|
}
|
|
@@ -30336,7 +30507,7 @@ function readUtf8WorkspaceFile(sessionParentPath, displayPath) {
|
|
|
30336
30507
|
const resolvedPath = resolveSafePathUnderCwd(sessionParentPath, displayPath);
|
|
30337
30508
|
if (!resolvedPath) return "";
|
|
30338
30509
|
try {
|
|
30339
|
-
return
|
|
30510
|
+
return readFileSync3(resolvedPath, "utf8");
|
|
30340
30511
|
} catch {
|
|
30341
30512
|
return "";
|
|
30342
30513
|
}
|
|
@@ -30840,6 +31011,9 @@ function createBridgeOnSessionUpdate(opts) {
|
|
|
30840
31011
|
const sentFileChangePaths = /* @__PURE__ */ new Set();
|
|
30841
31012
|
const p = params;
|
|
30842
31013
|
const updateKind = p.sessionUpdate ?? p.session_update ?? p.type ?? "update";
|
|
31014
|
+
if (updateKind === "config_option_update") {
|
|
31015
|
+
return;
|
|
31016
|
+
}
|
|
30843
31017
|
const isCompletedToolCallUpdate = updateKind === "tool_call_update" && isCompletedToolStatus(p.status);
|
|
30844
31018
|
const toolName = p.toolCall?.name ?? p.tool_call?.name ?? "";
|
|
30845
31019
|
const isToolUpdate = updateKind === "tool_call" || updateKind === "tool_call_update" || typeof toolName === "string" && toolName.length > 0;
|
|
@@ -30926,14 +31100,72 @@ function buildAcpSessionBridgeHooks(opts) {
|
|
|
30926
31100
|
};
|
|
30927
31101
|
}
|
|
30928
31102
|
|
|
31103
|
+
// src/agents/acp/local-agent-session-file.ts
|
|
31104
|
+
import fs9 from "node:fs";
|
|
31105
|
+
import os3 from "node:os";
|
|
31106
|
+
import path11 from "node:path";
|
|
31107
|
+
var LOCAL_AGENT_SESSION_DIR = path11.join(os3.homedir(), ".buildautomaton", "agent-sessions");
|
|
31108
|
+
function safeFileSlug(cloudSessionId) {
|
|
31109
|
+
const t = cloudSessionId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 220);
|
|
31110
|
+
return t.length > 0 ? t : "session";
|
|
31111
|
+
}
|
|
31112
|
+
function localAgentSessionFilePath(cloudSessionId) {
|
|
31113
|
+
return path11.join(LOCAL_AGENT_SESSION_DIR, `${safeFileSlug(cloudSessionId)}.json`);
|
|
31114
|
+
}
|
|
31115
|
+
function readLocalAgentSessionFile(cloudSessionId) {
|
|
31116
|
+
try {
|
|
31117
|
+
const p = localAgentSessionFilePath(cloudSessionId);
|
|
31118
|
+
const raw = fs9.readFileSync(p, "utf8");
|
|
31119
|
+
const parsed = JSON.parse(raw);
|
|
31120
|
+
if (parsed.v !== 1) return null;
|
|
31121
|
+
return {
|
|
31122
|
+
v: 1,
|
|
31123
|
+
acpSessionId: typeof parsed.acpSessionId === "string" ? parsed.acpSessionId : null,
|
|
31124
|
+
backendAgentType: typeof parsed.backendAgentType === "string" ? parsed.backendAgentType : null,
|
|
31125
|
+
configOptions: Array.isArray(parsed.configOptions) ? parsed.configOptions : null,
|
|
31126
|
+
updatedAt: typeof parsed.updatedAt === "string" ? parsed.updatedAt : (/* @__PURE__ */ new Date()).toISOString()
|
|
31127
|
+
};
|
|
31128
|
+
} catch {
|
|
31129
|
+
return null;
|
|
31130
|
+
}
|
|
31131
|
+
}
|
|
31132
|
+
function writeLocalAgentSessionFile(cloudSessionId, patch) {
|
|
31133
|
+
try {
|
|
31134
|
+
const dir = LOCAL_AGENT_SESSION_DIR;
|
|
31135
|
+
if (!fs9.existsSync(dir)) fs9.mkdirSync(dir, { recursive: true });
|
|
31136
|
+
const p = localAgentSessionFilePath(cloudSessionId);
|
|
31137
|
+
const prev = readLocalAgentSessionFile(cloudSessionId);
|
|
31138
|
+
const next = {
|
|
31139
|
+
v: 1,
|
|
31140
|
+
acpSessionId: patch.acpSessionId !== void 0 ? patch.acpSessionId : prev?.acpSessionId ?? null,
|
|
31141
|
+
backendAgentType: patch.backendAgentType !== void 0 ? patch.backendAgentType : prev?.backendAgentType ?? null,
|
|
31142
|
+
configOptions: patch.configOptions !== void 0 ? patch.configOptions : prev?.configOptions ?? null,
|
|
31143
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
31144
|
+
};
|
|
31145
|
+
fs9.writeFileSync(p, JSON.stringify(next, null, 2), "utf8");
|
|
31146
|
+
} catch {
|
|
31147
|
+
}
|
|
31148
|
+
}
|
|
31149
|
+
|
|
30929
31150
|
// src/agents/acp/ensure-acp-client.ts
|
|
30930
31151
|
async function ensureAcpClient(options) {
|
|
30931
|
-
const {
|
|
31152
|
+
const {
|
|
31153
|
+
state,
|
|
31154
|
+
preferredAgentType,
|
|
31155
|
+
mode,
|
|
31156
|
+
agentConfig,
|
|
31157
|
+
sessionParentPath,
|
|
31158
|
+
routing,
|
|
31159
|
+
cloudSessionId,
|
|
31160
|
+
sendSessionUpdate,
|
|
31161
|
+
sendRequest,
|
|
31162
|
+
log: log2
|
|
31163
|
+
} = options;
|
|
30932
31164
|
const targetSessionParentPath = resolveSessionParentPathForAgentProcess(sessionParentPath);
|
|
30933
31165
|
if (state.acpStartPromise && !state.acpHandle) {
|
|
30934
31166
|
await state.acpStartPromise;
|
|
30935
31167
|
}
|
|
30936
|
-
if (state.acpHandle && state.lastAcpCwd != null &&
|
|
31168
|
+
if (state.acpHandle && state.lastAcpCwd != null && path12.resolve(state.lastAcpCwd) !== path12.resolve(targetSessionParentPath)) {
|
|
30937
31169
|
try {
|
|
30938
31170
|
state.acpHandle.disconnect();
|
|
30939
31171
|
} catch {
|
|
@@ -30941,6 +31173,7 @@ async function ensureAcpClient(options) {
|
|
|
30941
31173
|
state.acpHandle = null;
|
|
30942
31174
|
state.acpStartPromise = null;
|
|
30943
31175
|
state.acpAgentKey = null;
|
|
31176
|
+
state.activeSessionConfigOptions = null;
|
|
30944
31177
|
}
|
|
30945
31178
|
const resolved = resolveAgentCommand(preferredAgentType);
|
|
30946
31179
|
if (!resolved) {
|
|
@@ -30961,12 +31194,13 @@ async function ensureAcpClient(options) {
|
|
|
30961
31194
|
state.acpHandle = null;
|
|
30962
31195
|
state.acpStartPromise = null;
|
|
30963
31196
|
state.acpAgentKey = null;
|
|
31197
|
+
state.activeSessionConfigOptions = null;
|
|
30964
31198
|
}
|
|
30965
31199
|
if (state.acpHandle) return state.acpHandle;
|
|
30966
31200
|
if (!state.acpStartPromise) {
|
|
30967
31201
|
let statOk = false;
|
|
30968
31202
|
try {
|
|
30969
|
-
const st =
|
|
31203
|
+
const st = fs10.statSync(targetSessionParentPath);
|
|
30970
31204
|
statOk = st.isDirectory();
|
|
30971
31205
|
if (!statOk) {
|
|
30972
31206
|
state.lastAcpStartError = `Agent cwd is not a directory: ${targetSessionParentPath}`;
|
|
@@ -30986,15 +31220,40 @@ async function ensureAcpClient(options) {
|
|
|
30986
31220
|
getSendRequest: () => sendRequest,
|
|
30987
31221
|
log: log2
|
|
30988
31222
|
});
|
|
31223
|
+
const persisted = cloudSessionId != null && cloudSessionId !== "" && preferredAgentType != null && preferredAgentType !== "" ? readLocalAgentSessionFile(cloudSessionId) : null;
|
|
31224
|
+
const persistedAcpSessionId = persisted && persisted.backendAgentType === preferredAgentType && typeof persisted.acpSessionId === "string" && persisted.acpSessionId.trim() !== "" ? persisted.acpSessionId.trim() : null;
|
|
31225
|
+
state.activeSessionConfigOptions = Array.isArray(persisted?.configOptions) ? persisted.configOptions : null;
|
|
30989
31226
|
state.acpStartPromise = resolved.createClient({
|
|
30990
31227
|
command: resolved.command,
|
|
30991
31228
|
sessionMode: mode,
|
|
30992
31229
|
agentConfig: agentConfig ?? null,
|
|
30993
31230
|
backendAgentType: preferredAgentType,
|
|
31231
|
+
persistedAcpSessionId,
|
|
31232
|
+
getActiveConfigOptions: () => state.activeSessionConfigOptions,
|
|
31233
|
+
onAcpSessionEstablished: (info) => {
|
|
31234
|
+
state.activeSessionConfigOptions = info.configOptions ?? state.activeSessionConfigOptions;
|
|
31235
|
+
if (cloudSessionId != null && cloudSessionId !== "" && preferredAgentType != null && preferredAgentType !== "") {
|
|
31236
|
+
writeLocalAgentSessionFile(cloudSessionId, {
|
|
31237
|
+
acpSessionId: info.acpSessionId,
|
|
31238
|
+
configOptions: info.configOptions,
|
|
31239
|
+
backendAgentType: preferredAgentType
|
|
31240
|
+
});
|
|
31241
|
+
}
|
|
31242
|
+
},
|
|
31243
|
+
onAcpConfigOptionsUpdated: (configOptions) => {
|
|
31244
|
+
state.activeSessionConfigOptions = configOptions;
|
|
31245
|
+
if (cloudSessionId != null && cloudSessionId !== "" && preferredAgentType != null && preferredAgentType !== "") {
|
|
31246
|
+
writeLocalAgentSessionFile(cloudSessionId, {
|
|
31247
|
+
configOptions,
|
|
31248
|
+
backendAgentType: preferredAgentType
|
|
31249
|
+
});
|
|
31250
|
+
}
|
|
31251
|
+
},
|
|
30994
31252
|
onAgentSubprocessExit: () => {
|
|
30995
31253
|
state.acpHandle = null;
|
|
30996
31254
|
state.acpStartPromise = null;
|
|
30997
31255
|
state.acpAgentKey = null;
|
|
31256
|
+
state.activeSessionConfigOptions = null;
|
|
30998
31257
|
state.lastAcpStartError = "Agent subprocess exited";
|
|
30999
31258
|
},
|
|
31000
31259
|
...hooks,
|
|
@@ -31024,7 +31283,8 @@ async function createAcpManager(options) {
|
|
|
31024
31283
|
acpStartPromise: null,
|
|
31025
31284
|
lastAcpStartError: null,
|
|
31026
31285
|
lastAcpCwd: null,
|
|
31027
|
-
acpAgentKey: null
|
|
31286
|
+
acpAgentKey: null,
|
|
31287
|
+
activeSessionConfigOptions: null
|
|
31028
31288
|
};
|
|
31029
31289
|
let backendFallbackAgentType = null;
|
|
31030
31290
|
const promptRouting = {};
|
|
@@ -31074,6 +31334,7 @@ async function createAcpManager(options) {
|
|
|
31074
31334
|
agentConfig: agentConfig ?? null,
|
|
31075
31335
|
sessionParentPath,
|
|
31076
31336
|
routing: promptRouting,
|
|
31337
|
+
cloudSessionId: sessionId,
|
|
31077
31338
|
sendSessionUpdate,
|
|
31078
31339
|
sendRequest: sendSessionUpdate,
|
|
31079
31340
|
log: log2
|
|
@@ -31164,6 +31425,7 @@ async function createAcpManager(options) {
|
|
|
31164
31425
|
state.acpHandle = null;
|
|
31165
31426
|
state.acpStartPromise = null;
|
|
31166
31427
|
state.acpAgentKey = null;
|
|
31428
|
+
state.activeSessionConfigOptions = null;
|
|
31167
31429
|
}
|
|
31168
31430
|
return {
|
|
31169
31431
|
setPreferredAgentType,
|
|
@@ -31176,12 +31438,12 @@ async function createAcpManager(options) {
|
|
|
31176
31438
|
}
|
|
31177
31439
|
|
|
31178
31440
|
// src/worktrees/session-worktree-manager.ts
|
|
31179
|
-
import * as
|
|
31180
|
-
import
|
|
31441
|
+
import * as path19 from "node:path";
|
|
31442
|
+
import os5 from "node:os";
|
|
31181
31443
|
|
|
31182
31444
|
// src/worktrees/prepare-new-session-worktrees.ts
|
|
31183
|
-
import * as
|
|
31184
|
-
import * as
|
|
31445
|
+
import * as fs12 from "node:fs";
|
|
31446
|
+
import * as path14 from "node:path";
|
|
31185
31447
|
|
|
31186
31448
|
// src/git/worktree-add.ts
|
|
31187
31449
|
async function gitWorktreeAddBranch(mainRepoPath, worktreePath, branch) {
|
|
@@ -31190,12 +31452,12 @@ async function gitWorktreeAddBranch(mainRepoPath, worktreePath, branch) {
|
|
|
31190
31452
|
}
|
|
31191
31453
|
|
|
31192
31454
|
// src/worktrees/worktree-layout-file.ts
|
|
31193
|
-
import * as
|
|
31194
|
-
import * as
|
|
31195
|
-
import
|
|
31455
|
+
import * as fs11 from "node:fs";
|
|
31456
|
+
import * as path13 from "node:path";
|
|
31457
|
+
import os4 from "node:os";
|
|
31196
31458
|
var LAYOUT_FILENAME = "worktree-launcher-layout.json";
|
|
31197
31459
|
function defaultWorktreeLayoutPath() {
|
|
31198
|
-
return
|
|
31460
|
+
return path13.join(os4.homedir(), ".buildautomaton", LAYOUT_FILENAME);
|
|
31199
31461
|
}
|
|
31200
31462
|
function normalizeLoadedLayout(raw) {
|
|
31201
31463
|
if (raw && typeof raw === "object" && "launcherCwds" in raw) {
|
|
@@ -31207,8 +31469,8 @@ function normalizeLoadedLayout(raw) {
|
|
|
31207
31469
|
function loadWorktreeLayout() {
|
|
31208
31470
|
try {
|
|
31209
31471
|
const p = defaultWorktreeLayoutPath();
|
|
31210
|
-
if (!
|
|
31211
|
-
const raw = JSON.parse(
|
|
31472
|
+
if (!fs11.existsSync(p)) return { launcherCwds: [] };
|
|
31473
|
+
const raw = JSON.parse(fs11.readFileSync(p, "utf8"));
|
|
31212
31474
|
return normalizeLoadedLayout(raw);
|
|
31213
31475
|
} catch {
|
|
31214
31476
|
return { launcherCwds: [] };
|
|
@@ -31216,24 +31478,24 @@ function loadWorktreeLayout() {
|
|
|
31216
31478
|
}
|
|
31217
31479
|
function saveWorktreeLayout(layout) {
|
|
31218
31480
|
try {
|
|
31219
|
-
const dir =
|
|
31220
|
-
|
|
31221
|
-
|
|
31481
|
+
const dir = path13.dirname(defaultWorktreeLayoutPath());
|
|
31482
|
+
fs11.mkdirSync(dir, { recursive: true });
|
|
31483
|
+
fs11.writeFileSync(defaultWorktreeLayoutPath(), JSON.stringify(layout, null, 2), "utf8");
|
|
31222
31484
|
} catch {
|
|
31223
31485
|
}
|
|
31224
31486
|
}
|
|
31225
31487
|
function baseNameSafe(pathString) {
|
|
31226
|
-
return
|
|
31488
|
+
return path13.basename(pathString).replace(/[^a-zA-Z0-9._-]+/g, "-") || "cwd";
|
|
31227
31489
|
}
|
|
31228
31490
|
function getLauncherDirNameIfPresent(layout, bridgeRootPath2) {
|
|
31229
|
-
const norm =
|
|
31230
|
-
const existing = layout.launcherCwds.find((e) =>
|
|
31491
|
+
const norm = path13.resolve(bridgeRootPath2);
|
|
31492
|
+
const existing = layout.launcherCwds.find((e) => path13.resolve(e.absolutePath) === norm);
|
|
31231
31493
|
return existing?.dirName;
|
|
31232
31494
|
}
|
|
31233
31495
|
function allocateDirNameForLauncherCwd(layout, bridgeRootPath2) {
|
|
31234
31496
|
const existing = getLauncherDirNameIfPresent(layout, bridgeRootPath2);
|
|
31235
31497
|
if (existing) return existing;
|
|
31236
|
-
const norm =
|
|
31498
|
+
const norm = path13.resolve(bridgeRootPath2);
|
|
31237
31499
|
const base = baseNameSafe(norm);
|
|
31238
31500
|
const used = new Set(layout.launcherCwds.map((e) => e.dirName));
|
|
31239
31501
|
let name = base;
|
|
@@ -31250,10 +31512,10 @@ function allocateDirNameForLauncherCwd(layout, bridgeRootPath2) {
|
|
|
31250
31512
|
// src/worktrees/prepare-new-session-worktrees.ts
|
|
31251
31513
|
async function prepareNewSessionWorktrees(options) {
|
|
31252
31514
|
const { worktreesRootPath, bridgeRoot, sessionId, layout, log: log2 } = options;
|
|
31253
|
-
const bridgeResolved =
|
|
31515
|
+
const bridgeResolved = path14.resolve(bridgeRoot);
|
|
31254
31516
|
const cwdKey = allocateDirNameForLauncherCwd(layout, bridgeResolved);
|
|
31255
|
-
const bridgeKeyDir =
|
|
31256
|
-
const sessionDir =
|
|
31517
|
+
const bridgeKeyDir = path14.join(worktreesRootPath, cwdKey);
|
|
31518
|
+
const sessionDir = path14.join(bridgeKeyDir, sessionId);
|
|
31257
31519
|
const repos = await discoverGitReposUnderRoot(bridgeResolved);
|
|
31258
31520
|
if (repos.length === 0) {
|
|
31259
31521
|
log2("[worktrees] No Git repositories under bridge root; skipping worktree creation.");
|
|
@@ -31261,14 +31523,14 @@ async function prepareNewSessionWorktrees(options) {
|
|
|
31261
31523
|
}
|
|
31262
31524
|
const branch = `session-${sessionId}`;
|
|
31263
31525
|
const worktreePaths = [];
|
|
31264
|
-
|
|
31526
|
+
fs12.mkdirSync(sessionDir, { recursive: true });
|
|
31265
31527
|
for (const repo of repos) {
|
|
31266
|
-
let rel =
|
|
31267
|
-
if (rel.startsWith("..") ||
|
|
31528
|
+
let rel = path14.relative(bridgeResolved, repo.absolutePath);
|
|
31529
|
+
if (rel.startsWith("..") || path14.isAbsolute(rel)) continue;
|
|
31268
31530
|
const relNorm = rel === "" ? "." : rel;
|
|
31269
|
-
const wtPath = relNorm === "." ? sessionDir :
|
|
31531
|
+
const wtPath = relNorm === "." ? sessionDir : path14.join(sessionDir, relNorm);
|
|
31270
31532
|
if (relNorm !== ".") {
|
|
31271
|
-
|
|
31533
|
+
fs12.mkdirSync(path14.dirname(wtPath), { recursive: true });
|
|
31272
31534
|
}
|
|
31273
31535
|
try {
|
|
31274
31536
|
await gitWorktreeAddBranch(repo.absolutePath, wtPath, branch);
|
|
@@ -31310,23 +31572,23 @@ async function renameSessionWorktreeBranches(paths, newBranch, log2) {
|
|
|
31310
31572
|
}
|
|
31311
31573
|
|
|
31312
31574
|
// src/worktrees/remove-session-worktrees.ts
|
|
31313
|
-
import * as
|
|
31575
|
+
import * as fs15 from "node:fs";
|
|
31314
31576
|
|
|
31315
31577
|
// src/git/worktree-remove.ts
|
|
31316
|
-
import * as
|
|
31578
|
+
import * as fs14 from "node:fs";
|
|
31317
31579
|
|
|
31318
31580
|
// src/git/resolve-main-repo-from-git-file.ts
|
|
31319
|
-
import * as
|
|
31320
|
-
import * as
|
|
31581
|
+
import * as fs13 from "node:fs";
|
|
31582
|
+
import * as path15 from "node:path";
|
|
31321
31583
|
function resolveMainRepoFromWorktreeGitFile(wt) {
|
|
31322
|
-
const gitDirFile =
|
|
31323
|
-
if (!
|
|
31324
|
-
const first2 =
|
|
31584
|
+
const gitDirFile = path15.join(wt, ".git");
|
|
31585
|
+
if (!fs13.existsSync(gitDirFile) || !fs13.statSync(gitDirFile).isFile()) return "";
|
|
31586
|
+
const first2 = fs13.readFileSync(gitDirFile, "utf8").trim();
|
|
31325
31587
|
const m = first2.match(/^gitdir:\s*(.+)$/im);
|
|
31326
31588
|
if (!m) return "";
|
|
31327
|
-
const gitWorktreePath =
|
|
31328
|
-
const gitDir =
|
|
31329
|
-
return
|
|
31589
|
+
const gitWorktreePath = path15.resolve(wt, m[1].trim());
|
|
31590
|
+
const gitDir = path15.dirname(path15.dirname(gitWorktreePath));
|
|
31591
|
+
return path15.dirname(gitDir);
|
|
31330
31592
|
}
|
|
31331
31593
|
|
|
31332
31594
|
// src/git/worktree-remove.ts
|
|
@@ -31335,7 +31597,7 @@ async function gitWorktreeRemoveForce(worktreePath) {
|
|
|
31335
31597
|
if (mainRepo) {
|
|
31336
31598
|
await cliSimpleGit(mainRepo).raw(["worktree", "remove", "--force", worktreePath]);
|
|
31337
31599
|
} else {
|
|
31338
|
-
|
|
31600
|
+
fs14.rmSync(worktreePath, { recursive: true, force: true });
|
|
31339
31601
|
}
|
|
31340
31602
|
}
|
|
31341
31603
|
|
|
@@ -31348,7 +31610,7 @@ async function removeSessionWorktrees(paths, log2) {
|
|
|
31348
31610
|
} catch (e) {
|
|
31349
31611
|
log2(`[worktrees] Remove failed for ${wt}: ${e instanceof Error ? e.message : String(e)}`);
|
|
31350
31612
|
try {
|
|
31351
|
-
|
|
31613
|
+
fs15.rmSync(wt, { recursive: true, force: true });
|
|
31352
31614
|
} catch {
|
|
31353
31615
|
}
|
|
31354
31616
|
}
|
|
@@ -31568,7 +31830,7 @@ function formatRemoteDisplayLabel(remoteUrl) {
|
|
|
31568
31830
|
}
|
|
31569
31831
|
|
|
31570
31832
|
// src/git/working-directory/changes/get-working-tree-change-repo-details.ts
|
|
31571
|
-
import * as
|
|
31833
|
+
import * as path17 from "node:path";
|
|
31572
31834
|
|
|
31573
31835
|
// src/git/working-directory/changes/parse-git-status.ts
|
|
31574
31836
|
function parseNameStatusLines(lines) {
|
|
@@ -31688,8 +31950,8 @@ async function listChangedFilesForCommit(repoGitCwd, repoRelPath, commitSha) {
|
|
|
31688
31950
|
}
|
|
31689
31951
|
|
|
31690
31952
|
// src/git/working-directory/changes/list-changed-files-for-repo.ts
|
|
31691
|
-
import * as
|
|
31692
|
-
import * as
|
|
31953
|
+
import * as fs17 from "node:fs";
|
|
31954
|
+
import * as path16 from "node:path";
|
|
31693
31955
|
|
|
31694
31956
|
// src/git/working-directory/changes/count-lines.ts
|
|
31695
31957
|
import { createReadStream } from "node:fs";
|
|
@@ -31713,7 +31975,7 @@ async function countTextFileLines(filePath) {
|
|
|
31713
31975
|
}
|
|
31714
31976
|
|
|
31715
31977
|
// src/git/working-directory/changes/hydrate-patch.ts
|
|
31716
|
-
import * as
|
|
31978
|
+
import * as fs16 from "node:fs";
|
|
31717
31979
|
var UNIFIED_HUNK_HEADER_RE = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/;
|
|
31718
31980
|
var MAX_HYDRATE_LINES_PER_GAP = 8e3;
|
|
31719
31981
|
var MAX_HYDRATE_LINES_PER_FILE = 8e4;
|
|
@@ -31728,7 +31990,7 @@ async function readGitBlobLines(repoCwd, pathInRepo) {
|
|
|
31728
31990
|
}
|
|
31729
31991
|
async function readWorktreeFileLines(filePath) {
|
|
31730
31992
|
try {
|
|
31731
|
-
const raw = await
|
|
31993
|
+
const raw = await fs16.promises.readFile(filePath, "utf8");
|
|
31732
31994
|
return raw.split(/\r?\n/);
|
|
31733
31995
|
} catch {
|
|
31734
31996
|
return null;
|
|
@@ -31863,7 +32125,7 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
|
|
|
31863
32125
|
const rows = [];
|
|
31864
32126
|
for (const pathInRepo of paths) {
|
|
31865
32127
|
const relLauncher = posixJoinDirFile(repoRelPath, pathInRepo.replace(/\\/g, "/"));
|
|
31866
|
-
const repoFilePath =
|
|
32128
|
+
const repoFilePath = path16.join(repoGitCwd, pathInRepo);
|
|
31867
32129
|
const nums = numByPath.get(pathInRepo);
|
|
31868
32130
|
let additions = nums?.additions ?? 0;
|
|
31869
32131
|
let deletions = nums?.deletions ?? 0;
|
|
@@ -31876,7 +32138,7 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
|
|
|
31876
32138
|
deletions = fromGit.deletions;
|
|
31877
32139
|
} else {
|
|
31878
32140
|
try {
|
|
31879
|
-
const st = await
|
|
32141
|
+
const st = await fs17.promises.stat(repoFilePath);
|
|
31880
32142
|
if (st.isFile()) additions = await countTextFileLines(repoFilePath);
|
|
31881
32143
|
else additions = 0;
|
|
31882
32144
|
} catch {
|
|
@@ -31902,7 +32164,7 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
|
|
|
31902
32164
|
} else {
|
|
31903
32165
|
pathInRepo = row.pathRelLauncher;
|
|
31904
32166
|
}
|
|
31905
|
-
const filePath =
|
|
32167
|
+
const filePath = path16.join(repoGitCwd, pathInRepo);
|
|
31906
32168
|
let patch = await unifiedDiffForFile(repoGitCwd, pathInRepo, row.change);
|
|
31907
32169
|
if (patch) {
|
|
31908
32170
|
patch = await hydrateUnifiedPatchWithFileContext(patch, filePath, repoGitCwd, pathInRepo, row.change);
|
|
@@ -31918,8 +32180,8 @@ function normRepoRel(p) {
|
|
|
31918
32180
|
return x === "" ? "." : x;
|
|
31919
32181
|
}
|
|
31920
32182
|
async function getWorkingTreeChangeRepoDetails(options) {
|
|
31921
|
-
const bridgeRoot =
|
|
31922
|
-
const sessionWtRoot = options.sessionWorktreeRootPath ?
|
|
32183
|
+
const bridgeRoot = path17.resolve(getBridgeRoot());
|
|
32184
|
+
const sessionWtRoot = options.sessionWorktreeRootPath ? path17.resolve(options.sessionWorktreeRootPath) : null;
|
|
31923
32185
|
const legacyNested = options.legacyRepoNestedSessionLayout === true;
|
|
31924
32186
|
const out = [];
|
|
31925
32187
|
const filter = options.repoFilterRelPath != null ? normRepoRel(options.repoFilterRelPath) : null;
|
|
@@ -31932,7 +32194,7 @@ async function getWorkingTreeChangeRepoDetails(options) {
|
|
|
31932
32194
|
}
|
|
31933
32195
|
const basis = filter == null && basisInput.kind === "commit" ? { kind: "working" } : basisInput;
|
|
31934
32196
|
for (const target of options.commitTargetPaths) {
|
|
31935
|
-
const t =
|
|
32197
|
+
const t = path17.resolve(target);
|
|
31936
32198
|
if (!await isGitRepoDirectory(t)) continue;
|
|
31937
32199
|
const g = cliSimpleGit(t);
|
|
31938
32200
|
let branch = "HEAD";
|
|
@@ -31945,8 +32207,8 @@ async function getWorkingTreeChangeRepoDetails(options) {
|
|
|
31945
32207
|
const remoteDisplay = formatRemoteDisplayLabel(remoteUrl);
|
|
31946
32208
|
let repoRelPath;
|
|
31947
32209
|
if (sessionWtRoot) {
|
|
31948
|
-
const anchor = legacyNested ?
|
|
31949
|
-
const relNorm =
|
|
32210
|
+
const anchor = legacyNested ? path17.dirname(t) : t;
|
|
32211
|
+
const relNorm = path17.relative(sessionWtRoot, anchor);
|
|
31950
32212
|
repoRelPath = relNorm === "" ? "." : relNorm.replace(/\\/g, "/");
|
|
31951
32213
|
} else {
|
|
31952
32214
|
let top = t;
|
|
@@ -31955,8 +32217,8 @@ async function getWorkingTreeChangeRepoDetails(options) {
|
|
|
31955
32217
|
} catch {
|
|
31956
32218
|
top = t;
|
|
31957
32219
|
}
|
|
31958
|
-
const rel =
|
|
31959
|
-
repoRelPath = rel.startsWith("..") ?
|
|
32220
|
+
const rel = path17.relative(bridgeRoot, path17.resolve(top)).replace(/\\/g, "/") || ".";
|
|
32221
|
+
repoRelPath = rel.startsWith("..") ? path17.basename(path17.resolve(top)) : rel;
|
|
31960
32222
|
}
|
|
31961
32223
|
const norm = normRepoRel(repoRelPath === "" ? "." : repoRelPath);
|
|
31962
32224
|
if (filter && norm !== filter) continue;
|
|
@@ -32021,11 +32283,11 @@ async function commitSessionWorktrees(options) {
|
|
|
32021
32283
|
}
|
|
32022
32284
|
|
|
32023
32285
|
// src/worktrees/discover-session-worktree-on-disk.ts
|
|
32024
|
-
import * as
|
|
32025
|
-
import * as
|
|
32286
|
+
import * as fs18 from "node:fs";
|
|
32287
|
+
import * as path18 from "node:path";
|
|
32026
32288
|
function isGitDir(dirPath) {
|
|
32027
32289
|
try {
|
|
32028
|
-
return
|
|
32290
|
+
return fs18.existsSync(path18.join(dirPath, ".git"));
|
|
32029
32291
|
} catch {
|
|
32030
32292
|
return false;
|
|
32031
32293
|
}
|
|
@@ -32034,23 +32296,23 @@ function collectGitRepoRootsUnderDirectory(rootPath) {
|
|
|
32034
32296
|
const out = [];
|
|
32035
32297
|
const walk = (dir) => {
|
|
32036
32298
|
if (isGitDir(dir)) {
|
|
32037
|
-
out.push(
|
|
32299
|
+
out.push(path18.resolve(dir));
|
|
32038
32300
|
return;
|
|
32039
32301
|
}
|
|
32040
32302
|
let entries;
|
|
32041
32303
|
try {
|
|
32042
|
-
entries =
|
|
32304
|
+
entries = fs18.readdirSync(dir, { withFileTypes: true });
|
|
32043
32305
|
} catch {
|
|
32044
32306
|
return;
|
|
32045
32307
|
}
|
|
32046
32308
|
for (const e of entries) {
|
|
32047
32309
|
if (e.name.startsWith(".")) continue;
|
|
32048
|
-
const full =
|
|
32310
|
+
const full = path18.join(dir, e.name);
|
|
32049
32311
|
if (!e.isDirectory()) continue;
|
|
32050
32312
|
walk(full);
|
|
32051
32313
|
}
|
|
32052
32314
|
};
|
|
32053
|
-
walk(
|
|
32315
|
+
walk(path18.resolve(rootPath));
|
|
32054
32316
|
return [...new Set(out)];
|
|
32055
32317
|
}
|
|
32056
32318
|
function collectWorktreeRootsNamed(root, sessionId, maxDepth) {
|
|
@@ -32059,16 +32321,16 @@ function collectWorktreeRootsNamed(root, sessionId, maxDepth) {
|
|
|
32059
32321
|
if (depth > maxDepth) return;
|
|
32060
32322
|
let entries;
|
|
32061
32323
|
try {
|
|
32062
|
-
entries =
|
|
32324
|
+
entries = fs18.readdirSync(dir, { withFileTypes: true });
|
|
32063
32325
|
} catch {
|
|
32064
32326
|
return;
|
|
32065
32327
|
}
|
|
32066
32328
|
for (const e of entries) {
|
|
32067
32329
|
if (e.name.startsWith(".")) continue;
|
|
32068
|
-
const full =
|
|
32330
|
+
const full = path18.join(dir, e.name);
|
|
32069
32331
|
if (!e.isDirectory()) continue;
|
|
32070
32332
|
if (e.name === sessionId) {
|
|
32071
|
-
if (isGitDir(full)) out.push(
|
|
32333
|
+
if (isGitDir(full)) out.push(path18.resolve(full));
|
|
32072
32334
|
} else {
|
|
32073
32335
|
walk(full, depth + 1);
|
|
32074
32336
|
}
|
|
@@ -32080,14 +32342,14 @@ function collectWorktreeRootsNamed(root, sessionId, maxDepth) {
|
|
|
32080
32342
|
function tryBindingFromSessionDirectory(sessionDir) {
|
|
32081
32343
|
let st;
|
|
32082
32344
|
try {
|
|
32083
|
-
st =
|
|
32345
|
+
st = fs18.statSync(sessionDir);
|
|
32084
32346
|
} catch {
|
|
32085
32347
|
return null;
|
|
32086
32348
|
}
|
|
32087
32349
|
if (!st.isDirectory()) return null;
|
|
32088
32350
|
const worktreePaths = collectGitRepoRootsUnderDirectory(sessionDir);
|
|
32089
32351
|
if (worktreePaths.length === 0) return null;
|
|
32090
|
-
const abs =
|
|
32352
|
+
const abs = path18.resolve(sessionDir);
|
|
32091
32353
|
return {
|
|
32092
32354
|
sessionParentPath: abs,
|
|
32093
32355
|
workingTreeRelRoot: abs,
|
|
@@ -32097,20 +32359,20 @@ function tryBindingFromSessionDirectory(sessionDir) {
|
|
|
32097
32359
|
function discoverLegacyBindingAscendingFromCheckout(sessionId, checkoutPath) {
|
|
32098
32360
|
const sid = sessionId.trim();
|
|
32099
32361
|
if (!sid) return null;
|
|
32100
|
-
const hintR =
|
|
32362
|
+
const hintR = path18.resolve(checkoutPath);
|
|
32101
32363
|
let best = null;
|
|
32102
|
-
let cur =
|
|
32364
|
+
let cur = path18.dirname(hintR);
|
|
32103
32365
|
for (let i = 0; i < 40; i++) {
|
|
32104
32366
|
const paths = collectWorktreeRootsNamed(cur, sid, 24);
|
|
32105
|
-
if (paths.some((p) =>
|
|
32106
|
-
const isolated = resolveIsolatedSessionParentPathFromCheckouts(paths) ??
|
|
32367
|
+
if (paths.some((p) => path18.resolve(p) === hintR)) {
|
|
32368
|
+
const isolated = resolveIsolatedSessionParentPathFromCheckouts(paths) ?? path18.resolve(paths[0]);
|
|
32107
32369
|
best = {
|
|
32108
|
-
sessionParentPath:
|
|
32109
|
-
workingTreeRelRoot:
|
|
32110
|
-
repoCheckoutPaths: paths.map((p) =>
|
|
32370
|
+
sessionParentPath: path18.resolve(isolated),
|
|
32371
|
+
workingTreeRelRoot: path18.resolve(cur),
|
|
32372
|
+
repoCheckoutPaths: paths.map((p) => path18.resolve(p))
|
|
32111
32373
|
};
|
|
32112
32374
|
}
|
|
32113
|
-
const next =
|
|
32375
|
+
const next = path18.dirname(cur);
|
|
32114
32376
|
if (next === cur) break;
|
|
32115
32377
|
cur = next;
|
|
32116
32378
|
}
|
|
@@ -32118,33 +32380,33 @@ function discoverLegacyBindingAscendingFromCheckout(sessionId, checkoutPath) {
|
|
|
32118
32380
|
}
|
|
32119
32381
|
function discoverSessionWorktreeOnDisk(options) {
|
|
32120
32382
|
const { sessionId, worktreesRootPath, layout, bridgeRoot } = options;
|
|
32121
|
-
if (!sessionId.trim() || !
|
|
32383
|
+
if (!sessionId.trim() || !fs18.existsSync(worktreesRootPath)) return null;
|
|
32122
32384
|
const preferredKey = getLauncherDirNameIfPresent(layout, bridgeRoot);
|
|
32123
32385
|
const keys = [];
|
|
32124
32386
|
if (preferredKey) keys.push(preferredKey);
|
|
32125
32387
|
try {
|
|
32126
|
-
for (const name of
|
|
32388
|
+
for (const name of fs18.readdirSync(worktreesRootPath)) {
|
|
32127
32389
|
if (name.startsWith(".")) continue;
|
|
32128
|
-
const p =
|
|
32129
|
-
if (!
|
|
32390
|
+
const p = path18.join(worktreesRootPath, name);
|
|
32391
|
+
if (!fs18.statSync(p).isDirectory()) continue;
|
|
32130
32392
|
if (name !== preferredKey) keys.push(name);
|
|
32131
32393
|
}
|
|
32132
32394
|
} catch {
|
|
32133
32395
|
return null;
|
|
32134
32396
|
}
|
|
32135
32397
|
for (const key of keys) {
|
|
32136
|
-
const layoutRoot =
|
|
32137
|
-
if (!
|
|
32138
|
-
const sessionDir =
|
|
32398
|
+
const layoutRoot = path18.join(worktreesRootPath, key);
|
|
32399
|
+
if (!fs18.existsSync(layoutRoot) || !fs18.statSync(layoutRoot).isDirectory()) continue;
|
|
32400
|
+
const sessionDir = path18.join(layoutRoot, sessionId);
|
|
32139
32401
|
const nested = tryBindingFromSessionDirectory(sessionDir);
|
|
32140
32402
|
if (nested) return nested;
|
|
32141
32403
|
const legacyPaths = collectWorktreeRootsNamed(layoutRoot, sessionId, 24);
|
|
32142
32404
|
if (legacyPaths.length > 0) {
|
|
32143
|
-
const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ??
|
|
32405
|
+
const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ?? path18.resolve(legacyPaths[0]);
|
|
32144
32406
|
return {
|
|
32145
|
-
sessionParentPath:
|
|
32146
|
-
workingTreeRelRoot:
|
|
32147
|
-
repoCheckoutPaths: legacyPaths.map((p) =>
|
|
32407
|
+
sessionParentPath: path18.resolve(isolated),
|
|
32408
|
+
workingTreeRelRoot: path18.resolve(layoutRoot),
|
|
32409
|
+
repoCheckoutPaths: legacyPaths.map((p) => path18.resolve(p))
|
|
32148
32410
|
};
|
|
32149
32411
|
}
|
|
32150
32412
|
}
|
|
@@ -32153,12 +32415,12 @@ function discoverSessionWorktreeOnDisk(options) {
|
|
|
32153
32415
|
function discoverSessionWorktreesUnderSessionWorktreeRoot(sessionWorktreeRootPathOrHint, sessionId) {
|
|
32154
32416
|
const sid = sessionId.trim();
|
|
32155
32417
|
if (!sid) return null;
|
|
32156
|
-
const hint =
|
|
32157
|
-
const underHint = tryBindingFromSessionDirectory(
|
|
32418
|
+
const hint = path18.resolve(sessionWorktreeRootPathOrHint);
|
|
32419
|
+
const underHint = tryBindingFromSessionDirectory(path18.join(hint, sid));
|
|
32158
32420
|
if (underHint) return underHint;
|
|
32159
32421
|
const direct = tryBindingFromSessionDirectory(hint);
|
|
32160
32422
|
if (direct) {
|
|
32161
|
-
if (
|
|
32423
|
+
if (path18.basename(hint) === sid && isGitDir(hint)) {
|
|
32162
32424
|
const legacyFromCheckout = discoverLegacyBindingAscendingFromCheckout(sid, hint);
|
|
32163
32425
|
if (legacyFromCheckout && legacyFromCheckout.repoCheckoutPaths.length > direct.repoCheckoutPaths.length) {
|
|
32164
32426
|
return legacyFromCheckout;
|
|
@@ -32166,24 +32428,24 @@ function discoverSessionWorktreesUnderSessionWorktreeRoot(sessionWorktreeRootPat
|
|
|
32166
32428
|
}
|
|
32167
32429
|
return direct;
|
|
32168
32430
|
}
|
|
32169
|
-
if (
|
|
32431
|
+
if (path18.basename(hint) === sid && isGitDir(hint)) {
|
|
32170
32432
|
const legacyFromCheckout = discoverLegacyBindingAscendingFromCheckout(sid, hint);
|
|
32171
32433
|
if (legacyFromCheckout) return legacyFromCheckout;
|
|
32172
32434
|
}
|
|
32173
32435
|
let st;
|
|
32174
32436
|
try {
|
|
32175
|
-
st =
|
|
32437
|
+
st = fs18.statSync(hint);
|
|
32176
32438
|
} catch {
|
|
32177
32439
|
return null;
|
|
32178
32440
|
}
|
|
32179
32441
|
if (!st.isDirectory()) return null;
|
|
32180
32442
|
const legacyPaths = collectWorktreeRootsNamed(hint, sid, 24);
|
|
32181
32443
|
if (legacyPaths.length === 0) return null;
|
|
32182
|
-
const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ??
|
|
32444
|
+
const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ?? path18.resolve(legacyPaths[0]);
|
|
32183
32445
|
return {
|
|
32184
|
-
sessionParentPath:
|
|
32446
|
+
sessionParentPath: path18.resolve(isolated),
|
|
32185
32447
|
workingTreeRelRoot: hint,
|
|
32186
|
-
repoCheckoutPaths: legacyPaths.map((p) =>
|
|
32448
|
+
repoCheckoutPaths: legacyPaths.map((p) => path18.resolve(p))
|
|
32187
32449
|
};
|
|
32188
32450
|
}
|
|
32189
32451
|
|
|
@@ -32206,10 +32468,10 @@ var SessionWorktreeManager = class {
|
|
|
32206
32468
|
this.layout = loadWorktreeLayout();
|
|
32207
32469
|
}
|
|
32208
32470
|
rememberSessionWorktrees(sessionId, binding) {
|
|
32209
|
-
const paths = binding.repoCheckoutPaths.map((p) =>
|
|
32471
|
+
const paths = binding.repoCheckoutPaths.map((p) => path19.resolve(p));
|
|
32210
32472
|
this.sessionRepoCheckoutPaths.set(sessionId, paths);
|
|
32211
|
-
this.sessionParentPathBySession.set(sessionId,
|
|
32212
|
-
this.sessionWorkingTreeRelRootBySession.set(sessionId,
|
|
32473
|
+
this.sessionParentPathBySession.set(sessionId, path19.resolve(binding.sessionParentPath));
|
|
32474
|
+
this.sessionWorkingTreeRelRootBySession.set(sessionId, path19.resolve(binding.workingTreeRelRoot));
|
|
32213
32475
|
}
|
|
32214
32476
|
sessionParentPathAfterRemember(sessionId) {
|
|
32215
32477
|
return this.sessionParentPathBySession.get(sessionId);
|
|
@@ -32226,7 +32488,7 @@ var SessionWorktreeManager = class {
|
|
|
32226
32488
|
const parent = this.sessionParentPathBySession.get(sessionId);
|
|
32227
32489
|
const relRoot = this.sessionWorkingTreeRelRootBySession.get(sessionId);
|
|
32228
32490
|
if (!parent || !relRoot) return false;
|
|
32229
|
-
return
|
|
32491
|
+
return path19.resolve(parent) !== path19.resolve(relRoot);
|
|
32230
32492
|
}
|
|
32231
32493
|
/**
|
|
32232
32494
|
* Session parent path for `worktrees_root`: the per-session directory (new layout) or primary checkout (legacy).
|
|
@@ -32235,7 +32497,7 @@ var SessionWorktreeManager = class {
|
|
|
32235
32497
|
if (!sessionId) return null;
|
|
32236
32498
|
const sid = sessionId.trim();
|
|
32237
32499
|
const cached2 = this.sessionParentPathBySession.get(sid);
|
|
32238
|
-
if (cached2) return
|
|
32500
|
+
if (cached2) return path19.resolve(cached2);
|
|
32239
32501
|
const paths = this.ensureRepoCheckoutPathsForSession(sid) ?? this.getRepoCheckoutPathsForSession(sid);
|
|
32240
32502
|
if (!paths?.length) return null;
|
|
32241
32503
|
return resolveIsolatedSessionParentPathFromCheckouts(paths);
|
|
@@ -32249,7 +32511,7 @@ var SessionWorktreeManager = class {
|
|
|
32249
32511
|
const sid = sessionId.trim();
|
|
32250
32512
|
const parentPathRaw = opts.sessionParentPath?.trim();
|
|
32251
32513
|
if (parentPathRaw) {
|
|
32252
|
-
const resolved =
|
|
32514
|
+
const resolved = path19.resolve(parentPathRaw);
|
|
32253
32515
|
if (sid && parseSessionParent(opts.sessionParent) === "worktrees_root") {
|
|
32254
32516
|
const diskFirst = this.tryDiscoverFromDisk(sid);
|
|
32255
32517
|
if (diskFirst) {
|
|
@@ -32268,7 +32530,7 @@ var SessionWorktreeManager = class {
|
|
|
32268
32530
|
this.rememberSessionWorktrees(sid, tryRoot);
|
|
32269
32531
|
return this.sessionParentPathAfterRemember(sid);
|
|
32270
32532
|
}
|
|
32271
|
-
const next =
|
|
32533
|
+
const next = path19.dirname(cur);
|
|
32272
32534
|
if (next === cur) break;
|
|
32273
32535
|
cur = next;
|
|
32274
32536
|
}
|
|
@@ -32421,15 +32683,15 @@ var SessionWorktreeManager = class {
|
|
|
32421
32683
|
}
|
|
32422
32684
|
};
|
|
32423
32685
|
function defaultWorktreesRootPath() {
|
|
32424
|
-
return
|
|
32686
|
+
return path19.join(os5.homedir(), ".buildautomaton", "worktrees");
|
|
32425
32687
|
}
|
|
32426
32688
|
|
|
32427
32689
|
// src/files/watch-file-index.ts
|
|
32428
32690
|
import { watch } from "node:fs";
|
|
32429
|
-
import
|
|
32691
|
+
import path26 from "node:path";
|
|
32430
32692
|
|
|
32431
32693
|
// src/files/index/build-file-index.ts
|
|
32432
|
-
import
|
|
32694
|
+
import path23 from "node:path";
|
|
32433
32695
|
|
|
32434
32696
|
// src/runtime/yield-to-event-loop.ts
|
|
32435
32697
|
function yieldToEventLoop() {
|
|
@@ -32437,14 +32699,14 @@ function yieldToEventLoop() {
|
|
|
32437
32699
|
}
|
|
32438
32700
|
|
|
32439
32701
|
// src/files/index/walk-workspace-tree.ts
|
|
32440
|
-
import
|
|
32441
|
-
import
|
|
32702
|
+
import fs19 from "node:fs";
|
|
32703
|
+
import path21 from "node:path";
|
|
32442
32704
|
|
|
32443
32705
|
// src/files/index/constants.ts
|
|
32444
|
-
import
|
|
32445
|
-
import
|
|
32706
|
+
import path20 from "node:path";
|
|
32707
|
+
import os6 from "node:os";
|
|
32446
32708
|
var INDEX_WORK_YIELD_EVERY = 256;
|
|
32447
|
-
var INDEX_DIR =
|
|
32709
|
+
var INDEX_DIR = path20.join(os6.homedir(), ".buildautomaton");
|
|
32448
32710
|
var INDEX_HASH_LEN = 16;
|
|
32449
32711
|
var INDEX_VERSION = 2;
|
|
32450
32712
|
var INDEX_LOG_PREFIX = "[file-index]";
|
|
@@ -32453,20 +32715,20 @@ var INDEX_LOG_PREFIX = "[file-index]";
|
|
|
32453
32715
|
function walkWorkspaceTreeSync(dir, baseDir, out) {
|
|
32454
32716
|
let names;
|
|
32455
32717
|
try {
|
|
32456
|
-
names =
|
|
32718
|
+
names = fs19.readdirSync(dir);
|
|
32457
32719
|
} catch {
|
|
32458
32720
|
return;
|
|
32459
32721
|
}
|
|
32460
32722
|
for (const name of names) {
|
|
32461
32723
|
if (name.startsWith(".")) continue;
|
|
32462
|
-
const full =
|
|
32724
|
+
const full = path21.join(dir, name);
|
|
32463
32725
|
let stat2;
|
|
32464
32726
|
try {
|
|
32465
|
-
stat2 =
|
|
32727
|
+
stat2 = fs19.statSync(full);
|
|
32466
32728
|
} catch {
|
|
32467
32729
|
continue;
|
|
32468
32730
|
}
|
|
32469
|
-
const relative5 =
|
|
32731
|
+
const relative5 = path21.relative(baseDir, full).replace(/\\/g, "/");
|
|
32470
32732
|
if (stat2.isDirectory()) {
|
|
32471
32733
|
walkWorkspaceTreeSync(full, baseDir, out);
|
|
32472
32734
|
} else if (stat2.isFile()) {
|
|
@@ -32477,7 +32739,7 @@ function walkWorkspaceTreeSync(dir, baseDir, out) {
|
|
|
32477
32739
|
async function walkWorkspaceTreeAsync(dir, baseDir, out, state) {
|
|
32478
32740
|
let names;
|
|
32479
32741
|
try {
|
|
32480
|
-
names = await
|
|
32742
|
+
names = await fs19.promises.readdir(dir);
|
|
32481
32743
|
} catch {
|
|
32482
32744
|
return;
|
|
32483
32745
|
}
|
|
@@ -32487,14 +32749,14 @@ async function walkWorkspaceTreeAsync(dir, baseDir, out, state) {
|
|
|
32487
32749
|
await yieldToEventLoop();
|
|
32488
32750
|
}
|
|
32489
32751
|
state.n++;
|
|
32490
|
-
const full =
|
|
32752
|
+
const full = path21.join(dir, name);
|
|
32491
32753
|
let stat2;
|
|
32492
32754
|
try {
|
|
32493
|
-
stat2 = await
|
|
32755
|
+
stat2 = await fs19.promises.stat(full);
|
|
32494
32756
|
} catch {
|
|
32495
32757
|
continue;
|
|
32496
32758
|
}
|
|
32497
|
-
const relative5 =
|
|
32759
|
+
const relative5 = path21.relative(baseDir, full).replace(/\\/g, "/");
|
|
32498
32760
|
if (stat2.isDirectory()) {
|
|
32499
32761
|
await walkWorkspaceTreeAsync(full, baseDir, out, state);
|
|
32500
32762
|
} else if (stat2.isFile()) {
|
|
@@ -32575,22 +32837,22 @@ async function buildTrigramMapForPathsAsync(paths) {
|
|
|
32575
32837
|
}
|
|
32576
32838
|
|
|
32577
32839
|
// src/files/index/write-index-file.ts
|
|
32578
|
-
import
|
|
32840
|
+
import fs20 from "node:fs";
|
|
32579
32841
|
|
|
32580
32842
|
// src/files/index/paths.ts
|
|
32581
|
-
import
|
|
32843
|
+
import path22 from "node:path";
|
|
32582
32844
|
import crypto2 from "node:crypto";
|
|
32583
32845
|
function getIndexPathForCwd(resolvedCwd) {
|
|
32584
32846
|
const hash = crypto2.createHash("sha256").update(resolvedCwd).digest("hex").slice(0, INDEX_HASH_LEN);
|
|
32585
|
-
return
|
|
32847
|
+
return path22.join(INDEX_DIR, `.file-index-${hash}.json`);
|
|
32586
32848
|
}
|
|
32587
32849
|
|
|
32588
32850
|
// src/files/index/write-index-file.ts
|
|
32589
32851
|
function writeIndexFileSync(resolvedCwd, data) {
|
|
32590
32852
|
const indexPath = getIndexPathForCwd(resolvedCwd);
|
|
32591
32853
|
try {
|
|
32592
|
-
if (!
|
|
32593
|
-
|
|
32854
|
+
if (!fs20.existsSync(INDEX_DIR)) fs20.mkdirSync(INDEX_DIR, { recursive: true });
|
|
32855
|
+
fs20.writeFileSync(indexPath, JSON.stringify(data), "utf8");
|
|
32594
32856
|
} catch (e) {
|
|
32595
32857
|
console.error(`${INDEX_LOG_PREFIX} Failed to write index:`, e);
|
|
32596
32858
|
}
|
|
@@ -32598,8 +32860,8 @@ function writeIndexFileSync(resolvedCwd, data) {
|
|
|
32598
32860
|
async function writeIndexFileAsync(resolvedCwd, data) {
|
|
32599
32861
|
const indexPath = getIndexPathForCwd(resolvedCwd);
|
|
32600
32862
|
try {
|
|
32601
|
-
await
|
|
32602
|
-
await
|
|
32863
|
+
await fs20.promises.mkdir(INDEX_DIR, { recursive: true });
|
|
32864
|
+
await fs20.promises.writeFile(indexPath, JSON.stringify(data), "utf8");
|
|
32603
32865
|
} catch (e) {
|
|
32604
32866
|
console.error(`${INDEX_LOG_PREFIX} Failed to write index:`, e);
|
|
32605
32867
|
}
|
|
@@ -32613,7 +32875,7 @@ function sortPaths(paths) {
|
|
|
32613
32875
|
paths.sort((a, b) => a.localeCompare(b, void 0, { sensitivity: "base" }));
|
|
32614
32876
|
}
|
|
32615
32877
|
function buildFileIndex(cwd) {
|
|
32616
|
-
const resolved =
|
|
32878
|
+
const resolved = path23.resolve(cwd);
|
|
32617
32879
|
const paths = [];
|
|
32618
32880
|
walkWorkspaceTreeSync(resolved, resolved, paths);
|
|
32619
32881
|
sortPaths(paths);
|
|
@@ -32623,7 +32885,7 @@ function buildFileIndex(cwd) {
|
|
|
32623
32885
|
return data;
|
|
32624
32886
|
}
|
|
32625
32887
|
async function buildFileIndexAsync(cwd) {
|
|
32626
|
-
const resolved =
|
|
32888
|
+
const resolved = path23.resolve(cwd);
|
|
32627
32889
|
const paths = [];
|
|
32628
32890
|
await walkWorkspaceTreeAsync(resolved, resolved, paths, createWalkYieldState());
|
|
32629
32891
|
await yieldToEventLoop();
|
|
@@ -32635,13 +32897,13 @@ async function buildFileIndexAsync(cwd) {
|
|
|
32635
32897
|
}
|
|
32636
32898
|
|
|
32637
32899
|
// src/files/index/load-file-index.ts
|
|
32638
|
-
import
|
|
32639
|
-
import
|
|
32900
|
+
import fs21 from "node:fs";
|
|
32901
|
+
import path24 from "node:path";
|
|
32640
32902
|
function loadFileIndex(cwd) {
|
|
32641
|
-
const resolved =
|
|
32903
|
+
const resolved = path24.resolve(cwd);
|
|
32642
32904
|
const indexPath = getIndexPathForCwd(resolved);
|
|
32643
32905
|
try {
|
|
32644
|
-
const raw =
|
|
32906
|
+
const raw = fs21.readFileSync(indexPath, "utf8");
|
|
32645
32907
|
const parsed = JSON.parse(raw);
|
|
32646
32908
|
if (parsed !== null && typeof parsed === "object" && Array.isArray(parsed.paths)) {
|
|
32647
32909
|
const obj = parsed;
|
|
@@ -32660,9 +32922,9 @@ function loadFileIndex(cwd) {
|
|
|
32660
32922
|
}
|
|
32661
32923
|
|
|
32662
32924
|
// src/files/index/ensure-file-index.ts
|
|
32663
|
-
import
|
|
32925
|
+
import path25 from "node:path";
|
|
32664
32926
|
async function ensureFileIndexAsync(cwd) {
|
|
32665
|
-
const resolved =
|
|
32927
|
+
const resolved = path25.resolve(cwd);
|
|
32666
32928
|
const cached2 = loadFileIndex(resolved);
|
|
32667
32929
|
if (cached2 !== null) return { data: cached2, fromCache: true };
|
|
32668
32930
|
const data = await buildFileIndexAsync(resolved);
|
|
@@ -32745,7 +33007,7 @@ function createFsWatcher(resolved, schedule) {
|
|
|
32745
33007
|
}
|
|
32746
33008
|
}
|
|
32747
33009
|
function startFileIndexWatcher(cwd = getBridgeRoot()) {
|
|
32748
|
-
const resolved =
|
|
33010
|
+
const resolved = path26.resolve(cwd);
|
|
32749
33011
|
void buildFileIndexAsync(resolved).catch((e) => {
|
|
32750
33012
|
console.error("[file-index] Initial index build failed:", e);
|
|
32751
33013
|
});
|
|
@@ -32773,7 +33035,7 @@ function startFileIndexWatcher(cwd = getBridgeRoot()) {
|
|
|
32773
33035
|
}
|
|
32774
33036
|
|
|
32775
33037
|
// src/connection/create-bridge-connection.ts
|
|
32776
|
-
import * as
|
|
33038
|
+
import * as path34 from "node:path";
|
|
32777
33039
|
|
|
32778
33040
|
// src/dev-servers/manager/dev-server-manager.ts
|
|
32779
33041
|
import { rm as rm2 } from "node:fs/promises";
|
|
@@ -32817,7 +33079,7 @@ function forceKillChild(proc, log2, shortId, graceMs) {
|
|
|
32817
33079
|
}
|
|
32818
33080
|
|
|
32819
33081
|
// src/dev-servers/process/wire-dev-server-child-process.ts
|
|
32820
|
-
import
|
|
33082
|
+
import fs22 from "node:fs";
|
|
32821
33083
|
|
|
32822
33084
|
// src/dev-servers/manager/forward-pipe.ts
|
|
32823
33085
|
function forwardChildPipe(childReadable, terminal, onData) {
|
|
@@ -32853,7 +33115,7 @@ function wireDevServerChildProcess(d) {
|
|
|
32853
33115
|
d.setPollInterval(void 0);
|
|
32854
33116
|
return;
|
|
32855
33117
|
}
|
|
32856
|
-
|
|
33118
|
+
fs22.readFile(d.mergedLogPath, (err, buf) => {
|
|
32857
33119
|
if (err || (d.getSpawnGeneration() ?? 0) !== d.scheduledGen) return;
|
|
32858
33120
|
if (buf.length <= d.mergedReadPos.value) return;
|
|
32859
33121
|
const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
|
|
@@ -32891,7 +33153,7 @@ ${errTail}` : ""}`);
|
|
|
32891
33153
|
d.sendStatus(code === 0 || code == null ? "stopped" : "error", detail, tails);
|
|
32892
33154
|
};
|
|
32893
33155
|
if (mergedPath) {
|
|
32894
|
-
|
|
33156
|
+
fs22.readFile(mergedPath, (err, buf) => {
|
|
32895
33157
|
if (!err && buf.length > d.mergedReadPos.value) {
|
|
32896
33158
|
const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
|
|
32897
33159
|
if (chunk.length > 0) {
|
|
@@ -32993,13 +33255,13 @@ function parseDevServerDefs(servers) {
|
|
|
32993
33255
|
}
|
|
32994
33256
|
|
|
32995
33257
|
// src/dev-servers/manager/shell-spawn/utils.ts
|
|
32996
|
-
import
|
|
33258
|
+
import fs23 from "node:fs";
|
|
32997
33259
|
function isSpawnEbadf(e) {
|
|
32998
33260
|
return typeof e === "object" && e !== null && "code" in e && e.code === "EBADF";
|
|
32999
33261
|
}
|
|
33000
33262
|
function rmDirQuiet(dir) {
|
|
33001
33263
|
try {
|
|
33002
|
-
|
|
33264
|
+
fs23.rmSync(dir, { recursive: true, force: true });
|
|
33003
33265
|
} catch {
|
|
33004
33266
|
}
|
|
33005
33267
|
}
|
|
@@ -33007,7 +33269,7 @@ var cachedDevNullReadFd;
|
|
|
33007
33269
|
function devNullReadFd() {
|
|
33008
33270
|
if (cachedDevNullReadFd === void 0) {
|
|
33009
33271
|
const devPath = process.platform === "win32" ? "nul" : "/dev/null";
|
|
33010
|
-
cachedDevNullReadFd =
|
|
33272
|
+
cachedDevNullReadFd = fs23.openSync(devPath, "r");
|
|
33011
33273
|
}
|
|
33012
33274
|
return cachedDevNullReadFd;
|
|
33013
33275
|
}
|
|
@@ -33081,15 +33343,15 @@ function trySpawnShellTruePiped(command, env, cwd, devNullFd, signal) {
|
|
|
33081
33343
|
|
|
33082
33344
|
// src/dev-servers/manager/shell-spawn/try-spawn-merged-log-file.ts
|
|
33083
33345
|
import { spawn as spawn7 } from "node:child_process";
|
|
33084
|
-
import
|
|
33346
|
+
import fs24 from "node:fs";
|
|
33085
33347
|
import { tmpdir } from "node:os";
|
|
33086
|
-
import
|
|
33348
|
+
import path27 from "node:path";
|
|
33087
33349
|
function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
33088
|
-
const tmpRoot =
|
|
33089
|
-
const logPath =
|
|
33350
|
+
const tmpRoot = fs24.mkdtempSync(path27.join(tmpdir(), "ba-devsrv-log-"));
|
|
33351
|
+
const logPath = path27.join(tmpRoot, "combined.log");
|
|
33090
33352
|
let logFd;
|
|
33091
33353
|
try {
|
|
33092
|
-
logFd =
|
|
33354
|
+
logFd = fs24.openSync(logPath, "a");
|
|
33093
33355
|
} catch {
|
|
33094
33356
|
rmDirQuiet(tmpRoot);
|
|
33095
33357
|
return null;
|
|
@@ -33108,7 +33370,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
33108
33370
|
} else {
|
|
33109
33371
|
proc = spawn7("/bin/sh", ["-c", command], { env, cwd, stdio, ...signal ? { signal } : {} });
|
|
33110
33372
|
}
|
|
33111
|
-
|
|
33373
|
+
fs24.closeSync(logFd);
|
|
33112
33374
|
return {
|
|
33113
33375
|
proc,
|
|
33114
33376
|
pipedStdoutStderr: true,
|
|
@@ -33117,7 +33379,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
33117
33379
|
};
|
|
33118
33380
|
} catch (e) {
|
|
33119
33381
|
try {
|
|
33120
|
-
|
|
33382
|
+
fs24.closeSync(logFd);
|
|
33121
33383
|
} catch {
|
|
33122
33384
|
}
|
|
33123
33385
|
rmDirQuiet(tmpRoot);
|
|
@@ -33128,22 +33390,22 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
33128
33390
|
|
|
33129
33391
|
// src/dev-servers/manager/shell-spawn/try-spawn-shell-script-log-redirect.ts
|
|
33130
33392
|
import { spawn as spawn8 } from "node:child_process";
|
|
33131
|
-
import
|
|
33393
|
+
import fs25 from "node:fs";
|
|
33132
33394
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
33133
|
-
import
|
|
33395
|
+
import path28 from "node:path";
|
|
33134
33396
|
function shSingleQuote(s) {
|
|
33135
33397
|
return `'${s.replace(/'/g, `'\\''`)}'`;
|
|
33136
33398
|
}
|
|
33137
33399
|
function trySpawnShellScriptLogRedirectUnix(command, env, cwd, signal) {
|
|
33138
|
-
const tmpRoot =
|
|
33139
|
-
const logPath =
|
|
33140
|
-
const innerPath =
|
|
33141
|
-
const runnerPath =
|
|
33400
|
+
const tmpRoot = fs25.mkdtempSync(path28.join(tmpdir2(), "ba-devsrv-sh-"));
|
|
33401
|
+
const logPath = path28.join(tmpRoot, "combined.log");
|
|
33402
|
+
const innerPath = path28.join(tmpRoot, "_cmd.sh");
|
|
33403
|
+
const runnerPath = path28.join(tmpRoot, "_run.sh");
|
|
33142
33404
|
try {
|
|
33143
|
-
|
|
33405
|
+
fs25.writeFileSync(innerPath, `#!/bin/sh
|
|
33144
33406
|
${command}
|
|
33145
33407
|
`);
|
|
33146
|
-
|
|
33408
|
+
fs25.writeFileSync(
|
|
33147
33409
|
runnerPath,
|
|
33148
33410
|
`#!/bin/sh
|
|
33149
33411
|
cd ${shSingleQuote(cwd)}
|
|
@@ -33169,13 +33431,13 @@ cd ${shSingleQuote(cwd)}
|
|
|
33169
33431
|
}
|
|
33170
33432
|
}
|
|
33171
33433
|
function trySpawnShellScriptLogRedirectWin(command, env, cwd, signal) {
|
|
33172
|
-
const tmpRoot =
|
|
33173
|
-
const logPath =
|
|
33174
|
-
const runnerPath =
|
|
33434
|
+
const tmpRoot = fs25.mkdtempSync(path28.join(tmpdir2(), "ba-devsrv-sh-"));
|
|
33435
|
+
const logPath = path28.join(tmpRoot, "combined.log");
|
|
33436
|
+
const runnerPath = path28.join(tmpRoot, "_run.bat");
|
|
33175
33437
|
const q = (p) => `"${p.replace(/"/g, '""')}"`;
|
|
33176
33438
|
const com = process.env.ComSpec || "cmd.exe";
|
|
33177
33439
|
try {
|
|
33178
|
-
|
|
33440
|
+
fs25.writeFileSync(
|
|
33179
33441
|
runnerPath,
|
|
33180
33442
|
`@ECHO OFF\r
|
|
33181
33443
|
CD /D ${q(cwd)}\r
|
|
@@ -33944,30 +34206,30 @@ function createOnBridgeIdentified(opts) {
|
|
|
33944
34206
|
}
|
|
33945
34207
|
|
|
33946
34208
|
// src/skills/discover-local-agent-skills.ts
|
|
33947
|
-
import
|
|
33948
|
-
import
|
|
34209
|
+
import fs26 from "node:fs";
|
|
34210
|
+
import path29 from "node:path";
|
|
33949
34211
|
var SKILL_DISCOVERY_ROOTS = [".agents/skills", ".claude/skills", ".cursor/skills", "skills"];
|
|
33950
34212
|
function discoverLocalSkills(cwd) {
|
|
33951
34213
|
const out = [];
|
|
33952
34214
|
const seenKeys = /* @__PURE__ */ new Set();
|
|
33953
34215
|
for (const rel of SKILL_DISCOVERY_ROOTS) {
|
|
33954
|
-
const base =
|
|
33955
|
-
if (!
|
|
34216
|
+
const base = path29.join(cwd, rel);
|
|
34217
|
+
if (!fs26.existsSync(base) || !fs26.statSync(base).isDirectory()) continue;
|
|
33956
34218
|
let entries = [];
|
|
33957
34219
|
try {
|
|
33958
|
-
entries =
|
|
34220
|
+
entries = fs26.readdirSync(base);
|
|
33959
34221
|
} catch {
|
|
33960
34222
|
continue;
|
|
33961
34223
|
}
|
|
33962
34224
|
for (const name of entries) {
|
|
33963
|
-
const dir =
|
|
34225
|
+
const dir = path29.join(base, name);
|
|
33964
34226
|
try {
|
|
33965
|
-
if (!
|
|
34227
|
+
if (!fs26.statSync(dir).isDirectory()) continue;
|
|
33966
34228
|
} catch {
|
|
33967
34229
|
continue;
|
|
33968
34230
|
}
|
|
33969
|
-
const skillMd =
|
|
33970
|
-
if (!
|
|
34231
|
+
const skillMd = path29.join(dir, "SKILL.md");
|
|
34232
|
+
if (!fs26.existsSync(skillMd)) continue;
|
|
33971
34233
|
const key = `${rel}/${name}`;
|
|
33972
34234
|
if (seenKeys.has(key)) continue;
|
|
33973
34235
|
seenKeys.add(key);
|
|
@@ -33979,23 +34241,23 @@ function discoverLocalSkills(cwd) {
|
|
|
33979
34241
|
function discoverSkillLayoutRoots(cwd) {
|
|
33980
34242
|
const roots = [];
|
|
33981
34243
|
for (const rel of SKILL_DISCOVERY_ROOTS) {
|
|
33982
|
-
const base =
|
|
33983
|
-
if (!
|
|
34244
|
+
const base = path29.join(cwd, rel);
|
|
34245
|
+
if (!fs26.existsSync(base) || !fs26.statSync(base).isDirectory()) continue;
|
|
33984
34246
|
let entries = [];
|
|
33985
34247
|
try {
|
|
33986
|
-
entries =
|
|
34248
|
+
entries = fs26.readdirSync(base);
|
|
33987
34249
|
} catch {
|
|
33988
34250
|
continue;
|
|
33989
34251
|
}
|
|
33990
34252
|
const skills2 = [];
|
|
33991
34253
|
for (const name of entries) {
|
|
33992
|
-
const dir =
|
|
34254
|
+
const dir = path29.join(base, name);
|
|
33993
34255
|
try {
|
|
33994
|
-
if (!
|
|
34256
|
+
if (!fs26.statSync(dir).isDirectory()) continue;
|
|
33995
34257
|
} catch {
|
|
33996
34258
|
continue;
|
|
33997
34259
|
}
|
|
33998
|
-
if (!
|
|
34260
|
+
if (!fs26.existsSync(path29.join(dir, "SKILL.md"))) continue;
|
|
33999
34261
|
const relPath = `${rel}/${name}`.replace(/\\/g, "/");
|
|
34000
34262
|
skills2.push({ name, relPath });
|
|
34001
34263
|
}
|
|
@@ -34177,7 +34439,7 @@ var handleAgentConfigMessage = (msg, deps) => {
|
|
|
34177
34439
|
};
|
|
34178
34440
|
|
|
34179
34441
|
// src/prompt-turn-queue/runner.ts
|
|
34180
|
-
import
|
|
34442
|
+
import fs29 from "node:fs";
|
|
34181
34443
|
|
|
34182
34444
|
// src/prompt-turn-queue/client-report.ts
|
|
34183
34445
|
function sendPromptQueueClientReport(ws, queues) {
|
|
@@ -34187,13 +34449,13 @@ function sendPromptQueueClientReport(ws, queues) {
|
|
|
34187
34449
|
}
|
|
34188
34450
|
|
|
34189
34451
|
// src/prompt-turn-queue/disk-store.ts
|
|
34190
|
-
import
|
|
34452
|
+
import fs28 from "node:fs";
|
|
34191
34453
|
|
|
34192
34454
|
// src/prompt-turn-queue/paths.ts
|
|
34193
34455
|
import crypto3 from "node:crypto";
|
|
34194
|
-
import
|
|
34195
|
-
import
|
|
34196
|
-
import
|
|
34456
|
+
import fs27 from "node:fs";
|
|
34457
|
+
import path30 from "node:path";
|
|
34458
|
+
import os7 from "node:os";
|
|
34197
34459
|
var QUEUE_KEY_HEX_64 = /^[a-f0-9]{64}$/i;
|
|
34198
34460
|
function queueStateFileSlug(queueKey) {
|
|
34199
34461
|
if (QUEUE_KEY_HEX_64.test(queueKey)) return queueKey.toLowerCase();
|
|
@@ -34201,15 +34463,15 @@ function queueStateFileSlug(queueKey) {
|
|
|
34201
34463
|
}
|
|
34202
34464
|
function getPromptQueuesDirectory() {
|
|
34203
34465
|
const override = process.env.BUILDAMATON_PROMPT_QUEUES_DIR?.trim();
|
|
34204
|
-
if (override) return
|
|
34205
|
-
return
|
|
34466
|
+
if (override) return path30.resolve(override);
|
|
34467
|
+
return path30.join(os7.homedir(), ".buildautomaton", "queues");
|
|
34206
34468
|
}
|
|
34207
34469
|
function ensurePromptQueuesDirectory() {
|
|
34208
34470
|
const dir = getPromptQueuesDirectory();
|
|
34209
|
-
if (!
|
|
34471
|
+
if (!fs27.existsSync(dir)) fs27.mkdirSync(dir, { recursive: true });
|
|
34210
34472
|
}
|
|
34211
34473
|
function queueStateFilePath(queueKey) {
|
|
34212
|
-
return
|
|
34474
|
+
return path30.join(getPromptQueuesDirectory(), `${queueStateFileSlug(queueKey)}.json`);
|
|
34213
34475
|
}
|
|
34214
34476
|
|
|
34215
34477
|
// src/prompt-turn-queue/disk-store.ts
|
|
@@ -34234,7 +34496,7 @@ function parsePersistedQueueFile(raw) {
|
|
|
34234
34496
|
function readPersistedQueue(queueKey) {
|
|
34235
34497
|
const p = queueStateFilePath(queueKey);
|
|
34236
34498
|
try {
|
|
34237
|
-
return parsePersistedQueueFile(
|
|
34499
|
+
return parsePersistedQueueFile(fs28.readFileSync(p, "utf8"));
|
|
34238
34500
|
} catch {
|
|
34239
34501
|
return null;
|
|
34240
34502
|
}
|
|
@@ -34242,7 +34504,7 @@ function readPersistedQueue(queueKey) {
|
|
|
34242
34504
|
function writePersistedQueue(file2) {
|
|
34243
34505
|
ensurePromptQueuesDirectory();
|
|
34244
34506
|
const p = queueStateFilePath(file2.queueKey);
|
|
34245
|
-
|
|
34507
|
+
fs28.writeFileSync(p, JSON.stringify(file2, null, 2), "utf8");
|
|
34246
34508
|
}
|
|
34247
34509
|
function mergeServerQueueSnapshot(queueKey, serverTurns) {
|
|
34248
34510
|
const prev = readPersistedQueue(queueKey);
|
|
@@ -34300,7 +34562,7 @@ async function runLocalRevertBeforeQueuedPrompt(next, deps) {
|
|
|
34300
34562
|
const tid = typeof pl.snapshotRevertTurnId === "string" && pl.snapshotRevertTurnId.trim() !== "" ? pl.snapshotRevertTurnId.trim() : next.turnId;
|
|
34301
34563
|
const agentBase = deps.sessionWorktreeManager.getSessionWorktreeRootForSession(sid) ?? getBridgeRoot();
|
|
34302
34564
|
const file2 = snapshotFilePath(agentBase, tid);
|
|
34303
|
-
if (!
|
|
34565
|
+
if (!fs29.existsSync(file2)) {
|
|
34304
34566
|
deps.log(
|
|
34305
34567
|
`[Queue] requeued_with_revert: no pre-turn snapshot for ${tid.slice(0, 8)}\u2026; continuing without revert.`
|
|
34306
34568
|
);
|
|
@@ -34523,9 +34785,9 @@ function parseChangeSummarySnapshots(raw) {
|
|
|
34523
34785
|
for (const item of raw) {
|
|
34524
34786
|
if (!item || typeof item !== "object") continue;
|
|
34525
34787
|
const o = item;
|
|
34526
|
-
const
|
|
34527
|
-
if (!
|
|
34528
|
-
const row = { path:
|
|
34788
|
+
const path35 = typeof o.path === "string" && o.path.trim() !== "" ? o.path.trim() : "";
|
|
34789
|
+
if (!path35) continue;
|
|
34790
|
+
const row = { path: path35 };
|
|
34529
34791
|
if (typeof o.patchContent === "string") row.patchContent = o.patchContent;
|
|
34530
34792
|
if (typeof o.oldText === "string") row.oldText = o.oldText;
|
|
34531
34793
|
if (typeof o.newText === "string") row.newText = o.newText;
|
|
@@ -34756,15 +35018,15 @@ var handleSkillCallMessage = (msg, { getWs, log: log2 }) => {
|
|
|
34756
35018
|
};
|
|
34757
35019
|
|
|
34758
35020
|
// src/files/list-dir.ts
|
|
34759
|
-
import
|
|
34760
|
-
import
|
|
35021
|
+
import fs30 from "node:fs";
|
|
35022
|
+
import path32 from "node:path";
|
|
34761
35023
|
|
|
34762
35024
|
// src/files/ensure-under-cwd.ts
|
|
34763
|
-
import
|
|
35025
|
+
import path31 from "node:path";
|
|
34764
35026
|
function ensureUnderCwd(relativePath, cwd = getBridgeRoot()) {
|
|
34765
|
-
const normalized =
|
|
34766
|
-
const resolved =
|
|
34767
|
-
if (!resolved.startsWith(cwd +
|
|
35027
|
+
const normalized = path31.normalize(relativePath).replace(/^(\.\/)+/, "");
|
|
35028
|
+
const resolved = path31.resolve(cwd, normalized);
|
|
35029
|
+
if (!resolved.startsWith(cwd + path31.sep) && resolved !== cwd) {
|
|
34768
35030
|
return null;
|
|
34769
35031
|
}
|
|
34770
35032
|
return resolved;
|
|
@@ -34778,7 +35040,7 @@ async function listDirAsync(relativePath) {
|
|
|
34778
35040
|
return { error: "Path is outside working directory" };
|
|
34779
35041
|
}
|
|
34780
35042
|
try {
|
|
34781
|
-
const names = await
|
|
35043
|
+
const names = await fs30.promises.readdir(resolved, { withFileTypes: true });
|
|
34782
35044
|
const visible = names.filter((d) => !d.name.startsWith("."));
|
|
34783
35045
|
const entries = [];
|
|
34784
35046
|
for (let i = 0; i < visible.length; i++) {
|
|
@@ -34786,12 +35048,12 @@ async function listDirAsync(relativePath) {
|
|
|
34786
35048
|
await yieldToEventLoop();
|
|
34787
35049
|
}
|
|
34788
35050
|
const d = visible[i];
|
|
34789
|
-
const entryPath =
|
|
34790
|
-
const fullPath =
|
|
35051
|
+
const entryPath = path32.join(relativePath || ".", d.name).replace(/\\/g, "/");
|
|
35052
|
+
const fullPath = path32.join(resolved, d.name);
|
|
34791
35053
|
let isDir = d.isDirectory();
|
|
34792
35054
|
if (d.isSymbolicLink()) {
|
|
34793
35055
|
try {
|
|
34794
|
-
const targetStat = await
|
|
35056
|
+
const targetStat = await fs30.promises.stat(fullPath);
|
|
34795
35057
|
isDir = targetStat.isDirectory();
|
|
34796
35058
|
} catch {
|
|
34797
35059
|
isDir = false;
|
|
@@ -34816,25 +35078,25 @@ async function listDirAsync(relativePath) {
|
|
|
34816
35078
|
}
|
|
34817
35079
|
|
|
34818
35080
|
// src/files/read-file.ts
|
|
34819
|
-
import
|
|
35081
|
+
import fs31 from "node:fs";
|
|
34820
35082
|
import { StringDecoder } from "node:string_decoder";
|
|
34821
35083
|
function resolveFilePath(relativePath) {
|
|
34822
35084
|
const resolved = ensureUnderCwd(relativePath, getBridgeRoot());
|
|
34823
35085
|
if (!resolved) return { error: "Path is outside working directory" };
|
|
34824
35086
|
let real;
|
|
34825
35087
|
try {
|
|
34826
|
-
real =
|
|
35088
|
+
real = fs31.realpathSync(resolved);
|
|
34827
35089
|
} catch {
|
|
34828
35090
|
real = resolved;
|
|
34829
35091
|
}
|
|
34830
|
-
const stat2 =
|
|
35092
|
+
const stat2 = fs31.statSync(real);
|
|
34831
35093
|
if (!stat2.isFile()) return { error: "Not a file" };
|
|
34832
35094
|
return real;
|
|
34833
35095
|
}
|
|
34834
35096
|
var LINE_CHUNK_SIZE = 64 * 1024;
|
|
34835
35097
|
function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize = LINE_CHUNK_SIZE) {
|
|
34836
|
-
const fileSize =
|
|
34837
|
-
const fd =
|
|
35098
|
+
const fileSize = fs31.statSync(filePath).size;
|
|
35099
|
+
const fd = fs31.openSync(filePath, "r");
|
|
34838
35100
|
const bufSize = 64 * 1024;
|
|
34839
35101
|
const buf = Buffer.alloc(bufSize);
|
|
34840
35102
|
const decoder = new StringDecoder("utf8");
|
|
@@ -34847,7 +35109,7 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
|
|
|
34847
35109
|
let line0Accum = "";
|
|
34848
35110
|
try {
|
|
34849
35111
|
let bytesRead;
|
|
34850
|
-
while (!done && (bytesRead =
|
|
35112
|
+
while (!done && (bytesRead = fs31.readSync(fd, buf, 0, bufSize, null)) > 0) {
|
|
34851
35113
|
const text = partial2 + decoder.write(buf.subarray(0, bytesRead));
|
|
34852
35114
|
partial2 = "";
|
|
34853
35115
|
let lineStart = 0;
|
|
@@ -34982,7 +35244,7 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
|
|
|
34982
35244
|
}
|
|
34983
35245
|
return { content: resultLines.join("\n"), size: fileSize };
|
|
34984
35246
|
} finally {
|
|
34985
|
-
|
|
35247
|
+
fs31.closeSync(fd);
|
|
34986
35248
|
}
|
|
34987
35249
|
}
|
|
34988
35250
|
function readFile2(relativePath, startLine, endLine, lineOffset, lineChunkSize = LINE_CHUNK_SIZE) {
|
|
@@ -34993,8 +35255,8 @@ function readFile2(relativePath, startLine, endLine, lineOffset, lineChunkSize =
|
|
|
34993
35255
|
if (hasRange) {
|
|
34994
35256
|
return readFileRange(result, startLine, endLine, lineOffset, lineChunkSize);
|
|
34995
35257
|
}
|
|
34996
|
-
const stat2 =
|
|
34997
|
-
const raw =
|
|
35258
|
+
const stat2 = fs31.statSync(result);
|
|
35259
|
+
const raw = fs31.readFileSync(result, "utf8");
|
|
34998
35260
|
const lines = raw.split(/\r?\n/);
|
|
34999
35261
|
return { content: raw, totalLines: lines.length, size: stat2.size };
|
|
35000
35262
|
} catch (err) {
|
|
@@ -35112,8 +35374,8 @@ function handleSkillLayoutRequest(msg, deps) {
|
|
|
35112
35374
|
}
|
|
35113
35375
|
|
|
35114
35376
|
// src/skills/install-remote-skills.ts
|
|
35115
|
-
import
|
|
35116
|
-
import
|
|
35377
|
+
import fs32 from "node:fs";
|
|
35378
|
+
import path33 from "node:path";
|
|
35117
35379
|
function installRemoteSkills(cwd, targetDir, items) {
|
|
35118
35380
|
const installed2 = [];
|
|
35119
35381
|
if (!Array.isArray(items)) {
|
|
@@ -35124,15 +35386,15 @@ function installRemoteSkills(cwd, targetDir, items) {
|
|
|
35124
35386
|
if (typeof item.sourceId !== "string" || typeof item.skillName !== "string" || typeof item.versionHash !== "string" || !Array.isArray(item.files)) {
|
|
35125
35387
|
continue;
|
|
35126
35388
|
}
|
|
35127
|
-
const skillDir =
|
|
35389
|
+
const skillDir = path33.join(cwd, targetDir, item.skillName);
|
|
35128
35390
|
for (const f of item.files) {
|
|
35129
35391
|
if (typeof f.path !== "string" || !f.text && !f.base64) continue;
|
|
35130
|
-
const dest =
|
|
35131
|
-
|
|
35392
|
+
const dest = path33.join(skillDir, f.path);
|
|
35393
|
+
fs32.mkdirSync(path33.dirname(dest), { recursive: true });
|
|
35132
35394
|
if (f.text !== void 0) {
|
|
35133
|
-
|
|
35395
|
+
fs32.writeFileSync(dest, f.text, "utf8");
|
|
35134
35396
|
} else if (f.base64) {
|
|
35135
|
-
|
|
35397
|
+
fs32.writeFileSync(dest, Buffer.from(f.base64, "base64"));
|
|
35136
35398
|
}
|
|
35137
35399
|
}
|
|
35138
35400
|
installed2.push({
|
|
@@ -35282,7 +35544,7 @@ var handleSessionDiscardedMessage = (msg, deps) => {
|
|
|
35282
35544
|
};
|
|
35283
35545
|
|
|
35284
35546
|
// src/routing/handlers/revert-turn-snapshot.ts
|
|
35285
|
-
import * as
|
|
35547
|
+
import * as fs33 from "node:fs";
|
|
35286
35548
|
var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
35287
35549
|
const id = typeof msg.id === "string" ? msg.id : "";
|
|
35288
35550
|
const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
|
|
@@ -35294,7 +35556,7 @@ var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
|
35294
35556
|
if (!s) return;
|
|
35295
35557
|
const agentBase = sessionWorktreeManager.getSessionWorktreeRootForSession(sessionId) ?? getBridgeRoot();
|
|
35296
35558
|
const file2 = snapshotFilePath(agentBase, turnId);
|
|
35297
|
-
if (!
|
|
35559
|
+
if (!fs33.existsSync(file2)) {
|
|
35298
35560
|
sendWsMessage(s, {
|
|
35299
35561
|
type: "revert_turn_snapshot_result",
|
|
35300
35562
|
id,
|
|
@@ -35735,8 +35997,8 @@ async function createBridgeConnection(options) {
|
|
|
35735
35997
|
getCloudAccessToken: () => tokens.accessToken
|
|
35736
35998
|
};
|
|
35737
35999
|
const identifyReportedPaths = {
|
|
35738
|
-
bridgeRootPath:
|
|
35739
|
-
worktreesRootPath:
|
|
36000
|
+
bridgeRootPath: path34.resolve(getBridgeRoot()),
|
|
36001
|
+
worktreesRootPath: path34.resolve(worktreesRootPath)
|
|
35740
36002
|
};
|
|
35741
36003
|
const { connect } = createMainBridgeWebSocketLifecycle({
|
|
35742
36004
|
state,
|