@buildautomaton/cli 0.1.24 → 0.1.26
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 +991 -612
- package/dist/cli.js.map +4 -4
- package/dist/index.js +1137 -763
- 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
|
}
|
|
@@ -22630,263 +22933,358 @@ function isClaudeCodePermissionMode(value) {
|
|
|
22630
22933
|
return MODE_SET.has(value);
|
|
22631
22934
|
}
|
|
22632
22935
|
|
|
22633
|
-
// ../types/src/
|
|
22634
|
-
var
|
|
22635
|
-
|
|
22636
|
-
|
|
22637
|
-
|
|
22638
|
-
if (typeof raw !== "string") return null;
|
|
22936
|
+
// ../types/src/cli-permission-mode.ts
|
|
22937
|
+
var CLI_PERMISSION_MODE_DEFAULT = "default";
|
|
22938
|
+
var CLI_PERMISSION_MODE_DANGEROUS = "dangerous";
|
|
22939
|
+
function normalizeCliPermissionModeInput(raw) {
|
|
22940
|
+
if (typeof raw !== "string") return CLI_PERMISSION_MODE_DEFAULT;
|
|
22639
22941
|
const t = raw.trim();
|
|
22640
|
-
|
|
22942
|
+
if (t === CLI_PERMISSION_MODE_DANGEROUS) return CLI_PERMISSION_MODE_DANGEROUS;
|
|
22943
|
+
if (t === "standard") return CLI_PERMISSION_MODE_DEFAULT;
|
|
22944
|
+
return CLI_PERMISSION_MODE_DEFAULT;
|
|
22641
22945
|
}
|
|
22642
22946
|
|
|
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
|
-
|
|
22947
|
+
// ../types/src/acp-permission-auto-approve.ts
|
|
22948
|
+
function isRejectKind(kind) {
|
|
22949
|
+
return kind === "reject_once" || kind === "reject_always";
|
|
22950
|
+
}
|
|
22951
|
+
function normalizeOptions(raw) {
|
|
22952
|
+
if (!Array.isArray(raw)) return [];
|
|
22953
|
+
const out = [];
|
|
22954
|
+
for (const item of raw) {
|
|
22955
|
+
if (item == null || typeof item !== "object" || Array.isArray(item)) continue;
|
|
22956
|
+
const o = item;
|
|
22957
|
+
const rawId = o.optionId ?? o.id;
|
|
22958
|
+
const optionId = typeof rawId === "string" && rawId.trim() !== "" ? rawId.trim() : typeof rawId === "number" && Number.isFinite(rawId) ? String(rawId) : "";
|
|
22959
|
+
if (!optionId) continue;
|
|
22960
|
+
const kind = typeof o.kind === "string" ? o.kind : void 0;
|
|
22961
|
+
out.push({ optionId, ...kind ? { kind } : {} });
|
|
22962
|
+
}
|
|
22963
|
+
return out;
|
|
22964
|
+
}
|
|
22965
|
+
function pickAllowOption(options) {
|
|
22966
|
+
const nonReject = options.filter((o) => !isRejectKind(o.kind));
|
|
22967
|
+
if (nonReject.length === 0) return null;
|
|
22968
|
+
const allowOnce = nonReject.find((o) => o.kind === "allow_once");
|
|
22969
|
+
if (allowOnce) return allowOnce;
|
|
22970
|
+
const notAlways = nonReject.filter((o) => o.kind !== "allow_always");
|
|
22971
|
+
if (notAlways.length > 0) return notAlways[0] ?? null;
|
|
22972
|
+
return nonReject.find((o) => o.kind === "allow_always") ?? nonReject[0] ?? null;
|
|
22973
|
+
}
|
|
22974
|
+
function firstNonEmptyOptionsArray(...candidates) {
|
|
22975
|
+
for (const c of candidates) {
|
|
22976
|
+
if (Array.isArray(c) && c.length > 0) return c;
|
|
22977
|
+
}
|
|
22978
|
+
const fallback = candidates[0];
|
|
22979
|
+
return Array.isArray(fallback) ? fallback : [];
|
|
22980
|
+
}
|
|
22981
|
+
function extractAcpPermissionRequestOptionArray(params) {
|
|
22982
|
+
const toolCall = params.toolCall;
|
|
22983
|
+
const fromToolCall = toolCall != null && typeof toolCall === "object" && !Array.isArray(toolCall) ? toolCall : null;
|
|
22984
|
+
return firstNonEmptyOptionsArray(
|
|
22985
|
+
params.options,
|
|
22986
|
+
params.permissionOptions,
|
|
22987
|
+
fromToolCall?.options,
|
|
22988
|
+
fromToolCall?.permissionOptions
|
|
22989
|
+
);
|
|
22990
|
+
}
|
|
22991
|
+
function buildCliAutoApprovedPermissionRpcResult(requestParams) {
|
|
22992
|
+
const opt = pickAllowOption(normalizeOptions(extractAcpPermissionRequestOptionArray(requestParams)));
|
|
22993
|
+
if (!opt) return null;
|
|
22994
|
+
const kind = opt.kind?.trim();
|
|
22995
|
+
return {
|
|
22996
|
+
outcome: {
|
|
22997
|
+
outcome: "selected",
|
|
22998
|
+
optionId: opt.optionId,
|
|
22999
|
+
...kind ? { _meta: { permissionOptionKind: kind } } : {}
|
|
23000
|
+
}
|
|
23001
|
+
};
|
|
22668
23002
|
}
|
|
22669
23003
|
|
|
22670
|
-
// src/
|
|
22671
|
-
|
|
22672
|
-
|
|
22673
|
-
|
|
22674
|
-
|
|
23004
|
+
// ../types/src/agent-config.ts
|
|
23005
|
+
var AGENT_CONFIG_CLAUDE_PERMISSION_MODE_KEY = "claude_permission_mode";
|
|
23006
|
+
var AGENT_CONFIG_CLI_PERMISSION_MODE_KEY = "cli_permission_mode";
|
|
23007
|
+
function getClaudePermissionModeFromAgentConfig(config2) {
|
|
23008
|
+
if (!config2) return null;
|
|
23009
|
+
const raw = config2[AGENT_CONFIG_CLAUDE_PERMISSION_MODE_KEY];
|
|
23010
|
+
if (typeof raw !== "string") return null;
|
|
23011
|
+
const t = raw.trim();
|
|
23012
|
+
return isClaudeCodePermissionMode(t) ? t : null;
|
|
23013
|
+
}
|
|
23014
|
+
function getCliPermissionModeFromAgentConfig(config2) {
|
|
23015
|
+
if (!config2) return CLI_PERMISSION_MODE_DEFAULT;
|
|
23016
|
+
return normalizeCliPermissionModeInput(config2[AGENT_CONFIG_CLI_PERMISSION_MODE_KEY]);
|
|
23017
|
+
}
|
|
22675
23018
|
|
|
22676
|
-
// src/
|
|
22677
|
-
function
|
|
22678
|
-
|
|
22679
|
-
const
|
|
22680
|
-
|
|
22681
|
-
|
|
22682
|
-
|
|
22683
|
-
|
|
22684
|
-
|
|
22685
|
-
|
|
22686
|
-
|
|
22687
|
-
|
|
22688
|
-
|
|
22689
|
-
|
|
23019
|
+
// src/agents/acp/claude-acp-permission-from-session.ts
|
|
23020
|
+
function flattenSelectOptions(options) {
|
|
23021
|
+
if (options == null || options.length === 0) return [];
|
|
23022
|
+
const first2 = options[0];
|
|
23023
|
+
if (first2 != null && typeof first2 === "object" && "group" in first2 && first2.group != null) {
|
|
23024
|
+
return options.flatMap(
|
|
23025
|
+
(g) => Array.isArray(g.options) ? g.options : []
|
|
23026
|
+
);
|
|
23027
|
+
}
|
|
23028
|
+
return options;
|
|
23029
|
+
}
|
|
23030
|
+
function pickModeConfigOption(configOptions) {
|
|
23031
|
+
if (configOptions == null || configOptions.length === 0) return null;
|
|
23032
|
+
const byCategory = configOptions.find((o) => o.category === "mode");
|
|
23033
|
+
if (byCategory) return byCategory;
|
|
23034
|
+
return configOptions.find((o) => o.id === "mode") ?? null;
|
|
23035
|
+
}
|
|
23036
|
+
async function applyClaudePermissionFromAcpSession(params) {
|
|
23037
|
+
const { sessionId, agentConfig, configOptions, modes, setSessionConfigOption, setSessionMode, logDebug: logDebug2 } = params;
|
|
23038
|
+
const desiredMode = getClaudePermissionModeFromAgentConfig(agentConfig);
|
|
23039
|
+
if (desiredMode == null) return;
|
|
23040
|
+
const modeOpt = pickModeConfigOption(configOptions ?? null);
|
|
23041
|
+
if (modeOpt != null) {
|
|
23042
|
+
const flat = flattenSelectOptions(modeOpt.options);
|
|
23043
|
+
const allowed = flat.some((o) => o.value === desiredMode);
|
|
23044
|
+
if (allowed && modeOpt.currentValue !== desiredMode) {
|
|
23045
|
+
try {
|
|
23046
|
+
logDebug2(
|
|
23047
|
+
`[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`
|
|
23048
|
+
);
|
|
23049
|
+
await setSessionConfigOption({ sessionId, configId: modeOpt.id, value: desiredMode });
|
|
23050
|
+
} catch (e) {
|
|
23051
|
+
logDebug2(
|
|
23052
|
+
`[Agent] Claude Code: session/set_config_option failed: ${e instanceof Error ? e.message : String(e)}`
|
|
23053
|
+
);
|
|
22690
23054
|
}
|
|
22691
23055
|
}
|
|
23056
|
+
return;
|
|
22692
23057
|
}
|
|
22693
|
-
|
|
22694
|
-
|
|
22695
|
-
|
|
22696
|
-
|
|
22697
|
-
|
|
22698
|
-
|
|
22699
|
-
|
|
22700
|
-
|
|
22701
|
-
|
|
22702
|
-
|
|
22703
|
-
|
|
22704
|
-
} else {
|
|
22705
|
-
result.unshift({ type: "remove", line: oldLines[i - 1] });
|
|
22706
|
-
i--;
|
|
23058
|
+
if (modes?.availableModes?.length) {
|
|
23059
|
+
const allowed = modes.availableModes.some((m) => m.id === desiredMode);
|
|
23060
|
+
if (allowed && desiredMode !== modes.currentModeId) {
|
|
23061
|
+
try {
|
|
23062
|
+
logDebug2(
|
|
23063
|
+
`[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`
|
|
23064
|
+
);
|
|
23065
|
+
await setSessionMode({ sessionId, modeId: desiredMode });
|
|
23066
|
+
} catch (e) {
|
|
23067
|
+
logDebug2(`[Agent] Claude Code: session/set_mode failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
23068
|
+
}
|
|
22707
23069
|
}
|
|
22708
23070
|
}
|
|
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
23071
|
}
|
|
22721
23072
|
|
|
22722
|
-
// src/
|
|
22723
|
-
|
|
22724
|
-
|
|
22725
|
-
|
|
22726
|
-
|
|
22727
|
-
bridgeRootPath = path.resolve(process.cwd());
|
|
22728
|
-
}
|
|
22729
|
-
return bridgeRootPath;
|
|
23073
|
+
// src/agents/acp/clients/shared/config-options-for-permission.ts
|
|
23074
|
+
function configOptionsForPermission(getActive, established) {
|
|
23075
|
+
const mem = getActive?.();
|
|
23076
|
+
if (Array.isArray(mem) && mem.length > 0) return mem;
|
|
23077
|
+
return established ?? void 0;
|
|
22730
23078
|
}
|
|
22731
23079
|
|
|
22732
|
-
// src/agents/acp/
|
|
22733
|
-
|
|
22734
|
-
|
|
22735
|
-
|
|
22736
|
-
|
|
22737
|
-
|
|
22738
|
-
|
|
22739
|
-
|
|
22740
|
-
if (rel.startsWith("..") || path2.isAbsolute(rel)) return null;
|
|
22741
|
-
return resolved;
|
|
23080
|
+
// src/agents/acp/clients/shared/establish-acp-session.ts
|
|
23081
|
+
function establishedFromResult(raw, sessionId) {
|
|
23082
|
+
const r = raw && typeof raw === "object" ? raw : {};
|
|
23083
|
+
return {
|
|
23084
|
+
sessionId,
|
|
23085
|
+
configOptions: Array.isArray(r.configOptions) ? r.configOptions : null,
|
|
23086
|
+
modes: r.modes ?? null
|
|
23087
|
+
};
|
|
22742
23088
|
}
|
|
22743
|
-
function
|
|
22744
|
-
const
|
|
22745
|
-
|
|
22746
|
-
if (!rel || rel === "") return path2.basename(absolutePath);
|
|
22747
|
-
return rel.split(path2.sep).join("/");
|
|
23089
|
+
function sessionIdFromNewSessionResult(raw) {
|
|
23090
|
+
const r = raw && typeof raw === "object" ? raw : {};
|
|
23091
|
+
return typeof r.sessionId === "string" ? r.sessionId : "";
|
|
22748
23092
|
}
|
|
22749
|
-
|
|
22750
|
-
|
|
22751
|
-
|
|
22752
|
-
|
|
22753
|
-
|
|
22754
|
-
let total = 0;
|
|
22755
|
-
return {
|
|
22756
|
-
append(chunk) {
|
|
23093
|
+
async function establishAcpSessionWithTransport(transport, ctx, canResume, canLoad) {
|
|
23094
|
+
const { cwd, mcpServers, persistedAcpSessionId, agentLabel, suppressLoadReplay } = ctx;
|
|
23095
|
+
const prev = typeof persistedAcpSessionId === "string" && persistedAcpSessionId.trim() !== "" ? persistedAcpSessionId.trim() : "";
|
|
23096
|
+
if (prev) {
|
|
23097
|
+
if (canResume) {
|
|
22757
23098
|
try {
|
|
22758
|
-
|
|
22759
|
-
|
|
23099
|
+
logDebug(`[Agent] ${agentLabel} ACP session/resume for stored session ${prev.slice(0, 8)}\u2026`);
|
|
23100
|
+
const result2 = await transport.resumeSession({ sessionId: prev, cwd, mcpServers });
|
|
23101
|
+
return establishedFromResult(result2, prev);
|
|
23102
|
+
} catch (e) {
|
|
23103
|
+
logDebug(`[Agent] ${agentLabel} ACP session/resume failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
23104
|
+
}
|
|
23105
|
+
}
|
|
23106
|
+
if (canLoad) {
|
|
23107
|
+
suppressLoadReplay.value = true;
|
|
23108
|
+
try {
|
|
23109
|
+
logDebug(`[Agent] ${agentLabel} ACP session/load for stored session ${prev.slice(0, 8)}\u2026`);
|
|
23110
|
+
const result2 = await transport.loadSession({ sessionId: prev, cwd, mcpServers });
|
|
23111
|
+
return establishedFromResult(result2, prev);
|
|
23112
|
+
} catch (e) {
|
|
23113
|
+
logDebug(`[Agent] ${agentLabel} ACP session/load failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
23114
|
+
} finally {
|
|
23115
|
+
suppressLoadReplay.value = false;
|
|
22760
23116
|
}
|
|
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
23117
|
}
|
|
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
23118
|
}
|
|
23119
|
+
const result = await transport.newSession({ cwd, mcpServers });
|
|
23120
|
+
const sid = sessionIdFromNewSessionResult(result);
|
|
23121
|
+
if (!sid) throw new Error(`${agentLabel} ACP session/new did not return sessionId`);
|
|
23122
|
+
return establishedFromResult(result, sid);
|
|
22786
23123
|
}
|
|
22787
|
-
|
|
22788
|
-
|
|
22789
|
-
|
|
22790
|
-
|
|
22791
|
-
|
|
22792
|
-
|
|
22793
|
-
|
|
22794
|
-
|
|
23124
|
+
|
|
23125
|
+
// src/agents/acp/clients/shared/parse-acp-init-capabilities.ts
|
|
23126
|
+
function parseAcpInitAgentCapabilities(initResult) {
|
|
23127
|
+
const agentCapabilities = initResult?.agentCapabilities;
|
|
23128
|
+
const canLoad = agentCapabilities?.loadSession === true;
|
|
23129
|
+
const sessionCaps = agentCapabilities?.sessionCapabilities;
|
|
23130
|
+
const canResume = Boolean(sessionCaps?.resume);
|
|
23131
|
+
return { canResume, canLoad };
|
|
22795
23132
|
}
|
|
22796
23133
|
|
|
22797
|
-
// src/agents/acp/clients/
|
|
22798
|
-
function
|
|
22799
|
-
const
|
|
22800
|
-
|
|
22801
|
-
|
|
22802
|
-
|
|
22803
|
-
|
|
22804
|
-
|
|
22805
|
-
|
|
22806
|
-
|
|
22807
|
-
|
|
22808
|
-
|
|
22809
|
-
|
|
22810
|
-
|
|
22811
|
-
|
|
23134
|
+
// src/agents/acp/clients/shared/bootstrap-acp-wire-session.ts
|
|
23135
|
+
async function bootstrapAcpWireSession(transport, ctx, initializeRequest) {
|
|
23136
|
+
const initResult = await transport.initialize(initializeRequest);
|
|
23137
|
+
const { canResume, canLoad } = parseAcpInitAgentCapabilities(initResult);
|
|
23138
|
+
await transport.afterInitialize?.();
|
|
23139
|
+
const established = await establishAcpSessionWithTransport(transport, ctx, canResume, canLoad);
|
|
23140
|
+
const sessionId = established.sessionId;
|
|
23141
|
+
ctx.onAcpSessionEstablished?.({
|
|
23142
|
+
acpSessionId: sessionId,
|
|
23143
|
+
configOptions: established.configOptions,
|
|
23144
|
+
modes: established.modes
|
|
23145
|
+
});
|
|
23146
|
+
if (ctx.backendAgentType === "claude-code") {
|
|
23147
|
+
const cfg = ctx.agentConfig != null && typeof ctx.agentConfig === "object" && !Array.isArray(ctx.agentConfig) ? ctx.agentConfig : null;
|
|
23148
|
+
const configOptionsTyped = established.configOptions;
|
|
23149
|
+
const modesTyped = established.modes;
|
|
23150
|
+
await applyClaudePermissionFromAcpSession({
|
|
23151
|
+
sessionId,
|
|
23152
|
+
agentConfig: cfg,
|
|
23153
|
+
configOptions: configOptionsForPermission(ctx.getActiveConfigOptions, configOptionsTyped),
|
|
23154
|
+
modes: modesTyped,
|
|
23155
|
+
setSessionConfigOption: transport.setSessionConfigOption ? (p) => transport.setSessionConfigOption(p) : async () => {
|
|
23156
|
+
},
|
|
23157
|
+
setSessionMode: transport.setSessionMode ? (p) => transport.setSessionMode(p) : async () => {
|
|
23158
|
+
},
|
|
23159
|
+
logDebug: ctx.logDebug
|
|
23160
|
+
});
|
|
23161
|
+
}
|
|
23162
|
+
return established;
|
|
22812
23163
|
}
|
|
22813
23164
|
|
|
22814
|
-
// src/agents/acp/clients/
|
|
22815
|
-
|
|
22816
|
-
};
|
|
22817
|
-
|
|
22818
|
-
|
|
22819
|
-
|
|
22820
|
-
|
|
22821
|
-
|
|
22822
|
-
default:
|
|
22823
|
-
return noopExtNotification;
|
|
23165
|
+
// src/agents/acp/clients/shared/dispatch-session-update.ts
|
|
23166
|
+
function dispatchAcpSessionUpdate(opts) {
|
|
23167
|
+
const { flatPayload, onAcpConfigOptionsUpdated, onSessionUpdate, suppressLoadReplay } = opts;
|
|
23168
|
+
const su = flatPayload.sessionUpdate ?? flatPayload.session_update;
|
|
23169
|
+
if (su === "config_option_update") {
|
|
23170
|
+
const co = flatPayload.configOptions;
|
|
23171
|
+
if (Array.isArray(co)) onAcpConfigOptionsUpdated?.(co);
|
|
23172
|
+
return;
|
|
22824
23173
|
}
|
|
23174
|
+
if (suppressLoadReplay()) return;
|
|
23175
|
+
onSessionUpdate?.(flatPayload);
|
|
22825
23176
|
}
|
|
22826
23177
|
|
|
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 "";
|
|
23178
|
+
// src/agents/acp/clients/shared/flatten-sdk-session-notification.ts
|
|
23179
|
+
function flattenSdkSessionNotificationParams(params) {
|
|
23180
|
+
return { sessionId: params.sessionId, ...params.update };
|
|
22834
23181
|
}
|
|
22835
|
-
|
|
22836
|
-
|
|
22837
|
-
|
|
22838
|
-
}
|
|
22839
|
-
const
|
|
22840
|
-
const
|
|
22841
|
-
|
|
22842
|
-
const
|
|
22843
|
-
|
|
22844
|
-
|
|
23182
|
+
|
|
23183
|
+
// src/agents/acp/clients/shared/normalize-acp-prompt-result.ts
|
|
23184
|
+
function normalizeAcpPromptTurnSuccess(opts) {
|
|
23185
|
+
const { stopReason, output, stderrCaptureText, backendAgentType } = opts;
|
|
23186
|
+
const mergedOutput = output || void 0;
|
|
23187
|
+
const stop = (stopReason ?? "").toLowerCase();
|
|
23188
|
+
const cancelled = stop === "cancelled";
|
|
23189
|
+
const refusal = stop === "refusal";
|
|
23190
|
+
const stderrEvaluated = Boolean(stderrCaptureText && backendAgentType);
|
|
23191
|
+
const stderrSuggestsAuth = stderrEvaluated ? localAgentErrorSuggestsAuth(backendAgentType, stderrCaptureText) : false;
|
|
23192
|
+
if (cancelled) {
|
|
23193
|
+
return {
|
|
23194
|
+
success: false,
|
|
23195
|
+
stopReason,
|
|
23196
|
+
output: mergedOutput,
|
|
23197
|
+
error: mergeErrorWithStderr("Stopped by user", stderrCaptureText)
|
|
23198
|
+
};
|
|
22845
23199
|
}
|
|
22846
|
-
|
|
22847
|
-
|
|
22848
|
-
|
|
22849
|
-
|
|
23200
|
+
if (refusal) {
|
|
23201
|
+
return {
|
|
23202
|
+
success: false,
|
|
23203
|
+
stopReason,
|
|
23204
|
+
output: mergedOutput,
|
|
23205
|
+
error: mergeErrorWithStderr("The agent refused the request.", stderrCaptureText)
|
|
23206
|
+
};
|
|
22850
23207
|
}
|
|
22851
|
-
|
|
22852
|
-
|
|
22853
|
-
|
|
22854
|
-
|
|
22855
|
-
|
|
22856
|
-
|
|
22857
|
-
|
|
22858
|
-
if (typeof rec.kind === "string" && rec.kind.trim() !== "") {
|
|
22859
|
-
matchedKind = rec.kind.trim();
|
|
22860
|
-
break;
|
|
22861
|
-
}
|
|
23208
|
+
if (stderrSuggestsAuth) {
|
|
23209
|
+
return {
|
|
23210
|
+
success: false,
|
|
23211
|
+
stopReason,
|
|
23212
|
+
output: mergedOutput,
|
|
23213
|
+
error: stderrCaptureText
|
|
23214
|
+
};
|
|
22862
23215
|
}
|
|
22863
|
-
if (!matchedKind) return result;
|
|
22864
23216
|
return {
|
|
22865
|
-
|
|
22866
|
-
|
|
22867
|
-
|
|
22868
|
-
|
|
23217
|
+
success: true,
|
|
23218
|
+
stopReason,
|
|
23219
|
+
output: mergedOutput
|
|
23220
|
+
};
|
|
23221
|
+
}
|
|
23222
|
+
function normalizeAcpPromptTurnFailure(err, stderrCaptureText) {
|
|
23223
|
+
const merged = mergeErrorWithStderr(formatJsonRpcStyleError(err), stderrCaptureText);
|
|
23224
|
+
return { success: false, error: merged };
|
|
23225
|
+
}
|
|
23226
|
+
|
|
23227
|
+
// src/agents/acp/clients/shared/send-acp-prompt-via-transport.ts
|
|
23228
|
+
async function sendAcpPromptViaTransport(transport, ctx, sessionId, promptText) {
|
|
23229
|
+
try {
|
|
23230
|
+
const response = await transport.prompt({
|
|
23231
|
+
sessionId,
|
|
23232
|
+
prompt: [{ type: "text", text: promptText }]
|
|
23233
|
+
});
|
|
23234
|
+
await new Promise((r2) => setImmediate(r2));
|
|
23235
|
+
const r = response;
|
|
23236
|
+
return normalizeAcpPromptTurnSuccess({
|
|
23237
|
+
stopReason: r?.stopReason,
|
|
23238
|
+
output: r?.output,
|
|
23239
|
+
stderrCaptureText: ctx.getStderrText(),
|
|
23240
|
+
backendAgentType: ctx.backendAgentType
|
|
23241
|
+
});
|
|
23242
|
+
} catch (err) {
|
|
23243
|
+
await new Promise((r) => setImmediate(r));
|
|
23244
|
+
return normalizeAcpPromptTurnFailure(err, ctx.getStderrText());
|
|
23245
|
+
}
|
|
23246
|
+
}
|
|
23247
|
+
|
|
23248
|
+
// src/agents/acp/clients/sdk/sdk-stdio-permission-request-handshake.ts
|
|
23249
|
+
function awaitSdkStdioPermissionRequestHandshake(params) {
|
|
23250
|
+
const { requestId, paramsRecord, pending, onRequest } = params;
|
|
23251
|
+
return new Promise((resolve16) => {
|
|
23252
|
+
pending.set(requestId, { resolve: resolve16, params: paramsRecord });
|
|
23253
|
+
try {
|
|
23254
|
+
onRequest?.({
|
|
23255
|
+
requestId,
|
|
23256
|
+
method: "session/request_permission",
|
|
23257
|
+
params: paramsRecord
|
|
23258
|
+
});
|
|
23259
|
+
} catch {
|
|
22869
23260
|
}
|
|
23261
|
+
});
|
|
23262
|
+
}
|
|
23263
|
+
|
|
23264
|
+
// src/agents/acp/clients/sdk/sdk-acp-session-transport.ts
|
|
23265
|
+
function createSdkAcpSessionTransport(connection) {
|
|
23266
|
+
const c = connection;
|
|
23267
|
+
return {
|
|
23268
|
+
initialize: (request) => c.initialize(request),
|
|
23269
|
+
resumeSession: (p) => c.unstable_resumeSession(p),
|
|
23270
|
+
loadSession: (p) => c.loadSession(p),
|
|
23271
|
+
newSession: (p) => c.newSession(p),
|
|
23272
|
+
prompt: (p) => c.prompt(p),
|
|
23273
|
+
cancelSession: async (sessionId) => {
|
|
23274
|
+
await c.cancel({ sessionId });
|
|
23275
|
+
},
|
|
23276
|
+
setSessionConfigOption: c.setSessionConfigOption ? (p) => c.setSessionConfigOption(p) : void 0,
|
|
23277
|
+
setSessionMode: c.setSessionMode ? (p) => c.setSessionMode(p) : void 0
|
|
22870
23278
|
};
|
|
22871
23279
|
}
|
|
22872
23280
|
|
|
22873
|
-
// src/agents/acp/clients/sdk-stdio-acp-client.ts
|
|
23281
|
+
// src/agents/acp/clients/sdk/sdk-stdio-acp-client.ts
|
|
22874
23282
|
function formatSpawnError(err, command) {
|
|
22875
23283
|
if (err.code === "ENOENT") {
|
|
22876
23284
|
return `Command "${command}" not found. Install the agent (e.g. Cursor CLI) or add it to PATH.`;
|
|
22877
23285
|
}
|
|
22878
23286
|
return err.message || String(err);
|
|
22879
23287
|
}
|
|
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
23288
|
async function createSdkStdioAcpClient(options) {
|
|
22891
23289
|
const { ClientSideConnection: ClientSideConnection2, ndJsonStream: ndJsonStream2, PROTOCOL_VERSION: PROTOCOL_VERSION2 } = await Promise.resolve().then(() => (init_acp(), acp_exports));
|
|
22892
23290
|
const {
|
|
@@ -22898,7 +23296,11 @@ async function createSdkStdioAcpClient(options) {
|
|
|
22898
23296
|
onFileChange,
|
|
22899
23297
|
killSubprocessAfterCancelMs,
|
|
22900
23298
|
onAgentSubprocessExit,
|
|
22901
|
-
agentConfig
|
|
23299
|
+
agentConfig,
|
|
23300
|
+
persistedAcpSessionId,
|
|
23301
|
+
onAcpSessionEstablished,
|
|
23302
|
+
onAcpConfigOptionsUpdated,
|
|
23303
|
+
getActiveConfigOptions
|
|
22902
23304
|
} = options;
|
|
22903
23305
|
const isWindows = process.platform === "win32";
|
|
22904
23306
|
const child = spawn(command[0], command.slice(1), {
|
|
@@ -22947,54 +23349,49 @@ async function createSdkStdioAcpClient(options) {
|
|
|
22947
23349
|
backendAgentType,
|
|
22948
23350
|
onSessionUpdate
|
|
22949
23351
|
});
|
|
23352
|
+
const suppressLoadReplayRef = { value: false };
|
|
23353
|
+
const sessionCtx = {
|
|
23354
|
+
cwd,
|
|
23355
|
+
onFileChange,
|
|
23356
|
+
mcpServers: [],
|
|
23357
|
+
persistedAcpSessionId,
|
|
23358
|
+
agentLabel: "ACP",
|
|
23359
|
+
suppressLoadReplay: suppressLoadReplayRef,
|
|
23360
|
+
backendAgentType: backendAgentType ?? null,
|
|
23361
|
+
agentConfig,
|
|
23362
|
+
getActiveConfigOptions,
|
|
23363
|
+
onAcpSessionEstablished,
|
|
23364
|
+
onAcpConfigOptionsUpdated,
|
|
23365
|
+
logDebug,
|
|
23366
|
+
getStderrText: () => stderrCapture.getText()
|
|
23367
|
+
};
|
|
22950
23368
|
let permissionSeq = 0;
|
|
22951
23369
|
const pendingPermissionReplies = /* @__PURE__ */ new Map();
|
|
22952
23370
|
const client = (_agent) => ({
|
|
22953
23371
|
async requestPermission(params) {
|
|
22954
23372
|
const requestId = `perm-${++permissionSeq}`;
|
|
22955
23373
|
const paramsRecord = params != null && typeof params === "object" ? params : {};
|
|
22956
|
-
|
|
22957
|
-
|
|
22958
|
-
|
|
22959
|
-
|
|
22960
|
-
|
|
22961
|
-
});
|
|
22962
|
-
} catch {
|
|
22963
|
-
}
|
|
22964
|
-
return await new Promise((resolve17) => {
|
|
22965
|
-
pendingPermissionReplies.set(requestId, { resolve: resolve17, params: paramsRecord });
|
|
23374
|
+
return await awaitSdkStdioPermissionRequestHandshake({
|
|
23375
|
+
requestId,
|
|
23376
|
+
paramsRecord,
|
|
23377
|
+
pending: pendingPermissionReplies,
|
|
23378
|
+
onRequest
|
|
22966
23379
|
});
|
|
22967
23380
|
},
|
|
22968
23381
|
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
|
-
}
|
|
23382
|
+
return acpReadTextFileInProcess(sessionCtx, params.path, params.line, params.limit);
|
|
22979
23383
|
},
|
|
22980
23384
|
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 {};
|
|
23385
|
+
return acpWriteTextFileInProcess(sessionCtx, params.path, params.content);
|
|
22995
23386
|
},
|
|
22996
23387
|
async sessionUpdate(params) {
|
|
22997
|
-
|
|
23388
|
+
const bridged = flattenSdkSessionNotificationParams(params);
|
|
23389
|
+
dispatchAcpSessionUpdate({
|
|
23390
|
+
flatPayload: bridged,
|
|
23391
|
+
onAcpConfigOptionsUpdated: sessionCtx.onAcpConfigOptionsUpdated,
|
|
23392
|
+
onSessionUpdate,
|
|
23393
|
+
suppressLoadReplay: () => sessionCtx.suppressLoadReplay.value
|
|
23394
|
+
});
|
|
22998
23395
|
},
|
|
22999
23396
|
async extNotification(method, params) {
|
|
23000
23397
|
await extNotification(method, params);
|
|
@@ -23004,84 +23401,19 @@ async function createSdkStdioAcpClient(options) {
|
|
|
23004
23401
|
connection.signal.addEventListener("abort", () => {
|
|
23005
23402
|
child.kill();
|
|
23006
23403
|
});
|
|
23007
|
-
|
|
23404
|
+
const transport = createSdkAcpSessionTransport(connection);
|
|
23405
|
+
const established = await bootstrapAcpWireSession(transport, sessionCtx, {
|
|
23008
23406
|
protocolVersion: PROTOCOL_VERSION2,
|
|
23009
23407
|
clientCapabilities: {
|
|
23010
23408
|
fs: { readTextFile: true, writeTextFile: true }
|
|
23011
23409
|
},
|
|
23012
23410
|
clientInfo: { name: "buildautomaton-cli", version: "0.1.0" }
|
|
23013
23411
|
});
|
|
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
|
-
}
|
|
23412
|
+
const sessionId = established.sessionId;
|
|
23030
23413
|
settleResolve({
|
|
23031
23414
|
sessionId,
|
|
23032
23415
|
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
|
-
}
|
|
23416
|
+
return sendAcpPromptViaTransport(transport, sessionCtx, sessionId, prompt);
|
|
23085
23417
|
},
|
|
23086
23418
|
async cancel() {
|
|
23087
23419
|
for (const [id, entry] of [...pendingPermissionReplies.entries()]) {
|
|
@@ -23089,7 +23421,7 @@ async function createSdkStdioAcpClient(options) {
|
|
|
23089
23421
|
entry.resolve({ outcome: { outcome: "cancelled" } });
|
|
23090
23422
|
}
|
|
23091
23423
|
try {
|
|
23092
|
-
await
|
|
23424
|
+
await transport.cancelSession(sessionId);
|
|
23093
23425
|
} catch {
|
|
23094
23426
|
}
|
|
23095
23427
|
if (killSubprocessAfterCancelMs != null && killSubprocessAfterCancelMs >= 0) {
|
|
@@ -23315,8 +23647,8 @@ function randomSecret() {
|
|
|
23315
23647
|
}
|
|
23316
23648
|
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
23317
23649
|
}
|
|
23318
|
-
async function requestPreviewApi(port, secret, method,
|
|
23319
|
-
const url2 = `http://127.0.0.1:${port}${
|
|
23650
|
+
async function requestPreviewApi(port, secret, method, path35, body) {
|
|
23651
|
+
const url2 = `http://127.0.0.1:${port}${path35}`;
|
|
23320
23652
|
const headers = {
|
|
23321
23653
|
[PREVIEW_SECRET_HEADER]: secret,
|
|
23322
23654
|
"Content-Type": "application/json"
|
|
@@ -23328,7 +23660,7 @@ async function requestPreviewApi(port, secret, method, path34, body) {
|
|
|
23328
23660
|
});
|
|
23329
23661
|
const data = await res.json().catch(() => ({}));
|
|
23330
23662
|
if (!res.ok) {
|
|
23331
|
-
throw new Error(data?.error ?? `Preview API ${method} ${
|
|
23663
|
+
throw new Error(data?.error ?? `Preview API ${method} ${path35}: ${res.status}`);
|
|
23332
23664
|
}
|
|
23333
23665
|
return data;
|
|
23334
23666
|
}
|
|
@@ -23471,40 +23803,6 @@ async function callSkill(skillId, operationId, params) {
|
|
|
23471
23803
|
return skill.execute(operationId, params);
|
|
23472
23804
|
}
|
|
23473
23805
|
|
|
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
23806
|
// src/config.ts
|
|
23509
23807
|
import fs from "node:fs";
|
|
23510
23808
|
import path3 from "node:path";
|
|
@@ -23577,7 +23875,7 @@ function installBridgeProcessResilience() {
|
|
|
23577
23875
|
}
|
|
23578
23876
|
|
|
23579
23877
|
// src/cli-version.ts
|
|
23580
|
-
var CLI_VERSION = "0.1.
|
|
23878
|
+
var CLI_VERSION = "0.1.26".length > 0 ? "0.1.26" : "0.0.0-dev";
|
|
23581
23879
|
|
|
23582
23880
|
// ../../node_modules/.pnpm/open@10.2.0/node_modules/open/index.js
|
|
23583
23881
|
import process7 from "node:process";
|
|
@@ -24741,8 +25039,8 @@ function pathspec(...paths) {
|
|
|
24741
25039
|
cache.set(key, paths);
|
|
24742
25040
|
return key;
|
|
24743
25041
|
}
|
|
24744
|
-
function isPathSpec(
|
|
24745
|
-
return
|
|
25042
|
+
function isPathSpec(path35) {
|
|
25043
|
+
return path35 instanceof String && cache.has(path35);
|
|
24746
25044
|
}
|
|
24747
25045
|
function toPaths(pathSpec) {
|
|
24748
25046
|
return cache.get(pathSpec) || [];
|
|
@@ -24831,8 +25129,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
|
|
|
24831
25129
|
function forEachLineWithContent(input, callback) {
|
|
24832
25130
|
return toLinesWithContent(input, true).map((line) => callback(line));
|
|
24833
25131
|
}
|
|
24834
|
-
function folderExists(
|
|
24835
|
-
return (0, import_file_exists.exists)(
|
|
25132
|
+
function folderExists(path35) {
|
|
25133
|
+
return (0, import_file_exists.exists)(path35, import_file_exists.FOLDER);
|
|
24836
25134
|
}
|
|
24837
25135
|
function append(target, item) {
|
|
24838
25136
|
if (Array.isArray(target)) {
|
|
@@ -25236,8 +25534,8 @@ function checkIsRepoRootTask() {
|
|
|
25236
25534
|
commands,
|
|
25237
25535
|
format: "utf-8",
|
|
25238
25536
|
onError,
|
|
25239
|
-
parser(
|
|
25240
|
-
return /^\.(git)?$/.test(
|
|
25537
|
+
parser(path35) {
|
|
25538
|
+
return /^\.(git)?$/.test(path35.trim());
|
|
25241
25539
|
}
|
|
25242
25540
|
};
|
|
25243
25541
|
}
|
|
@@ -25671,11 +25969,11 @@ function parseGrep(grep) {
|
|
|
25671
25969
|
const paths = /* @__PURE__ */ new Set();
|
|
25672
25970
|
const results = {};
|
|
25673
25971
|
forEachLineWithContent(grep, (input) => {
|
|
25674
|
-
const [
|
|
25675
|
-
paths.add(
|
|
25676
|
-
(results[
|
|
25972
|
+
const [path35, line, preview] = input.split(NULL);
|
|
25973
|
+
paths.add(path35);
|
|
25974
|
+
(results[path35] = results[path35] || []).push({
|
|
25677
25975
|
line: asNumber(line),
|
|
25678
|
-
path:
|
|
25976
|
+
path: path35,
|
|
25679
25977
|
preview
|
|
25680
25978
|
});
|
|
25681
25979
|
});
|
|
@@ -26440,14 +26738,14 @@ var init_hash_object = __esm2({
|
|
|
26440
26738
|
init_task();
|
|
26441
26739
|
}
|
|
26442
26740
|
});
|
|
26443
|
-
function parseInit(bare,
|
|
26741
|
+
function parseInit(bare, path35, text) {
|
|
26444
26742
|
const response = String(text).trim();
|
|
26445
26743
|
let result;
|
|
26446
26744
|
if (result = initResponseRegex.exec(response)) {
|
|
26447
|
-
return new InitSummary(bare,
|
|
26745
|
+
return new InitSummary(bare, path35, false, result[1]);
|
|
26448
26746
|
}
|
|
26449
26747
|
if (result = reInitResponseRegex.exec(response)) {
|
|
26450
|
-
return new InitSummary(bare,
|
|
26748
|
+
return new InitSummary(bare, path35, true, result[1]);
|
|
26451
26749
|
}
|
|
26452
26750
|
let gitDir = "";
|
|
26453
26751
|
const tokens = response.split(" ");
|
|
@@ -26458,7 +26756,7 @@ function parseInit(bare, path34, text) {
|
|
|
26458
26756
|
break;
|
|
26459
26757
|
}
|
|
26460
26758
|
}
|
|
26461
|
-
return new InitSummary(bare,
|
|
26759
|
+
return new InitSummary(bare, path35, /^re/i.test(response), gitDir);
|
|
26462
26760
|
}
|
|
26463
26761
|
var InitSummary;
|
|
26464
26762
|
var initResponseRegex;
|
|
@@ -26467,9 +26765,9 @@ var init_InitSummary = __esm2({
|
|
|
26467
26765
|
"src/lib/responses/InitSummary.ts"() {
|
|
26468
26766
|
"use strict";
|
|
26469
26767
|
InitSummary = class {
|
|
26470
|
-
constructor(bare,
|
|
26768
|
+
constructor(bare, path35, existing, gitDir) {
|
|
26471
26769
|
this.bare = bare;
|
|
26472
|
-
this.path =
|
|
26770
|
+
this.path = path35;
|
|
26473
26771
|
this.existing = existing;
|
|
26474
26772
|
this.gitDir = gitDir;
|
|
26475
26773
|
}
|
|
@@ -26481,7 +26779,7 @@ var init_InitSummary = __esm2({
|
|
|
26481
26779
|
function hasBareCommand(command) {
|
|
26482
26780
|
return command.includes(bareCommand);
|
|
26483
26781
|
}
|
|
26484
|
-
function initTask(bare = false,
|
|
26782
|
+
function initTask(bare = false, path35, customArgs) {
|
|
26485
26783
|
const commands = ["init", ...customArgs];
|
|
26486
26784
|
if (bare && !hasBareCommand(commands)) {
|
|
26487
26785
|
commands.splice(1, 0, bareCommand);
|
|
@@ -26490,7 +26788,7 @@ function initTask(bare = false, path34, customArgs) {
|
|
|
26490
26788
|
commands,
|
|
26491
26789
|
format: "utf-8",
|
|
26492
26790
|
parser(text) {
|
|
26493
|
-
return parseInit(commands.includes("--bare"),
|
|
26791
|
+
return parseInit(commands.includes("--bare"), path35, text);
|
|
26494
26792
|
}
|
|
26495
26793
|
};
|
|
26496
26794
|
}
|
|
@@ -27306,12 +27604,12 @@ var init_FileStatusSummary = __esm2({
|
|
|
27306
27604
|
"use strict";
|
|
27307
27605
|
fromPathRegex = /^(.+)\0(.+)$/;
|
|
27308
27606
|
FileStatusSummary = class {
|
|
27309
|
-
constructor(
|
|
27310
|
-
this.path =
|
|
27607
|
+
constructor(path35, index, working_dir) {
|
|
27608
|
+
this.path = path35;
|
|
27311
27609
|
this.index = index;
|
|
27312
27610
|
this.working_dir = working_dir;
|
|
27313
27611
|
if (index === "R" || working_dir === "R") {
|
|
27314
|
-
const detail = fromPathRegex.exec(
|
|
27612
|
+
const detail = fromPathRegex.exec(path35) || [null, path35, path35];
|
|
27315
27613
|
this.from = detail[2] || "";
|
|
27316
27614
|
this.path = detail[1] || "";
|
|
27317
27615
|
}
|
|
@@ -27342,14 +27640,14 @@ function splitLine(result, lineStr) {
|
|
|
27342
27640
|
default:
|
|
27343
27641
|
return;
|
|
27344
27642
|
}
|
|
27345
|
-
function data(index, workingDir,
|
|
27643
|
+
function data(index, workingDir, path35) {
|
|
27346
27644
|
const raw = `${index}${workingDir}`;
|
|
27347
27645
|
const handler = parsers6.get(raw);
|
|
27348
27646
|
if (handler) {
|
|
27349
|
-
handler(result,
|
|
27647
|
+
handler(result, path35);
|
|
27350
27648
|
}
|
|
27351
27649
|
if (raw !== "##" && raw !== "!!") {
|
|
27352
|
-
result.files.push(new FileStatusSummary(
|
|
27650
|
+
result.files.push(new FileStatusSummary(path35, index, workingDir));
|
|
27353
27651
|
}
|
|
27354
27652
|
}
|
|
27355
27653
|
}
|
|
@@ -27658,9 +27956,9 @@ var init_simple_git_api = __esm2({
|
|
|
27658
27956
|
next
|
|
27659
27957
|
);
|
|
27660
27958
|
}
|
|
27661
|
-
hashObject(
|
|
27959
|
+
hashObject(path35, write) {
|
|
27662
27960
|
return this._runTask(
|
|
27663
|
-
hashObjectTask(
|
|
27961
|
+
hashObjectTask(path35, write === true),
|
|
27664
27962
|
trailingFunctionArgument(arguments)
|
|
27665
27963
|
);
|
|
27666
27964
|
}
|
|
@@ -28013,8 +28311,8 @@ var init_branch = __esm2({
|
|
|
28013
28311
|
}
|
|
28014
28312
|
});
|
|
28015
28313
|
function toPath(input) {
|
|
28016
|
-
const
|
|
28017
|
-
return
|
|
28314
|
+
const path35 = input.trim().replace(/^["']|["']$/g, "");
|
|
28315
|
+
return path35 && normalize2(path35);
|
|
28018
28316
|
}
|
|
28019
28317
|
var parseCheckIgnore;
|
|
28020
28318
|
var init_CheckIgnore = __esm2({
|
|
@@ -28328,8 +28626,8 @@ __export2(sub_module_exports, {
|
|
|
28328
28626
|
subModuleTask: () => subModuleTask,
|
|
28329
28627
|
updateSubModuleTask: () => updateSubModuleTask
|
|
28330
28628
|
});
|
|
28331
|
-
function addSubModuleTask(repo,
|
|
28332
|
-
return subModuleTask(["add", repo,
|
|
28629
|
+
function addSubModuleTask(repo, path35) {
|
|
28630
|
+
return subModuleTask(["add", repo, path35]);
|
|
28333
28631
|
}
|
|
28334
28632
|
function initSubModuleTask(customArgs) {
|
|
28335
28633
|
return subModuleTask(["init", ...customArgs]);
|
|
@@ -28662,8 +28960,8 @@ var require_git = __commonJS2({
|
|
|
28662
28960
|
}
|
|
28663
28961
|
return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
|
|
28664
28962
|
};
|
|
28665
|
-
Git2.prototype.submoduleAdd = function(repo,
|
|
28666
|
-
return this._runTask(addSubModuleTask2(repo,
|
|
28963
|
+
Git2.prototype.submoduleAdd = function(repo, path35, then) {
|
|
28964
|
+
return this._runTask(addSubModuleTask2(repo, path35), trailingFunctionArgument2(arguments));
|
|
28667
28965
|
};
|
|
28668
28966
|
Git2.prototype.submoduleUpdate = function(args, then) {
|
|
28669
28967
|
return this._runTask(
|
|
@@ -29550,9 +29848,9 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
|
|
|
29550
29848
|
// src/agents/acp/put-summarize-change-summaries.ts
|
|
29551
29849
|
async function putEncryptedChangeSummaryRows(params) {
|
|
29552
29850
|
const base = params.apiBaseUrl.replace(/\/+$/, "");
|
|
29553
|
-
const entries = params.rows.map(({ path:
|
|
29851
|
+
const entries = params.rows.map(({ path: path35, summary }) => {
|
|
29554
29852
|
const enc = params.e2ee.encryptFields({ summary }, ["summary"]);
|
|
29555
|
-
return { path:
|
|
29853
|
+
return { path: path35, summary: JSON.stringify(enc) };
|
|
29556
29854
|
});
|
|
29557
29855
|
const res = await fetch(
|
|
29558
29856
|
`${base}/api/sessions/${encodeURIComponent(params.sessionId)}/follow-ups/summarize-changes`,
|
|
@@ -29734,8 +30032,8 @@ async function sendPromptToAgent(options) {
|
|
|
29734
30032
|
}
|
|
29735
30033
|
|
|
29736
30034
|
// src/agents/acp/ensure-acp-client.ts
|
|
29737
|
-
import * as
|
|
29738
|
-
import * as
|
|
30035
|
+
import * as fs10 from "node:fs";
|
|
30036
|
+
import * as path12 from "node:path";
|
|
29739
30037
|
|
|
29740
30038
|
// src/error-message.ts
|
|
29741
30039
|
function errorMessage(err) {
|
|
@@ -29825,7 +30123,7 @@ async function createCodexAcpClient(options) {
|
|
|
29825
30123
|
return createSdkStdioAcpClient({ ...options, command });
|
|
29826
30124
|
}
|
|
29827
30125
|
|
|
29828
|
-
// src/agents/acp/clients/cursor-acp-client.ts
|
|
30126
|
+
// src/agents/acp/clients/cursor/cursor-acp-client.ts
|
|
29829
30127
|
var cursor_acp_client_exports = {};
|
|
29830
30128
|
__export(cursor_acp_client_exports, {
|
|
29831
30129
|
BACKEND_LOCAL_AGENT_TYPE: () => BACKEND_LOCAL_AGENT_TYPE3,
|
|
@@ -29833,8 +30131,6 @@ __export(cursor_acp_client_exports, {
|
|
|
29833
30131
|
createCursorAcpClient: () => createCursorAcpClient,
|
|
29834
30132
|
detectLocalAgentPresence: () => detectLocalAgentPresence3
|
|
29835
30133
|
});
|
|
29836
|
-
import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "node:fs";
|
|
29837
|
-
import { dirname as dirname3 } from "node:path";
|
|
29838
30134
|
import { spawn as spawn4 } from "node:child_process";
|
|
29839
30135
|
import * as readline from "node:readline";
|
|
29840
30136
|
|
|
@@ -29851,7 +30147,23 @@ function formatSessionUpdateKindForLog(kind) {
|
|
|
29851
30147
|
return kind.split("_").filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join(" ");
|
|
29852
30148
|
}
|
|
29853
30149
|
|
|
29854
|
-
// src/agents/acp/clients/cursor-acp-
|
|
30150
|
+
// src/agents/acp/clients/cursor/cursor-json-rpc-acp-transport.ts
|
|
30151
|
+
function createCursorJsonRpcAcpTransport(deps) {
|
|
30152
|
+
const { send, cancelSessionNotification } = deps;
|
|
30153
|
+
return {
|
|
30154
|
+
initialize: (request) => send("initialize", request),
|
|
30155
|
+
afterInitialize: async () => {
|
|
30156
|
+
await send("authenticate", { methodId: "cursor_login" });
|
|
30157
|
+
},
|
|
30158
|
+
resumeSession: (p) => send("session/resume", p),
|
|
30159
|
+
loadSession: (p) => send("session/load", p),
|
|
30160
|
+
newSession: (p) => send("session/new", p),
|
|
30161
|
+
prompt: (p) => send("session/prompt", p),
|
|
30162
|
+
cancelSession: (sessionId) => cancelSessionNotification(sessionId)
|
|
30163
|
+
};
|
|
30164
|
+
}
|
|
30165
|
+
|
|
30166
|
+
// src/agents/acp/clients/cursor/cursor-acp-client.ts
|
|
29855
30167
|
var FS_READ_METHODS = /* @__PURE__ */ new Set(["fs/read_text_file", "fs/readTextFile"]);
|
|
29856
30168
|
var FS_WRITE_METHODS = /* @__PURE__ */ new Set(["fs/write_text_file", "fs/writeTextFile"]);
|
|
29857
30169
|
function formatSpawnError2(err, command) {
|
|
@@ -29868,13 +30180,6 @@ function safeJsonParse(value) {
|
|
|
29868
30180
|
return null;
|
|
29869
30181
|
}
|
|
29870
30182
|
}
|
|
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
30183
|
function buildCursorAcpSpawnCommand(base, sessionMode) {
|
|
29879
30184
|
if (!sessionMode) return [...base];
|
|
29880
30185
|
const m = sessionMode.trim();
|
|
@@ -29888,7 +30193,11 @@ async function createCursorAcpClient(options) {
|
|
|
29888
30193
|
backendAgentType,
|
|
29889
30194
|
onSessionUpdate,
|
|
29890
30195
|
onRequest,
|
|
29891
|
-
onFileChange
|
|
30196
|
+
onFileChange,
|
|
30197
|
+
persistedAcpSessionId,
|
|
30198
|
+
onAcpSessionEstablished,
|
|
30199
|
+
onAcpConfigOptionsUpdated,
|
|
30200
|
+
onAgentSubprocessExit
|
|
29892
30201
|
} = options;
|
|
29893
30202
|
const dbgFs = process.env.BUILDAUTOMATON_DEBUG_ACP_FS === "1";
|
|
29894
30203
|
const isWindows = process.platform === "win32";
|
|
@@ -29900,6 +30209,25 @@ async function createCursorAcpClient(options) {
|
|
|
29900
30209
|
});
|
|
29901
30210
|
const stderrCapture = createStderrCapture(child);
|
|
29902
30211
|
child.stderr?.on("data", (chunk) => stderrCapture.append(chunk));
|
|
30212
|
+
child.once("close", (code, signal) => {
|
|
30213
|
+
onAgentSubprocessExit?.({ code, signal });
|
|
30214
|
+
});
|
|
30215
|
+
const suppressLoadReplayRef = { value: false };
|
|
30216
|
+
const sessionCtx = {
|
|
30217
|
+
cwd,
|
|
30218
|
+
onFileChange,
|
|
30219
|
+
mcpServers: [],
|
|
30220
|
+
persistedAcpSessionId,
|
|
30221
|
+
agentLabel: "Cursor",
|
|
30222
|
+
suppressLoadReplay: suppressLoadReplayRef,
|
|
30223
|
+
backendAgentType: backendAgentType ?? null,
|
|
30224
|
+
agentConfig: options.agentConfig,
|
|
30225
|
+
getActiveConfigOptions: options.getActiveConfigOptions,
|
|
30226
|
+
onAcpSessionEstablished,
|
|
30227
|
+
onAcpConfigOptionsUpdated,
|
|
30228
|
+
logDebug,
|
|
30229
|
+
getStderrText: () => stderrCapture.getText()
|
|
30230
|
+
};
|
|
29903
30231
|
return new Promise((resolve16, reject) => {
|
|
29904
30232
|
child.on("error", (err) => {
|
|
29905
30233
|
child.kill();
|
|
@@ -29908,6 +30236,16 @@ async function createCursorAcpClient(options) {
|
|
|
29908
30236
|
let nextId = 1;
|
|
29909
30237
|
const pending = /* @__PURE__ */ new Map();
|
|
29910
30238
|
const pendingRequests = /* @__PURE__ */ new Map();
|
|
30239
|
+
function cancelSessionNotification(sessionId) {
|
|
30240
|
+
const line = JSON.stringify({
|
|
30241
|
+
jsonrpc: "2.0",
|
|
30242
|
+
method: "session/cancel",
|
|
30243
|
+
params: { sessionId }
|
|
30244
|
+
}) + "\n";
|
|
30245
|
+
return new Promise((res, rej) => {
|
|
30246
|
+
child.stdin.write(line, (err) => err ? rej(err) : res());
|
|
30247
|
+
});
|
|
30248
|
+
}
|
|
29911
30249
|
function send(method, params) {
|
|
29912
30250
|
const id = nextId++;
|
|
29913
30251
|
const line = JSON.stringify({ jsonrpc: "2.0", id, method, params }) + "\n";
|
|
@@ -29931,7 +30269,6 @@ async function createCursorAcpClient(options) {
|
|
|
29931
30269
|
respond(requestId, payload);
|
|
29932
30270
|
pendingRequests.delete(requestId);
|
|
29933
30271
|
}
|
|
29934
|
-
let promptOutputBuffer = "";
|
|
29935
30272
|
const rl = readline.createInterface({ input: child.stdout });
|
|
29936
30273
|
rl.on("line", (line) => {
|
|
29937
30274
|
const msg = safeJsonParse(line);
|
|
@@ -29960,11 +30297,12 @@ async function createCursorAcpClient(options) {
|
|
|
29960
30297
|
`[acp] Received session update (${kindLabel}) tool=${toolName || "(none)"}`
|
|
29961
30298
|
);
|
|
29962
30299
|
}
|
|
29963
|
-
|
|
29964
|
-
|
|
29965
|
-
|
|
29966
|
-
|
|
29967
|
-
|
|
30300
|
+
dispatchAcpSessionUpdate({
|
|
30301
|
+
flatPayload: update,
|
|
30302
|
+
onAcpConfigOptionsUpdated: sessionCtx.onAcpConfigOptionsUpdated,
|
|
30303
|
+
onSessionUpdate,
|
|
30304
|
+
suppressLoadReplay: () => sessionCtx.suppressLoadReplay.value
|
|
30305
|
+
});
|
|
29968
30306
|
return;
|
|
29969
30307
|
}
|
|
29970
30308
|
if (method === "session/request_permission" && typeof id === "number") {
|
|
@@ -29984,21 +30322,13 @@ async function createCursorAcpClient(options) {
|
|
|
29984
30322
|
if (dbgFs) {
|
|
29985
30323
|
console.error(`[acp-fs] ${method} path=${filePath.slice(0, 200)}${filePath.length > 200 ? "\u2026" : ""}`);
|
|
29986
30324
|
}
|
|
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
30325
|
try {
|
|
29994
|
-
|
|
29995
|
-
const
|
|
29996
|
-
const
|
|
29997
|
-
|
|
29998
|
-
respond(id, { content });
|
|
30326
|
+
const lineNum = typeof params.line === "number" ? params.line : void 0;
|
|
30327
|
+
const limitNum = typeof params.limit === "number" ? params.limit : void 0;
|
|
30328
|
+
const out = acpReadTextFileInProcess(sessionCtx, filePath, lineNum, limitNum);
|
|
30329
|
+
respond(id, out);
|
|
29999
30330
|
} catch (e) {
|
|
30000
|
-
|
|
30001
|
-
if (code === "ENOENT") {
|
|
30331
|
+
if (e?.code === "ENOENT") {
|
|
30002
30332
|
respond(id, { content: "" });
|
|
30003
30333
|
} else {
|
|
30004
30334
|
respondJsonRpcError(id, -32e3, e instanceof Error ? e.message : String(e));
|
|
@@ -30015,32 +30345,17 @@ async function createCursorAcpClient(options) {
|
|
|
30015
30345
|
`[acp-fs] ${method} path=${filePath.slice(0, 200)}${filePath.length > 200 ? "\u2026" : ""} newBytes=${newText.length}`
|
|
30016
30346
|
);
|
|
30017
30347
|
}
|
|
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
30348
|
try {
|
|
30026
|
-
|
|
30349
|
+
acpWriteTextFileInProcess(sessionCtx, filePath, newText);
|
|
30350
|
+
respond(id, null);
|
|
30027
30351
|
} catch (e) {
|
|
30028
|
-
if (e.
|
|
30352
|
+
if (e.message === "Invalid or disallowed path") {
|
|
30353
|
+
if (dbgFs) console.error(`[acp-fs] ${method} rejected path (outside cwd or empty): ${filePath.slice(0, 120)}`);
|
|
30354
|
+
respondJsonRpcError(id, -32602, "Invalid or disallowed path");
|
|
30355
|
+
} else {
|
|
30029
30356
|
respondJsonRpcError(id, -32e3, e instanceof Error ? e.message : String(e));
|
|
30030
|
-
return;
|
|
30031
30357
|
}
|
|
30032
30358
|
}
|
|
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
30359
|
return;
|
|
30045
30360
|
}
|
|
30046
30361
|
if (method === "cursor/create_plan" || method === "cursor/ask_question") {
|
|
@@ -30062,16 +30377,7 @@ async function createCursorAcpClient(options) {
|
|
|
30062
30377
|
});
|
|
30063
30378
|
(async () => {
|
|
30064
30379
|
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() {
|
|
30380
|
+
let cancelPendingPermissionRequests2 = function() {
|
|
30075
30381
|
for (const [reqId, pending2] of [...pendingRequests.entries()]) {
|
|
30076
30382
|
if (pending2.method === "session/request_permission") {
|
|
30077
30383
|
respond(reqId, { outcome: { outcome: "cancelled" } });
|
|
@@ -30079,76 +30385,25 @@ async function createCursorAcpClient(options) {
|
|
|
30079
30385
|
}
|
|
30080
30386
|
}
|
|
30081
30387
|
};
|
|
30082
|
-
var
|
|
30083
|
-
|
|
30388
|
+
var cancelPendingPermissionRequests = cancelPendingPermissionRequests2;
|
|
30389
|
+
const transport = createCursorJsonRpcAcpTransport({
|
|
30390
|
+
send,
|
|
30391
|
+
cancelSessionNotification
|
|
30392
|
+
});
|
|
30393
|
+
const established = await bootstrapAcpWireSession(transport, sessionCtx, {
|
|
30084
30394
|
protocolVersion: 1,
|
|
30085
30395
|
clientCapabilities: { fs: { readTextFile: true, writeTextFile: true }, terminal: false },
|
|
30086
30396
|
clientInfo: { name: "buildautomaton-cli", version: "0.1.0" }
|
|
30087
30397
|
});
|
|
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");
|
|
30398
|
+
const sessionId = established.sessionId;
|
|
30092
30399
|
resolve16({
|
|
30093
30400
|
sessionId,
|
|
30094
30401
|
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
|
-
}
|
|
30402
|
+
return sendAcpPromptViaTransport(transport, sessionCtx, sessionId, prompt);
|
|
30148
30403
|
},
|
|
30149
30404
|
async cancel() {
|
|
30150
30405
|
cancelPendingPermissionRequests2();
|
|
30151
|
-
await
|
|
30406
|
+
await transport.cancelSession(sessionId);
|
|
30152
30407
|
},
|
|
30153
30408
|
resolveRequest(requestId, result) {
|
|
30154
30409
|
const numericId = Number(requestId);
|
|
@@ -30296,7 +30551,7 @@ function getGitRepoRootSync(startDir) {
|
|
|
30296
30551
|
|
|
30297
30552
|
// src/agents/acp/workspace-files.ts
|
|
30298
30553
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
30299
|
-
import { readFileSync as
|
|
30554
|
+
import { readFileSync as readFileSync3 } from "node:fs";
|
|
30300
30555
|
import * as path10 from "node:path";
|
|
30301
30556
|
function resolveWorkspaceFilePath(sessionParentPath, rawPath) {
|
|
30302
30557
|
const trimmed2 = rawPath.trim();
|
|
@@ -30328,7 +30583,7 @@ function readUtf8WorkspaceFile(sessionParentPath, displayPath) {
|
|
|
30328
30583
|
const rel = path10.relative(gitRoot, resolvedPath2);
|
|
30329
30584
|
if (!rel.startsWith("..") && !path10.isAbsolute(rel)) {
|
|
30330
30585
|
try {
|
|
30331
|
-
return
|
|
30586
|
+
return readFileSync3(resolvedPath2, "utf8");
|
|
30332
30587
|
} catch {
|
|
30333
30588
|
}
|
|
30334
30589
|
}
|
|
@@ -30336,7 +30591,7 @@ function readUtf8WorkspaceFile(sessionParentPath, displayPath) {
|
|
|
30336
30591
|
const resolvedPath = resolveSafePathUnderCwd(sessionParentPath, displayPath);
|
|
30337
30592
|
if (!resolvedPath) return "";
|
|
30338
30593
|
try {
|
|
30339
|
-
return
|
|
30594
|
+
return readFileSync3(resolvedPath, "utf8");
|
|
30340
30595
|
} catch {
|
|
30341
30596
|
return "";
|
|
30342
30597
|
}
|
|
@@ -30432,7 +30687,7 @@ function createBridgeOnFileChange(opts) {
|
|
|
30432
30687
|
|
|
30433
30688
|
// src/agents/acp/hooks/bridge-on-request.ts
|
|
30434
30689
|
function createBridgeOnRequest(opts) {
|
|
30435
|
-
const { routing, getSendRequest, log: log2 } = opts;
|
|
30690
|
+
const { routing, getSendRequest, log: log2, getAutoApproveAcpPermissions, resolveAcpPermissionRequest } = opts;
|
|
30436
30691
|
return (request) => {
|
|
30437
30692
|
const runId = routing.runId;
|
|
30438
30693
|
const sessionId = routing.sessionId;
|
|
@@ -30440,6 +30695,26 @@ function createBridgeOnRequest(opts) {
|
|
|
30440
30695
|
if (!runId || !sendReq) return;
|
|
30441
30696
|
const kind = request.method === "cursor/create_plan" ? "plan" : request.method === "session/request_permission" ? "permission" : "question";
|
|
30442
30697
|
const sessionUpdate = request.method === "cursor/create_plan" ? "plan" : request.method === "session/request_permission" ? "permission" : "question";
|
|
30698
|
+
if (request.method === "session/request_permission" && getAutoApproveAcpPermissions() && resolveAcpPermissionRequest) {
|
|
30699
|
+
const params = request.params != null && typeof request.params === "object" && !Array.isArray(request.params) ? request.params : {};
|
|
30700
|
+
const auto = buildCliAutoApprovedPermissionRpcResult(params);
|
|
30701
|
+
if (auto != null) {
|
|
30702
|
+
try {
|
|
30703
|
+
resolveAcpPermissionRequest(request.requestId, auto);
|
|
30704
|
+
log2(
|
|
30705
|
+
`[Bridge service] CLI dangerous mode: auto-approved permission requestId=${request.requestId} runId=${runId}`
|
|
30706
|
+
);
|
|
30707
|
+
return;
|
|
30708
|
+
} catch (err) {
|
|
30709
|
+
log2(
|
|
30710
|
+
`[Bridge service] CLI dangerous mode: auto-approve failed (${errorMessage(err)}); forwarding permission`
|
|
30711
|
+
);
|
|
30712
|
+
}
|
|
30713
|
+
}
|
|
30714
|
+
log2(
|
|
30715
|
+
`[Bridge service] CLI dangerous mode: no allow option to auto-select; forwarding permission requestId=${request.requestId}`
|
|
30716
|
+
);
|
|
30717
|
+
}
|
|
30443
30718
|
try {
|
|
30444
30719
|
sendReq({
|
|
30445
30720
|
type: "session_update",
|
|
@@ -30840,6 +31115,9 @@ function createBridgeOnSessionUpdate(opts) {
|
|
|
30840
31115
|
const sentFileChangePaths = /* @__PURE__ */ new Set();
|
|
30841
31116
|
const p = params;
|
|
30842
31117
|
const updateKind = p.sessionUpdate ?? p.session_update ?? p.type ?? "update";
|
|
31118
|
+
if (updateKind === "config_option_update") {
|
|
31119
|
+
return;
|
|
31120
|
+
}
|
|
30843
31121
|
const isCompletedToolCallUpdate = updateKind === "tool_call_update" && isCompletedToolStatus(p.status);
|
|
30844
31122
|
const toolName = p.toolCall?.name ?? p.tool_call?.name ?? "";
|
|
30845
31123
|
const isToolUpdate = updateKind === "tool_call" || updateKind === "tool_call_update" || typeof toolName === "string" && toolName.length > 0;
|
|
@@ -30926,14 +31204,73 @@ function buildAcpSessionBridgeHooks(opts) {
|
|
|
30926
31204
|
};
|
|
30927
31205
|
}
|
|
30928
31206
|
|
|
31207
|
+
// src/agents/acp/local-agent-session-file.ts
|
|
31208
|
+
import fs9 from "node:fs";
|
|
31209
|
+
import os3 from "node:os";
|
|
31210
|
+
import path11 from "node:path";
|
|
31211
|
+
var LOCAL_AGENT_SESSION_DIR = path11.join(os3.homedir(), ".buildautomaton", "agent-sessions");
|
|
31212
|
+
function safeFileSlug(cloudSessionId) {
|
|
31213
|
+
const t = cloudSessionId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 220);
|
|
31214
|
+
return t.length > 0 ? t : "session";
|
|
31215
|
+
}
|
|
31216
|
+
function localAgentSessionFilePath(cloudSessionId) {
|
|
31217
|
+
return path11.join(LOCAL_AGENT_SESSION_DIR, `${safeFileSlug(cloudSessionId)}.json`);
|
|
31218
|
+
}
|
|
31219
|
+
function readLocalAgentSessionFile(cloudSessionId) {
|
|
31220
|
+
try {
|
|
31221
|
+
const p = localAgentSessionFilePath(cloudSessionId);
|
|
31222
|
+
const raw = fs9.readFileSync(p, "utf8");
|
|
31223
|
+
const parsed = JSON.parse(raw);
|
|
31224
|
+
if (parsed.v !== 1) return null;
|
|
31225
|
+
return {
|
|
31226
|
+
v: 1,
|
|
31227
|
+
acpSessionId: typeof parsed.acpSessionId === "string" ? parsed.acpSessionId : null,
|
|
31228
|
+
backendAgentType: typeof parsed.backendAgentType === "string" ? parsed.backendAgentType : null,
|
|
31229
|
+
configOptions: Array.isArray(parsed.configOptions) ? parsed.configOptions : null,
|
|
31230
|
+
updatedAt: typeof parsed.updatedAt === "string" ? parsed.updatedAt : (/* @__PURE__ */ new Date()).toISOString()
|
|
31231
|
+
};
|
|
31232
|
+
} catch {
|
|
31233
|
+
return null;
|
|
31234
|
+
}
|
|
31235
|
+
}
|
|
31236
|
+
function writeLocalAgentSessionFile(cloudSessionId, patch) {
|
|
31237
|
+
try {
|
|
31238
|
+
const dir = LOCAL_AGENT_SESSION_DIR;
|
|
31239
|
+
if (!fs9.existsSync(dir)) fs9.mkdirSync(dir, { recursive: true });
|
|
31240
|
+
const p = localAgentSessionFilePath(cloudSessionId);
|
|
31241
|
+
const prev = readLocalAgentSessionFile(cloudSessionId);
|
|
31242
|
+
const next = {
|
|
31243
|
+
v: 1,
|
|
31244
|
+
acpSessionId: patch.acpSessionId !== void 0 ? patch.acpSessionId : prev?.acpSessionId ?? null,
|
|
31245
|
+
backendAgentType: patch.backendAgentType !== void 0 ? patch.backendAgentType : prev?.backendAgentType ?? null,
|
|
31246
|
+
configOptions: patch.configOptions !== void 0 ? patch.configOptions : prev?.configOptions ?? null,
|
|
31247
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
31248
|
+
};
|
|
31249
|
+
fs9.writeFileSync(p, JSON.stringify(next, null, 2), "utf8");
|
|
31250
|
+
} catch {
|
|
31251
|
+
}
|
|
31252
|
+
}
|
|
31253
|
+
|
|
30929
31254
|
// src/agents/acp/ensure-acp-client.ts
|
|
30930
31255
|
async function ensureAcpClient(options) {
|
|
30931
|
-
const {
|
|
31256
|
+
const {
|
|
31257
|
+
state,
|
|
31258
|
+
preferredAgentType,
|
|
31259
|
+
mode,
|
|
31260
|
+
agentConfig,
|
|
31261
|
+
sessionParentPath,
|
|
31262
|
+
routing,
|
|
31263
|
+
cloudSessionId,
|
|
31264
|
+
sendSessionUpdate,
|
|
31265
|
+
sendRequest,
|
|
31266
|
+
log: log2
|
|
31267
|
+
} = options;
|
|
31268
|
+
state.latestAgentConfigForBridgeHooks = agentConfig != null && typeof agentConfig === "object" && !Array.isArray(agentConfig) ? agentConfig : null;
|
|
30932
31269
|
const targetSessionParentPath = resolveSessionParentPathForAgentProcess(sessionParentPath);
|
|
30933
31270
|
if (state.acpStartPromise && !state.acpHandle) {
|
|
30934
31271
|
await state.acpStartPromise;
|
|
30935
31272
|
}
|
|
30936
|
-
if (state.acpHandle && state.lastAcpCwd != null &&
|
|
31273
|
+
if (state.acpHandle && state.lastAcpCwd != null && path12.resolve(state.lastAcpCwd) !== path12.resolve(targetSessionParentPath)) {
|
|
30937
31274
|
try {
|
|
30938
31275
|
state.acpHandle.disconnect();
|
|
30939
31276
|
} catch {
|
|
@@ -30941,6 +31278,7 @@ async function ensureAcpClient(options) {
|
|
|
30941
31278
|
state.acpHandle = null;
|
|
30942
31279
|
state.acpStartPromise = null;
|
|
30943
31280
|
state.acpAgentKey = null;
|
|
31281
|
+
state.activeSessionConfigOptions = null;
|
|
30944
31282
|
}
|
|
30945
31283
|
const resolved = resolveAgentCommand(preferredAgentType);
|
|
30946
31284
|
if (!resolved) {
|
|
@@ -30961,12 +31299,13 @@ async function ensureAcpClient(options) {
|
|
|
30961
31299
|
state.acpHandle = null;
|
|
30962
31300
|
state.acpStartPromise = null;
|
|
30963
31301
|
state.acpAgentKey = null;
|
|
31302
|
+
state.activeSessionConfigOptions = null;
|
|
30964
31303
|
}
|
|
30965
31304
|
if (state.acpHandle) return state.acpHandle;
|
|
30966
31305
|
if (!state.acpStartPromise) {
|
|
30967
31306
|
let statOk = false;
|
|
30968
31307
|
try {
|
|
30969
|
-
const st =
|
|
31308
|
+
const st = fs10.statSync(targetSessionParentPath);
|
|
30970
31309
|
statOk = st.isDirectory();
|
|
30971
31310
|
if (!statOk) {
|
|
30972
31311
|
state.lastAcpStartError = `Agent cwd is not a directory: ${targetSessionParentPath}`;
|
|
@@ -30984,17 +31323,47 @@ async function ensureAcpClient(options) {
|
|
|
30984
31323
|
sessionParentPath: targetSessionParentPath,
|
|
30985
31324
|
getSendSessionUpdate: () => sendSessionUpdate,
|
|
30986
31325
|
getSendRequest: () => sendRequest,
|
|
30987
|
-
log: log2
|
|
31326
|
+
log: log2,
|
|
31327
|
+
getAutoApproveAcpPermissions: () => getCliPermissionModeFromAgentConfig(state.latestAgentConfigForBridgeHooks) === CLI_PERMISSION_MODE_DANGEROUS,
|
|
31328
|
+
resolveAcpPermissionRequest: (requestId, result) => {
|
|
31329
|
+
state.acpHandle?.resolveRequest?.(requestId, result);
|
|
31330
|
+
}
|
|
30988
31331
|
});
|
|
31332
|
+
const persisted = cloudSessionId != null && cloudSessionId !== "" && preferredAgentType != null && preferredAgentType !== "" ? readLocalAgentSessionFile(cloudSessionId) : null;
|
|
31333
|
+
const persistedAcpSessionId = persisted && persisted.backendAgentType === preferredAgentType && typeof persisted.acpSessionId === "string" && persisted.acpSessionId.trim() !== "" ? persisted.acpSessionId.trim() : null;
|
|
31334
|
+
state.activeSessionConfigOptions = Array.isArray(persisted?.configOptions) ? persisted.configOptions : null;
|
|
30989
31335
|
state.acpStartPromise = resolved.createClient({
|
|
30990
31336
|
command: resolved.command,
|
|
30991
31337
|
sessionMode: mode,
|
|
30992
31338
|
agentConfig: agentConfig ?? null,
|
|
30993
31339
|
backendAgentType: preferredAgentType,
|
|
31340
|
+
persistedAcpSessionId,
|
|
31341
|
+
getActiveConfigOptions: () => state.activeSessionConfigOptions,
|
|
31342
|
+
onAcpSessionEstablished: (info) => {
|
|
31343
|
+
state.activeSessionConfigOptions = info.configOptions ?? state.activeSessionConfigOptions;
|
|
31344
|
+
if (cloudSessionId != null && cloudSessionId !== "" && preferredAgentType != null && preferredAgentType !== "") {
|
|
31345
|
+
writeLocalAgentSessionFile(cloudSessionId, {
|
|
31346
|
+
acpSessionId: info.acpSessionId,
|
|
31347
|
+
configOptions: info.configOptions,
|
|
31348
|
+
backendAgentType: preferredAgentType
|
|
31349
|
+
});
|
|
31350
|
+
}
|
|
31351
|
+
},
|
|
31352
|
+
onAcpConfigOptionsUpdated: (configOptions) => {
|
|
31353
|
+
state.activeSessionConfigOptions = configOptions;
|
|
31354
|
+
if (cloudSessionId != null && cloudSessionId !== "" && preferredAgentType != null && preferredAgentType !== "") {
|
|
31355
|
+
writeLocalAgentSessionFile(cloudSessionId, {
|
|
31356
|
+
configOptions,
|
|
31357
|
+
backendAgentType: preferredAgentType
|
|
31358
|
+
});
|
|
31359
|
+
}
|
|
31360
|
+
},
|
|
30994
31361
|
onAgentSubprocessExit: () => {
|
|
30995
31362
|
state.acpHandle = null;
|
|
30996
31363
|
state.acpStartPromise = null;
|
|
30997
31364
|
state.acpAgentKey = null;
|
|
31365
|
+
state.activeSessionConfigOptions = null;
|
|
31366
|
+
state.latestAgentConfigForBridgeHooks = null;
|
|
30998
31367
|
state.lastAcpStartError = "Agent subprocess exited";
|
|
30999
31368
|
},
|
|
31000
31369
|
...hooks,
|
|
@@ -31024,7 +31393,9 @@ async function createAcpManager(options) {
|
|
|
31024
31393
|
acpStartPromise: null,
|
|
31025
31394
|
lastAcpStartError: null,
|
|
31026
31395
|
lastAcpCwd: null,
|
|
31027
|
-
acpAgentKey: null
|
|
31396
|
+
acpAgentKey: null,
|
|
31397
|
+
activeSessionConfigOptions: null,
|
|
31398
|
+
latestAgentConfigForBridgeHooks: null
|
|
31028
31399
|
};
|
|
31029
31400
|
let backendFallbackAgentType = null;
|
|
31030
31401
|
const promptRouting = {};
|
|
@@ -31074,6 +31445,7 @@ async function createAcpManager(options) {
|
|
|
31074
31445
|
agentConfig: agentConfig ?? null,
|
|
31075
31446
|
sessionParentPath,
|
|
31076
31447
|
routing: promptRouting,
|
|
31448
|
+
cloudSessionId: sessionId,
|
|
31077
31449
|
sendSessionUpdate,
|
|
31078
31450
|
sendRequest: sendSessionUpdate,
|
|
31079
31451
|
log: log2
|
|
@@ -31164,6 +31536,8 @@ async function createAcpManager(options) {
|
|
|
31164
31536
|
state.acpHandle = null;
|
|
31165
31537
|
state.acpStartPromise = null;
|
|
31166
31538
|
state.acpAgentKey = null;
|
|
31539
|
+
state.activeSessionConfigOptions = null;
|
|
31540
|
+
state.latestAgentConfigForBridgeHooks = null;
|
|
31167
31541
|
}
|
|
31168
31542
|
return {
|
|
31169
31543
|
setPreferredAgentType,
|
|
@@ -31176,12 +31550,12 @@ async function createAcpManager(options) {
|
|
|
31176
31550
|
}
|
|
31177
31551
|
|
|
31178
31552
|
// src/worktrees/session-worktree-manager.ts
|
|
31179
|
-
import * as
|
|
31180
|
-
import
|
|
31553
|
+
import * as path19 from "node:path";
|
|
31554
|
+
import os5 from "node:os";
|
|
31181
31555
|
|
|
31182
31556
|
// src/worktrees/prepare-new-session-worktrees.ts
|
|
31183
|
-
import * as
|
|
31184
|
-
import * as
|
|
31557
|
+
import * as fs12 from "node:fs";
|
|
31558
|
+
import * as path14 from "node:path";
|
|
31185
31559
|
|
|
31186
31560
|
// src/git/worktree-add.ts
|
|
31187
31561
|
async function gitWorktreeAddBranch(mainRepoPath, worktreePath, branch) {
|
|
@@ -31190,12 +31564,12 @@ async function gitWorktreeAddBranch(mainRepoPath, worktreePath, branch) {
|
|
|
31190
31564
|
}
|
|
31191
31565
|
|
|
31192
31566
|
// src/worktrees/worktree-layout-file.ts
|
|
31193
|
-
import * as
|
|
31194
|
-
import * as
|
|
31195
|
-
import
|
|
31567
|
+
import * as fs11 from "node:fs";
|
|
31568
|
+
import * as path13 from "node:path";
|
|
31569
|
+
import os4 from "node:os";
|
|
31196
31570
|
var LAYOUT_FILENAME = "worktree-launcher-layout.json";
|
|
31197
31571
|
function defaultWorktreeLayoutPath() {
|
|
31198
|
-
return
|
|
31572
|
+
return path13.join(os4.homedir(), ".buildautomaton", LAYOUT_FILENAME);
|
|
31199
31573
|
}
|
|
31200
31574
|
function normalizeLoadedLayout(raw) {
|
|
31201
31575
|
if (raw && typeof raw === "object" && "launcherCwds" in raw) {
|
|
@@ -31207,8 +31581,8 @@ function normalizeLoadedLayout(raw) {
|
|
|
31207
31581
|
function loadWorktreeLayout() {
|
|
31208
31582
|
try {
|
|
31209
31583
|
const p = defaultWorktreeLayoutPath();
|
|
31210
|
-
if (!
|
|
31211
|
-
const raw = JSON.parse(
|
|
31584
|
+
if (!fs11.existsSync(p)) return { launcherCwds: [] };
|
|
31585
|
+
const raw = JSON.parse(fs11.readFileSync(p, "utf8"));
|
|
31212
31586
|
return normalizeLoadedLayout(raw);
|
|
31213
31587
|
} catch {
|
|
31214
31588
|
return { launcherCwds: [] };
|
|
@@ -31216,24 +31590,24 @@ function loadWorktreeLayout() {
|
|
|
31216
31590
|
}
|
|
31217
31591
|
function saveWorktreeLayout(layout) {
|
|
31218
31592
|
try {
|
|
31219
|
-
const dir =
|
|
31220
|
-
|
|
31221
|
-
|
|
31593
|
+
const dir = path13.dirname(defaultWorktreeLayoutPath());
|
|
31594
|
+
fs11.mkdirSync(dir, { recursive: true });
|
|
31595
|
+
fs11.writeFileSync(defaultWorktreeLayoutPath(), JSON.stringify(layout, null, 2), "utf8");
|
|
31222
31596
|
} catch {
|
|
31223
31597
|
}
|
|
31224
31598
|
}
|
|
31225
31599
|
function baseNameSafe(pathString) {
|
|
31226
|
-
return
|
|
31600
|
+
return path13.basename(pathString).replace(/[^a-zA-Z0-9._-]+/g, "-") || "cwd";
|
|
31227
31601
|
}
|
|
31228
31602
|
function getLauncherDirNameIfPresent(layout, bridgeRootPath2) {
|
|
31229
|
-
const norm =
|
|
31230
|
-
const existing = layout.launcherCwds.find((e) =>
|
|
31603
|
+
const norm = path13.resolve(bridgeRootPath2);
|
|
31604
|
+
const existing = layout.launcherCwds.find((e) => path13.resolve(e.absolutePath) === norm);
|
|
31231
31605
|
return existing?.dirName;
|
|
31232
31606
|
}
|
|
31233
31607
|
function allocateDirNameForLauncherCwd(layout, bridgeRootPath2) {
|
|
31234
31608
|
const existing = getLauncherDirNameIfPresent(layout, bridgeRootPath2);
|
|
31235
31609
|
if (existing) return existing;
|
|
31236
|
-
const norm =
|
|
31610
|
+
const norm = path13.resolve(bridgeRootPath2);
|
|
31237
31611
|
const base = baseNameSafe(norm);
|
|
31238
31612
|
const used = new Set(layout.launcherCwds.map((e) => e.dirName));
|
|
31239
31613
|
let name = base;
|
|
@@ -31250,10 +31624,10 @@ function allocateDirNameForLauncherCwd(layout, bridgeRootPath2) {
|
|
|
31250
31624
|
// src/worktrees/prepare-new-session-worktrees.ts
|
|
31251
31625
|
async function prepareNewSessionWorktrees(options) {
|
|
31252
31626
|
const { worktreesRootPath, bridgeRoot, sessionId, layout, log: log2 } = options;
|
|
31253
|
-
const bridgeResolved =
|
|
31627
|
+
const bridgeResolved = path14.resolve(bridgeRoot);
|
|
31254
31628
|
const cwdKey = allocateDirNameForLauncherCwd(layout, bridgeResolved);
|
|
31255
|
-
const bridgeKeyDir =
|
|
31256
|
-
const sessionDir =
|
|
31629
|
+
const bridgeKeyDir = path14.join(worktreesRootPath, cwdKey);
|
|
31630
|
+
const sessionDir = path14.join(bridgeKeyDir, sessionId);
|
|
31257
31631
|
const repos = await discoverGitReposUnderRoot(bridgeResolved);
|
|
31258
31632
|
if (repos.length === 0) {
|
|
31259
31633
|
log2("[worktrees] No Git repositories under bridge root; skipping worktree creation.");
|
|
@@ -31261,14 +31635,14 @@ async function prepareNewSessionWorktrees(options) {
|
|
|
31261
31635
|
}
|
|
31262
31636
|
const branch = `session-${sessionId}`;
|
|
31263
31637
|
const worktreePaths = [];
|
|
31264
|
-
|
|
31638
|
+
fs12.mkdirSync(sessionDir, { recursive: true });
|
|
31265
31639
|
for (const repo of repos) {
|
|
31266
|
-
let rel =
|
|
31267
|
-
if (rel.startsWith("..") ||
|
|
31640
|
+
let rel = path14.relative(bridgeResolved, repo.absolutePath);
|
|
31641
|
+
if (rel.startsWith("..") || path14.isAbsolute(rel)) continue;
|
|
31268
31642
|
const relNorm = rel === "" ? "." : rel;
|
|
31269
|
-
const wtPath = relNorm === "." ? sessionDir :
|
|
31643
|
+
const wtPath = relNorm === "." ? sessionDir : path14.join(sessionDir, relNorm);
|
|
31270
31644
|
if (relNorm !== ".") {
|
|
31271
|
-
|
|
31645
|
+
fs12.mkdirSync(path14.dirname(wtPath), { recursive: true });
|
|
31272
31646
|
}
|
|
31273
31647
|
try {
|
|
31274
31648
|
await gitWorktreeAddBranch(repo.absolutePath, wtPath, branch);
|
|
@@ -31310,23 +31684,23 @@ async function renameSessionWorktreeBranches(paths, newBranch, log2) {
|
|
|
31310
31684
|
}
|
|
31311
31685
|
|
|
31312
31686
|
// src/worktrees/remove-session-worktrees.ts
|
|
31313
|
-
import * as
|
|
31687
|
+
import * as fs15 from "node:fs";
|
|
31314
31688
|
|
|
31315
31689
|
// src/git/worktree-remove.ts
|
|
31316
|
-
import * as
|
|
31690
|
+
import * as fs14 from "node:fs";
|
|
31317
31691
|
|
|
31318
31692
|
// src/git/resolve-main-repo-from-git-file.ts
|
|
31319
|
-
import * as
|
|
31320
|
-
import * as
|
|
31693
|
+
import * as fs13 from "node:fs";
|
|
31694
|
+
import * as path15 from "node:path";
|
|
31321
31695
|
function resolveMainRepoFromWorktreeGitFile(wt) {
|
|
31322
|
-
const gitDirFile =
|
|
31323
|
-
if (!
|
|
31324
|
-
const first2 =
|
|
31696
|
+
const gitDirFile = path15.join(wt, ".git");
|
|
31697
|
+
if (!fs13.existsSync(gitDirFile) || !fs13.statSync(gitDirFile).isFile()) return "";
|
|
31698
|
+
const first2 = fs13.readFileSync(gitDirFile, "utf8").trim();
|
|
31325
31699
|
const m = first2.match(/^gitdir:\s*(.+)$/im);
|
|
31326
31700
|
if (!m) return "";
|
|
31327
|
-
const gitWorktreePath =
|
|
31328
|
-
const gitDir =
|
|
31329
|
-
return
|
|
31701
|
+
const gitWorktreePath = path15.resolve(wt, m[1].trim());
|
|
31702
|
+
const gitDir = path15.dirname(path15.dirname(gitWorktreePath));
|
|
31703
|
+
return path15.dirname(gitDir);
|
|
31330
31704
|
}
|
|
31331
31705
|
|
|
31332
31706
|
// src/git/worktree-remove.ts
|
|
@@ -31335,7 +31709,7 @@ async function gitWorktreeRemoveForce(worktreePath) {
|
|
|
31335
31709
|
if (mainRepo) {
|
|
31336
31710
|
await cliSimpleGit(mainRepo).raw(["worktree", "remove", "--force", worktreePath]);
|
|
31337
31711
|
} else {
|
|
31338
|
-
|
|
31712
|
+
fs14.rmSync(worktreePath, { recursive: true, force: true });
|
|
31339
31713
|
}
|
|
31340
31714
|
}
|
|
31341
31715
|
|
|
@@ -31348,7 +31722,7 @@ async function removeSessionWorktrees(paths, log2) {
|
|
|
31348
31722
|
} catch (e) {
|
|
31349
31723
|
log2(`[worktrees] Remove failed for ${wt}: ${e instanceof Error ? e.message : String(e)}`);
|
|
31350
31724
|
try {
|
|
31351
|
-
|
|
31725
|
+
fs15.rmSync(wt, { recursive: true, force: true });
|
|
31352
31726
|
} catch {
|
|
31353
31727
|
}
|
|
31354
31728
|
}
|
|
@@ -31568,7 +31942,7 @@ function formatRemoteDisplayLabel(remoteUrl) {
|
|
|
31568
31942
|
}
|
|
31569
31943
|
|
|
31570
31944
|
// src/git/working-directory/changes/get-working-tree-change-repo-details.ts
|
|
31571
|
-
import * as
|
|
31945
|
+
import * as path17 from "node:path";
|
|
31572
31946
|
|
|
31573
31947
|
// src/git/working-directory/changes/parse-git-status.ts
|
|
31574
31948
|
function parseNameStatusLines(lines) {
|
|
@@ -31688,8 +32062,8 @@ async function listChangedFilesForCommit(repoGitCwd, repoRelPath, commitSha) {
|
|
|
31688
32062
|
}
|
|
31689
32063
|
|
|
31690
32064
|
// src/git/working-directory/changes/list-changed-files-for-repo.ts
|
|
31691
|
-
import * as
|
|
31692
|
-
import * as
|
|
32065
|
+
import * as fs17 from "node:fs";
|
|
32066
|
+
import * as path16 from "node:path";
|
|
31693
32067
|
|
|
31694
32068
|
// src/git/working-directory/changes/count-lines.ts
|
|
31695
32069
|
import { createReadStream } from "node:fs";
|
|
@@ -31713,7 +32087,7 @@ async function countTextFileLines(filePath) {
|
|
|
31713
32087
|
}
|
|
31714
32088
|
|
|
31715
32089
|
// src/git/working-directory/changes/hydrate-patch.ts
|
|
31716
|
-
import * as
|
|
32090
|
+
import * as fs16 from "node:fs";
|
|
31717
32091
|
var UNIFIED_HUNK_HEADER_RE = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/;
|
|
31718
32092
|
var MAX_HYDRATE_LINES_PER_GAP = 8e3;
|
|
31719
32093
|
var MAX_HYDRATE_LINES_PER_FILE = 8e4;
|
|
@@ -31728,7 +32102,7 @@ async function readGitBlobLines(repoCwd, pathInRepo) {
|
|
|
31728
32102
|
}
|
|
31729
32103
|
async function readWorktreeFileLines(filePath) {
|
|
31730
32104
|
try {
|
|
31731
|
-
const raw = await
|
|
32105
|
+
const raw = await fs16.promises.readFile(filePath, "utf8");
|
|
31732
32106
|
return raw.split(/\r?\n/);
|
|
31733
32107
|
} catch {
|
|
31734
32108
|
return null;
|
|
@@ -31863,7 +32237,7 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
|
|
|
31863
32237
|
const rows = [];
|
|
31864
32238
|
for (const pathInRepo of paths) {
|
|
31865
32239
|
const relLauncher = posixJoinDirFile(repoRelPath, pathInRepo.replace(/\\/g, "/"));
|
|
31866
|
-
const repoFilePath =
|
|
32240
|
+
const repoFilePath = path16.join(repoGitCwd, pathInRepo);
|
|
31867
32241
|
const nums = numByPath.get(pathInRepo);
|
|
31868
32242
|
let additions = nums?.additions ?? 0;
|
|
31869
32243
|
let deletions = nums?.deletions ?? 0;
|
|
@@ -31876,7 +32250,7 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
|
|
|
31876
32250
|
deletions = fromGit.deletions;
|
|
31877
32251
|
} else {
|
|
31878
32252
|
try {
|
|
31879
|
-
const st = await
|
|
32253
|
+
const st = await fs17.promises.stat(repoFilePath);
|
|
31880
32254
|
if (st.isFile()) additions = await countTextFileLines(repoFilePath);
|
|
31881
32255
|
else additions = 0;
|
|
31882
32256
|
} catch {
|
|
@@ -31902,7 +32276,7 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
|
|
|
31902
32276
|
} else {
|
|
31903
32277
|
pathInRepo = row.pathRelLauncher;
|
|
31904
32278
|
}
|
|
31905
|
-
const filePath =
|
|
32279
|
+
const filePath = path16.join(repoGitCwd, pathInRepo);
|
|
31906
32280
|
let patch = await unifiedDiffForFile(repoGitCwd, pathInRepo, row.change);
|
|
31907
32281
|
if (patch) {
|
|
31908
32282
|
patch = await hydrateUnifiedPatchWithFileContext(patch, filePath, repoGitCwd, pathInRepo, row.change);
|
|
@@ -31918,8 +32292,8 @@ function normRepoRel(p) {
|
|
|
31918
32292
|
return x === "" ? "." : x;
|
|
31919
32293
|
}
|
|
31920
32294
|
async function getWorkingTreeChangeRepoDetails(options) {
|
|
31921
|
-
const bridgeRoot =
|
|
31922
|
-
const sessionWtRoot = options.sessionWorktreeRootPath ?
|
|
32295
|
+
const bridgeRoot = path17.resolve(getBridgeRoot());
|
|
32296
|
+
const sessionWtRoot = options.sessionWorktreeRootPath ? path17.resolve(options.sessionWorktreeRootPath) : null;
|
|
31923
32297
|
const legacyNested = options.legacyRepoNestedSessionLayout === true;
|
|
31924
32298
|
const out = [];
|
|
31925
32299
|
const filter = options.repoFilterRelPath != null ? normRepoRel(options.repoFilterRelPath) : null;
|
|
@@ -31932,7 +32306,7 @@ async function getWorkingTreeChangeRepoDetails(options) {
|
|
|
31932
32306
|
}
|
|
31933
32307
|
const basis = filter == null && basisInput.kind === "commit" ? { kind: "working" } : basisInput;
|
|
31934
32308
|
for (const target of options.commitTargetPaths) {
|
|
31935
|
-
const t =
|
|
32309
|
+
const t = path17.resolve(target);
|
|
31936
32310
|
if (!await isGitRepoDirectory(t)) continue;
|
|
31937
32311
|
const g = cliSimpleGit(t);
|
|
31938
32312
|
let branch = "HEAD";
|
|
@@ -31945,8 +32319,8 @@ async function getWorkingTreeChangeRepoDetails(options) {
|
|
|
31945
32319
|
const remoteDisplay = formatRemoteDisplayLabel(remoteUrl);
|
|
31946
32320
|
let repoRelPath;
|
|
31947
32321
|
if (sessionWtRoot) {
|
|
31948
|
-
const anchor = legacyNested ?
|
|
31949
|
-
const relNorm =
|
|
32322
|
+
const anchor = legacyNested ? path17.dirname(t) : t;
|
|
32323
|
+
const relNorm = path17.relative(sessionWtRoot, anchor);
|
|
31950
32324
|
repoRelPath = relNorm === "" ? "." : relNorm.replace(/\\/g, "/");
|
|
31951
32325
|
} else {
|
|
31952
32326
|
let top = t;
|
|
@@ -31955,8 +32329,8 @@ async function getWorkingTreeChangeRepoDetails(options) {
|
|
|
31955
32329
|
} catch {
|
|
31956
32330
|
top = t;
|
|
31957
32331
|
}
|
|
31958
|
-
const rel =
|
|
31959
|
-
repoRelPath = rel.startsWith("..") ?
|
|
32332
|
+
const rel = path17.relative(bridgeRoot, path17.resolve(top)).replace(/\\/g, "/") || ".";
|
|
32333
|
+
repoRelPath = rel.startsWith("..") ? path17.basename(path17.resolve(top)) : rel;
|
|
31960
32334
|
}
|
|
31961
32335
|
const norm = normRepoRel(repoRelPath === "" ? "." : repoRelPath);
|
|
31962
32336
|
if (filter && norm !== filter) continue;
|
|
@@ -32021,11 +32395,11 @@ async function commitSessionWorktrees(options) {
|
|
|
32021
32395
|
}
|
|
32022
32396
|
|
|
32023
32397
|
// src/worktrees/discover-session-worktree-on-disk.ts
|
|
32024
|
-
import * as
|
|
32025
|
-
import * as
|
|
32398
|
+
import * as fs18 from "node:fs";
|
|
32399
|
+
import * as path18 from "node:path";
|
|
32026
32400
|
function isGitDir(dirPath) {
|
|
32027
32401
|
try {
|
|
32028
|
-
return
|
|
32402
|
+
return fs18.existsSync(path18.join(dirPath, ".git"));
|
|
32029
32403
|
} catch {
|
|
32030
32404
|
return false;
|
|
32031
32405
|
}
|
|
@@ -32034,23 +32408,23 @@ function collectGitRepoRootsUnderDirectory(rootPath) {
|
|
|
32034
32408
|
const out = [];
|
|
32035
32409
|
const walk = (dir) => {
|
|
32036
32410
|
if (isGitDir(dir)) {
|
|
32037
|
-
out.push(
|
|
32411
|
+
out.push(path18.resolve(dir));
|
|
32038
32412
|
return;
|
|
32039
32413
|
}
|
|
32040
32414
|
let entries;
|
|
32041
32415
|
try {
|
|
32042
|
-
entries =
|
|
32416
|
+
entries = fs18.readdirSync(dir, { withFileTypes: true });
|
|
32043
32417
|
} catch {
|
|
32044
32418
|
return;
|
|
32045
32419
|
}
|
|
32046
32420
|
for (const e of entries) {
|
|
32047
32421
|
if (e.name.startsWith(".")) continue;
|
|
32048
|
-
const full =
|
|
32422
|
+
const full = path18.join(dir, e.name);
|
|
32049
32423
|
if (!e.isDirectory()) continue;
|
|
32050
32424
|
walk(full);
|
|
32051
32425
|
}
|
|
32052
32426
|
};
|
|
32053
|
-
walk(
|
|
32427
|
+
walk(path18.resolve(rootPath));
|
|
32054
32428
|
return [...new Set(out)];
|
|
32055
32429
|
}
|
|
32056
32430
|
function collectWorktreeRootsNamed(root, sessionId, maxDepth) {
|
|
@@ -32059,16 +32433,16 @@ function collectWorktreeRootsNamed(root, sessionId, maxDepth) {
|
|
|
32059
32433
|
if (depth > maxDepth) return;
|
|
32060
32434
|
let entries;
|
|
32061
32435
|
try {
|
|
32062
|
-
entries =
|
|
32436
|
+
entries = fs18.readdirSync(dir, { withFileTypes: true });
|
|
32063
32437
|
} catch {
|
|
32064
32438
|
return;
|
|
32065
32439
|
}
|
|
32066
32440
|
for (const e of entries) {
|
|
32067
32441
|
if (e.name.startsWith(".")) continue;
|
|
32068
|
-
const full =
|
|
32442
|
+
const full = path18.join(dir, e.name);
|
|
32069
32443
|
if (!e.isDirectory()) continue;
|
|
32070
32444
|
if (e.name === sessionId) {
|
|
32071
|
-
if (isGitDir(full)) out.push(
|
|
32445
|
+
if (isGitDir(full)) out.push(path18.resolve(full));
|
|
32072
32446
|
} else {
|
|
32073
32447
|
walk(full, depth + 1);
|
|
32074
32448
|
}
|
|
@@ -32080,14 +32454,14 @@ function collectWorktreeRootsNamed(root, sessionId, maxDepth) {
|
|
|
32080
32454
|
function tryBindingFromSessionDirectory(sessionDir) {
|
|
32081
32455
|
let st;
|
|
32082
32456
|
try {
|
|
32083
|
-
st =
|
|
32457
|
+
st = fs18.statSync(sessionDir);
|
|
32084
32458
|
} catch {
|
|
32085
32459
|
return null;
|
|
32086
32460
|
}
|
|
32087
32461
|
if (!st.isDirectory()) return null;
|
|
32088
32462
|
const worktreePaths = collectGitRepoRootsUnderDirectory(sessionDir);
|
|
32089
32463
|
if (worktreePaths.length === 0) return null;
|
|
32090
|
-
const abs =
|
|
32464
|
+
const abs = path18.resolve(sessionDir);
|
|
32091
32465
|
return {
|
|
32092
32466
|
sessionParentPath: abs,
|
|
32093
32467
|
workingTreeRelRoot: abs,
|
|
@@ -32097,20 +32471,20 @@ function tryBindingFromSessionDirectory(sessionDir) {
|
|
|
32097
32471
|
function discoverLegacyBindingAscendingFromCheckout(sessionId, checkoutPath) {
|
|
32098
32472
|
const sid = sessionId.trim();
|
|
32099
32473
|
if (!sid) return null;
|
|
32100
|
-
const hintR =
|
|
32474
|
+
const hintR = path18.resolve(checkoutPath);
|
|
32101
32475
|
let best = null;
|
|
32102
|
-
let cur =
|
|
32476
|
+
let cur = path18.dirname(hintR);
|
|
32103
32477
|
for (let i = 0; i < 40; i++) {
|
|
32104
32478
|
const paths = collectWorktreeRootsNamed(cur, sid, 24);
|
|
32105
|
-
if (paths.some((p) =>
|
|
32106
|
-
const isolated = resolveIsolatedSessionParentPathFromCheckouts(paths) ??
|
|
32479
|
+
if (paths.some((p) => path18.resolve(p) === hintR)) {
|
|
32480
|
+
const isolated = resolveIsolatedSessionParentPathFromCheckouts(paths) ?? path18.resolve(paths[0]);
|
|
32107
32481
|
best = {
|
|
32108
|
-
sessionParentPath:
|
|
32109
|
-
workingTreeRelRoot:
|
|
32110
|
-
repoCheckoutPaths: paths.map((p) =>
|
|
32482
|
+
sessionParentPath: path18.resolve(isolated),
|
|
32483
|
+
workingTreeRelRoot: path18.resolve(cur),
|
|
32484
|
+
repoCheckoutPaths: paths.map((p) => path18.resolve(p))
|
|
32111
32485
|
};
|
|
32112
32486
|
}
|
|
32113
|
-
const next =
|
|
32487
|
+
const next = path18.dirname(cur);
|
|
32114
32488
|
if (next === cur) break;
|
|
32115
32489
|
cur = next;
|
|
32116
32490
|
}
|
|
@@ -32118,33 +32492,33 @@ function discoverLegacyBindingAscendingFromCheckout(sessionId, checkoutPath) {
|
|
|
32118
32492
|
}
|
|
32119
32493
|
function discoverSessionWorktreeOnDisk(options) {
|
|
32120
32494
|
const { sessionId, worktreesRootPath, layout, bridgeRoot } = options;
|
|
32121
|
-
if (!sessionId.trim() || !
|
|
32495
|
+
if (!sessionId.trim() || !fs18.existsSync(worktreesRootPath)) return null;
|
|
32122
32496
|
const preferredKey = getLauncherDirNameIfPresent(layout, bridgeRoot);
|
|
32123
32497
|
const keys = [];
|
|
32124
32498
|
if (preferredKey) keys.push(preferredKey);
|
|
32125
32499
|
try {
|
|
32126
|
-
for (const name of
|
|
32500
|
+
for (const name of fs18.readdirSync(worktreesRootPath)) {
|
|
32127
32501
|
if (name.startsWith(".")) continue;
|
|
32128
|
-
const p =
|
|
32129
|
-
if (!
|
|
32502
|
+
const p = path18.join(worktreesRootPath, name);
|
|
32503
|
+
if (!fs18.statSync(p).isDirectory()) continue;
|
|
32130
32504
|
if (name !== preferredKey) keys.push(name);
|
|
32131
32505
|
}
|
|
32132
32506
|
} catch {
|
|
32133
32507
|
return null;
|
|
32134
32508
|
}
|
|
32135
32509
|
for (const key of keys) {
|
|
32136
|
-
const layoutRoot =
|
|
32137
|
-
if (!
|
|
32138
|
-
const sessionDir =
|
|
32510
|
+
const layoutRoot = path18.join(worktreesRootPath, key);
|
|
32511
|
+
if (!fs18.existsSync(layoutRoot) || !fs18.statSync(layoutRoot).isDirectory()) continue;
|
|
32512
|
+
const sessionDir = path18.join(layoutRoot, sessionId);
|
|
32139
32513
|
const nested = tryBindingFromSessionDirectory(sessionDir);
|
|
32140
32514
|
if (nested) return nested;
|
|
32141
32515
|
const legacyPaths = collectWorktreeRootsNamed(layoutRoot, sessionId, 24);
|
|
32142
32516
|
if (legacyPaths.length > 0) {
|
|
32143
|
-
const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ??
|
|
32517
|
+
const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ?? path18.resolve(legacyPaths[0]);
|
|
32144
32518
|
return {
|
|
32145
|
-
sessionParentPath:
|
|
32146
|
-
workingTreeRelRoot:
|
|
32147
|
-
repoCheckoutPaths: legacyPaths.map((p) =>
|
|
32519
|
+
sessionParentPath: path18.resolve(isolated),
|
|
32520
|
+
workingTreeRelRoot: path18.resolve(layoutRoot),
|
|
32521
|
+
repoCheckoutPaths: legacyPaths.map((p) => path18.resolve(p))
|
|
32148
32522
|
};
|
|
32149
32523
|
}
|
|
32150
32524
|
}
|
|
@@ -32153,12 +32527,12 @@ function discoverSessionWorktreeOnDisk(options) {
|
|
|
32153
32527
|
function discoverSessionWorktreesUnderSessionWorktreeRoot(sessionWorktreeRootPathOrHint, sessionId) {
|
|
32154
32528
|
const sid = sessionId.trim();
|
|
32155
32529
|
if (!sid) return null;
|
|
32156
|
-
const hint =
|
|
32157
|
-
const underHint = tryBindingFromSessionDirectory(
|
|
32530
|
+
const hint = path18.resolve(sessionWorktreeRootPathOrHint);
|
|
32531
|
+
const underHint = tryBindingFromSessionDirectory(path18.join(hint, sid));
|
|
32158
32532
|
if (underHint) return underHint;
|
|
32159
32533
|
const direct = tryBindingFromSessionDirectory(hint);
|
|
32160
32534
|
if (direct) {
|
|
32161
|
-
if (
|
|
32535
|
+
if (path18.basename(hint) === sid && isGitDir(hint)) {
|
|
32162
32536
|
const legacyFromCheckout = discoverLegacyBindingAscendingFromCheckout(sid, hint);
|
|
32163
32537
|
if (legacyFromCheckout && legacyFromCheckout.repoCheckoutPaths.length > direct.repoCheckoutPaths.length) {
|
|
32164
32538
|
return legacyFromCheckout;
|
|
@@ -32166,24 +32540,24 @@ function discoverSessionWorktreesUnderSessionWorktreeRoot(sessionWorktreeRootPat
|
|
|
32166
32540
|
}
|
|
32167
32541
|
return direct;
|
|
32168
32542
|
}
|
|
32169
|
-
if (
|
|
32543
|
+
if (path18.basename(hint) === sid && isGitDir(hint)) {
|
|
32170
32544
|
const legacyFromCheckout = discoverLegacyBindingAscendingFromCheckout(sid, hint);
|
|
32171
32545
|
if (legacyFromCheckout) return legacyFromCheckout;
|
|
32172
32546
|
}
|
|
32173
32547
|
let st;
|
|
32174
32548
|
try {
|
|
32175
|
-
st =
|
|
32549
|
+
st = fs18.statSync(hint);
|
|
32176
32550
|
} catch {
|
|
32177
32551
|
return null;
|
|
32178
32552
|
}
|
|
32179
32553
|
if (!st.isDirectory()) return null;
|
|
32180
32554
|
const legacyPaths = collectWorktreeRootsNamed(hint, sid, 24);
|
|
32181
32555
|
if (legacyPaths.length === 0) return null;
|
|
32182
|
-
const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ??
|
|
32556
|
+
const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ?? path18.resolve(legacyPaths[0]);
|
|
32183
32557
|
return {
|
|
32184
|
-
sessionParentPath:
|
|
32558
|
+
sessionParentPath: path18.resolve(isolated),
|
|
32185
32559
|
workingTreeRelRoot: hint,
|
|
32186
|
-
repoCheckoutPaths: legacyPaths.map((p) =>
|
|
32560
|
+
repoCheckoutPaths: legacyPaths.map((p) => path18.resolve(p))
|
|
32187
32561
|
};
|
|
32188
32562
|
}
|
|
32189
32563
|
|
|
@@ -32206,10 +32580,10 @@ var SessionWorktreeManager = class {
|
|
|
32206
32580
|
this.layout = loadWorktreeLayout();
|
|
32207
32581
|
}
|
|
32208
32582
|
rememberSessionWorktrees(sessionId, binding) {
|
|
32209
|
-
const paths = binding.repoCheckoutPaths.map((p) =>
|
|
32583
|
+
const paths = binding.repoCheckoutPaths.map((p) => path19.resolve(p));
|
|
32210
32584
|
this.sessionRepoCheckoutPaths.set(sessionId, paths);
|
|
32211
|
-
this.sessionParentPathBySession.set(sessionId,
|
|
32212
|
-
this.sessionWorkingTreeRelRootBySession.set(sessionId,
|
|
32585
|
+
this.sessionParentPathBySession.set(sessionId, path19.resolve(binding.sessionParentPath));
|
|
32586
|
+
this.sessionWorkingTreeRelRootBySession.set(sessionId, path19.resolve(binding.workingTreeRelRoot));
|
|
32213
32587
|
}
|
|
32214
32588
|
sessionParentPathAfterRemember(sessionId) {
|
|
32215
32589
|
return this.sessionParentPathBySession.get(sessionId);
|
|
@@ -32226,7 +32600,7 @@ var SessionWorktreeManager = class {
|
|
|
32226
32600
|
const parent = this.sessionParentPathBySession.get(sessionId);
|
|
32227
32601
|
const relRoot = this.sessionWorkingTreeRelRootBySession.get(sessionId);
|
|
32228
32602
|
if (!parent || !relRoot) return false;
|
|
32229
|
-
return
|
|
32603
|
+
return path19.resolve(parent) !== path19.resolve(relRoot);
|
|
32230
32604
|
}
|
|
32231
32605
|
/**
|
|
32232
32606
|
* Session parent path for `worktrees_root`: the per-session directory (new layout) or primary checkout (legacy).
|
|
@@ -32235,7 +32609,7 @@ var SessionWorktreeManager = class {
|
|
|
32235
32609
|
if (!sessionId) return null;
|
|
32236
32610
|
const sid = sessionId.trim();
|
|
32237
32611
|
const cached2 = this.sessionParentPathBySession.get(sid);
|
|
32238
|
-
if (cached2) return
|
|
32612
|
+
if (cached2) return path19.resolve(cached2);
|
|
32239
32613
|
const paths = this.ensureRepoCheckoutPathsForSession(sid) ?? this.getRepoCheckoutPathsForSession(sid);
|
|
32240
32614
|
if (!paths?.length) return null;
|
|
32241
32615
|
return resolveIsolatedSessionParentPathFromCheckouts(paths);
|
|
@@ -32249,7 +32623,7 @@ var SessionWorktreeManager = class {
|
|
|
32249
32623
|
const sid = sessionId.trim();
|
|
32250
32624
|
const parentPathRaw = opts.sessionParentPath?.trim();
|
|
32251
32625
|
if (parentPathRaw) {
|
|
32252
|
-
const resolved =
|
|
32626
|
+
const resolved = path19.resolve(parentPathRaw);
|
|
32253
32627
|
if (sid && parseSessionParent(opts.sessionParent) === "worktrees_root") {
|
|
32254
32628
|
const diskFirst = this.tryDiscoverFromDisk(sid);
|
|
32255
32629
|
if (diskFirst) {
|
|
@@ -32268,7 +32642,7 @@ var SessionWorktreeManager = class {
|
|
|
32268
32642
|
this.rememberSessionWorktrees(sid, tryRoot);
|
|
32269
32643
|
return this.sessionParentPathAfterRemember(sid);
|
|
32270
32644
|
}
|
|
32271
|
-
const next =
|
|
32645
|
+
const next = path19.dirname(cur);
|
|
32272
32646
|
if (next === cur) break;
|
|
32273
32647
|
cur = next;
|
|
32274
32648
|
}
|
|
@@ -32421,15 +32795,15 @@ var SessionWorktreeManager = class {
|
|
|
32421
32795
|
}
|
|
32422
32796
|
};
|
|
32423
32797
|
function defaultWorktreesRootPath() {
|
|
32424
|
-
return
|
|
32798
|
+
return path19.join(os5.homedir(), ".buildautomaton", "worktrees");
|
|
32425
32799
|
}
|
|
32426
32800
|
|
|
32427
32801
|
// src/files/watch-file-index.ts
|
|
32428
32802
|
import { watch } from "node:fs";
|
|
32429
|
-
import
|
|
32803
|
+
import path26 from "node:path";
|
|
32430
32804
|
|
|
32431
32805
|
// src/files/index/build-file-index.ts
|
|
32432
|
-
import
|
|
32806
|
+
import path23 from "node:path";
|
|
32433
32807
|
|
|
32434
32808
|
// src/runtime/yield-to-event-loop.ts
|
|
32435
32809
|
function yieldToEventLoop() {
|
|
@@ -32437,14 +32811,14 @@ function yieldToEventLoop() {
|
|
|
32437
32811
|
}
|
|
32438
32812
|
|
|
32439
32813
|
// src/files/index/walk-workspace-tree.ts
|
|
32440
|
-
import
|
|
32441
|
-
import
|
|
32814
|
+
import fs19 from "node:fs";
|
|
32815
|
+
import path21 from "node:path";
|
|
32442
32816
|
|
|
32443
32817
|
// src/files/index/constants.ts
|
|
32444
|
-
import
|
|
32445
|
-
import
|
|
32818
|
+
import path20 from "node:path";
|
|
32819
|
+
import os6 from "node:os";
|
|
32446
32820
|
var INDEX_WORK_YIELD_EVERY = 256;
|
|
32447
|
-
var INDEX_DIR =
|
|
32821
|
+
var INDEX_DIR = path20.join(os6.homedir(), ".buildautomaton");
|
|
32448
32822
|
var INDEX_HASH_LEN = 16;
|
|
32449
32823
|
var INDEX_VERSION = 2;
|
|
32450
32824
|
var INDEX_LOG_PREFIX = "[file-index]";
|
|
@@ -32453,20 +32827,20 @@ var INDEX_LOG_PREFIX = "[file-index]";
|
|
|
32453
32827
|
function walkWorkspaceTreeSync(dir, baseDir, out) {
|
|
32454
32828
|
let names;
|
|
32455
32829
|
try {
|
|
32456
|
-
names =
|
|
32830
|
+
names = fs19.readdirSync(dir);
|
|
32457
32831
|
} catch {
|
|
32458
32832
|
return;
|
|
32459
32833
|
}
|
|
32460
32834
|
for (const name of names) {
|
|
32461
32835
|
if (name.startsWith(".")) continue;
|
|
32462
|
-
const full =
|
|
32836
|
+
const full = path21.join(dir, name);
|
|
32463
32837
|
let stat2;
|
|
32464
32838
|
try {
|
|
32465
|
-
stat2 =
|
|
32839
|
+
stat2 = fs19.statSync(full);
|
|
32466
32840
|
} catch {
|
|
32467
32841
|
continue;
|
|
32468
32842
|
}
|
|
32469
|
-
const relative5 =
|
|
32843
|
+
const relative5 = path21.relative(baseDir, full).replace(/\\/g, "/");
|
|
32470
32844
|
if (stat2.isDirectory()) {
|
|
32471
32845
|
walkWorkspaceTreeSync(full, baseDir, out);
|
|
32472
32846
|
} else if (stat2.isFile()) {
|
|
@@ -32477,7 +32851,7 @@ function walkWorkspaceTreeSync(dir, baseDir, out) {
|
|
|
32477
32851
|
async function walkWorkspaceTreeAsync(dir, baseDir, out, state) {
|
|
32478
32852
|
let names;
|
|
32479
32853
|
try {
|
|
32480
|
-
names = await
|
|
32854
|
+
names = await fs19.promises.readdir(dir);
|
|
32481
32855
|
} catch {
|
|
32482
32856
|
return;
|
|
32483
32857
|
}
|
|
@@ -32487,14 +32861,14 @@ async function walkWorkspaceTreeAsync(dir, baseDir, out, state) {
|
|
|
32487
32861
|
await yieldToEventLoop();
|
|
32488
32862
|
}
|
|
32489
32863
|
state.n++;
|
|
32490
|
-
const full =
|
|
32864
|
+
const full = path21.join(dir, name);
|
|
32491
32865
|
let stat2;
|
|
32492
32866
|
try {
|
|
32493
|
-
stat2 = await
|
|
32867
|
+
stat2 = await fs19.promises.stat(full);
|
|
32494
32868
|
} catch {
|
|
32495
32869
|
continue;
|
|
32496
32870
|
}
|
|
32497
|
-
const relative5 =
|
|
32871
|
+
const relative5 = path21.relative(baseDir, full).replace(/\\/g, "/");
|
|
32498
32872
|
if (stat2.isDirectory()) {
|
|
32499
32873
|
await walkWorkspaceTreeAsync(full, baseDir, out, state);
|
|
32500
32874
|
} else if (stat2.isFile()) {
|
|
@@ -32575,22 +32949,22 @@ async function buildTrigramMapForPathsAsync(paths) {
|
|
|
32575
32949
|
}
|
|
32576
32950
|
|
|
32577
32951
|
// src/files/index/write-index-file.ts
|
|
32578
|
-
import
|
|
32952
|
+
import fs20 from "node:fs";
|
|
32579
32953
|
|
|
32580
32954
|
// src/files/index/paths.ts
|
|
32581
|
-
import
|
|
32955
|
+
import path22 from "node:path";
|
|
32582
32956
|
import crypto2 from "node:crypto";
|
|
32583
32957
|
function getIndexPathForCwd(resolvedCwd) {
|
|
32584
32958
|
const hash = crypto2.createHash("sha256").update(resolvedCwd).digest("hex").slice(0, INDEX_HASH_LEN);
|
|
32585
|
-
return
|
|
32959
|
+
return path22.join(INDEX_DIR, `.file-index-${hash}.json`);
|
|
32586
32960
|
}
|
|
32587
32961
|
|
|
32588
32962
|
// src/files/index/write-index-file.ts
|
|
32589
32963
|
function writeIndexFileSync(resolvedCwd, data) {
|
|
32590
32964
|
const indexPath = getIndexPathForCwd(resolvedCwd);
|
|
32591
32965
|
try {
|
|
32592
|
-
if (!
|
|
32593
|
-
|
|
32966
|
+
if (!fs20.existsSync(INDEX_DIR)) fs20.mkdirSync(INDEX_DIR, { recursive: true });
|
|
32967
|
+
fs20.writeFileSync(indexPath, JSON.stringify(data), "utf8");
|
|
32594
32968
|
} catch (e) {
|
|
32595
32969
|
console.error(`${INDEX_LOG_PREFIX} Failed to write index:`, e);
|
|
32596
32970
|
}
|
|
@@ -32598,8 +32972,8 @@ function writeIndexFileSync(resolvedCwd, data) {
|
|
|
32598
32972
|
async function writeIndexFileAsync(resolvedCwd, data) {
|
|
32599
32973
|
const indexPath = getIndexPathForCwd(resolvedCwd);
|
|
32600
32974
|
try {
|
|
32601
|
-
await
|
|
32602
|
-
await
|
|
32975
|
+
await fs20.promises.mkdir(INDEX_DIR, { recursive: true });
|
|
32976
|
+
await fs20.promises.writeFile(indexPath, JSON.stringify(data), "utf8");
|
|
32603
32977
|
} catch (e) {
|
|
32604
32978
|
console.error(`${INDEX_LOG_PREFIX} Failed to write index:`, e);
|
|
32605
32979
|
}
|
|
@@ -32613,7 +32987,7 @@ function sortPaths(paths) {
|
|
|
32613
32987
|
paths.sort((a, b) => a.localeCompare(b, void 0, { sensitivity: "base" }));
|
|
32614
32988
|
}
|
|
32615
32989
|
function buildFileIndex(cwd) {
|
|
32616
|
-
const resolved =
|
|
32990
|
+
const resolved = path23.resolve(cwd);
|
|
32617
32991
|
const paths = [];
|
|
32618
32992
|
walkWorkspaceTreeSync(resolved, resolved, paths);
|
|
32619
32993
|
sortPaths(paths);
|
|
@@ -32623,7 +32997,7 @@ function buildFileIndex(cwd) {
|
|
|
32623
32997
|
return data;
|
|
32624
32998
|
}
|
|
32625
32999
|
async function buildFileIndexAsync(cwd) {
|
|
32626
|
-
const resolved =
|
|
33000
|
+
const resolved = path23.resolve(cwd);
|
|
32627
33001
|
const paths = [];
|
|
32628
33002
|
await walkWorkspaceTreeAsync(resolved, resolved, paths, createWalkYieldState());
|
|
32629
33003
|
await yieldToEventLoop();
|
|
@@ -32635,13 +33009,13 @@ async function buildFileIndexAsync(cwd) {
|
|
|
32635
33009
|
}
|
|
32636
33010
|
|
|
32637
33011
|
// src/files/index/load-file-index.ts
|
|
32638
|
-
import
|
|
32639
|
-
import
|
|
33012
|
+
import fs21 from "node:fs";
|
|
33013
|
+
import path24 from "node:path";
|
|
32640
33014
|
function loadFileIndex(cwd) {
|
|
32641
|
-
const resolved =
|
|
33015
|
+
const resolved = path24.resolve(cwd);
|
|
32642
33016
|
const indexPath = getIndexPathForCwd(resolved);
|
|
32643
33017
|
try {
|
|
32644
|
-
const raw =
|
|
33018
|
+
const raw = fs21.readFileSync(indexPath, "utf8");
|
|
32645
33019
|
const parsed = JSON.parse(raw);
|
|
32646
33020
|
if (parsed !== null && typeof parsed === "object" && Array.isArray(parsed.paths)) {
|
|
32647
33021
|
const obj = parsed;
|
|
@@ -32660,9 +33034,9 @@ function loadFileIndex(cwd) {
|
|
|
32660
33034
|
}
|
|
32661
33035
|
|
|
32662
33036
|
// src/files/index/ensure-file-index.ts
|
|
32663
|
-
import
|
|
33037
|
+
import path25 from "node:path";
|
|
32664
33038
|
async function ensureFileIndexAsync(cwd) {
|
|
32665
|
-
const resolved =
|
|
33039
|
+
const resolved = path25.resolve(cwd);
|
|
32666
33040
|
const cached2 = loadFileIndex(resolved);
|
|
32667
33041
|
if (cached2 !== null) return { data: cached2, fromCache: true };
|
|
32668
33042
|
const data = await buildFileIndexAsync(resolved);
|
|
@@ -32745,7 +33119,7 @@ function createFsWatcher(resolved, schedule) {
|
|
|
32745
33119
|
}
|
|
32746
33120
|
}
|
|
32747
33121
|
function startFileIndexWatcher(cwd = getBridgeRoot()) {
|
|
32748
|
-
const resolved =
|
|
33122
|
+
const resolved = path26.resolve(cwd);
|
|
32749
33123
|
void buildFileIndexAsync(resolved).catch((e) => {
|
|
32750
33124
|
console.error("[file-index] Initial index build failed:", e);
|
|
32751
33125
|
});
|
|
@@ -32773,7 +33147,7 @@ function startFileIndexWatcher(cwd = getBridgeRoot()) {
|
|
|
32773
33147
|
}
|
|
32774
33148
|
|
|
32775
33149
|
// src/connection/create-bridge-connection.ts
|
|
32776
|
-
import * as
|
|
33150
|
+
import * as path34 from "node:path";
|
|
32777
33151
|
|
|
32778
33152
|
// src/dev-servers/manager/dev-server-manager.ts
|
|
32779
33153
|
import { rm as rm2 } from "node:fs/promises";
|
|
@@ -32817,7 +33191,7 @@ function forceKillChild(proc, log2, shortId, graceMs) {
|
|
|
32817
33191
|
}
|
|
32818
33192
|
|
|
32819
33193
|
// src/dev-servers/process/wire-dev-server-child-process.ts
|
|
32820
|
-
import
|
|
33194
|
+
import fs22 from "node:fs";
|
|
32821
33195
|
|
|
32822
33196
|
// src/dev-servers/manager/forward-pipe.ts
|
|
32823
33197
|
function forwardChildPipe(childReadable, terminal, onData) {
|
|
@@ -32853,7 +33227,7 @@ function wireDevServerChildProcess(d) {
|
|
|
32853
33227
|
d.setPollInterval(void 0);
|
|
32854
33228
|
return;
|
|
32855
33229
|
}
|
|
32856
|
-
|
|
33230
|
+
fs22.readFile(d.mergedLogPath, (err, buf) => {
|
|
32857
33231
|
if (err || (d.getSpawnGeneration() ?? 0) !== d.scheduledGen) return;
|
|
32858
33232
|
if (buf.length <= d.mergedReadPos.value) return;
|
|
32859
33233
|
const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
|
|
@@ -32891,7 +33265,7 @@ ${errTail}` : ""}`);
|
|
|
32891
33265
|
d.sendStatus(code === 0 || code == null ? "stopped" : "error", detail, tails);
|
|
32892
33266
|
};
|
|
32893
33267
|
if (mergedPath) {
|
|
32894
|
-
|
|
33268
|
+
fs22.readFile(mergedPath, (err, buf) => {
|
|
32895
33269
|
if (!err && buf.length > d.mergedReadPos.value) {
|
|
32896
33270
|
const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
|
|
32897
33271
|
if (chunk.length > 0) {
|
|
@@ -32993,13 +33367,13 @@ function parseDevServerDefs(servers) {
|
|
|
32993
33367
|
}
|
|
32994
33368
|
|
|
32995
33369
|
// src/dev-servers/manager/shell-spawn/utils.ts
|
|
32996
|
-
import
|
|
33370
|
+
import fs23 from "node:fs";
|
|
32997
33371
|
function isSpawnEbadf(e) {
|
|
32998
33372
|
return typeof e === "object" && e !== null && "code" in e && e.code === "EBADF";
|
|
32999
33373
|
}
|
|
33000
33374
|
function rmDirQuiet(dir) {
|
|
33001
33375
|
try {
|
|
33002
|
-
|
|
33376
|
+
fs23.rmSync(dir, { recursive: true, force: true });
|
|
33003
33377
|
} catch {
|
|
33004
33378
|
}
|
|
33005
33379
|
}
|
|
@@ -33007,7 +33381,7 @@ var cachedDevNullReadFd;
|
|
|
33007
33381
|
function devNullReadFd() {
|
|
33008
33382
|
if (cachedDevNullReadFd === void 0) {
|
|
33009
33383
|
const devPath = process.platform === "win32" ? "nul" : "/dev/null";
|
|
33010
|
-
cachedDevNullReadFd =
|
|
33384
|
+
cachedDevNullReadFd = fs23.openSync(devPath, "r");
|
|
33011
33385
|
}
|
|
33012
33386
|
return cachedDevNullReadFd;
|
|
33013
33387
|
}
|
|
@@ -33081,15 +33455,15 @@ function trySpawnShellTruePiped(command, env, cwd, devNullFd, signal) {
|
|
|
33081
33455
|
|
|
33082
33456
|
// src/dev-servers/manager/shell-spawn/try-spawn-merged-log-file.ts
|
|
33083
33457
|
import { spawn as spawn7 } from "node:child_process";
|
|
33084
|
-
import
|
|
33458
|
+
import fs24 from "node:fs";
|
|
33085
33459
|
import { tmpdir } from "node:os";
|
|
33086
|
-
import
|
|
33460
|
+
import path27 from "node:path";
|
|
33087
33461
|
function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
33088
|
-
const tmpRoot =
|
|
33089
|
-
const logPath =
|
|
33462
|
+
const tmpRoot = fs24.mkdtempSync(path27.join(tmpdir(), "ba-devsrv-log-"));
|
|
33463
|
+
const logPath = path27.join(tmpRoot, "combined.log");
|
|
33090
33464
|
let logFd;
|
|
33091
33465
|
try {
|
|
33092
|
-
logFd =
|
|
33466
|
+
logFd = fs24.openSync(logPath, "a");
|
|
33093
33467
|
} catch {
|
|
33094
33468
|
rmDirQuiet(tmpRoot);
|
|
33095
33469
|
return null;
|
|
@@ -33108,7 +33482,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
33108
33482
|
} else {
|
|
33109
33483
|
proc = spawn7("/bin/sh", ["-c", command], { env, cwd, stdio, ...signal ? { signal } : {} });
|
|
33110
33484
|
}
|
|
33111
|
-
|
|
33485
|
+
fs24.closeSync(logFd);
|
|
33112
33486
|
return {
|
|
33113
33487
|
proc,
|
|
33114
33488
|
pipedStdoutStderr: true,
|
|
@@ -33117,7 +33491,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
33117
33491
|
};
|
|
33118
33492
|
} catch (e) {
|
|
33119
33493
|
try {
|
|
33120
|
-
|
|
33494
|
+
fs24.closeSync(logFd);
|
|
33121
33495
|
} catch {
|
|
33122
33496
|
}
|
|
33123
33497
|
rmDirQuiet(tmpRoot);
|
|
@@ -33128,22 +33502,22 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
33128
33502
|
|
|
33129
33503
|
// src/dev-servers/manager/shell-spawn/try-spawn-shell-script-log-redirect.ts
|
|
33130
33504
|
import { spawn as spawn8 } from "node:child_process";
|
|
33131
|
-
import
|
|
33505
|
+
import fs25 from "node:fs";
|
|
33132
33506
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
33133
|
-
import
|
|
33507
|
+
import path28 from "node:path";
|
|
33134
33508
|
function shSingleQuote(s) {
|
|
33135
33509
|
return `'${s.replace(/'/g, `'\\''`)}'`;
|
|
33136
33510
|
}
|
|
33137
33511
|
function trySpawnShellScriptLogRedirectUnix(command, env, cwd, signal) {
|
|
33138
|
-
const tmpRoot =
|
|
33139
|
-
const logPath =
|
|
33140
|
-
const innerPath =
|
|
33141
|
-
const runnerPath =
|
|
33512
|
+
const tmpRoot = fs25.mkdtempSync(path28.join(tmpdir2(), "ba-devsrv-sh-"));
|
|
33513
|
+
const logPath = path28.join(tmpRoot, "combined.log");
|
|
33514
|
+
const innerPath = path28.join(tmpRoot, "_cmd.sh");
|
|
33515
|
+
const runnerPath = path28.join(tmpRoot, "_run.sh");
|
|
33142
33516
|
try {
|
|
33143
|
-
|
|
33517
|
+
fs25.writeFileSync(innerPath, `#!/bin/sh
|
|
33144
33518
|
${command}
|
|
33145
33519
|
`);
|
|
33146
|
-
|
|
33520
|
+
fs25.writeFileSync(
|
|
33147
33521
|
runnerPath,
|
|
33148
33522
|
`#!/bin/sh
|
|
33149
33523
|
cd ${shSingleQuote(cwd)}
|
|
@@ -33169,13 +33543,13 @@ cd ${shSingleQuote(cwd)}
|
|
|
33169
33543
|
}
|
|
33170
33544
|
}
|
|
33171
33545
|
function trySpawnShellScriptLogRedirectWin(command, env, cwd, signal) {
|
|
33172
|
-
const tmpRoot =
|
|
33173
|
-
const logPath =
|
|
33174
|
-
const runnerPath =
|
|
33546
|
+
const tmpRoot = fs25.mkdtempSync(path28.join(tmpdir2(), "ba-devsrv-sh-"));
|
|
33547
|
+
const logPath = path28.join(tmpRoot, "combined.log");
|
|
33548
|
+
const runnerPath = path28.join(tmpRoot, "_run.bat");
|
|
33175
33549
|
const q = (p) => `"${p.replace(/"/g, '""')}"`;
|
|
33176
33550
|
const com = process.env.ComSpec || "cmd.exe";
|
|
33177
33551
|
try {
|
|
33178
|
-
|
|
33552
|
+
fs25.writeFileSync(
|
|
33179
33553
|
runnerPath,
|
|
33180
33554
|
`@ECHO OFF\r
|
|
33181
33555
|
CD /D ${q(cwd)}\r
|
|
@@ -33944,30 +34318,30 @@ function createOnBridgeIdentified(opts) {
|
|
|
33944
34318
|
}
|
|
33945
34319
|
|
|
33946
34320
|
// src/skills/discover-local-agent-skills.ts
|
|
33947
|
-
import
|
|
33948
|
-
import
|
|
34321
|
+
import fs26 from "node:fs";
|
|
34322
|
+
import path29 from "node:path";
|
|
33949
34323
|
var SKILL_DISCOVERY_ROOTS = [".agents/skills", ".claude/skills", ".cursor/skills", "skills"];
|
|
33950
34324
|
function discoverLocalSkills(cwd) {
|
|
33951
34325
|
const out = [];
|
|
33952
34326
|
const seenKeys = /* @__PURE__ */ new Set();
|
|
33953
34327
|
for (const rel of SKILL_DISCOVERY_ROOTS) {
|
|
33954
|
-
const base =
|
|
33955
|
-
if (!
|
|
34328
|
+
const base = path29.join(cwd, rel);
|
|
34329
|
+
if (!fs26.existsSync(base) || !fs26.statSync(base).isDirectory()) continue;
|
|
33956
34330
|
let entries = [];
|
|
33957
34331
|
try {
|
|
33958
|
-
entries =
|
|
34332
|
+
entries = fs26.readdirSync(base);
|
|
33959
34333
|
} catch {
|
|
33960
34334
|
continue;
|
|
33961
34335
|
}
|
|
33962
34336
|
for (const name of entries) {
|
|
33963
|
-
const dir =
|
|
34337
|
+
const dir = path29.join(base, name);
|
|
33964
34338
|
try {
|
|
33965
|
-
if (!
|
|
34339
|
+
if (!fs26.statSync(dir).isDirectory()) continue;
|
|
33966
34340
|
} catch {
|
|
33967
34341
|
continue;
|
|
33968
34342
|
}
|
|
33969
|
-
const skillMd =
|
|
33970
|
-
if (!
|
|
34343
|
+
const skillMd = path29.join(dir, "SKILL.md");
|
|
34344
|
+
if (!fs26.existsSync(skillMd)) continue;
|
|
33971
34345
|
const key = `${rel}/${name}`;
|
|
33972
34346
|
if (seenKeys.has(key)) continue;
|
|
33973
34347
|
seenKeys.add(key);
|
|
@@ -33979,23 +34353,23 @@ function discoverLocalSkills(cwd) {
|
|
|
33979
34353
|
function discoverSkillLayoutRoots(cwd) {
|
|
33980
34354
|
const roots = [];
|
|
33981
34355
|
for (const rel of SKILL_DISCOVERY_ROOTS) {
|
|
33982
|
-
const base =
|
|
33983
|
-
if (!
|
|
34356
|
+
const base = path29.join(cwd, rel);
|
|
34357
|
+
if (!fs26.existsSync(base) || !fs26.statSync(base).isDirectory()) continue;
|
|
33984
34358
|
let entries = [];
|
|
33985
34359
|
try {
|
|
33986
|
-
entries =
|
|
34360
|
+
entries = fs26.readdirSync(base);
|
|
33987
34361
|
} catch {
|
|
33988
34362
|
continue;
|
|
33989
34363
|
}
|
|
33990
34364
|
const skills2 = [];
|
|
33991
34365
|
for (const name of entries) {
|
|
33992
|
-
const dir =
|
|
34366
|
+
const dir = path29.join(base, name);
|
|
33993
34367
|
try {
|
|
33994
|
-
if (!
|
|
34368
|
+
if (!fs26.statSync(dir).isDirectory()) continue;
|
|
33995
34369
|
} catch {
|
|
33996
34370
|
continue;
|
|
33997
34371
|
}
|
|
33998
|
-
if (!
|
|
34372
|
+
if (!fs26.existsSync(path29.join(dir, "SKILL.md"))) continue;
|
|
33999
34373
|
const relPath = `${rel}/${name}`.replace(/\\/g, "/");
|
|
34000
34374
|
skills2.push({ name, relPath });
|
|
34001
34375
|
}
|
|
@@ -34177,7 +34551,7 @@ var handleAgentConfigMessage = (msg, deps) => {
|
|
|
34177
34551
|
};
|
|
34178
34552
|
|
|
34179
34553
|
// src/prompt-turn-queue/runner.ts
|
|
34180
|
-
import
|
|
34554
|
+
import fs29 from "node:fs";
|
|
34181
34555
|
|
|
34182
34556
|
// src/prompt-turn-queue/client-report.ts
|
|
34183
34557
|
function sendPromptQueueClientReport(ws, queues) {
|
|
@@ -34187,13 +34561,13 @@ function sendPromptQueueClientReport(ws, queues) {
|
|
|
34187
34561
|
}
|
|
34188
34562
|
|
|
34189
34563
|
// src/prompt-turn-queue/disk-store.ts
|
|
34190
|
-
import
|
|
34564
|
+
import fs28 from "node:fs";
|
|
34191
34565
|
|
|
34192
34566
|
// src/prompt-turn-queue/paths.ts
|
|
34193
34567
|
import crypto3 from "node:crypto";
|
|
34194
|
-
import
|
|
34195
|
-
import
|
|
34196
|
-
import
|
|
34568
|
+
import fs27 from "node:fs";
|
|
34569
|
+
import path30 from "node:path";
|
|
34570
|
+
import os7 from "node:os";
|
|
34197
34571
|
var QUEUE_KEY_HEX_64 = /^[a-f0-9]{64}$/i;
|
|
34198
34572
|
function queueStateFileSlug(queueKey) {
|
|
34199
34573
|
if (QUEUE_KEY_HEX_64.test(queueKey)) return queueKey.toLowerCase();
|
|
@@ -34201,15 +34575,15 @@ function queueStateFileSlug(queueKey) {
|
|
|
34201
34575
|
}
|
|
34202
34576
|
function getPromptQueuesDirectory() {
|
|
34203
34577
|
const override = process.env.BUILDAMATON_PROMPT_QUEUES_DIR?.trim();
|
|
34204
|
-
if (override) return
|
|
34205
|
-
return
|
|
34578
|
+
if (override) return path30.resolve(override);
|
|
34579
|
+
return path30.join(os7.homedir(), ".buildautomaton", "queues");
|
|
34206
34580
|
}
|
|
34207
34581
|
function ensurePromptQueuesDirectory() {
|
|
34208
34582
|
const dir = getPromptQueuesDirectory();
|
|
34209
|
-
if (!
|
|
34583
|
+
if (!fs27.existsSync(dir)) fs27.mkdirSync(dir, { recursive: true });
|
|
34210
34584
|
}
|
|
34211
34585
|
function queueStateFilePath(queueKey) {
|
|
34212
|
-
return
|
|
34586
|
+
return path30.join(getPromptQueuesDirectory(), `${queueStateFileSlug(queueKey)}.json`);
|
|
34213
34587
|
}
|
|
34214
34588
|
|
|
34215
34589
|
// src/prompt-turn-queue/disk-store.ts
|
|
@@ -34234,7 +34608,7 @@ function parsePersistedQueueFile(raw) {
|
|
|
34234
34608
|
function readPersistedQueue(queueKey) {
|
|
34235
34609
|
const p = queueStateFilePath(queueKey);
|
|
34236
34610
|
try {
|
|
34237
|
-
return parsePersistedQueueFile(
|
|
34611
|
+
return parsePersistedQueueFile(fs28.readFileSync(p, "utf8"));
|
|
34238
34612
|
} catch {
|
|
34239
34613
|
return null;
|
|
34240
34614
|
}
|
|
@@ -34242,7 +34616,7 @@ function readPersistedQueue(queueKey) {
|
|
|
34242
34616
|
function writePersistedQueue(file2) {
|
|
34243
34617
|
ensurePromptQueuesDirectory();
|
|
34244
34618
|
const p = queueStateFilePath(file2.queueKey);
|
|
34245
|
-
|
|
34619
|
+
fs28.writeFileSync(p, JSON.stringify(file2, null, 2), "utf8");
|
|
34246
34620
|
}
|
|
34247
34621
|
function mergeServerQueueSnapshot(queueKey, serverTurns) {
|
|
34248
34622
|
const prev = readPersistedQueue(queueKey);
|
|
@@ -34300,7 +34674,7 @@ async function runLocalRevertBeforeQueuedPrompt(next, deps) {
|
|
|
34300
34674
|
const tid = typeof pl.snapshotRevertTurnId === "string" && pl.snapshotRevertTurnId.trim() !== "" ? pl.snapshotRevertTurnId.trim() : next.turnId;
|
|
34301
34675
|
const agentBase = deps.sessionWorktreeManager.getSessionWorktreeRootForSession(sid) ?? getBridgeRoot();
|
|
34302
34676
|
const file2 = snapshotFilePath(agentBase, tid);
|
|
34303
|
-
if (!
|
|
34677
|
+
if (!fs29.existsSync(file2)) {
|
|
34304
34678
|
deps.log(
|
|
34305
34679
|
`[Queue] requeued_with_revert: no pre-turn snapshot for ${tid.slice(0, 8)}\u2026; continuing without revert.`
|
|
34306
34680
|
);
|
|
@@ -34523,9 +34897,9 @@ function parseChangeSummarySnapshots(raw) {
|
|
|
34523
34897
|
for (const item of raw) {
|
|
34524
34898
|
if (!item || typeof item !== "object") continue;
|
|
34525
34899
|
const o = item;
|
|
34526
|
-
const
|
|
34527
|
-
if (!
|
|
34528
|
-
const row = { path:
|
|
34900
|
+
const path35 = typeof o.path === "string" && o.path.trim() !== "" ? o.path.trim() : "";
|
|
34901
|
+
if (!path35) continue;
|
|
34902
|
+
const row = { path: path35 };
|
|
34529
34903
|
if (typeof o.patchContent === "string") row.patchContent = o.patchContent;
|
|
34530
34904
|
if (typeof o.oldText === "string") row.oldText = o.oldText;
|
|
34531
34905
|
if (typeof o.newText === "string") row.newText = o.newText;
|
|
@@ -34756,15 +35130,15 @@ var handleSkillCallMessage = (msg, { getWs, log: log2 }) => {
|
|
|
34756
35130
|
};
|
|
34757
35131
|
|
|
34758
35132
|
// src/files/list-dir.ts
|
|
34759
|
-
import
|
|
34760
|
-
import
|
|
35133
|
+
import fs30 from "node:fs";
|
|
35134
|
+
import path32 from "node:path";
|
|
34761
35135
|
|
|
34762
35136
|
// src/files/ensure-under-cwd.ts
|
|
34763
|
-
import
|
|
35137
|
+
import path31 from "node:path";
|
|
34764
35138
|
function ensureUnderCwd(relativePath, cwd = getBridgeRoot()) {
|
|
34765
|
-
const normalized =
|
|
34766
|
-
const resolved =
|
|
34767
|
-
if (!resolved.startsWith(cwd +
|
|
35139
|
+
const normalized = path31.normalize(relativePath).replace(/^(\.\/)+/, "");
|
|
35140
|
+
const resolved = path31.resolve(cwd, normalized);
|
|
35141
|
+
if (!resolved.startsWith(cwd + path31.sep) && resolved !== cwd) {
|
|
34768
35142
|
return null;
|
|
34769
35143
|
}
|
|
34770
35144
|
return resolved;
|
|
@@ -34778,7 +35152,7 @@ async function listDirAsync(relativePath) {
|
|
|
34778
35152
|
return { error: "Path is outside working directory" };
|
|
34779
35153
|
}
|
|
34780
35154
|
try {
|
|
34781
|
-
const names = await
|
|
35155
|
+
const names = await fs30.promises.readdir(resolved, { withFileTypes: true });
|
|
34782
35156
|
const visible = names.filter((d) => !d.name.startsWith("."));
|
|
34783
35157
|
const entries = [];
|
|
34784
35158
|
for (let i = 0; i < visible.length; i++) {
|
|
@@ -34786,12 +35160,12 @@ async function listDirAsync(relativePath) {
|
|
|
34786
35160
|
await yieldToEventLoop();
|
|
34787
35161
|
}
|
|
34788
35162
|
const d = visible[i];
|
|
34789
|
-
const entryPath =
|
|
34790
|
-
const fullPath =
|
|
35163
|
+
const entryPath = path32.join(relativePath || ".", d.name).replace(/\\/g, "/");
|
|
35164
|
+
const fullPath = path32.join(resolved, d.name);
|
|
34791
35165
|
let isDir = d.isDirectory();
|
|
34792
35166
|
if (d.isSymbolicLink()) {
|
|
34793
35167
|
try {
|
|
34794
|
-
const targetStat = await
|
|
35168
|
+
const targetStat = await fs30.promises.stat(fullPath);
|
|
34795
35169
|
isDir = targetStat.isDirectory();
|
|
34796
35170
|
} catch {
|
|
34797
35171
|
isDir = false;
|
|
@@ -34816,25 +35190,25 @@ async function listDirAsync(relativePath) {
|
|
|
34816
35190
|
}
|
|
34817
35191
|
|
|
34818
35192
|
// src/files/read-file.ts
|
|
34819
|
-
import
|
|
35193
|
+
import fs31 from "node:fs";
|
|
34820
35194
|
import { StringDecoder } from "node:string_decoder";
|
|
34821
35195
|
function resolveFilePath(relativePath) {
|
|
34822
35196
|
const resolved = ensureUnderCwd(relativePath, getBridgeRoot());
|
|
34823
35197
|
if (!resolved) return { error: "Path is outside working directory" };
|
|
34824
35198
|
let real;
|
|
34825
35199
|
try {
|
|
34826
|
-
real =
|
|
35200
|
+
real = fs31.realpathSync(resolved);
|
|
34827
35201
|
} catch {
|
|
34828
35202
|
real = resolved;
|
|
34829
35203
|
}
|
|
34830
|
-
const stat2 =
|
|
35204
|
+
const stat2 = fs31.statSync(real);
|
|
34831
35205
|
if (!stat2.isFile()) return { error: "Not a file" };
|
|
34832
35206
|
return real;
|
|
34833
35207
|
}
|
|
34834
35208
|
var LINE_CHUNK_SIZE = 64 * 1024;
|
|
34835
35209
|
function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize = LINE_CHUNK_SIZE) {
|
|
34836
|
-
const fileSize =
|
|
34837
|
-
const fd =
|
|
35210
|
+
const fileSize = fs31.statSync(filePath).size;
|
|
35211
|
+
const fd = fs31.openSync(filePath, "r");
|
|
34838
35212
|
const bufSize = 64 * 1024;
|
|
34839
35213
|
const buf = Buffer.alloc(bufSize);
|
|
34840
35214
|
const decoder = new StringDecoder("utf8");
|
|
@@ -34847,7 +35221,7 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
|
|
|
34847
35221
|
let line0Accum = "";
|
|
34848
35222
|
try {
|
|
34849
35223
|
let bytesRead;
|
|
34850
|
-
while (!done && (bytesRead =
|
|
35224
|
+
while (!done && (bytesRead = fs31.readSync(fd, buf, 0, bufSize, null)) > 0) {
|
|
34851
35225
|
const text = partial2 + decoder.write(buf.subarray(0, bytesRead));
|
|
34852
35226
|
partial2 = "";
|
|
34853
35227
|
let lineStart = 0;
|
|
@@ -34982,7 +35356,7 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
|
|
|
34982
35356
|
}
|
|
34983
35357
|
return { content: resultLines.join("\n"), size: fileSize };
|
|
34984
35358
|
} finally {
|
|
34985
|
-
|
|
35359
|
+
fs31.closeSync(fd);
|
|
34986
35360
|
}
|
|
34987
35361
|
}
|
|
34988
35362
|
function readFile2(relativePath, startLine, endLine, lineOffset, lineChunkSize = LINE_CHUNK_SIZE) {
|
|
@@ -34993,8 +35367,8 @@ function readFile2(relativePath, startLine, endLine, lineOffset, lineChunkSize =
|
|
|
34993
35367
|
if (hasRange) {
|
|
34994
35368
|
return readFileRange(result, startLine, endLine, lineOffset, lineChunkSize);
|
|
34995
35369
|
}
|
|
34996
|
-
const stat2 =
|
|
34997
|
-
const raw =
|
|
35370
|
+
const stat2 = fs31.statSync(result);
|
|
35371
|
+
const raw = fs31.readFileSync(result, "utf8");
|
|
34998
35372
|
const lines = raw.split(/\r?\n/);
|
|
34999
35373
|
return { content: raw, totalLines: lines.length, size: stat2.size };
|
|
35000
35374
|
} catch (err) {
|
|
@@ -35112,8 +35486,8 @@ function handleSkillLayoutRequest(msg, deps) {
|
|
|
35112
35486
|
}
|
|
35113
35487
|
|
|
35114
35488
|
// src/skills/install-remote-skills.ts
|
|
35115
|
-
import
|
|
35116
|
-
import
|
|
35489
|
+
import fs32 from "node:fs";
|
|
35490
|
+
import path33 from "node:path";
|
|
35117
35491
|
function installRemoteSkills(cwd, targetDir, items) {
|
|
35118
35492
|
const installed2 = [];
|
|
35119
35493
|
if (!Array.isArray(items)) {
|
|
@@ -35124,15 +35498,15 @@ function installRemoteSkills(cwd, targetDir, items) {
|
|
|
35124
35498
|
if (typeof item.sourceId !== "string" || typeof item.skillName !== "string" || typeof item.versionHash !== "string" || !Array.isArray(item.files)) {
|
|
35125
35499
|
continue;
|
|
35126
35500
|
}
|
|
35127
|
-
const skillDir =
|
|
35501
|
+
const skillDir = path33.join(cwd, targetDir, item.skillName);
|
|
35128
35502
|
for (const f of item.files) {
|
|
35129
35503
|
if (typeof f.path !== "string" || !f.text && !f.base64) continue;
|
|
35130
|
-
const dest =
|
|
35131
|
-
|
|
35504
|
+
const dest = path33.join(skillDir, f.path);
|
|
35505
|
+
fs32.mkdirSync(path33.dirname(dest), { recursive: true });
|
|
35132
35506
|
if (f.text !== void 0) {
|
|
35133
|
-
|
|
35507
|
+
fs32.writeFileSync(dest, f.text, "utf8");
|
|
35134
35508
|
} else if (f.base64) {
|
|
35135
|
-
|
|
35509
|
+
fs32.writeFileSync(dest, Buffer.from(f.base64, "base64"));
|
|
35136
35510
|
}
|
|
35137
35511
|
}
|
|
35138
35512
|
installed2.push({
|
|
@@ -35282,7 +35656,7 @@ var handleSessionDiscardedMessage = (msg, deps) => {
|
|
|
35282
35656
|
};
|
|
35283
35657
|
|
|
35284
35658
|
// src/routing/handlers/revert-turn-snapshot.ts
|
|
35285
|
-
import * as
|
|
35659
|
+
import * as fs33 from "node:fs";
|
|
35286
35660
|
var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
35287
35661
|
const id = typeof msg.id === "string" ? msg.id : "";
|
|
35288
35662
|
const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
|
|
@@ -35294,7 +35668,7 @@ var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
|
35294
35668
|
if (!s) return;
|
|
35295
35669
|
const agentBase = sessionWorktreeManager.getSessionWorktreeRootForSession(sessionId) ?? getBridgeRoot();
|
|
35296
35670
|
const file2 = snapshotFilePath(agentBase, turnId);
|
|
35297
|
-
if (!
|
|
35671
|
+
if (!fs33.existsSync(file2)) {
|
|
35298
35672
|
sendWsMessage(s, {
|
|
35299
35673
|
type: "revert_turn_snapshot_result",
|
|
35300
35674
|
id,
|
|
@@ -35735,8 +36109,8 @@ async function createBridgeConnection(options) {
|
|
|
35735
36109
|
getCloudAccessToken: () => tokens.accessToken
|
|
35736
36110
|
};
|
|
35737
36111
|
const identifyReportedPaths = {
|
|
35738
|
-
bridgeRootPath:
|
|
35739
|
-
worktreesRootPath:
|
|
36112
|
+
bridgeRootPath: path34.resolve(getBridgeRoot()),
|
|
36113
|
+
worktreesRootPath: path34.resolve(worktreesRootPath)
|
|
35740
36114
|
};
|
|
35741
36115
|
const { connect } = createMainBridgeWebSocketLifecycle({
|
|
35742
36116
|
state,
|