@buildautomaton/cli 0.1.28 → 0.1.29
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 +809 -611
- package/dist/cli.js.map +4 -4
- package/dist/index.js +774 -576
- package/dist/index.js.map +4 -4
- package/dist/migrations/000_bootstrap_migrations_table.sql +4 -0
- package/dist/migrations/001_cli_sqlite_checkpoint_v1.sql +20 -0
- package/package.json +3 -2
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: path39, errorMaps, issueData } = params;
|
|
4069
|
+
const fullPath = [...path39, ...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, path39, key) {
|
|
4378
4378
|
this._cachedPath = [];
|
|
4379
4379
|
this.parent = parent;
|
|
4380
4380
|
this.data = value;
|
|
4381
|
-
this._path =
|
|
4381
|
+
this._path = path39;
|
|
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, path39) {
|
|
7997
|
+
if (!path39)
|
|
7998
7998
|
return obj;
|
|
7999
|
-
return
|
|
7999
|
+
return path39.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(path39, 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(path39);
|
|
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, path39 = []) => {
|
|
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 = [...path39, ...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(path39) {
|
|
8482
8482
|
const segs = [];
|
|
8483
|
-
for (const seg of
|
|
8483
|
+
for (const seg of path39) {
|
|
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 os9 = __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 = os9.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(path39, isFile, isDirectory) {
|
|
21967
|
+
log2(`checking %s`, path39);
|
|
21968
21968
|
try {
|
|
21969
|
-
const stat2 = fs_1.statSync(
|
|
21969
|
+
const stat2 = fs_1.statSync(path39);
|
|
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(path39, type = exports.READABLE) {
|
|
21990
|
+
return check2(path39, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
|
|
21991
21991
|
}
|
|
21992
21992
|
exports.exists = exists2;
|
|
21993
21993
|
exports.FILE = 1;
|
|
@@ -22792,9 +22792,9 @@ function parseChangeSummaryJson(raw, allowedPaths, options) {
|
|
|
22792
22792
|
const rawPath = typeof o.path === "string" ? o.path.trim() : "";
|
|
22793
22793
|
const summary = typeof o.summary === "string" ? o.summary.trim() : "";
|
|
22794
22794
|
if (!rawPath || !summary) continue;
|
|
22795
|
-
const
|
|
22796
|
-
if (!
|
|
22797
|
-
rows.push({ path:
|
|
22795
|
+
const path39 = skip ? normalizeRepoRelativePath(rawPath) || rawPath : resolveChangeSummaryPathAgainstAllowed(rawPath, allowedPaths);
|
|
22796
|
+
if (!path39) continue;
|
|
22797
|
+
rows.push({ path: path39, summary: clampSummaryToAtMostTwoLines(summary) });
|
|
22798
22798
|
}
|
|
22799
22799
|
return rows;
|
|
22800
22800
|
}
|
|
@@ -23668,8 +23668,8 @@ function randomSecret() {
|
|
|
23668
23668
|
}
|
|
23669
23669
|
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
23670
23670
|
}
|
|
23671
|
-
async function requestPreviewApi(port, secret, method,
|
|
23672
|
-
const url2 = `http://127.0.0.1:${port}${
|
|
23671
|
+
async function requestPreviewApi(port, secret, method, path39, body) {
|
|
23672
|
+
const url2 = `http://127.0.0.1:${port}${path39}`;
|
|
23673
23673
|
const headers = {
|
|
23674
23674
|
[PREVIEW_SECRET_HEADER]: secret,
|
|
23675
23675
|
"Content-Type": "application/json"
|
|
@@ -23681,7 +23681,7 @@ async function requestPreviewApi(port, secret, method, path35, body) {
|
|
|
23681
23681
|
});
|
|
23682
23682
|
const data = await res.json().catch(() => ({}));
|
|
23683
23683
|
if (!res.ok) {
|
|
23684
|
-
throw new Error(data?.error ?? `Preview API ${method} ${
|
|
23684
|
+
throw new Error(data?.error ?? `Preview API ${method} ${path39}: ${res.status}`);
|
|
23685
23685
|
}
|
|
23686
23686
|
return data;
|
|
23687
23687
|
}
|
|
@@ -23896,7 +23896,7 @@ function installBridgeProcessResilience() {
|
|
|
23896
23896
|
}
|
|
23897
23897
|
|
|
23898
23898
|
// src/cli-version.ts
|
|
23899
|
-
var CLI_VERSION = "0.1.
|
|
23899
|
+
var CLI_VERSION = "0.1.29".length > 0 ? "0.1.29" : "0.0.0-dev";
|
|
23900
23900
|
|
|
23901
23901
|
// src/connection/heartbeat/constants.ts
|
|
23902
23902
|
var BRIDGE_APP_HEARTBEAT_INTERVAL_MS = 1e4;
|
|
@@ -24956,6 +24956,321 @@ function runPendingAuth(options) {
|
|
|
24956
24956
|
};
|
|
24957
24957
|
}
|
|
24958
24958
|
|
|
24959
|
+
// src/sqlite/cli-database.ts
|
|
24960
|
+
import sqliteWasm from "node-sqlite3-wasm";
|
|
24961
|
+
|
|
24962
|
+
// src/sqlite/cli-sqlite-paths.ts
|
|
24963
|
+
import fs7 from "node:fs";
|
|
24964
|
+
import path5 from "node:path";
|
|
24965
|
+
import os3 from "node:os";
|
|
24966
|
+
function getCliSqlitePath() {
|
|
24967
|
+
const override = process.env.BUILDAMATON_CLI_SQLITE_PATH?.trim();
|
|
24968
|
+
if (override) return path5.resolve(override);
|
|
24969
|
+
return path5.join(os3.homedir(), ".buildautomaton", "cli.sqlite");
|
|
24970
|
+
}
|
|
24971
|
+
function ensureCliSqliteParentDir(sqlitePath) {
|
|
24972
|
+
const dir = path5.dirname(sqlitePath);
|
|
24973
|
+
if (!fs7.existsSync(dir)) fs7.mkdirSync(dir, { recursive: true });
|
|
24974
|
+
}
|
|
24975
|
+
|
|
24976
|
+
// src/sqlite/legacy_migration/import-cli-legacy-disk-data.ts
|
|
24977
|
+
import fs12 from "node:fs";
|
|
24978
|
+
|
|
24979
|
+
// src/files/index/constants.ts
|
|
24980
|
+
import path6 from "node:path";
|
|
24981
|
+
import os4 from "node:os";
|
|
24982
|
+
var INDEX_WORK_YIELD_EVERY = 256;
|
|
24983
|
+
var INDEX_DIR = path6.join(os4.homedir(), ".buildautomaton");
|
|
24984
|
+
var INDEX_HASH_LEN = 16;
|
|
24985
|
+
|
|
24986
|
+
// src/prompt-turn-queue/paths.ts
|
|
24987
|
+
import path7 from "node:path";
|
|
24988
|
+
import os5 from "node:os";
|
|
24989
|
+
function getPromptQueuesDirectory() {
|
|
24990
|
+
const override = process.env.BUILDAMATON_PROMPT_QUEUES_DIR?.trim();
|
|
24991
|
+
if (override) return path7.resolve(override);
|
|
24992
|
+
return path7.join(os5.homedir(), ".buildautomaton", "queues");
|
|
24993
|
+
}
|
|
24994
|
+
|
|
24995
|
+
// src/sqlite/legacy_migration/archive-file-index-json.ts
|
|
24996
|
+
import fs9 from "node:fs";
|
|
24997
|
+
import path9 from "node:path";
|
|
24998
|
+
|
|
24999
|
+
// src/sqlite/legacy_migration/archive-to-old-version.ts
|
|
25000
|
+
import fs8 from "node:fs";
|
|
25001
|
+
import path8 from "node:path";
|
|
25002
|
+
var OLD_VERSION_DIR = path8.join(INDEX_DIR, "old-version");
|
|
25003
|
+
function moveLegacyFileToOldVersionBackup(category, sourcePath) {
|
|
25004
|
+
const destDir = path8.join(OLD_VERSION_DIR, category);
|
|
25005
|
+
fs8.mkdirSync(destDir, { recursive: true });
|
|
25006
|
+
const base = path8.basename(sourcePath);
|
|
25007
|
+
let dest = path8.join(destDir, base);
|
|
25008
|
+
if (fs8.existsSync(dest)) {
|
|
25009
|
+
const ext = path8.extname(base);
|
|
25010
|
+
const stem = ext ? base.slice(0, -ext.length) : base;
|
|
25011
|
+
dest = path8.join(destDir, `${stem}-${Date.now()}${ext}`);
|
|
25012
|
+
}
|
|
25013
|
+
fs8.renameSync(sourcePath, dest);
|
|
25014
|
+
}
|
|
25015
|
+
|
|
25016
|
+
// src/sqlite/legacy_migration/archive-file-index-json.ts
|
|
25017
|
+
function archiveLegacyFileIndexJsonFiles() {
|
|
25018
|
+
try {
|
|
25019
|
+
if (!fs9.existsSync(INDEX_DIR)) return;
|
|
25020
|
+
for (const name of fs9.readdirSync(INDEX_DIR)) {
|
|
25021
|
+
if (name.startsWith(".file-index-") && name.endsWith(".json")) {
|
|
25022
|
+
const full = path9.join(INDEX_DIR, name);
|
|
25023
|
+
try {
|
|
25024
|
+
moveLegacyFileToOldVersionBackup("file-index", full);
|
|
25025
|
+
} catch (err) {
|
|
25026
|
+
console.error(`[cli-sqlite] legacy import: could not archive ${name}`, err);
|
|
25027
|
+
}
|
|
25028
|
+
}
|
|
25029
|
+
}
|
|
25030
|
+
} catch (e) {
|
|
25031
|
+
console.error("[cli-sqlite] legacy import: archive file-index json failed", e);
|
|
25032
|
+
}
|
|
25033
|
+
}
|
|
25034
|
+
|
|
25035
|
+
// src/sqlite/legacy_migration/import-agent-sessions-from-disk.ts
|
|
25036
|
+
import fs10 from "node:fs";
|
|
25037
|
+
import path10 from "node:path";
|
|
25038
|
+
import os6 from "node:os";
|
|
25039
|
+
var LEGACY_AGENT_SESSION_DIR = path10.join(os6.homedir(), ".buildautomaton", "agent-sessions");
|
|
25040
|
+
function importLegacyAgentSessionsFromDisk(db) {
|
|
25041
|
+
try {
|
|
25042
|
+
if (!fs10.existsSync(LEGACY_AGENT_SESSION_DIR)) return;
|
|
25043
|
+
const names = fs10.readdirSync(LEGACY_AGENT_SESSION_DIR).filter((n) => n.endsWith(".json"));
|
|
25044
|
+
for (const name of names) {
|
|
25045
|
+
const sessionKey = name.slice(0, -".json".length);
|
|
25046
|
+
const full = path10.join(LEGACY_AGENT_SESSION_DIR, name);
|
|
25047
|
+
let raw;
|
|
25048
|
+
try {
|
|
25049
|
+
raw = fs10.readFileSync(full, "utf8");
|
|
25050
|
+
} catch {
|
|
25051
|
+
continue;
|
|
25052
|
+
}
|
|
25053
|
+
let parsed;
|
|
25054
|
+
try {
|
|
25055
|
+
parsed = JSON.parse(raw);
|
|
25056
|
+
} catch {
|
|
25057
|
+
continue;
|
|
25058
|
+
}
|
|
25059
|
+
if (parsed.v !== 1) continue;
|
|
25060
|
+
const acpSessionId = typeof parsed.acpSessionId === "string" ? parsed.acpSessionId : null;
|
|
25061
|
+
const backendAgentType = typeof parsed.backendAgentType === "string" ? parsed.backendAgentType : null;
|
|
25062
|
+
const configOptionsJson = Array.isArray(parsed.configOptions) ? JSON.stringify(parsed.configOptions) : null;
|
|
25063
|
+
const updatedAt = typeof parsed.updatedAt === "string" ? parsed.updatedAt : (/* @__PURE__ */ new Date()).toISOString();
|
|
25064
|
+
db.run(
|
|
25065
|
+
`INSERT OR REPLACE INTO agent_session (session_key, acp_session_id, backend_agent_type, config_options_json, updated_at)
|
|
25066
|
+
VALUES (?, ?, ?, ?, ?)`,
|
|
25067
|
+
[sessionKey, acpSessionId, backendAgentType, configOptionsJson, updatedAt]
|
|
25068
|
+
);
|
|
25069
|
+
try {
|
|
25070
|
+
moveLegacyFileToOldVersionBackup("agent-sessions", full);
|
|
25071
|
+
} catch {
|
|
25072
|
+
}
|
|
25073
|
+
}
|
|
25074
|
+
} catch (e) {
|
|
25075
|
+
console.error("[cli-sqlite] legacy import: agent_sessions from disk failed", e);
|
|
25076
|
+
}
|
|
25077
|
+
}
|
|
25078
|
+
|
|
25079
|
+
// src/sqlite/legacy_migration/import-prompt-queues-from-disk.ts
|
|
25080
|
+
import fs11 from "node:fs";
|
|
25081
|
+
import path11 from "node:path";
|
|
25082
|
+
|
|
25083
|
+
// src/sqlite/legacy_migration/parse-persisted-queue-json.ts
|
|
25084
|
+
function parsePersistedQueueFromJson(raw) {
|
|
25085
|
+
try {
|
|
25086
|
+
const o = JSON.parse(raw);
|
|
25087
|
+
const queueKey = typeof o.queueKey === "string" ? o.queueKey : typeof o.queueKeyHash === "string" ? o.queueKeyHash : null;
|
|
25088
|
+
if (!queueKey || typeof o.updatedAt !== "string" || !Array.isArray(o.turns)) return null;
|
|
25089
|
+
return { queueKey, updatedAt: o.updatedAt, turns: o.turns };
|
|
25090
|
+
} catch {
|
|
25091
|
+
return null;
|
|
25092
|
+
}
|
|
25093
|
+
}
|
|
25094
|
+
|
|
25095
|
+
// src/sqlite/legacy_migration/import-prompt-queues-from-disk.ts
|
|
25096
|
+
function importLegacyPromptQueuesFromDisk(db) {
|
|
25097
|
+
try {
|
|
25098
|
+
const dir = getPromptQueuesDirectory();
|
|
25099
|
+
if (!fs11.existsSync(dir)) return;
|
|
25100
|
+
for (const name of fs11.readdirSync(dir)) {
|
|
25101
|
+
if (!name.endsWith(".json")) continue;
|
|
25102
|
+
const full = path11.join(dir, name);
|
|
25103
|
+
let raw;
|
|
25104
|
+
try {
|
|
25105
|
+
raw = fs11.readFileSync(full, "utf8");
|
|
25106
|
+
} catch {
|
|
25107
|
+
continue;
|
|
25108
|
+
}
|
|
25109
|
+
const file2 = parsePersistedQueueFromJson(raw);
|
|
25110
|
+
if (!file2) continue;
|
|
25111
|
+
db.run(
|
|
25112
|
+
`INSERT OR REPLACE INTO prompt_queue (queue_key, updated_at, turns_json) VALUES (?, ?, ?)`,
|
|
25113
|
+
[file2.queueKey, file2.updatedAt, JSON.stringify(file2.turns)]
|
|
25114
|
+
);
|
|
25115
|
+
try {
|
|
25116
|
+
moveLegacyFileToOldVersionBackup("queues", full);
|
|
25117
|
+
} catch {
|
|
25118
|
+
}
|
|
25119
|
+
}
|
|
25120
|
+
} catch (e) {
|
|
25121
|
+
console.error("[cli-sqlite] legacy import: prompt queues from disk failed", e);
|
|
25122
|
+
}
|
|
25123
|
+
}
|
|
25124
|
+
|
|
25125
|
+
// src/sqlite/legacy_migration/import-cli-legacy-disk-data.ts
|
|
25126
|
+
function legacyCliDiskMigrationIsPending() {
|
|
25127
|
+
try {
|
|
25128
|
+
if (fs12.existsSync(INDEX_DIR)) {
|
|
25129
|
+
for (const name of fs12.readdirSync(INDEX_DIR)) {
|
|
25130
|
+
if (name.startsWith(".file-index-") && name.endsWith(".json")) return true;
|
|
25131
|
+
}
|
|
25132
|
+
}
|
|
25133
|
+
} catch {
|
|
25134
|
+
}
|
|
25135
|
+
try {
|
|
25136
|
+
if (fs12.existsSync(LEGACY_AGENT_SESSION_DIR)) {
|
|
25137
|
+
if (fs12.readdirSync(LEGACY_AGENT_SESSION_DIR).some((n) => n.endsWith(".json"))) return true;
|
|
25138
|
+
}
|
|
25139
|
+
} catch {
|
|
25140
|
+
}
|
|
25141
|
+
try {
|
|
25142
|
+
const dir = getPromptQueuesDirectory();
|
|
25143
|
+
if (fs12.existsSync(dir) && fs12.readdirSync(dir).some((n) => n.endsWith(".json"))) return true;
|
|
25144
|
+
} catch {
|
|
25145
|
+
}
|
|
25146
|
+
return false;
|
|
25147
|
+
}
|
|
25148
|
+
function importCliSqliteLegacyDiskData(db, log2) {
|
|
25149
|
+
const pending = legacyCliDiskMigrationIsPending();
|
|
25150
|
+
if (pending && log2) {
|
|
25151
|
+
log2("Migrating legacy on-disk CLI data to SQLite\u2026");
|
|
25152
|
+
}
|
|
25153
|
+
archiveLegacyFileIndexJsonFiles();
|
|
25154
|
+
importLegacyAgentSessionsFromDisk(db);
|
|
25155
|
+
importLegacyPromptQueuesFromDisk(db);
|
|
25156
|
+
if (pending && log2) {
|
|
25157
|
+
log2("Legacy on-disk CLI data migration finished.");
|
|
25158
|
+
}
|
|
25159
|
+
}
|
|
25160
|
+
|
|
25161
|
+
// src/sqlite/load-cli-migration-sql.ts
|
|
25162
|
+
import { existsSync, readFileSync as readFileSync2 } from "node:fs";
|
|
25163
|
+
import { dirname as dirname2, join } from "node:path";
|
|
25164
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
25165
|
+
function readCliSqliteMigrationSql(filename) {
|
|
25166
|
+
const dir = dirname2(fileURLToPath2(import.meta.url));
|
|
25167
|
+
const resolved = join(dir, "migrations", filename);
|
|
25168
|
+
if (!existsSync(resolved)) {
|
|
25169
|
+
throw new Error(`Missing CLI SQLite migration SQL: ${resolved}`);
|
|
25170
|
+
}
|
|
25171
|
+
return readFileSync2(resolved, "utf8");
|
|
25172
|
+
}
|
|
25173
|
+
|
|
25174
|
+
// src/sqlite/migrate-cli-sqlite.ts
|
|
25175
|
+
function checkpointSatisfiedByLegacyChain(applied2, replacesLegacyMigrations) {
|
|
25176
|
+
return Array.isArray(replacesLegacyMigrations) && replacesLegacyMigrations.length > 0 && replacesLegacyMigrations.every((n) => applied2.has(n));
|
|
25177
|
+
}
|
|
25178
|
+
function recordMigrationAndPruneCheckpointLegacy(db, migration, applied2) {
|
|
25179
|
+
db.run("INSERT INTO __migrations (name) VALUES (?)", [migration.name]);
|
|
25180
|
+
applied2.add(migration.name);
|
|
25181
|
+
if (migration.checkpoint !== true) return;
|
|
25182
|
+
const legacy = migration.replacesLegacyMigrations;
|
|
25183
|
+
if (!legacy?.length) return;
|
|
25184
|
+
for (const legacyName of legacy) {
|
|
25185
|
+
if (legacyName === migration.name) continue;
|
|
25186
|
+
db.run("DELETE FROM __migrations WHERE name = ?", [legacyName]);
|
|
25187
|
+
applied2.delete(legacyName);
|
|
25188
|
+
}
|
|
25189
|
+
}
|
|
25190
|
+
var CHECKPOINT_V1 = "001_cli_sqlite_checkpoint_v1";
|
|
25191
|
+
var CHECKPOINT_V1_SQL = readCliSqliteMigrationSql("001_cli_sqlite_checkpoint_v1.sql");
|
|
25192
|
+
var CLI_SQLITE_MIGRATIONS = [
|
|
25193
|
+
{
|
|
25194
|
+
name: CHECKPOINT_V1,
|
|
25195
|
+
checkpoint: true,
|
|
25196
|
+
migrate: (db) => {
|
|
25197
|
+
db.exec(CHECKPOINT_V1_SQL);
|
|
25198
|
+
}
|
|
25199
|
+
}
|
|
25200
|
+
];
|
|
25201
|
+
function migrateCliSqlite(db) {
|
|
25202
|
+
db.exec(readCliSqliteMigrationSql("000_bootstrap_migrations_table.sql"));
|
|
25203
|
+
const appliedRows = db.all("SELECT name FROM __migrations");
|
|
25204
|
+
const applied2 = new Set(appliedRows.map((r) => r.name));
|
|
25205
|
+
for (const migration of CLI_SQLITE_MIGRATIONS) {
|
|
25206
|
+
if (applied2.has(migration.name)) continue;
|
|
25207
|
+
if (migration.checkpoint === true && checkpointSatisfiedByLegacyChain(applied2, migration.replacesLegacyMigrations)) {
|
|
25208
|
+
recordMigrationAndPruneCheckpointLegacy(db, migration, applied2);
|
|
25209
|
+
continue;
|
|
25210
|
+
}
|
|
25211
|
+
if (migration.alreadyApplied?.(db)) {
|
|
25212
|
+
recordMigrationAndPruneCheckpointLegacy(db, migration, applied2);
|
|
25213
|
+
continue;
|
|
25214
|
+
}
|
|
25215
|
+
try {
|
|
25216
|
+
migration.migrate(db);
|
|
25217
|
+
recordMigrationAndPruneCheckpointLegacy(db, migration, applied2);
|
|
25218
|
+
} catch (e) {
|
|
25219
|
+
console.error(`[cli-sqlite] Migration failed: ${migration.name}`, e);
|
|
25220
|
+
throw e;
|
|
25221
|
+
}
|
|
25222
|
+
}
|
|
25223
|
+
}
|
|
25224
|
+
|
|
25225
|
+
// src/sqlite/cli-database.ts
|
|
25226
|
+
var { Database: SqliteDatabase } = sqliteWasm;
|
|
25227
|
+
var openDatabases = /* @__PURE__ */ new Map();
|
|
25228
|
+
var processExitCloseRegistered = false;
|
|
25229
|
+
function registerProcessExitSqliteClose() {
|
|
25230
|
+
if (processExitCloseRegistered) return;
|
|
25231
|
+
processExitCloseRegistered = true;
|
|
25232
|
+
process.once("exit", () => {
|
|
25233
|
+
for (const db of openDatabases.values()) {
|
|
25234
|
+
safeCloseCliSqliteDatabase(db);
|
|
25235
|
+
}
|
|
25236
|
+
openDatabases.clear();
|
|
25237
|
+
});
|
|
25238
|
+
}
|
|
25239
|
+
function safeCloseCliSqliteDatabase(db) {
|
|
25240
|
+
if (db == null) return;
|
|
25241
|
+
try {
|
|
25242
|
+
if (db.isOpen) db.close();
|
|
25243
|
+
} catch {
|
|
25244
|
+
}
|
|
25245
|
+
}
|
|
25246
|
+
function closeAllCliSqliteConnections() {
|
|
25247
|
+
for (const db of openDatabases.values()) {
|
|
25248
|
+
safeCloseCliSqliteDatabase(db);
|
|
25249
|
+
}
|
|
25250
|
+
openDatabases.clear();
|
|
25251
|
+
}
|
|
25252
|
+
function getCliDatabase(options) {
|
|
25253
|
+
const sqlitePath = getCliSqlitePath();
|
|
25254
|
+
const existing = openDatabases.get(sqlitePath);
|
|
25255
|
+
if (existing?.isOpen) return existing;
|
|
25256
|
+
if (existing && !existing.isOpen) {
|
|
25257
|
+
safeCloseCliSqliteDatabase(existing);
|
|
25258
|
+
openDatabases.delete(sqlitePath);
|
|
25259
|
+
}
|
|
25260
|
+
ensureCliSqliteParentDir(sqlitePath);
|
|
25261
|
+
const db = new SqliteDatabase(sqlitePath);
|
|
25262
|
+
try {
|
|
25263
|
+
migrateCliSqlite(db);
|
|
25264
|
+
importCliSqliteLegacyDiskData(db, options?.logLegacyMigration);
|
|
25265
|
+
} catch (e) {
|
|
25266
|
+
safeCloseCliSqliteDatabase(db);
|
|
25267
|
+
throw e;
|
|
25268
|
+
}
|
|
25269
|
+
openDatabases.set(sqlitePath, db);
|
|
25270
|
+
registerProcessExitSqliteClose();
|
|
25271
|
+
return db;
|
|
25272
|
+
}
|
|
25273
|
+
|
|
24959
25274
|
// src/connection/close-bridge-connection.ts
|
|
24960
25275
|
async function closeBridgeConnection(state, acpManager, devServerManager, log2) {
|
|
24961
25276
|
const say = log2 ?? logImmediate;
|
|
@@ -24999,20 +25314,24 @@ async function closeBridgeConnection(state, acpManager, devServerManager, log2)
|
|
|
24999
25314
|
say("Stopping local dev server processes\u2026");
|
|
25000
25315
|
await devServerManager.shutdownAllGraceful();
|
|
25001
25316
|
}
|
|
25317
|
+
try {
|
|
25318
|
+
closeAllCliSqliteConnections();
|
|
25319
|
+
} catch {
|
|
25320
|
+
}
|
|
25002
25321
|
say("Shutdown complete.");
|
|
25003
25322
|
}
|
|
25004
25323
|
|
|
25005
25324
|
// src/paths/session-layout-paths.ts
|
|
25006
|
-
import * as
|
|
25325
|
+
import * as path12 from "node:path";
|
|
25007
25326
|
function resolveIsolatedSessionParentPathFromCheckouts(worktreePaths) {
|
|
25008
|
-
const resolved = worktreePaths.map((p) =>
|
|
25327
|
+
const resolved = worktreePaths.map((p) => path12.resolve(p)).filter(Boolean);
|
|
25009
25328
|
if (resolved.length === 0) return null;
|
|
25010
25329
|
resolved.sort();
|
|
25011
25330
|
return resolved[0];
|
|
25012
25331
|
}
|
|
25013
25332
|
function resolveSessionParentPathForAgentProcess(resolvedSessionParentPath) {
|
|
25014
25333
|
if (resolvedSessionParentPath != null && String(resolvedSessionParentPath).trim() !== "") {
|
|
25015
|
-
return
|
|
25334
|
+
return path12.resolve(String(resolvedSessionParentPath).trim());
|
|
25016
25335
|
}
|
|
25017
25336
|
return getBridgeRoot();
|
|
25018
25337
|
}
|
|
@@ -25021,17 +25340,17 @@ function resolveSessionParentPathForAgentProcess(resolvedSessionParentPath) {
|
|
|
25021
25340
|
import { execFile as execFile7 } from "node:child_process";
|
|
25022
25341
|
import { readFile, stat } from "node:fs/promises";
|
|
25023
25342
|
import { promisify as promisify7 } from "node:util";
|
|
25024
|
-
import * as
|
|
25343
|
+
import * as path15 from "node:path";
|
|
25025
25344
|
|
|
25026
25345
|
// src/git/pre-turn-snapshot.ts
|
|
25027
|
-
import * as
|
|
25028
|
-
import * as
|
|
25346
|
+
import * as fs14 from "node:fs";
|
|
25347
|
+
import * as path14 from "node:path";
|
|
25029
25348
|
import { execFile as execFile6 } from "node:child_process";
|
|
25030
25349
|
import { promisify as promisify6 } from "node:util";
|
|
25031
25350
|
|
|
25032
25351
|
// src/git/discover-repos.ts
|
|
25033
|
-
import * as
|
|
25034
|
-
import * as
|
|
25352
|
+
import * as fs13 from "node:fs";
|
|
25353
|
+
import * as path13 from "node:path";
|
|
25035
25354
|
|
|
25036
25355
|
// ../../node_modules/.pnpm/simple-git@3.32.3/node_modules/simple-git/dist/esm/index.js
|
|
25037
25356
|
var import_file_exists = __toESM(require_dist(), 1);
|
|
@@ -25070,8 +25389,8 @@ function pathspec(...paths) {
|
|
|
25070
25389
|
cache.set(key, paths);
|
|
25071
25390
|
return key;
|
|
25072
25391
|
}
|
|
25073
|
-
function isPathSpec(
|
|
25074
|
-
return
|
|
25392
|
+
function isPathSpec(path39) {
|
|
25393
|
+
return path39 instanceof String && cache.has(path39);
|
|
25075
25394
|
}
|
|
25076
25395
|
function toPaths(pathSpec) {
|
|
25077
25396
|
return cache.get(pathSpec) || [];
|
|
@@ -25160,8 +25479,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
|
|
|
25160
25479
|
function forEachLineWithContent(input, callback) {
|
|
25161
25480
|
return toLinesWithContent(input, true).map((line) => callback(line));
|
|
25162
25481
|
}
|
|
25163
|
-
function folderExists(
|
|
25164
|
-
return (0, import_file_exists.exists)(
|
|
25482
|
+
function folderExists(path39) {
|
|
25483
|
+
return (0, import_file_exists.exists)(path39, import_file_exists.FOLDER);
|
|
25165
25484
|
}
|
|
25166
25485
|
function append(target, item) {
|
|
25167
25486
|
if (Array.isArray(target)) {
|
|
@@ -25565,8 +25884,8 @@ function checkIsRepoRootTask() {
|
|
|
25565
25884
|
commands,
|
|
25566
25885
|
format: "utf-8",
|
|
25567
25886
|
onError,
|
|
25568
|
-
parser(
|
|
25569
|
-
return /^\.(git)?$/.test(
|
|
25887
|
+
parser(path39) {
|
|
25888
|
+
return /^\.(git)?$/.test(path39.trim());
|
|
25570
25889
|
}
|
|
25571
25890
|
};
|
|
25572
25891
|
}
|
|
@@ -26000,11 +26319,11 @@ function parseGrep(grep) {
|
|
|
26000
26319
|
const paths = /* @__PURE__ */ new Set();
|
|
26001
26320
|
const results = {};
|
|
26002
26321
|
forEachLineWithContent(grep, (input) => {
|
|
26003
|
-
const [
|
|
26004
|
-
paths.add(
|
|
26005
|
-
(results[
|
|
26322
|
+
const [path39, line, preview] = input.split(NULL);
|
|
26323
|
+
paths.add(path39);
|
|
26324
|
+
(results[path39] = results[path39] || []).push({
|
|
26006
26325
|
line: asNumber(line),
|
|
26007
|
-
path:
|
|
26326
|
+
path: path39,
|
|
26008
26327
|
preview
|
|
26009
26328
|
});
|
|
26010
26329
|
});
|
|
@@ -26769,14 +27088,14 @@ var init_hash_object = __esm2({
|
|
|
26769
27088
|
init_task();
|
|
26770
27089
|
}
|
|
26771
27090
|
});
|
|
26772
|
-
function parseInit(bare,
|
|
27091
|
+
function parseInit(bare, path39, text) {
|
|
26773
27092
|
const response = String(text).trim();
|
|
26774
27093
|
let result;
|
|
26775
27094
|
if (result = initResponseRegex.exec(response)) {
|
|
26776
|
-
return new InitSummary(bare,
|
|
27095
|
+
return new InitSummary(bare, path39, false, result[1]);
|
|
26777
27096
|
}
|
|
26778
27097
|
if (result = reInitResponseRegex.exec(response)) {
|
|
26779
|
-
return new InitSummary(bare,
|
|
27098
|
+
return new InitSummary(bare, path39, true, result[1]);
|
|
26780
27099
|
}
|
|
26781
27100
|
let gitDir = "";
|
|
26782
27101
|
const tokens = response.split(" ");
|
|
@@ -26787,7 +27106,7 @@ function parseInit(bare, path35, text) {
|
|
|
26787
27106
|
break;
|
|
26788
27107
|
}
|
|
26789
27108
|
}
|
|
26790
|
-
return new InitSummary(bare,
|
|
27109
|
+
return new InitSummary(bare, path39, /^re/i.test(response), gitDir);
|
|
26791
27110
|
}
|
|
26792
27111
|
var InitSummary;
|
|
26793
27112
|
var initResponseRegex;
|
|
@@ -26796,9 +27115,9 @@ var init_InitSummary = __esm2({
|
|
|
26796
27115
|
"src/lib/responses/InitSummary.ts"() {
|
|
26797
27116
|
"use strict";
|
|
26798
27117
|
InitSummary = class {
|
|
26799
|
-
constructor(bare,
|
|
27118
|
+
constructor(bare, path39, existing, gitDir) {
|
|
26800
27119
|
this.bare = bare;
|
|
26801
|
-
this.path =
|
|
27120
|
+
this.path = path39;
|
|
26802
27121
|
this.existing = existing;
|
|
26803
27122
|
this.gitDir = gitDir;
|
|
26804
27123
|
}
|
|
@@ -26810,7 +27129,7 @@ var init_InitSummary = __esm2({
|
|
|
26810
27129
|
function hasBareCommand(command) {
|
|
26811
27130
|
return command.includes(bareCommand);
|
|
26812
27131
|
}
|
|
26813
|
-
function initTask(bare = false,
|
|
27132
|
+
function initTask(bare = false, path39, customArgs) {
|
|
26814
27133
|
const commands = ["init", ...customArgs];
|
|
26815
27134
|
if (bare && !hasBareCommand(commands)) {
|
|
26816
27135
|
commands.splice(1, 0, bareCommand);
|
|
@@ -26819,7 +27138,7 @@ function initTask(bare = false, path35, customArgs) {
|
|
|
26819
27138
|
commands,
|
|
26820
27139
|
format: "utf-8",
|
|
26821
27140
|
parser(text) {
|
|
26822
|
-
return parseInit(commands.includes("--bare"),
|
|
27141
|
+
return parseInit(commands.includes("--bare"), path39, text);
|
|
26823
27142
|
}
|
|
26824
27143
|
};
|
|
26825
27144
|
}
|
|
@@ -27635,12 +27954,12 @@ var init_FileStatusSummary = __esm2({
|
|
|
27635
27954
|
"use strict";
|
|
27636
27955
|
fromPathRegex = /^(.+)\0(.+)$/;
|
|
27637
27956
|
FileStatusSummary = class {
|
|
27638
|
-
constructor(
|
|
27639
|
-
this.path =
|
|
27957
|
+
constructor(path39, index, working_dir) {
|
|
27958
|
+
this.path = path39;
|
|
27640
27959
|
this.index = index;
|
|
27641
27960
|
this.working_dir = working_dir;
|
|
27642
27961
|
if (index === "R" || working_dir === "R") {
|
|
27643
|
-
const detail = fromPathRegex.exec(
|
|
27962
|
+
const detail = fromPathRegex.exec(path39) || [null, path39, path39];
|
|
27644
27963
|
this.from = detail[2] || "";
|
|
27645
27964
|
this.path = detail[1] || "";
|
|
27646
27965
|
}
|
|
@@ -27671,14 +27990,14 @@ function splitLine(result, lineStr) {
|
|
|
27671
27990
|
default:
|
|
27672
27991
|
return;
|
|
27673
27992
|
}
|
|
27674
|
-
function data(index, workingDir,
|
|
27993
|
+
function data(index, workingDir, path39) {
|
|
27675
27994
|
const raw = `${index}${workingDir}`;
|
|
27676
27995
|
const handler = parsers6.get(raw);
|
|
27677
27996
|
if (handler) {
|
|
27678
|
-
handler(result,
|
|
27997
|
+
handler(result, path39);
|
|
27679
27998
|
}
|
|
27680
27999
|
if (raw !== "##" && raw !== "!!") {
|
|
27681
|
-
result.files.push(new FileStatusSummary(
|
|
28000
|
+
result.files.push(new FileStatusSummary(path39, index, workingDir));
|
|
27682
28001
|
}
|
|
27683
28002
|
}
|
|
27684
28003
|
}
|
|
@@ -27951,15 +28270,15 @@ var init_simple_git_api = __esm2({
|
|
|
27951
28270
|
this._executor = _executor;
|
|
27952
28271
|
}
|
|
27953
28272
|
_runTask(task, then) {
|
|
27954
|
-
const
|
|
27955
|
-
const promise2 =
|
|
28273
|
+
const chain2 = this._executor.chain();
|
|
28274
|
+
const promise2 = chain2.push(task);
|
|
27956
28275
|
if (then) {
|
|
27957
28276
|
taskCallback(task, promise2, then);
|
|
27958
28277
|
}
|
|
27959
28278
|
return Object.create(this, {
|
|
27960
28279
|
then: { value: promise2.then.bind(promise2) },
|
|
27961
28280
|
catch: { value: promise2.catch.bind(promise2) },
|
|
27962
|
-
_executor: { value:
|
|
28281
|
+
_executor: { value: chain2 }
|
|
27963
28282
|
});
|
|
27964
28283
|
}
|
|
27965
28284
|
add(files) {
|
|
@@ -27987,9 +28306,9 @@ var init_simple_git_api = __esm2({
|
|
|
27987
28306
|
next
|
|
27988
28307
|
);
|
|
27989
28308
|
}
|
|
27990
|
-
hashObject(
|
|
28309
|
+
hashObject(path39, write) {
|
|
27991
28310
|
return this._runTask(
|
|
27992
|
-
hashObjectTask(
|
|
28311
|
+
hashObjectTask(path39, write === true),
|
|
27993
28312
|
trailingFunctionArgument(arguments)
|
|
27994
28313
|
);
|
|
27995
28314
|
}
|
|
@@ -28342,8 +28661,8 @@ var init_branch = __esm2({
|
|
|
28342
28661
|
}
|
|
28343
28662
|
});
|
|
28344
28663
|
function toPath(input) {
|
|
28345
|
-
const
|
|
28346
|
-
return
|
|
28664
|
+
const path39 = input.trim().replace(/^["']|["']$/g, "");
|
|
28665
|
+
return path39 && normalize2(path39);
|
|
28347
28666
|
}
|
|
28348
28667
|
var parseCheckIgnore;
|
|
28349
28668
|
var init_CheckIgnore = __esm2({
|
|
@@ -28657,8 +28976,8 @@ __export2(sub_module_exports, {
|
|
|
28657
28976
|
subModuleTask: () => subModuleTask,
|
|
28658
28977
|
updateSubModuleTask: () => updateSubModuleTask
|
|
28659
28978
|
});
|
|
28660
|
-
function addSubModuleTask(repo,
|
|
28661
|
-
return subModuleTask(["add", repo,
|
|
28979
|
+
function addSubModuleTask(repo, path39) {
|
|
28980
|
+
return subModuleTask(["add", repo, path39]);
|
|
28662
28981
|
}
|
|
28663
28982
|
function initSubModuleTask(customArgs) {
|
|
28664
28983
|
return subModuleTask(["init", ...customArgs]);
|
|
@@ -28991,8 +29310,8 @@ var require_git = __commonJS2({
|
|
|
28991
29310
|
}
|
|
28992
29311
|
return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
|
|
28993
29312
|
};
|
|
28994
|
-
Git2.prototype.submoduleAdd = function(repo,
|
|
28995
|
-
return this._runTask(addSubModuleTask2(repo,
|
|
29313
|
+
Git2.prototype.submoduleAdd = function(repo, path39, then) {
|
|
29314
|
+
return this._runTask(addSubModuleTask2(repo, path39), trailingFunctionArgument2(arguments));
|
|
28996
29315
|
};
|
|
28997
29316
|
Git2.prototype.submoduleUpdate = function(args, then) {
|
|
28998
29317
|
return this._runTask(
|
|
@@ -29636,20 +29955,20 @@ async function isGitRepoDirectory(dirPath) {
|
|
|
29636
29955
|
// src/git/discover-repos.ts
|
|
29637
29956
|
async function discoverGitRepos(cwd = getBridgeRoot()) {
|
|
29638
29957
|
const result = [];
|
|
29639
|
-
const cwdResolved =
|
|
29958
|
+
const cwdResolved = path13.resolve(cwd);
|
|
29640
29959
|
if (await isGitRepoDirectory(cwdResolved)) {
|
|
29641
29960
|
const remoteUrl = await getRemoteOriginUrl(cwdResolved);
|
|
29642
29961
|
result.push({ absolutePath: cwdResolved, remoteUrl });
|
|
29643
29962
|
}
|
|
29644
29963
|
let entries;
|
|
29645
29964
|
try {
|
|
29646
|
-
entries =
|
|
29965
|
+
entries = fs13.readdirSync(cwdResolved, { withFileTypes: true });
|
|
29647
29966
|
} catch {
|
|
29648
29967
|
return result;
|
|
29649
29968
|
}
|
|
29650
29969
|
for (const ent of entries) {
|
|
29651
29970
|
if (!ent.isDirectory()) continue;
|
|
29652
|
-
const childPath =
|
|
29971
|
+
const childPath = path13.join(cwdResolved, ent.name);
|
|
29653
29972
|
if (await isGitRepoDirectory(childPath)) {
|
|
29654
29973
|
const remoteUrl = await getRemoteOriginUrl(childPath);
|
|
29655
29974
|
result.push({ absolutePath: childPath, remoteUrl });
|
|
@@ -29658,22 +29977,22 @@ async function discoverGitRepos(cwd = getBridgeRoot()) {
|
|
|
29658
29977
|
return result;
|
|
29659
29978
|
}
|
|
29660
29979
|
async function discoverGitReposUnderRoot(rootPath) {
|
|
29661
|
-
const root =
|
|
29980
|
+
const root = path13.resolve(rootPath);
|
|
29662
29981
|
const roots = [];
|
|
29663
29982
|
async function walk(dir) {
|
|
29664
29983
|
if (await isGitRepoDirectory(dir)) {
|
|
29665
|
-
roots.push(
|
|
29984
|
+
roots.push(path13.resolve(dir));
|
|
29666
29985
|
return;
|
|
29667
29986
|
}
|
|
29668
29987
|
let entries;
|
|
29669
29988
|
try {
|
|
29670
|
-
entries =
|
|
29989
|
+
entries = fs13.readdirSync(dir, { withFileTypes: true });
|
|
29671
29990
|
} catch {
|
|
29672
29991
|
return;
|
|
29673
29992
|
}
|
|
29674
29993
|
for (const ent of entries) {
|
|
29675
29994
|
if (!ent.isDirectory() || ent.name === ".git") continue;
|
|
29676
|
-
await walk(
|
|
29995
|
+
await walk(path13.join(dir, ent.name));
|
|
29677
29996
|
}
|
|
29678
29997
|
}
|
|
29679
29998
|
await walk(root);
|
|
@@ -29689,7 +30008,7 @@ async function discoverGitReposUnderRoot(rootPath) {
|
|
|
29689
30008
|
// src/git/pre-turn-snapshot.ts
|
|
29690
30009
|
var execFileAsync5 = promisify6(execFile6);
|
|
29691
30010
|
function snapshotsDirForCwd(agentCwd) {
|
|
29692
|
-
return
|
|
30011
|
+
return path14.join(agentCwd, ".buildautomaton", "snapshots");
|
|
29693
30012
|
}
|
|
29694
30013
|
async function gitStashCreate(repoRoot, log2) {
|
|
29695
30014
|
try {
|
|
@@ -29718,7 +30037,7 @@ async function gitRun(repoRoot, args, log2, label) {
|
|
|
29718
30037
|
async function resolveSnapshotRepoRoots(options) {
|
|
29719
30038
|
const { worktreePaths, fallbackCwd, sessionId, log: log2 } = options;
|
|
29720
30039
|
if (worktreePaths?.length) {
|
|
29721
|
-
const uniq = [...new Set(worktreePaths.map((p) =>
|
|
30040
|
+
const uniq = [...new Set(worktreePaths.map((p) => path14.resolve(p)))];
|
|
29722
30041
|
return uniq;
|
|
29723
30042
|
}
|
|
29724
30043
|
try {
|
|
@@ -29726,7 +30045,7 @@ async function resolveSnapshotRepoRoots(options) {
|
|
|
29726
30045
|
const mapped = repos.map((r) => r.absolutePath);
|
|
29727
30046
|
const sid = sessionId?.trim();
|
|
29728
30047
|
if (sid) {
|
|
29729
|
-
const filtered = mapped.filter((root) =>
|
|
30048
|
+
const filtered = mapped.filter((root) => path14.basename(root) === sid);
|
|
29730
30049
|
if (filtered.length > 0) return filtered;
|
|
29731
30050
|
}
|
|
29732
30051
|
return mapped;
|
|
@@ -29747,7 +30066,7 @@ async function capturePreTurnSnapshot(options) {
|
|
|
29747
30066
|
}
|
|
29748
30067
|
const dir = snapshotsDirForCwd(agentCwd);
|
|
29749
30068
|
try {
|
|
29750
|
-
|
|
30069
|
+
fs14.mkdirSync(dir, { recursive: true });
|
|
29751
30070
|
} catch (e) {
|
|
29752
30071
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
29753
30072
|
}
|
|
@@ -29756,9 +30075,9 @@ async function capturePreTurnSnapshot(options) {
|
|
|
29756
30075
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
29757
30076
|
repos
|
|
29758
30077
|
};
|
|
29759
|
-
const filePath =
|
|
30078
|
+
const filePath = path14.join(dir, `${runId}.json`);
|
|
29760
30079
|
try {
|
|
29761
|
-
|
|
30080
|
+
fs14.writeFileSync(filePath, JSON.stringify(payload, null, 2), "utf8");
|
|
29762
30081
|
} catch (e) {
|
|
29763
30082
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
29764
30083
|
}
|
|
@@ -29771,7 +30090,7 @@ async function capturePreTurnSnapshot(options) {
|
|
|
29771
30090
|
async function applyPreTurnSnapshot(filePath, log2) {
|
|
29772
30091
|
let data;
|
|
29773
30092
|
try {
|
|
29774
|
-
const raw =
|
|
30093
|
+
const raw = fs14.readFileSync(filePath, "utf8");
|
|
29775
30094
|
data = JSON.parse(raw);
|
|
29776
30095
|
} catch (e) {
|
|
29777
30096
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
@@ -29794,7 +30113,7 @@ async function applyPreTurnSnapshot(filePath, log2) {
|
|
|
29794
30113
|
return { ok: true };
|
|
29795
30114
|
}
|
|
29796
30115
|
function snapshotFilePath(agentCwd, runId) {
|
|
29797
|
-
return
|
|
30116
|
+
return path14.join(snapshotsDirForCwd(agentCwd), `${runId}.json`);
|
|
29798
30117
|
}
|
|
29799
30118
|
|
|
29800
30119
|
// src/git/session-git-queue.ts
|
|
@@ -29843,7 +30162,7 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
|
|
|
29843
30162
|
continue;
|
|
29844
30163
|
}
|
|
29845
30164
|
const lines = namesRaw.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
29846
|
-
const slug =
|
|
30165
|
+
const slug = path15.basename(repo.path).replace(/[^\w.-]+/g, "_") || "repo";
|
|
29847
30166
|
for (const rel of lines) {
|
|
29848
30167
|
if (rel.includes("..")) continue;
|
|
29849
30168
|
try {
|
|
@@ -29857,7 +30176,7 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
|
|
|
29857
30176
|
);
|
|
29858
30177
|
if (!patchContent.trim()) continue;
|
|
29859
30178
|
const displayPath = multiRepo ? `${slug}/${rel}` : rel;
|
|
29860
|
-
const workspaceFilePath =
|
|
30179
|
+
const workspaceFilePath = path15.join(repo.path, rel);
|
|
29861
30180
|
const newText = await readWorkspaceFileAsUtf8(workspaceFilePath);
|
|
29862
30181
|
sendSessionUpdate({
|
|
29863
30182
|
type: "session_file_change",
|
|
@@ -29879,9 +30198,9 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
|
|
|
29879
30198
|
// src/agents/acp/put-summarize-change-summaries.ts
|
|
29880
30199
|
async function putEncryptedChangeSummaryRows(params) {
|
|
29881
30200
|
const base = params.apiBaseUrl.replace(/\/+$/, "");
|
|
29882
|
-
const entries = params.rows.map(({ path:
|
|
30201
|
+
const entries = params.rows.map(({ path: path39, summary }) => {
|
|
29883
30202
|
const enc = params.e2ee.encryptFields({ summary }, ["summary"]);
|
|
29884
|
-
return { path:
|
|
30203
|
+
return { path: path39, summary: JSON.stringify(enc) };
|
|
29885
30204
|
});
|
|
29886
30205
|
const res = await fetch(
|
|
29887
30206
|
`${base}/api/sessions/${encodeURIComponent(params.sessionId)}/follow-ups/summarize-changes`,
|
|
@@ -30218,8 +30537,8 @@ async function sendPromptToAgent(options) {
|
|
|
30218
30537
|
}
|
|
30219
30538
|
|
|
30220
30539
|
// src/agents/acp/ensure-acp-client.ts
|
|
30221
|
-
import * as
|
|
30222
|
-
import * as
|
|
30540
|
+
import * as fs15 from "node:fs";
|
|
30541
|
+
import * as path18 from "node:path";
|
|
30223
30542
|
|
|
30224
30543
|
// src/error-message.ts
|
|
30225
30544
|
function errorMessage(err) {
|
|
@@ -30721,20 +31040,20 @@ function resolveAgentCommand(preferredAgentType) {
|
|
|
30721
31040
|
|
|
30722
31041
|
// src/agents/acp/session-file-change-path-kind.ts
|
|
30723
31042
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
30724
|
-
import { existsSync, statSync } from "node:fs";
|
|
31043
|
+
import { existsSync as existsSync2, statSync } from "node:fs";
|
|
30725
31044
|
|
|
30726
31045
|
// src/git/get-git-repo-root-sync.ts
|
|
30727
31046
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
30728
|
-
import * as
|
|
31047
|
+
import * as path16 from "node:path";
|
|
30729
31048
|
function getGitRepoRootSync(startDir) {
|
|
30730
31049
|
try {
|
|
30731
31050
|
const out = execFileSync2("git", ["rev-parse", "--show-toplevel"], {
|
|
30732
|
-
cwd:
|
|
31051
|
+
cwd: path16.resolve(startDir),
|
|
30733
31052
|
encoding: "utf8",
|
|
30734
31053
|
stdio: ["ignore", "pipe", "ignore"],
|
|
30735
31054
|
maxBuffer: 1024 * 1024
|
|
30736
31055
|
}).trim();
|
|
30737
|
-
return out ?
|
|
31056
|
+
return out ? path16.resolve(out) : null;
|
|
30738
31057
|
} catch {
|
|
30739
31058
|
return null;
|
|
30740
31059
|
}
|
|
@@ -30742,26 +31061,26 @@ function getGitRepoRootSync(startDir) {
|
|
|
30742
31061
|
|
|
30743
31062
|
// src/agents/acp/workspace-files.ts
|
|
30744
31063
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
30745
|
-
import { readFileSync as
|
|
30746
|
-
import * as
|
|
31064
|
+
import { readFileSync as readFileSync4 } from "node:fs";
|
|
31065
|
+
import * as path17 from "node:path";
|
|
30747
31066
|
function resolveWorkspaceFilePath(sessionParentPath, rawPath) {
|
|
30748
31067
|
const trimmed2 = rawPath.trim();
|
|
30749
31068
|
if (!trimmed2) return null;
|
|
30750
|
-
const normalizedSessionParent =
|
|
31069
|
+
const normalizedSessionParent = path17.resolve(sessionParentPath);
|
|
30751
31070
|
let resolvedPath = resolveSafePathUnderCwd(sessionParentPath, trimmed2);
|
|
30752
31071
|
if (!resolvedPath) {
|
|
30753
|
-
const candidate =
|
|
31072
|
+
const candidate = path17.isAbsolute(trimmed2) ? path17.normalize(trimmed2) : path17.normalize(path17.resolve(normalizedSessionParent, trimmed2));
|
|
30754
31073
|
const gitRoot2 = getGitRepoRootSync(sessionParentPath);
|
|
30755
31074
|
if (!gitRoot2) return null;
|
|
30756
|
-
const rel =
|
|
30757
|
-
if (rel.startsWith("..") ||
|
|
31075
|
+
const rel = path17.relative(gitRoot2, candidate);
|
|
31076
|
+
if (rel.startsWith("..") || path17.isAbsolute(rel)) return null;
|
|
30758
31077
|
resolvedPath = candidate;
|
|
30759
31078
|
}
|
|
30760
31079
|
const gitRoot = getGitRepoRootSync(sessionParentPath);
|
|
30761
31080
|
if (gitRoot) {
|
|
30762
|
-
const relFromRoot =
|
|
30763
|
-
if (!relFromRoot.startsWith("..") && !
|
|
30764
|
-
return { resolvedPath, display: relFromRoot.split(
|
|
31081
|
+
const relFromRoot = path17.relative(gitRoot, resolvedPath);
|
|
31082
|
+
if (!relFromRoot.startsWith("..") && !path17.isAbsolute(relFromRoot)) {
|
|
31083
|
+
return { resolvedPath, display: relFromRoot.split(path17.sep).join("/") };
|
|
30765
31084
|
}
|
|
30766
31085
|
}
|
|
30767
31086
|
return { resolvedPath, display: toDisplayPathRelativeToCwd(sessionParentPath, resolvedPath) };
|
|
@@ -30770,11 +31089,11 @@ function readUtf8WorkspaceFile(sessionParentPath, displayPath) {
|
|
|
30770
31089
|
if (!displayPath || displayPath.includes("..")) return "";
|
|
30771
31090
|
const gitRoot = getGitRepoRootSync(sessionParentPath);
|
|
30772
31091
|
if (gitRoot) {
|
|
30773
|
-
const resolvedPath2 =
|
|
30774
|
-
const rel =
|
|
30775
|
-
if (!rel.startsWith("..") && !
|
|
31092
|
+
const resolvedPath2 = path17.resolve(gitRoot, displayPath);
|
|
31093
|
+
const rel = path17.relative(gitRoot, resolvedPath2);
|
|
31094
|
+
if (!rel.startsWith("..") && !path17.isAbsolute(rel)) {
|
|
30776
31095
|
try {
|
|
30777
|
-
return
|
|
31096
|
+
return readFileSync4(resolvedPath2, "utf8");
|
|
30778
31097
|
} catch {
|
|
30779
31098
|
}
|
|
30780
31099
|
}
|
|
@@ -30782,7 +31101,7 @@ function readUtf8WorkspaceFile(sessionParentPath, displayPath) {
|
|
|
30782
31101
|
const resolvedPath = resolveSafePathUnderCwd(sessionParentPath, displayPath);
|
|
30783
31102
|
if (!resolvedPath) return "";
|
|
30784
31103
|
try {
|
|
30785
|
-
return
|
|
31104
|
+
return readFileSync4(resolvedPath, "utf8");
|
|
30786
31105
|
} catch {
|
|
30787
31106
|
return "";
|
|
30788
31107
|
}
|
|
@@ -30791,9 +31110,9 @@ function tryWorkspaceDisplayToPath(sessionParentPath, displayPath) {
|
|
|
30791
31110
|
if (!displayPath || displayPath.includes("..")) return null;
|
|
30792
31111
|
const gitRoot = getGitRepoRootSync(sessionParentPath);
|
|
30793
31112
|
if (gitRoot) {
|
|
30794
|
-
const resolvedPath =
|
|
30795
|
-
const rel =
|
|
30796
|
-
if (!rel.startsWith("..") && !
|
|
31113
|
+
const resolvedPath = path17.resolve(gitRoot, displayPath);
|
|
31114
|
+
const rel = path17.relative(gitRoot, resolvedPath);
|
|
31115
|
+
if (!rel.startsWith("..") && !path17.isAbsolute(rel)) return resolvedPath;
|
|
30797
31116
|
}
|
|
30798
31117
|
return resolveSafePathUnderCwd(sessionParentPath, displayPath);
|
|
30799
31118
|
}
|
|
@@ -30828,7 +31147,7 @@ function gitHeadPathObjectType(sessionParentPath, displayPath) {
|
|
|
30828
31147
|
}
|
|
30829
31148
|
function getSessionFileChangeDirectoryFlags(sessionParentPath, displayPath) {
|
|
30830
31149
|
const resolvedPath = tryWorkspaceDisplayToPath(sessionParentPath, displayPath);
|
|
30831
|
-
if (resolvedPath &&
|
|
31150
|
+
if (resolvedPath && existsSync2(resolvedPath)) {
|
|
30832
31151
|
try {
|
|
30833
31152
|
if (statSync(resolvedPath).isDirectory()) {
|
|
30834
31153
|
return { isDirectory: true, directoryRemoved: false };
|
|
@@ -30928,7 +31247,7 @@ function createBridgeOnRequest(opts) {
|
|
|
30928
31247
|
}
|
|
30929
31248
|
|
|
30930
31249
|
// src/agents/acp/hooks/extract-acp-file-diffs-from-update/paths-and-text.ts
|
|
30931
|
-
import { fileURLToPath as
|
|
31250
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
30932
31251
|
function readOptionalTextField(v) {
|
|
30933
31252
|
if (v === null || v === void 0) return "";
|
|
30934
31253
|
if (typeof v === "string") return v;
|
|
@@ -30938,7 +31257,7 @@ function normalizePathField(raw) {
|
|
|
30938
31257
|
const t = raw.trim();
|
|
30939
31258
|
if (t.startsWith("file://")) {
|
|
30940
31259
|
try {
|
|
30941
|
-
return
|
|
31260
|
+
return fileURLToPath3(t);
|
|
30942
31261
|
} catch {
|
|
30943
31262
|
return t;
|
|
30944
31263
|
}
|
|
@@ -31396,29 +31715,34 @@ function buildAcpSessionBridgeHooks(opts) {
|
|
|
31396
31715
|
}
|
|
31397
31716
|
|
|
31398
31717
|
// src/agents/acp/local-agent-session-file.ts
|
|
31399
|
-
|
|
31400
|
-
import os3 from "node:os";
|
|
31401
|
-
import path11 from "node:path";
|
|
31402
|
-
var LOCAL_AGENT_SESSION_DIR = path11.join(os3.homedir(), ".buildautomaton", "agent-sessions");
|
|
31403
|
-
function safeFileSlug(cloudSessionId) {
|
|
31718
|
+
function sessionKeyForCloudSessionId(cloudSessionId) {
|
|
31404
31719
|
const t = cloudSessionId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 220);
|
|
31405
31720
|
return t.length > 0 ? t : "session";
|
|
31406
31721
|
}
|
|
31407
|
-
function localAgentSessionFilePath(cloudSessionId) {
|
|
31408
|
-
return path11.join(LOCAL_AGENT_SESSION_DIR, `${safeFileSlug(cloudSessionId)}.json`);
|
|
31409
|
-
}
|
|
31410
31722
|
function readLocalAgentSessionFile(cloudSessionId) {
|
|
31411
31723
|
try {
|
|
31412
|
-
const
|
|
31413
|
-
const
|
|
31414
|
-
const
|
|
31415
|
-
|
|
31724
|
+
const db = getCliDatabase();
|
|
31725
|
+
const key = sessionKeyForCloudSessionId(cloudSessionId);
|
|
31726
|
+
const row = db.get(
|
|
31727
|
+
"SELECT acp_session_id, backend_agent_type, config_options_json, updated_at FROM agent_session WHERE session_key = ?",
|
|
31728
|
+
[key]
|
|
31729
|
+
);
|
|
31730
|
+
if (!row) return null;
|
|
31731
|
+
let configOptions = null;
|
|
31732
|
+
if (row.config_options_json != null && row.config_options_json !== "") {
|
|
31733
|
+
try {
|
|
31734
|
+
const parsed = JSON.parse(row.config_options_json);
|
|
31735
|
+
configOptions = Array.isArray(parsed) ? parsed : null;
|
|
31736
|
+
} catch {
|
|
31737
|
+
configOptions = null;
|
|
31738
|
+
}
|
|
31739
|
+
}
|
|
31416
31740
|
return {
|
|
31417
31741
|
v: 1,
|
|
31418
|
-
acpSessionId:
|
|
31419
|
-
backendAgentType:
|
|
31420
|
-
configOptions
|
|
31421
|
-
updatedAt:
|
|
31742
|
+
acpSessionId: row.acp_session_id,
|
|
31743
|
+
backendAgentType: row.backend_agent_type,
|
|
31744
|
+
configOptions,
|
|
31745
|
+
updatedAt: row.updated_at
|
|
31422
31746
|
};
|
|
31423
31747
|
} catch {
|
|
31424
31748
|
return null;
|
|
@@ -31426,9 +31750,8 @@ function readLocalAgentSessionFile(cloudSessionId) {
|
|
|
31426
31750
|
}
|
|
31427
31751
|
function writeLocalAgentSessionFile(cloudSessionId, patch) {
|
|
31428
31752
|
try {
|
|
31429
|
-
const
|
|
31430
|
-
|
|
31431
|
-
const p = localAgentSessionFilePath(cloudSessionId);
|
|
31753
|
+
const db = getCliDatabase();
|
|
31754
|
+
const key = sessionKeyForCloudSessionId(cloudSessionId);
|
|
31432
31755
|
const prev = readLocalAgentSessionFile(cloudSessionId);
|
|
31433
31756
|
const next = {
|
|
31434
31757
|
v: 1,
|
|
@@ -31437,7 +31760,17 @@ function writeLocalAgentSessionFile(cloudSessionId, patch) {
|
|
|
31437
31760
|
configOptions: patch.configOptions !== void 0 ? patch.configOptions : prev?.configOptions ?? null,
|
|
31438
31761
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
31439
31762
|
};
|
|
31440
|
-
|
|
31763
|
+
const configJson = next.configOptions != null ? JSON.stringify(next.configOptions) : null;
|
|
31764
|
+
db.run(
|
|
31765
|
+
`INSERT INTO agent_session (session_key, acp_session_id, backend_agent_type, config_options_json, updated_at)
|
|
31766
|
+
VALUES (?, ?, ?, ?, ?)
|
|
31767
|
+
ON CONFLICT(session_key) DO UPDATE SET
|
|
31768
|
+
acp_session_id = excluded.acp_session_id,
|
|
31769
|
+
backend_agent_type = excluded.backend_agent_type,
|
|
31770
|
+
config_options_json = excluded.config_options_json,
|
|
31771
|
+
updated_at = excluded.updated_at`,
|
|
31772
|
+
[key, next.acpSessionId, next.backendAgentType, configJson, next.updatedAt]
|
|
31773
|
+
);
|
|
31441
31774
|
} catch {
|
|
31442
31775
|
}
|
|
31443
31776
|
}
|
|
@@ -31461,7 +31794,7 @@ async function ensureAcpClient(options) {
|
|
|
31461
31794
|
if (state.acpStartPromise && !state.acpHandle) {
|
|
31462
31795
|
await state.acpStartPromise;
|
|
31463
31796
|
}
|
|
31464
|
-
if (state.acpHandle && state.lastAcpCwd != null &&
|
|
31797
|
+
if (state.acpHandle && state.lastAcpCwd != null && path18.resolve(state.lastAcpCwd) !== path18.resolve(targetSessionParentPath)) {
|
|
31465
31798
|
try {
|
|
31466
31799
|
state.acpHandle.disconnect();
|
|
31467
31800
|
} catch {
|
|
@@ -31496,7 +31829,7 @@ async function ensureAcpClient(options) {
|
|
|
31496
31829
|
if (!state.acpStartPromise) {
|
|
31497
31830
|
let statOk = false;
|
|
31498
31831
|
try {
|
|
31499
|
-
const st =
|
|
31832
|
+
const st = fs15.statSync(targetSessionParentPath);
|
|
31500
31833
|
statOk = st.isDirectory();
|
|
31501
31834
|
if (!statOk) {
|
|
31502
31835
|
state.lastAcpStartError = `Agent cwd is not a directory: ${targetSessionParentPath}`;
|
|
@@ -31743,12 +32076,12 @@ async function createAcpManager(options) {
|
|
|
31743
32076
|
}
|
|
31744
32077
|
|
|
31745
32078
|
// src/worktrees/session-worktree-manager.ts
|
|
31746
|
-
import * as
|
|
31747
|
-
import
|
|
32079
|
+
import * as path25 from "node:path";
|
|
32080
|
+
import os8 from "node:os";
|
|
31748
32081
|
|
|
31749
32082
|
// src/worktrees/prepare-new-session-worktrees.ts
|
|
31750
|
-
import * as
|
|
31751
|
-
import * as
|
|
32083
|
+
import * as fs17 from "node:fs";
|
|
32084
|
+
import * as path20 from "node:path";
|
|
31752
32085
|
|
|
31753
32086
|
// src/git/worktree-add.ts
|
|
31754
32087
|
async function gitWorktreeAddBranch(mainRepoPath, worktreePath, branch) {
|
|
@@ -31757,12 +32090,12 @@ async function gitWorktreeAddBranch(mainRepoPath, worktreePath, branch) {
|
|
|
31757
32090
|
}
|
|
31758
32091
|
|
|
31759
32092
|
// src/worktrees/worktree-layout-file.ts
|
|
31760
|
-
import * as
|
|
31761
|
-
import * as
|
|
31762
|
-
import
|
|
32093
|
+
import * as fs16 from "node:fs";
|
|
32094
|
+
import * as path19 from "node:path";
|
|
32095
|
+
import os7 from "node:os";
|
|
31763
32096
|
var LAYOUT_FILENAME = "worktree-launcher-layout.json";
|
|
31764
32097
|
function defaultWorktreeLayoutPath() {
|
|
31765
|
-
return
|
|
32098
|
+
return path19.join(os7.homedir(), ".buildautomaton", LAYOUT_FILENAME);
|
|
31766
32099
|
}
|
|
31767
32100
|
function normalizeLoadedLayout(raw) {
|
|
31768
32101
|
if (raw && typeof raw === "object" && "launcherCwds" in raw) {
|
|
@@ -31774,8 +32107,8 @@ function normalizeLoadedLayout(raw) {
|
|
|
31774
32107
|
function loadWorktreeLayout() {
|
|
31775
32108
|
try {
|
|
31776
32109
|
const p = defaultWorktreeLayoutPath();
|
|
31777
|
-
if (!
|
|
31778
|
-
const raw = JSON.parse(
|
|
32110
|
+
if (!fs16.existsSync(p)) return { launcherCwds: [] };
|
|
32111
|
+
const raw = JSON.parse(fs16.readFileSync(p, "utf8"));
|
|
31779
32112
|
return normalizeLoadedLayout(raw);
|
|
31780
32113
|
} catch {
|
|
31781
32114
|
return { launcherCwds: [] };
|
|
@@ -31783,24 +32116,24 @@ function loadWorktreeLayout() {
|
|
|
31783
32116
|
}
|
|
31784
32117
|
function saveWorktreeLayout(layout) {
|
|
31785
32118
|
try {
|
|
31786
|
-
const dir =
|
|
31787
|
-
|
|
31788
|
-
|
|
32119
|
+
const dir = path19.dirname(defaultWorktreeLayoutPath());
|
|
32120
|
+
fs16.mkdirSync(dir, { recursive: true });
|
|
32121
|
+
fs16.writeFileSync(defaultWorktreeLayoutPath(), JSON.stringify(layout, null, 2), "utf8");
|
|
31789
32122
|
} catch {
|
|
31790
32123
|
}
|
|
31791
32124
|
}
|
|
31792
32125
|
function baseNameSafe(pathString) {
|
|
31793
|
-
return
|
|
32126
|
+
return path19.basename(pathString).replace(/[^a-zA-Z0-9._-]+/g, "-") || "cwd";
|
|
31794
32127
|
}
|
|
31795
32128
|
function getLauncherDirNameIfPresent(layout, bridgeRootPath2) {
|
|
31796
|
-
const norm =
|
|
31797
|
-
const existing = layout.launcherCwds.find((e) =>
|
|
32129
|
+
const norm = path19.resolve(bridgeRootPath2);
|
|
32130
|
+
const existing = layout.launcherCwds.find((e) => path19.resolve(e.absolutePath) === norm);
|
|
31798
32131
|
return existing?.dirName;
|
|
31799
32132
|
}
|
|
31800
32133
|
function allocateDirNameForLauncherCwd(layout, bridgeRootPath2) {
|
|
31801
32134
|
const existing = getLauncherDirNameIfPresent(layout, bridgeRootPath2);
|
|
31802
32135
|
if (existing) return existing;
|
|
31803
|
-
const norm =
|
|
32136
|
+
const norm = path19.resolve(bridgeRootPath2);
|
|
31804
32137
|
const base = baseNameSafe(norm);
|
|
31805
32138
|
const used = new Set(layout.launcherCwds.map((e) => e.dirName));
|
|
31806
32139
|
let name = base;
|
|
@@ -31817,10 +32150,10 @@ function allocateDirNameForLauncherCwd(layout, bridgeRootPath2) {
|
|
|
31817
32150
|
// src/worktrees/prepare-new-session-worktrees.ts
|
|
31818
32151
|
async function prepareNewSessionWorktrees(options) {
|
|
31819
32152
|
const { worktreesRootPath, bridgeRoot, sessionId, layout, log: log2 } = options;
|
|
31820
|
-
const bridgeResolved =
|
|
32153
|
+
const bridgeResolved = path20.resolve(bridgeRoot);
|
|
31821
32154
|
const cwdKey = allocateDirNameForLauncherCwd(layout, bridgeResolved);
|
|
31822
|
-
const bridgeKeyDir =
|
|
31823
|
-
const sessionDir =
|
|
32155
|
+
const bridgeKeyDir = path20.join(worktreesRootPath, cwdKey);
|
|
32156
|
+
const sessionDir = path20.join(bridgeKeyDir, sessionId);
|
|
31824
32157
|
const repos = await discoverGitReposUnderRoot(bridgeResolved);
|
|
31825
32158
|
if (repos.length === 0) {
|
|
31826
32159
|
log2("[worktrees] No Git repositories under bridge root; skipping worktree creation.");
|
|
@@ -31828,14 +32161,14 @@ async function prepareNewSessionWorktrees(options) {
|
|
|
31828
32161
|
}
|
|
31829
32162
|
const branch = `session-${sessionId}`;
|
|
31830
32163
|
const worktreePaths = [];
|
|
31831
|
-
|
|
32164
|
+
fs17.mkdirSync(sessionDir, { recursive: true });
|
|
31832
32165
|
for (const repo of repos) {
|
|
31833
|
-
let rel =
|
|
31834
|
-
if (rel.startsWith("..") ||
|
|
32166
|
+
let rel = path20.relative(bridgeResolved, repo.absolutePath);
|
|
32167
|
+
if (rel.startsWith("..") || path20.isAbsolute(rel)) continue;
|
|
31835
32168
|
const relNorm = rel === "" ? "." : rel;
|
|
31836
|
-
const wtPath = relNorm === "." ? sessionDir :
|
|
32169
|
+
const wtPath = relNorm === "." ? sessionDir : path20.join(sessionDir, relNorm);
|
|
31837
32170
|
if (relNorm !== ".") {
|
|
31838
|
-
|
|
32171
|
+
fs17.mkdirSync(path20.dirname(wtPath), { recursive: true });
|
|
31839
32172
|
}
|
|
31840
32173
|
try {
|
|
31841
32174
|
await gitWorktreeAddBranch(repo.absolutePath, wtPath, branch);
|
|
@@ -31877,23 +32210,23 @@ async function renameSessionWorktreeBranches(paths, newBranch, log2) {
|
|
|
31877
32210
|
}
|
|
31878
32211
|
|
|
31879
32212
|
// src/worktrees/remove-session-worktrees.ts
|
|
31880
|
-
import * as
|
|
32213
|
+
import * as fs20 from "node:fs";
|
|
31881
32214
|
|
|
31882
32215
|
// src/git/worktree-remove.ts
|
|
31883
|
-
import * as
|
|
32216
|
+
import * as fs19 from "node:fs";
|
|
31884
32217
|
|
|
31885
32218
|
// src/git/resolve-main-repo-from-git-file.ts
|
|
31886
|
-
import * as
|
|
31887
|
-
import * as
|
|
32219
|
+
import * as fs18 from "node:fs";
|
|
32220
|
+
import * as path21 from "node:path";
|
|
31888
32221
|
function resolveMainRepoFromWorktreeGitFile(wt) {
|
|
31889
|
-
const gitDirFile =
|
|
31890
|
-
if (!
|
|
31891
|
-
const first2 =
|
|
32222
|
+
const gitDirFile = path21.join(wt, ".git");
|
|
32223
|
+
if (!fs18.existsSync(gitDirFile) || !fs18.statSync(gitDirFile).isFile()) return "";
|
|
32224
|
+
const first2 = fs18.readFileSync(gitDirFile, "utf8").trim();
|
|
31892
32225
|
const m = first2.match(/^gitdir:\s*(.+)$/im);
|
|
31893
32226
|
if (!m) return "";
|
|
31894
|
-
const gitWorktreePath =
|
|
31895
|
-
const gitDir =
|
|
31896
|
-
return
|
|
32227
|
+
const gitWorktreePath = path21.resolve(wt, m[1].trim());
|
|
32228
|
+
const gitDir = path21.dirname(path21.dirname(gitWorktreePath));
|
|
32229
|
+
return path21.dirname(gitDir);
|
|
31897
32230
|
}
|
|
31898
32231
|
|
|
31899
32232
|
// src/git/worktree-remove.ts
|
|
@@ -31902,7 +32235,7 @@ async function gitWorktreeRemoveForce(worktreePath) {
|
|
|
31902
32235
|
if (mainRepo) {
|
|
31903
32236
|
await cliSimpleGit(mainRepo).raw(["worktree", "remove", "--force", worktreePath]);
|
|
31904
32237
|
} else {
|
|
31905
|
-
|
|
32238
|
+
fs19.rmSync(worktreePath, { recursive: true, force: true });
|
|
31906
32239
|
}
|
|
31907
32240
|
}
|
|
31908
32241
|
|
|
@@ -31915,7 +32248,7 @@ async function removeSessionWorktrees(paths, log2) {
|
|
|
31915
32248
|
} catch (e) {
|
|
31916
32249
|
log2(`[worktrees] Remove failed for ${wt}: ${e instanceof Error ? e.message : String(e)}`);
|
|
31917
32250
|
try {
|
|
31918
|
-
|
|
32251
|
+
fs20.rmSync(wt, { recursive: true, force: true });
|
|
31919
32252
|
} catch {
|
|
31920
32253
|
}
|
|
31921
32254
|
}
|
|
@@ -32135,7 +32468,7 @@ function formatRemoteDisplayLabel(remoteUrl) {
|
|
|
32135
32468
|
}
|
|
32136
32469
|
|
|
32137
32470
|
// src/git/working-directory/changes/get-working-tree-change-repo-details.ts
|
|
32138
|
-
import * as
|
|
32471
|
+
import * as path23 from "node:path";
|
|
32139
32472
|
|
|
32140
32473
|
// src/git/working-directory/changes/parse-git-status.ts
|
|
32141
32474
|
function parseNameStatusLines(lines) {
|
|
@@ -32255,8 +32588,8 @@ async function listChangedFilesForCommit(repoGitCwd, repoRelPath, commitSha) {
|
|
|
32255
32588
|
}
|
|
32256
32589
|
|
|
32257
32590
|
// src/git/working-directory/changes/list-changed-files-for-repo.ts
|
|
32258
|
-
import * as
|
|
32259
|
-
import * as
|
|
32591
|
+
import * as fs22 from "node:fs";
|
|
32592
|
+
import * as path22 from "node:path";
|
|
32260
32593
|
|
|
32261
32594
|
// src/git/working-directory/changes/count-lines.ts
|
|
32262
32595
|
import { createReadStream } from "node:fs";
|
|
@@ -32280,7 +32613,7 @@ async function countTextFileLines(filePath) {
|
|
|
32280
32613
|
}
|
|
32281
32614
|
|
|
32282
32615
|
// src/git/working-directory/changes/hydrate-patch.ts
|
|
32283
|
-
import * as
|
|
32616
|
+
import * as fs21 from "node:fs";
|
|
32284
32617
|
var UNIFIED_HUNK_HEADER_RE = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/;
|
|
32285
32618
|
var MAX_HYDRATE_LINES_PER_GAP = 8e3;
|
|
32286
32619
|
var MAX_HYDRATE_LINES_PER_FILE = 8e4;
|
|
@@ -32295,7 +32628,7 @@ async function readGitBlobLines(repoCwd, pathInRepo) {
|
|
|
32295
32628
|
}
|
|
32296
32629
|
async function readWorktreeFileLines(filePath) {
|
|
32297
32630
|
try {
|
|
32298
|
-
const raw = await
|
|
32631
|
+
const raw = await fs21.promises.readFile(filePath, "utf8");
|
|
32299
32632
|
return raw.split(/\r?\n/);
|
|
32300
32633
|
} catch {
|
|
32301
32634
|
return null;
|
|
@@ -32430,7 +32763,7 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
|
|
|
32430
32763
|
const rows = [];
|
|
32431
32764
|
for (const pathInRepo of paths) {
|
|
32432
32765
|
const relLauncher = posixJoinDirFile(repoRelPath, pathInRepo.replace(/\\/g, "/"));
|
|
32433
|
-
const repoFilePath =
|
|
32766
|
+
const repoFilePath = path22.join(repoGitCwd, pathInRepo);
|
|
32434
32767
|
const nums = numByPath.get(pathInRepo);
|
|
32435
32768
|
let additions = nums?.additions ?? 0;
|
|
32436
32769
|
let deletions = nums?.deletions ?? 0;
|
|
@@ -32443,7 +32776,7 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
|
|
|
32443
32776
|
deletions = fromGit.deletions;
|
|
32444
32777
|
} else {
|
|
32445
32778
|
try {
|
|
32446
|
-
const st = await
|
|
32779
|
+
const st = await fs22.promises.stat(repoFilePath);
|
|
32447
32780
|
if (st.isFile()) additions = await countTextFileLines(repoFilePath);
|
|
32448
32781
|
else additions = 0;
|
|
32449
32782
|
} catch {
|
|
@@ -32469,7 +32802,7 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
|
|
|
32469
32802
|
} else {
|
|
32470
32803
|
pathInRepo = row.pathRelLauncher;
|
|
32471
32804
|
}
|
|
32472
|
-
const filePath =
|
|
32805
|
+
const filePath = path22.join(repoGitCwd, pathInRepo);
|
|
32473
32806
|
let patch = await unifiedDiffForFile(repoGitCwd, pathInRepo, row.change);
|
|
32474
32807
|
if (patch) {
|
|
32475
32808
|
patch = await hydrateUnifiedPatchWithFileContext(patch, filePath, repoGitCwd, pathInRepo, row.change);
|
|
@@ -32485,8 +32818,8 @@ function normRepoRel(p) {
|
|
|
32485
32818
|
return x === "" ? "." : x;
|
|
32486
32819
|
}
|
|
32487
32820
|
async function getWorkingTreeChangeRepoDetails(options) {
|
|
32488
|
-
const bridgeRoot =
|
|
32489
|
-
const sessionWtRoot = options.sessionWorktreeRootPath ?
|
|
32821
|
+
const bridgeRoot = path23.resolve(getBridgeRoot());
|
|
32822
|
+
const sessionWtRoot = options.sessionWorktreeRootPath ? path23.resolve(options.sessionWorktreeRootPath) : null;
|
|
32490
32823
|
const legacyNested = options.legacyRepoNestedSessionLayout === true;
|
|
32491
32824
|
const out = [];
|
|
32492
32825
|
const filter = options.repoFilterRelPath != null ? normRepoRel(options.repoFilterRelPath) : null;
|
|
@@ -32499,7 +32832,7 @@ async function getWorkingTreeChangeRepoDetails(options) {
|
|
|
32499
32832
|
}
|
|
32500
32833
|
const basis = filter == null && basisInput.kind === "commit" ? { kind: "working" } : basisInput;
|
|
32501
32834
|
for (const target of options.commitTargetPaths) {
|
|
32502
|
-
const t =
|
|
32835
|
+
const t = path23.resolve(target);
|
|
32503
32836
|
if (!await isGitRepoDirectory(t)) continue;
|
|
32504
32837
|
const g = cliSimpleGit(t);
|
|
32505
32838
|
let branch = "HEAD";
|
|
@@ -32512,8 +32845,8 @@ async function getWorkingTreeChangeRepoDetails(options) {
|
|
|
32512
32845
|
const remoteDisplay = formatRemoteDisplayLabel(remoteUrl);
|
|
32513
32846
|
let repoRelPath;
|
|
32514
32847
|
if (sessionWtRoot) {
|
|
32515
|
-
const anchor = legacyNested ?
|
|
32516
|
-
const relNorm =
|
|
32848
|
+
const anchor = legacyNested ? path23.dirname(t) : t;
|
|
32849
|
+
const relNorm = path23.relative(sessionWtRoot, anchor);
|
|
32517
32850
|
repoRelPath = relNorm === "" ? "." : relNorm.replace(/\\/g, "/");
|
|
32518
32851
|
} else {
|
|
32519
32852
|
let top = t;
|
|
@@ -32522,8 +32855,8 @@ async function getWorkingTreeChangeRepoDetails(options) {
|
|
|
32522
32855
|
} catch {
|
|
32523
32856
|
top = t;
|
|
32524
32857
|
}
|
|
32525
|
-
const rel =
|
|
32526
|
-
repoRelPath = rel.startsWith("..") ?
|
|
32858
|
+
const rel = path23.relative(bridgeRoot, path23.resolve(top)).replace(/\\/g, "/") || ".";
|
|
32859
|
+
repoRelPath = rel.startsWith("..") ? path23.basename(path23.resolve(top)) : rel;
|
|
32527
32860
|
}
|
|
32528
32861
|
const norm = normRepoRel(repoRelPath === "" ? "." : repoRelPath);
|
|
32529
32862
|
if (filter && norm !== filter) continue;
|
|
@@ -32588,11 +32921,11 @@ async function commitSessionWorktrees(options) {
|
|
|
32588
32921
|
}
|
|
32589
32922
|
|
|
32590
32923
|
// src/worktrees/discover-session-worktree-on-disk.ts
|
|
32591
|
-
import * as
|
|
32592
|
-
import * as
|
|
32924
|
+
import * as fs23 from "node:fs";
|
|
32925
|
+
import * as path24 from "node:path";
|
|
32593
32926
|
function isGitDir(dirPath) {
|
|
32594
32927
|
try {
|
|
32595
|
-
return
|
|
32928
|
+
return fs23.existsSync(path24.join(dirPath, ".git"));
|
|
32596
32929
|
} catch {
|
|
32597
32930
|
return false;
|
|
32598
32931
|
}
|
|
@@ -32601,23 +32934,23 @@ function collectGitRepoRootsUnderDirectory(rootPath) {
|
|
|
32601
32934
|
const out = [];
|
|
32602
32935
|
const walk = (dir) => {
|
|
32603
32936
|
if (isGitDir(dir)) {
|
|
32604
|
-
out.push(
|
|
32937
|
+
out.push(path24.resolve(dir));
|
|
32605
32938
|
return;
|
|
32606
32939
|
}
|
|
32607
32940
|
let entries;
|
|
32608
32941
|
try {
|
|
32609
|
-
entries =
|
|
32942
|
+
entries = fs23.readdirSync(dir, { withFileTypes: true });
|
|
32610
32943
|
} catch {
|
|
32611
32944
|
return;
|
|
32612
32945
|
}
|
|
32613
32946
|
for (const e of entries) {
|
|
32614
32947
|
if (e.name.startsWith(".")) continue;
|
|
32615
|
-
const full =
|
|
32948
|
+
const full = path24.join(dir, e.name);
|
|
32616
32949
|
if (!e.isDirectory()) continue;
|
|
32617
32950
|
walk(full);
|
|
32618
32951
|
}
|
|
32619
32952
|
};
|
|
32620
|
-
walk(
|
|
32953
|
+
walk(path24.resolve(rootPath));
|
|
32621
32954
|
return [...new Set(out)];
|
|
32622
32955
|
}
|
|
32623
32956
|
function collectWorktreeRootsNamed(root, sessionId, maxDepth) {
|
|
@@ -32626,16 +32959,16 @@ function collectWorktreeRootsNamed(root, sessionId, maxDepth) {
|
|
|
32626
32959
|
if (depth > maxDepth) return;
|
|
32627
32960
|
let entries;
|
|
32628
32961
|
try {
|
|
32629
|
-
entries =
|
|
32962
|
+
entries = fs23.readdirSync(dir, { withFileTypes: true });
|
|
32630
32963
|
} catch {
|
|
32631
32964
|
return;
|
|
32632
32965
|
}
|
|
32633
32966
|
for (const e of entries) {
|
|
32634
32967
|
if (e.name.startsWith(".")) continue;
|
|
32635
|
-
const full =
|
|
32968
|
+
const full = path24.join(dir, e.name);
|
|
32636
32969
|
if (!e.isDirectory()) continue;
|
|
32637
32970
|
if (e.name === sessionId) {
|
|
32638
|
-
if (isGitDir(full)) out.push(
|
|
32971
|
+
if (isGitDir(full)) out.push(path24.resolve(full));
|
|
32639
32972
|
} else {
|
|
32640
32973
|
walk(full, depth + 1);
|
|
32641
32974
|
}
|
|
@@ -32647,14 +32980,14 @@ function collectWorktreeRootsNamed(root, sessionId, maxDepth) {
|
|
|
32647
32980
|
function tryBindingFromSessionDirectory(sessionDir) {
|
|
32648
32981
|
let st;
|
|
32649
32982
|
try {
|
|
32650
|
-
st =
|
|
32983
|
+
st = fs23.statSync(sessionDir);
|
|
32651
32984
|
} catch {
|
|
32652
32985
|
return null;
|
|
32653
32986
|
}
|
|
32654
32987
|
if (!st.isDirectory()) return null;
|
|
32655
32988
|
const worktreePaths = collectGitRepoRootsUnderDirectory(sessionDir);
|
|
32656
32989
|
if (worktreePaths.length === 0) return null;
|
|
32657
|
-
const abs =
|
|
32990
|
+
const abs = path24.resolve(sessionDir);
|
|
32658
32991
|
return {
|
|
32659
32992
|
sessionParentPath: abs,
|
|
32660
32993
|
workingTreeRelRoot: abs,
|
|
@@ -32664,20 +32997,20 @@ function tryBindingFromSessionDirectory(sessionDir) {
|
|
|
32664
32997
|
function discoverLegacyBindingAscendingFromCheckout(sessionId, checkoutPath) {
|
|
32665
32998
|
const sid = sessionId.trim();
|
|
32666
32999
|
if (!sid) return null;
|
|
32667
|
-
const hintR =
|
|
33000
|
+
const hintR = path24.resolve(checkoutPath);
|
|
32668
33001
|
let best = null;
|
|
32669
|
-
let cur =
|
|
33002
|
+
let cur = path24.dirname(hintR);
|
|
32670
33003
|
for (let i = 0; i < 40; i++) {
|
|
32671
33004
|
const paths = collectWorktreeRootsNamed(cur, sid, 24);
|
|
32672
|
-
if (paths.some((p) =>
|
|
32673
|
-
const isolated = resolveIsolatedSessionParentPathFromCheckouts(paths) ??
|
|
33005
|
+
if (paths.some((p) => path24.resolve(p) === hintR)) {
|
|
33006
|
+
const isolated = resolveIsolatedSessionParentPathFromCheckouts(paths) ?? path24.resolve(paths[0]);
|
|
32674
33007
|
best = {
|
|
32675
|
-
sessionParentPath:
|
|
32676
|
-
workingTreeRelRoot:
|
|
32677
|
-
repoCheckoutPaths: paths.map((p) =>
|
|
33008
|
+
sessionParentPath: path24.resolve(isolated),
|
|
33009
|
+
workingTreeRelRoot: path24.resolve(cur),
|
|
33010
|
+
repoCheckoutPaths: paths.map((p) => path24.resolve(p))
|
|
32678
33011
|
};
|
|
32679
33012
|
}
|
|
32680
|
-
const next =
|
|
33013
|
+
const next = path24.dirname(cur);
|
|
32681
33014
|
if (next === cur) break;
|
|
32682
33015
|
cur = next;
|
|
32683
33016
|
}
|
|
@@ -32685,33 +33018,33 @@ function discoverLegacyBindingAscendingFromCheckout(sessionId, checkoutPath) {
|
|
|
32685
33018
|
}
|
|
32686
33019
|
function discoverSessionWorktreeOnDisk(options) {
|
|
32687
33020
|
const { sessionId, worktreesRootPath, layout, bridgeRoot } = options;
|
|
32688
|
-
if (!sessionId.trim() || !
|
|
33021
|
+
if (!sessionId.trim() || !fs23.existsSync(worktreesRootPath)) return null;
|
|
32689
33022
|
const preferredKey = getLauncherDirNameIfPresent(layout, bridgeRoot);
|
|
32690
33023
|
const keys = [];
|
|
32691
33024
|
if (preferredKey) keys.push(preferredKey);
|
|
32692
33025
|
try {
|
|
32693
|
-
for (const name of
|
|
33026
|
+
for (const name of fs23.readdirSync(worktreesRootPath)) {
|
|
32694
33027
|
if (name.startsWith(".")) continue;
|
|
32695
|
-
const p =
|
|
32696
|
-
if (!
|
|
33028
|
+
const p = path24.join(worktreesRootPath, name);
|
|
33029
|
+
if (!fs23.statSync(p).isDirectory()) continue;
|
|
32697
33030
|
if (name !== preferredKey) keys.push(name);
|
|
32698
33031
|
}
|
|
32699
33032
|
} catch {
|
|
32700
33033
|
return null;
|
|
32701
33034
|
}
|
|
32702
33035
|
for (const key of keys) {
|
|
32703
|
-
const layoutRoot =
|
|
32704
|
-
if (!
|
|
32705
|
-
const sessionDir =
|
|
33036
|
+
const layoutRoot = path24.join(worktreesRootPath, key);
|
|
33037
|
+
if (!fs23.existsSync(layoutRoot) || !fs23.statSync(layoutRoot).isDirectory()) continue;
|
|
33038
|
+
const sessionDir = path24.join(layoutRoot, sessionId);
|
|
32706
33039
|
const nested = tryBindingFromSessionDirectory(sessionDir);
|
|
32707
33040
|
if (nested) return nested;
|
|
32708
33041
|
const legacyPaths = collectWorktreeRootsNamed(layoutRoot, sessionId, 24);
|
|
32709
33042
|
if (legacyPaths.length > 0) {
|
|
32710
|
-
const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ??
|
|
33043
|
+
const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ?? path24.resolve(legacyPaths[0]);
|
|
32711
33044
|
return {
|
|
32712
|
-
sessionParentPath:
|
|
32713
|
-
workingTreeRelRoot:
|
|
32714
|
-
repoCheckoutPaths: legacyPaths.map((p) =>
|
|
33045
|
+
sessionParentPath: path24.resolve(isolated),
|
|
33046
|
+
workingTreeRelRoot: path24.resolve(layoutRoot),
|
|
33047
|
+
repoCheckoutPaths: legacyPaths.map((p) => path24.resolve(p))
|
|
32715
33048
|
};
|
|
32716
33049
|
}
|
|
32717
33050
|
}
|
|
@@ -32720,12 +33053,12 @@ function discoverSessionWorktreeOnDisk(options) {
|
|
|
32720
33053
|
function discoverSessionWorktreesUnderSessionWorktreeRoot(sessionWorktreeRootPathOrHint, sessionId) {
|
|
32721
33054
|
const sid = sessionId.trim();
|
|
32722
33055
|
if (!sid) return null;
|
|
32723
|
-
const hint =
|
|
32724
|
-
const underHint = tryBindingFromSessionDirectory(
|
|
33056
|
+
const hint = path24.resolve(sessionWorktreeRootPathOrHint);
|
|
33057
|
+
const underHint = tryBindingFromSessionDirectory(path24.join(hint, sid));
|
|
32725
33058
|
if (underHint) return underHint;
|
|
32726
33059
|
const direct = tryBindingFromSessionDirectory(hint);
|
|
32727
33060
|
if (direct) {
|
|
32728
|
-
if (
|
|
33061
|
+
if (path24.basename(hint) === sid && isGitDir(hint)) {
|
|
32729
33062
|
const legacyFromCheckout = discoverLegacyBindingAscendingFromCheckout(sid, hint);
|
|
32730
33063
|
if (legacyFromCheckout && legacyFromCheckout.repoCheckoutPaths.length > direct.repoCheckoutPaths.length) {
|
|
32731
33064
|
return legacyFromCheckout;
|
|
@@ -32733,24 +33066,24 @@ function discoverSessionWorktreesUnderSessionWorktreeRoot(sessionWorktreeRootPat
|
|
|
32733
33066
|
}
|
|
32734
33067
|
return direct;
|
|
32735
33068
|
}
|
|
32736
|
-
if (
|
|
33069
|
+
if (path24.basename(hint) === sid && isGitDir(hint)) {
|
|
32737
33070
|
const legacyFromCheckout = discoverLegacyBindingAscendingFromCheckout(sid, hint);
|
|
32738
33071
|
if (legacyFromCheckout) return legacyFromCheckout;
|
|
32739
33072
|
}
|
|
32740
33073
|
let st;
|
|
32741
33074
|
try {
|
|
32742
|
-
st =
|
|
33075
|
+
st = fs23.statSync(hint);
|
|
32743
33076
|
} catch {
|
|
32744
33077
|
return null;
|
|
32745
33078
|
}
|
|
32746
33079
|
if (!st.isDirectory()) return null;
|
|
32747
33080
|
const legacyPaths = collectWorktreeRootsNamed(hint, sid, 24);
|
|
32748
33081
|
if (legacyPaths.length === 0) return null;
|
|
32749
|
-
const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ??
|
|
33082
|
+
const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ?? path24.resolve(legacyPaths[0]);
|
|
32750
33083
|
return {
|
|
32751
|
-
sessionParentPath:
|
|
33084
|
+
sessionParentPath: path24.resolve(isolated),
|
|
32752
33085
|
workingTreeRelRoot: hint,
|
|
32753
|
-
repoCheckoutPaths: legacyPaths.map((p) =>
|
|
33086
|
+
repoCheckoutPaths: legacyPaths.map((p) => path24.resolve(p))
|
|
32754
33087
|
};
|
|
32755
33088
|
}
|
|
32756
33089
|
|
|
@@ -32773,10 +33106,10 @@ var SessionWorktreeManager = class {
|
|
|
32773
33106
|
this.layout = loadWorktreeLayout();
|
|
32774
33107
|
}
|
|
32775
33108
|
rememberSessionWorktrees(sessionId, binding) {
|
|
32776
|
-
const paths = binding.repoCheckoutPaths.map((p) =>
|
|
33109
|
+
const paths = binding.repoCheckoutPaths.map((p) => path25.resolve(p));
|
|
32777
33110
|
this.sessionRepoCheckoutPaths.set(sessionId, paths);
|
|
32778
|
-
this.sessionParentPathBySession.set(sessionId,
|
|
32779
|
-
this.sessionWorkingTreeRelRootBySession.set(sessionId,
|
|
33111
|
+
this.sessionParentPathBySession.set(sessionId, path25.resolve(binding.sessionParentPath));
|
|
33112
|
+
this.sessionWorkingTreeRelRootBySession.set(sessionId, path25.resolve(binding.workingTreeRelRoot));
|
|
32780
33113
|
}
|
|
32781
33114
|
sessionParentPathAfterRemember(sessionId) {
|
|
32782
33115
|
return this.sessionParentPathBySession.get(sessionId);
|
|
@@ -32793,7 +33126,7 @@ var SessionWorktreeManager = class {
|
|
|
32793
33126
|
const parent = this.sessionParentPathBySession.get(sessionId);
|
|
32794
33127
|
const relRoot = this.sessionWorkingTreeRelRootBySession.get(sessionId);
|
|
32795
33128
|
if (!parent || !relRoot) return false;
|
|
32796
|
-
return
|
|
33129
|
+
return path25.resolve(parent) !== path25.resolve(relRoot);
|
|
32797
33130
|
}
|
|
32798
33131
|
/**
|
|
32799
33132
|
* Session parent path for `worktrees_root`: the per-session directory (new layout) or primary checkout (legacy).
|
|
@@ -32802,7 +33135,7 @@ var SessionWorktreeManager = class {
|
|
|
32802
33135
|
if (!sessionId) return null;
|
|
32803
33136
|
const sid = sessionId.trim();
|
|
32804
33137
|
const cached2 = this.sessionParentPathBySession.get(sid);
|
|
32805
|
-
if (cached2) return
|
|
33138
|
+
if (cached2) return path25.resolve(cached2);
|
|
32806
33139
|
const paths = this.ensureRepoCheckoutPathsForSession(sid) ?? this.getRepoCheckoutPathsForSession(sid);
|
|
32807
33140
|
if (!paths?.length) return null;
|
|
32808
33141
|
return resolveIsolatedSessionParentPathFromCheckouts(paths);
|
|
@@ -32816,7 +33149,7 @@ var SessionWorktreeManager = class {
|
|
|
32816
33149
|
const sid = sessionId.trim();
|
|
32817
33150
|
const parentPathRaw = opts.sessionParentPath?.trim();
|
|
32818
33151
|
if (parentPathRaw) {
|
|
32819
|
-
const resolved =
|
|
33152
|
+
const resolved = path25.resolve(parentPathRaw);
|
|
32820
33153
|
if (sid && parseSessionParent(opts.sessionParent) === "worktrees_root") {
|
|
32821
33154
|
const diskFirst = this.tryDiscoverFromDisk(sid);
|
|
32822
33155
|
if (diskFirst) {
|
|
@@ -32835,7 +33168,7 @@ var SessionWorktreeManager = class {
|
|
|
32835
33168
|
this.rememberSessionWorktrees(sid, tryRoot);
|
|
32836
33169
|
return this.sessionParentPathAfterRemember(sid);
|
|
32837
33170
|
}
|
|
32838
|
-
const next =
|
|
33171
|
+
const next = path25.dirname(cur);
|
|
32839
33172
|
if (next === cur) break;
|
|
32840
33173
|
cur = next;
|
|
32841
33174
|
}
|
|
@@ -32988,15 +33321,22 @@ var SessionWorktreeManager = class {
|
|
|
32988
33321
|
}
|
|
32989
33322
|
};
|
|
32990
33323
|
function defaultWorktreesRootPath() {
|
|
32991
|
-
return
|
|
33324
|
+
return path25.join(os8.homedir(), ".buildautomaton", "worktrees");
|
|
32992
33325
|
}
|
|
32993
33326
|
|
|
32994
33327
|
// src/files/watch-file-index.ts
|
|
32995
33328
|
import { watch } from "node:fs";
|
|
33329
|
+
import path30 from "node:path";
|
|
33330
|
+
|
|
33331
|
+
// src/files/index/paths.ts
|
|
32996
33332
|
import path26 from "node:path";
|
|
33333
|
+
import crypto2 from "node:crypto";
|
|
33334
|
+
function getCwdHashForFileIndex(resolvedCwd) {
|
|
33335
|
+
return crypto2.createHash("sha256").update(path26.resolve(resolvedCwd)).digest("hex").slice(0, INDEX_HASH_LEN);
|
|
33336
|
+
}
|
|
32997
33337
|
|
|
32998
33338
|
// src/files/index/build-file-index.ts
|
|
32999
|
-
import
|
|
33339
|
+
import path28 from "node:path";
|
|
33000
33340
|
|
|
33001
33341
|
// src/runtime/yield-to-event-loop.ts
|
|
33002
33342
|
function yieldToEventLoop() {
|
|
@@ -33004,47 +33344,12 @@ function yieldToEventLoop() {
|
|
|
33004
33344
|
}
|
|
33005
33345
|
|
|
33006
33346
|
// src/files/index/walk-workspace-tree.ts
|
|
33007
|
-
import
|
|
33008
|
-
import
|
|
33009
|
-
|
|
33010
|
-
// src/files/index/constants.ts
|
|
33011
|
-
import path20 from "node:path";
|
|
33012
|
-
import os6 from "node:os";
|
|
33013
|
-
var INDEX_WORK_YIELD_EVERY = 256;
|
|
33014
|
-
var INDEX_DIR = path20.join(os6.homedir(), ".buildautomaton");
|
|
33015
|
-
var INDEX_HASH_LEN = 16;
|
|
33016
|
-
var INDEX_VERSION = 2;
|
|
33017
|
-
var INDEX_LOG_PREFIX = "[file-index]";
|
|
33018
|
-
|
|
33019
|
-
// src/files/index/walk-workspace-tree.ts
|
|
33020
|
-
function walkWorkspaceTreeSync(dir, baseDir, out) {
|
|
33021
|
-
let names;
|
|
33022
|
-
try {
|
|
33023
|
-
names = fs19.readdirSync(dir);
|
|
33024
|
-
} catch {
|
|
33025
|
-
return;
|
|
33026
|
-
}
|
|
33027
|
-
for (const name of names) {
|
|
33028
|
-
if (name.startsWith(".")) continue;
|
|
33029
|
-
const full = path21.join(dir, name);
|
|
33030
|
-
let stat2;
|
|
33031
|
-
try {
|
|
33032
|
-
stat2 = fs19.statSync(full);
|
|
33033
|
-
} catch {
|
|
33034
|
-
continue;
|
|
33035
|
-
}
|
|
33036
|
-
const relative5 = path21.relative(baseDir, full).replace(/\\/g, "/");
|
|
33037
|
-
if (stat2.isDirectory()) {
|
|
33038
|
-
walkWorkspaceTreeSync(full, baseDir, out);
|
|
33039
|
-
} else if (stat2.isFile()) {
|
|
33040
|
-
out.push(relative5);
|
|
33041
|
-
}
|
|
33042
|
-
}
|
|
33043
|
-
}
|
|
33347
|
+
import fs24 from "node:fs";
|
|
33348
|
+
import path27 from "node:path";
|
|
33044
33349
|
async function walkWorkspaceTreeAsync(dir, baseDir, out, state) {
|
|
33045
33350
|
let names;
|
|
33046
33351
|
try {
|
|
33047
|
-
names = await
|
|
33352
|
+
names = await fs24.promises.readdir(dir);
|
|
33048
33353
|
} catch {
|
|
33049
33354
|
return;
|
|
33050
33355
|
}
|
|
@@ -33054,14 +33359,14 @@ async function walkWorkspaceTreeAsync(dir, baseDir, out, state) {
|
|
|
33054
33359
|
await yieldToEventLoop();
|
|
33055
33360
|
}
|
|
33056
33361
|
state.n++;
|
|
33057
|
-
const full =
|
|
33362
|
+
const full = path27.join(dir, name);
|
|
33058
33363
|
let stat2;
|
|
33059
33364
|
try {
|
|
33060
|
-
stat2 = await
|
|
33365
|
+
stat2 = await fs24.promises.stat(full);
|
|
33061
33366
|
} catch {
|
|
33062
33367
|
continue;
|
|
33063
33368
|
}
|
|
33064
|
-
const relative5 =
|
|
33369
|
+
const relative5 = path27.relative(baseDir, full).replace(/\\/g, "/");
|
|
33065
33370
|
if (stat2.isDirectory()) {
|
|
33066
33371
|
await walkWorkspaceTreeAsync(full, baseDir, out, state);
|
|
33067
33372
|
} else if (stat2.isFile()) {
|
|
@@ -33073,205 +33378,124 @@ function createWalkYieldState() {
|
|
|
33073
33378
|
return { n: 0 };
|
|
33074
33379
|
}
|
|
33075
33380
|
|
|
33076
|
-
// src/files/index/
|
|
33077
|
-
|
|
33078
|
-
|
|
33079
|
-
const
|
|
33080
|
-
|
|
33081
|
-
out.push(lower.slice(i, i + 3));
|
|
33082
|
-
}
|
|
33083
|
-
return out;
|
|
33084
|
-
}
|
|
33085
|
-
function binarySearch(arr, x) {
|
|
33086
|
-
let lo = 0;
|
|
33087
|
-
let hi = arr.length - 1;
|
|
33088
|
-
while (lo <= hi) {
|
|
33089
|
-
const mid = lo + hi >>> 1;
|
|
33090
|
-
if (arr[mid] < x) lo = mid + 1;
|
|
33091
|
-
else if (arr[mid] > x) hi = mid - 1;
|
|
33092
|
-
else return mid;
|
|
33093
|
-
}
|
|
33094
|
-
return -1;
|
|
33095
|
-
}
|
|
33096
|
-
function intersectSortedTrigramSets(arrays) {
|
|
33097
|
-
if (arrays.length === 0) return [];
|
|
33098
|
-
if (arrays.length === 1) return arrays[0];
|
|
33099
|
-
const byLength = arrays.slice().sort((a, b) => a.length - b.length);
|
|
33100
|
-
const smallest = byLength[0];
|
|
33101
|
-
const rest = byLength.slice(1);
|
|
33102
|
-
const result = [];
|
|
33103
|
-
for (const idx of smallest) {
|
|
33104
|
-
if (rest.every((arr) => binarySearch(arr, idx) >= 0)) {
|
|
33105
|
-
result.push(idx);
|
|
33106
|
-
}
|
|
33107
|
-
}
|
|
33108
|
-
return result;
|
|
33109
|
-
}
|
|
33110
|
-
|
|
33111
|
-
// src/files/index/build-trigram-map.ts
|
|
33112
|
-
function buildTrigramMapForPaths(paths) {
|
|
33113
|
-
const trigramIndex = {};
|
|
33114
|
-
for (let i = 0; i < paths.length; i++) {
|
|
33115
|
-
const trigrams = getTrigrams(paths[i]);
|
|
33116
|
-
const seen = /* @__PURE__ */ new Set();
|
|
33117
|
-
for (const tri of trigrams) {
|
|
33118
|
-
if (seen.has(tri)) continue;
|
|
33119
|
-
seen.add(tri);
|
|
33120
|
-
if (!trigramIndex[tri]) trigramIndex[tri] = [];
|
|
33121
|
-
trigramIndex[tri].push(i);
|
|
33122
|
-
}
|
|
33123
|
-
}
|
|
33124
|
-
return trigramIndex;
|
|
33381
|
+
// src/files/index/file-index-sqlite-lock.ts
|
|
33382
|
+
import fs25 from "node:fs";
|
|
33383
|
+
function isSqliteCorruptError(e) {
|
|
33384
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
33385
|
+
return msg.includes("malformed") || msg.includes("database disk image is malformed") || msg.includes("corrupt");
|
|
33125
33386
|
}
|
|
33126
|
-
|
|
33127
|
-
|
|
33128
|
-
|
|
33129
|
-
|
|
33130
|
-
await
|
|
33131
|
-
}
|
|
33132
|
-
|
|
33133
|
-
|
|
33134
|
-
|
|
33135
|
-
|
|
33136
|
-
|
|
33137
|
-
|
|
33138
|
-
|
|
33387
|
+
var chain = Promise.resolve();
|
|
33388
|
+
function withFileIndexSqliteLock(fn) {
|
|
33389
|
+
const run = async () => {
|
|
33390
|
+
try {
|
|
33391
|
+
return await Promise.resolve(fn());
|
|
33392
|
+
} catch (e) {
|
|
33393
|
+
if (!isSqliteCorruptError(e)) throw e;
|
|
33394
|
+
closeAllCliSqliteConnections();
|
|
33395
|
+
try {
|
|
33396
|
+
fs25.unlinkSync(getCliSqlitePath());
|
|
33397
|
+
} catch {
|
|
33398
|
+
}
|
|
33399
|
+
chain = Promise.resolve();
|
|
33400
|
+
return await Promise.resolve(fn());
|
|
33139
33401
|
}
|
|
33140
|
-
}
|
|
33141
|
-
|
|
33142
|
-
|
|
33143
|
-
|
|
33144
|
-
|
|
33145
|
-
|
|
33146
|
-
|
|
33147
|
-
// src/files/index/paths.ts
|
|
33148
|
-
import path22 from "node:path";
|
|
33149
|
-
import crypto2 from "node:crypto";
|
|
33150
|
-
function getIndexPathForCwd(resolvedCwd) {
|
|
33151
|
-
const hash = crypto2.createHash("sha256").update(resolvedCwd).digest("hex").slice(0, INDEX_HASH_LEN);
|
|
33152
|
-
return path22.join(INDEX_DIR, `.file-index-${hash}.json`);
|
|
33153
|
-
}
|
|
33154
|
-
|
|
33155
|
-
// src/files/index/write-index-file.ts
|
|
33156
|
-
function writeIndexFileSync(resolvedCwd, data) {
|
|
33157
|
-
const indexPath = getIndexPathForCwd(resolvedCwd);
|
|
33158
|
-
try {
|
|
33159
|
-
if (!fs20.existsSync(INDEX_DIR)) fs20.mkdirSync(INDEX_DIR, { recursive: true });
|
|
33160
|
-
fs20.writeFileSync(indexPath, JSON.stringify(data), "utf8");
|
|
33161
|
-
} catch (e) {
|
|
33162
|
-
console.error(`${INDEX_LOG_PREFIX} Failed to write index:`, e);
|
|
33163
|
-
}
|
|
33164
|
-
}
|
|
33165
|
-
async function writeIndexFileAsync(resolvedCwd, data) {
|
|
33166
|
-
const indexPath = getIndexPathForCwd(resolvedCwd);
|
|
33167
|
-
try {
|
|
33168
|
-
await fs20.promises.mkdir(INDEX_DIR, { recursive: true });
|
|
33169
|
-
await fs20.promises.writeFile(indexPath, JSON.stringify(data), "utf8");
|
|
33170
|
-
} catch (e) {
|
|
33171
|
-
console.error(`${INDEX_LOG_PREFIX} Failed to write index:`, e);
|
|
33172
|
-
}
|
|
33173
|
-
}
|
|
33174
|
-
function makeTrigramIndexData(paths, trigramIndex) {
|
|
33175
|
-
return { version: INDEX_VERSION, paths, trigramIndex };
|
|
33402
|
+
};
|
|
33403
|
+
const next = chain.then(run);
|
|
33404
|
+
chain = next.then(
|
|
33405
|
+
() => void 0,
|
|
33406
|
+
() => void 0
|
|
33407
|
+
);
|
|
33408
|
+
return next;
|
|
33176
33409
|
}
|
|
33177
33410
|
|
|
33178
33411
|
// src/files/index/build-file-index.ts
|
|
33179
33412
|
function sortPaths(paths) {
|
|
33180
33413
|
paths.sort((a, b) => a.localeCompare(b, void 0, { sensitivity: "base" }));
|
|
33181
33414
|
}
|
|
33182
|
-
function
|
|
33183
|
-
const
|
|
33184
|
-
const
|
|
33185
|
-
|
|
33186
|
-
sortPaths(paths);
|
|
33187
|
-
const trigramIndex = buildTrigramMapForPaths(paths);
|
|
33188
|
-
const data = makeTrigramIndexData(paths, trigramIndex);
|
|
33189
|
-
writeIndexFileSync(resolved, data);
|
|
33190
|
-
return data;
|
|
33191
|
-
}
|
|
33192
|
-
async function buildFileIndexAsync(cwd) {
|
|
33193
|
-
const resolved = path23.resolve(cwd);
|
|
33194
|
-
const paths = [];
|
|
33195
|
-
await walkWorkspaceTreeAsync(resolved, resolved, paths, createWalkYieldState());
|
|
33196
|
-
await yieldToEventLoop();
|
|
33197
|
-
sortPaths(paths);
|
|
33198
|
-
const trigramIndex = await buildTrigramMapForPathsAsync(paths);
|
|
33199
|
-
const data = makeTrigramIndexData(paths, trigramIndex);
|
|
33200
|
-
await writeIndexFileAsync(resolved, data);
|
|
33201
|
-
return data;
|
|
33202
|
-
}
|
|
33203
|
-
|
|
33204
|
-
// src/files/index/load-file-index.ts
|
|
33205
|
-
import fs21 from "node:fs";
|
|
33206
|
-
import path24 from "node:path";
|
|
33207
|
-
function loadFileIndex(cwd) {
|
|
33208
|
-
const resolved = path24.resolve(cwd);
|
|
33209
|
-
const indexPath = getIndexPathForCwd(resolved);
|
|
33415
|
+
function persistPathsToSqlite(resolved, paths) {
|
|
33416
|
+
const db = getCliDatabase();
|
|
33417
|
+
const h = getCwdHashForFileIndex(resolved);
|
|
33418
|
+
db.run("BEGIN IMMEDIATE");
|
|
33210
33419
|
try {
|
|
33211
|
-
|
|
33212
|
-
const
|
|
33213
|
-
|
|
33214
|
-
const
|
|
33215
|
-
|
|
33216
|
-
return obj;
|
|
33420
|
+
db.run("DELETE FROM file_index_path WHERE cwd_hash = ?", [h]);
|
|
33421
|
+
const ins = db.prepare("INSERT INTO file_index_path (cwd_hash, path) VALUES (?, ?)");
|
|
33422
|
+
try {
|
|
33423
|
+
for (const rel of paths) {
|
|
33424
|
+
ins.run([h, rel]);
|
|
33217
33425
|
}
|
|
33218
|
-
|
|
33426
|
+
} finally {
|
|
33427
|
+
ins.finalize();
|
|
33219
33428
|
}
|
|
33220
|
-
|
|
33221
|
-
|
|
33429
|
+
db.run("COMMIT");
|
|
33430
|
+
} catch (e) {
|
|
33431
|
+
try {
|
|
33432
|
+
db.run("ROLLBACK");
|
|
33433
|
+
} catch {
|
|
33222
33434
|
}
|
|
33223
|
-
|
|
33224
|
-
} catch {
|
|
33225
|
-
return null;
|
|
33435
|
+
throw e;
|
|
33226
33436
|
}
|
|
33227
33437
|
}
|
|
33438
|
+
async function buildFileIndexAsync(cwd) {
|
|
33439
|
+
return withFileIndexSqliteLock(async () => {
|
|
33440
|
+
const resolved = path28.resolve(cwd);
|
|
33441
|
+
const paths = [];
|
|
33442
|
+
await walkWorkspaceTreeAsync(resolved, resolved, paths, createWalkYieldState());
|
|
33443
|
+
await yieldToEventLoop();
|
|
33444
|
+
sortPaths(paths);
|
|
33445
|
+
persistPathsToSqlite(resolved, paths);
|
|
33446
|
+
return { pathCount: paths.length };
|
|
33447
|
+
});
|
|
33448
|
+
}
|
|
33228
33449
|
|
|
33229
33450
|
// src/files/index/ensure-file-index.ts
|
|
33230
|
-
import
|
|
33231
|
-
async function ensureFileIndexAsync(cwd) {
|
|
33232
|
-
const resolved = path25.resolve(cwd);
|
|
33233
|
-
const cached2 = loadFileIndex(resolved);
|
|
33234
|
-
if (cached2 !== null) return { data: cached2, fromCache: true };
|
|
33235
|
-
const data = await buildFileIndexAsync(resolved);
|
|
33236
|
-
return { data, fromCache: false };
|
|
33237
|
-
}
|
|
33451
|
+
import path29 from "node:path";
|
|
33238
33452
|
|
|
33239
33453
|
// src/files/index/search-file-index.ts
|
|
33240
|
-
function
|
|
33241
|
-
|
|
33242
|
-
|
|
33243
|
-
|
|
33244
|
-
|
|
33245
|
-
const
|
|
33246
|
-
|
|
33247
|
-
|
|
33248
|
-
|
|
33249
|
-
|
|
33250
|
-
|
|
33251
|
-
|
|
33252
|
-
|
|
33253
|
-
|
|
33254
|
-
|
|
33454
|
+
function escapeLikePattern(fragment) {
|
|
33455
|
+
return fragment.replace(/\\/g, "\\\\").replace(/%/g, "\\%").replace(/_/g, "\\_");
|
|
33456
|
+
}
|
|
33457
|
+
function bridgeFileIndexIsPopulated(resolvedCwd) {
|
|
33458
|
+
const db = getCliDatabase();
|
|
33459
|
+
const h = getCwdHashForFileIndex(resolvedCwd);
|
|
33460
|
+
const row = db.get("SELECT 1 as ok FROM file_index_path WHERE cwd_hash = ? LIMIT 1", [h]);
|
|
33461
|
+
return row != null;
|
|
33462
|
+
}
|
|
33463
|
+
function bridgeFileIndexPathCount(resolvedCwd) {
|
|
33464
|
+
const db = getCliDatabase();
|
|
33465
|
+
const h = getCwdHashForFileIndex(resolvedCwd);
|
|
33466
|
+
const row = db.get("SELECT COUNT(*) as c FROM file_index_path WHERE cwd_hash = ?", [h]);
|
|
33467
|
+
const c = row?.c ?? 0;
|
|
33468
|
+
return Number(c);
|
|
33469
|
+
}
|
|
33470
|
+
function searchBridgeFilePaths(resolvedCwd, query, limit = 100) {
|
|
33255
33471
|
const q = query.trim().toLowerCase();
|
|
33256
33472
|
if (!q) return [];
|
|
33257
|
-
const
|
|
33258
|
-
const
|
|
33259
|
-
const
|
|
33260
|
-
|
|
33261
|
-
|
|
33262
|
-
|
|
33263
|
-
|
|
33264
|
-
|
|
33265
|
-
|
|
33266
|
-
|
|
33267
|
-
|
|
33268
|
-
|
|
33269
|
-
|
|
33270
|
-
|
|
33271
|
-
}
|
|
33473
|
+
const db = getCliDatabase();
|
|
33474
|
+
const h = getCwdHashForFileIndex(resolvedCwd);
|
|
33475
|
+
const pattern = `%${escapeLikePattern(q)}%`;
|
|
33476
|
+
const lim = Math.max(0, Math.min(1e4, Math.floor(limit)));
|
|
33477
|
+
const rows = db.all(
|
|
33478
|
+
`SELECT path FROM file_index_path WHERE cwd_hash = ? AND lower(path) LIKE ? ESCAPE '\\' LIMIT ?`,
|
|
33479
|
+
[h, pattern, lim]
|
|
33480
|
+
);
|
|
33481
|
+
return rows.map((r) => String(r.path));
|
|
33482
|
+
}
|
|
33483
|
+
async function searchBridgeFilePathsAsync(resolvedCwd, query, limit = 100) {
|
|
33484
|
+
await yieldToEventLoop();
|
|
33485
|
+
const out = searchBridgeFilePaths(resolvedCwd, query, limit);
|
|
33486
|
+
if (out.length >= INDEX_WORK_YIELD_EVERY) await yieldToEventLoop();
|
|
33272
33487
|
return out;
|
|
33273
33488
|
}
|
|
33274
33489
|
|
|
33490
|
+
// src/files/index/ensure-file-index.ts
|
|
33491
|
+
async function ensureFileIndexAsync(cwd) {
|
|
33492
|
+
const resolved = path29.resolve(cwd);
|
|
33493
|
+
if (bridgeFileIndexIsPopulated(resolved)) {
|
|
33494
|
+
return { fromCache: true, pathCount: bridgeFileIndexPathCount(resolved) };
|
|
33495
|
+
}
|
|
33496
|
+
return { ...await buildFileIndexAsync(resolved), fromCache: false };
|
|
33497
|
+
}
|
|
33498
|
+
|
|
33275
33499
|
// src/files/watch-file-index.ts
|
|
33276
33500
|
var DEBOUNCE_MS = 900;
|
|
33277
33501
|
function shouldIgnoreRelative(rel) {
|
|
@@ -33312,7 +33536,7 @@ function createFsWatcher(resolved, schedule) {
|
|
|
33312
33536
|
}
|
|
33313
33537
|
}
|
|
33314
33538
|
function startFileIndexWatcher(cwd = getBridgeRoot()) {
|
|
33315
|
-
const resolved =
|
|
33539
|
+
const resolved = path30.resolve(cwd);
|
|
33316
33540
|
void buildFileIndexAsync(resolved).catch((e) => {
|
|
33317
33541
|
console.error("[file-index] Initial index build failed:", e);
|
|
33318
33542
|
});
|
|
@@ -33340,7 +33564,7 @@ function startFileIndexWatcher(cwd = getBridgeRoot()) {
|
|
|
33340
33564
|
}
|
|
33341
33565
|
|
|
33342
33566
|
// src/connection/create-bridge-connection.ts
|
|
33343
|
-
import * as
|
|
33567
|
+
import * as path38 from "node:path";
|
|
33344
33568
|
|
|
33345
33569
|
// src/dev-servers/manager/dev-server-manager.ts
|
|
33346
33570
|
import { rm as rm2 } from "node:fs/promises";
|
|
@@ -33384,7 +33608,7 @@ function forceKillChild(proc, log2, shortId, graceMs) {
|
|
|
33384
33608
|
}
|
|
33385
33609
|
|
|
33386
33610
|
// src/dev-servers/process/wire-dev-server-child-process.ts
|
|
33387
|
-
import
|
|
33611
|
+
import fs26 from "node:fs";
|
|
33388
33612
|
|
|
33389
33613
|
// src/dev-servers/manager/forward-pipe.ts
|
|
33390
33614
|
function forwardChildPipe(childReadable, terminal, onData) {
|
|
@@ -33420,7 +33644,7 @@ function wireDevServerChildProcess(d) {
|
|
|
33420
33644
|
d.setPollInterval(void 0);
|
|
33421
33645
|
return;
|
|
33422
33646
|
}
|
|
33423
|
-
|
|
33647
|
+
fs26.readFile(d.mergedLogPath, (err, buf) => {
|
|
33424
33648
|
if (err || (d.getSpawnGeneration() ?? 0) !== d.scheduledGen) return;
|
|
33425
33649
|
if (buf.length <= d.mergedReadPos.value) return;
|
|
33426
33650
|
const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
|
|
@@ -33458,7 +33682,7 @@ ${errTail}` : ""}`);
|
|
|
33458
33682
|
d.sendStatus(code === 0 || code == null ? "stopped" : "error", detail, tails);
|
|
33459
33683
|
};
|
|
33460
33684
|
if (mergedPath) {
|
|
33461
|
-
|
|
33685
|
+
fs26.readFile(mergedPath, (err, buf) => {
|
|
33462
33686
|
if (!err && buf.length > d.mergedReadPos.value) {
|
|
33463
33687
|
const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
|
|
33464
33688
|
if (chunk.length > 0) {
|
|
@@ -33560,13 +33784,13 @@ function parseDevServerDefs(servers) {
|
|
|
33560
33784
|
}
|
|
33561
33785
|
|
|
33562
33786
|
// src/dev-servers/manager/shell-spawn/utils.ts
|
|
33563
|
-
import
|
|
33787
|
+
import fs27 from "node:fs";
|
|
33564
33788
|
function isSpawnEbadf(e) {
|
|
33565
33789
|
return typeof e === "object" && e !== null && "code" in e && e.code === "EBADF";
|
|
33566
33790
|
}
|
|
33567
33791
|
function rmDirQuiet(dir) {
|
|
33568
33792
|
try {
|
|
33569
|
-
|
|
33793
|
+
fs27.rmSync(dir, { recursive: true, force: true });
|
|
33570
33794
|
} catch {
|
|
33571
33795
|
}
|
|
33572
33796
|
}
|
|
@@ -33574,7 +33798,7 @@ var cachedDevNullReadFd;
|
|
|
33574
33798
|
function devNullReadFd() {
|
|
33575
33799
|
if (cachedDevNullReadFd === void 0) {
|
|
33576
33800
|
const devPath = process.platform === "win32" ? "nul" : "/dev/null";
|
|
33577
|
-
cachedDevNullReadFd =
|
|
33801
|
+
cachedDevNullReadFd = fs27.openSync(devPath, "r");
|
|
33578
33802
|
}
|
|
33579
33803
|
return cachedDevNullReadFd;
|
|
33580
33804
|
}
|
|
@@ -33648,15 +33872,15 @@ function trySpawnShellTruePiped(command, env, cwd, devNullFd, signal) {
|
|
|
33648
33872
|
|
|
33649
33873
|
// src/dev-servers/manager/shell-spawn/try-spawn-merged-log-file.ts
|
|
33650
33874
|
import { spawn as spawn7 } from "node:child_process";
|
|
33651
|
-
import
|
|
33875
|
+
import fs28 from "node:fs";
|
|
33652
33876
|
import { tmpdir } from "node:os";
|
|
33653
|
-
import
|
|
33877
|
+
import path31 from "node:path";
|
|
33654
33878
|
function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
33655
|
-
const tmpRoot =
|
|
33656
|
-
const logPath =
|
|
33879
|
+
const tmpRoot = fs28.mkdtempSync(path31.join(tmpdir(), "ba-devsrv-log-"));
|
|
33880
|
+
const logPath = path31.join(tmpRoot, "combined.log");
|
|
33657
33881
|
let logFd;
|
|
33658
33882
|
try {
|
|
33659
|
-
logFd =
|
|
33883
|
+
logFd = fs28.openSync(logPath, "a");
|
|
33660
33884
|
} catch {
|
|
33661
33885
|
rmDirQuiet(tmpRoot);
|
|
33662
33886
|
return null;
|
|
@@ -33675,7 +33899,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
33675
33899
|
} else {
|
|
33676
33900
|
proc = spawn7("/bin/sh", ["-c", command], { env, cwd, stdio, ...signal ? { signal } : {} });
|
|
33677
33901
|
}
|
|
33678
|
-
|
|
33902
|
+
fs28.closeSync(logFd);
|
|
33679
33903
|
return {
|
|
33680
33904
|
proc,
|
|
33681
33905
|
pipedStdoutStderr: true,
|
|
@@ -33684,7 +33908,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
33684
33908
|
};
|
|
33685
33909
|
} catch (e) {
|
|
33686
33910
|
try {
|
|
33687
|
-
|
|
33911
|
+
fs28.closeSync(logFd);
|
|
33688
33912
|
} catch {
|
|
33689
33913
|
}
|
|
33690
33914
|
rmDirQuiet(tmpRoot);
|
|
@@ -33695,22 +33919,22 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
33695
33919
|
|
|
33696
33920
|
// src/dev-servers/manager/shell-spawn/try-spawn-shell-script-log-redirect.ts
|
|
33697
33921
|
import { spawn as spawn8 } from "node:child_process";
|
|
33698
|
-
import
|
|
33922
|
+
import fs29 from "node:fs";
|
|
33699
33923
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
33700
|
-
import
|
|
33924
|
+
import path32 from "node:path";
|
|
33701
33925
|
function shSingleQuote(s) {
|
|
33702
33926
|
return `'${s.replace(/'/g, `'\\''`)}'`;
|
|
33703
33927
|
}
|
|
33704
33928
|
function trySpawnShellScriptLogRedirectUnix(command, env, cwd, signal) {
|
|
33705
|
-
const tmpRoot =
|
|
33706
|
-
const logPath =
|
|
33707
|
-
const innerPath =
|
|
33708
|
-
const runnerPath =
|
|
33929
|
+
const tmpRoot = fs29.mkdtempSync(path32.join(tmpdir2(), "ba-devsrv-sh-"));
|
|
33930
|
+
const logPath = path32.join(tmpRoot, "combined.log");
|
|
33931
|
+
const innerPath = path32.join(tmpRoot, "_cmd.sh");
|
|
33932
|
+
const runnerPath = path32.join(tmpRoot, "_run.sh");
|
|
33709
33933
|
try {
|
|
33710
|
-
|
|
33934
|
+
fs29.writeFileSync(innerPath, `#!/bin/sh
|
|
33711
33935
|
${command}
|
|
33712
33936
|
`);
|
|
33713
|
-
|
|
33937
|
+
fs29.writeFileSync(
|
|
33714
33938
|
runnerPath,
|
|
33715
33939
|
`#!/bin/sh
|
|
33716
33940
|
cd ${shSingleQuote(cwd)}
|
|
@@ -33736,13 +33960,13 @@ cd ${shSingleQuote(cwd)}
|
|
|
33736
33960
|
}
|
|
33737
33961
|
}
|
|
33738
33962
|
function trySpawnShellScriptLogRedirectWin(command, env, cwd, signal) {
|
|
33739
|
-
const tmpRoot =
|
|
33740
|
-
const logPath =
|
|
33741
|
-
const runnerPath =
|
|
33963
|
+
const tmpRoot = fs29.mkdtempSync(path32.join(tmpdir2(), "ba-devsrv-sh-"));
|
|
33964
|
+
const logPath = path32.join(tmpRoot, "combined.log");
|
|
33965
|
+
const runnerPath = path32.join(tmpRoot, "_run.bat");
|
|
33742
33966
|
const q = (p) => `"${p.replace(/"/g, '""')}"`;
|
|
33743
33967
|
const com = process.env.ComSpec || "cmd.exe";
|
|
33744
33968
|
try {
|
|
33745
|
-
|
|
33969
|
+
fs29.writeFileSync(
|
|
33746
33970
|
runnerPath,
|
|
33747
33971
|
`@ECHO OFF\r
|
|
33748
33972
|
CD /D ${q(cwd)}\r
|
|
@@ -34511,30 +34735,30 @@ function createOnBridgeIdentified(opts) {
|
|
|
34511
34735
|
}
|
|
34512
34736
|
|
|
34513
34737
|
// src/skills/discover-local-agent-skills.ts
|
|
34514
|
-
import
|
|
34515
|
-
import
|
|
34738
|
+
import fs30 from "node:fs";
|
|
34739
|
+
import path33 from "node:path";
|
|
34516
34740
|
var SKILL_DISCOVERY_ROOTS = [".agents/skills", ".claude/skills", ".cursor/skills", "skills"];
|
|
34517
34741
|
function discoverLocalSkills(cwd) {
|
|
34518
34742
|
const out = [];
|
|
34519
34743
|
const seenKeys = /* @__PURE__ */ new Set();
|
|
34520
34744
|
for (const rel of SKILL_DISCOVERY_ROOTS) {
|
|
34521
|
-
const base =
|
|
34522
|
-
if (!
|
|
34745
|
+
const base = path33.join(cwd, rel);
|
|
34746
|
+
if (!fs30.existsSync(base) || !fs30.statSync(base).isDirectory()) continue;
|
|
34523
34747
|
let entries = [];
|
|
34524
34748
|
try {
|
|
34525
|
-
entries =
|
|
34749
|
+
entries = fs30.readdirSync(base);
|
|
34526
34750
|
} catch {
|
|
34527
34751
|
continue;
|
|
34528
34752
|
}
|
|
34529
34753
|
for (const name of entries) {
|
|
34530
|
-
const dir =
|
|
34754
|
+
const dir = path33.join(base, name);
|
|
34531
34755
|
try {
|
|
34532
|
-
if (!
|
|
34756
|
+
if (!fs30.statSync(dir).isDirectory()) continue;
|
|
34533
34757
|
} catch {
|
|
34534
34758
|
continue;
|
|
34535
34759
|
}
|
|
34536
|
-
const skillMd =
|
|
34537
|
-
if (!
|
|
34760
|
+
const skillMd = path33.join(dir, "SKILL.md");
|
|
34761
|
+
if (!fs30.existsSync(skillMd)) continue;
|
|
34538
34762
|
const key = `${rel}/${name}`;
|
|
34539
34763
|
if (seenKeys.has(key)) continue;
|
|
34540
34764
|
seenKeys.add(key);
|
|
@@ -34546,23 +34770,23 @@ function discoverLocalSkills(cwd) {
|
|
|
34546
34770
|
function discoverSkillLayoutRoots(cwd) {
|
|
34547
34771
|
const roots = [];
|
|
34548
34772
|
for (const rel of SKILL_DISCOVERY_ROOTS) {
|
|
34549
|
-
const base =
|
|
34550
|
-
if (!
|
|
34773
|
+
const base = path33.join(cwd, rel);
|
|
34774
|
+
if (!fs30.existsSync(base) || !fs30.statSync(base).isDirectory()) continue;
|
|
34551
34775
|
let entries = [];
|
|
34552
34776
|
try {
|
|
34553
|
-
entries =
|
|
34777
|
+
entries = fs30.readdirSync(base);
|
|
34554
34778
|
} catch {
|
|
34555
34779
|
continue;
|
|
34556
34780
|
}
|
|
34557
34781
|
const skills2 = [];
|
|
34558
34782
|
for (const name of entries) {
|
|
34559
|
-
const dir =
|
|
34783
|
+
const dir = path33.join(base, name);
|
|
34560
34784
|
try {
|
|
34561
|
-
if (!
|
|
34785
|
+
if (!fs30.statSync(dir).isDirectory()) continue;
|
|
34562
34786
|
} catch {
|
|
34563
34787
|
continue;
|
|
34564
34788
|
}
|
|
34565
|
-
if (!
|
|
34789
|
+
if (!fs30.existsSync(path33.join(dir, "SKILL.md"))) continue;
|
|
34566
34790
|
const relPath = `${rel}/${name}`.replace(/\\/g, "/");
|
|
34567
34791
|
skills2.push({ name, relPath });
|
|
34568
34792
|
}
|
|
@@ -34756,7 +34980,7 @@ var handleAgentConfigMessage = (msg, deps) => {
|
|
|
34756
34980
|
};
|
|
34757
34981
|
|
|
34758
34982
|
// src/prompt-turn-queue/runner.ts
|
|
34759
|
-
import
|
|
34983
|
+
import fs31 from "node:fs";
|
|
34760
34984
|
|
|
34761
34985
|
// src/prompt-turn-queue/client-report.ts
|
|
34762
34986
|
function sendPromptQueueClientReport(ws, queues) {
|
|
@@ -34765,32 +34989,6 @@ function sendPromptQueueClientReport(ws, queues) {
|
|
|
34765
34989
|
return true;
|
|
34766
34990
|
}
|
|
34767
34991
|
|
|
34768
|
-
// src/prompt-turn-queue/disk-store.ts
|
|
34769
|
-
import fs28 from "node:fs";
|
|
34770
|
-
|
|
34771
|
-
// src/prompt-turn-queue/paths.ts
|
|
34772
|
-
import crypto3 from "node:crypto";
|
|
34773
|
-
import fs27 from "node:fs";
|
|
34774
|
-
import path30 from "node:path";
|
|
34775
|
-
import os7 from "node:os";
|
|
34776
|
-
var QUEUE_KEY_HEX_64 = /^[a-f0-9]{64}$/i;
|
|
34777
|
-
function queueStateFileSlug(queueKey) {
|
|
34778
|
-
if (QUEUE_KEY_HEX_64.test(queueKey)) return queueKey.toLowerCase();
|
|
34779
|
-
return crypto3.createHash("sha256").update(queueKey, "utf8").digest("hex");
|
|
34780
|
-
}
|
|
34781
|
-
function getPromptQueuesDirectory() {
|
|
34782
|
-
const override = process.env.BUILDAMATON_PROMPT_QUEUES_DIR?.trim();
|
|
34783
|
-
if (override) return path30.resolve(override);
|
|
34784
|
-
return path30.join(os7.homedir(), ".buildautomaton", "queues");
|
|
34785
|
-
}
|
|
34786
|
-
function ensurePromptQueuesDirectory() {
|
|
34787
|
-
const dir = getPromptQueuesDirectory();
|
|
34788
|
-
if (!fs27.existsSync(dir)) fs27.mkdirSync(dir, { recursive: true });
|
|
34789
|
-
}
|
|
34790
|
-
function queueStateFilePath(queueKey) {
|
|
34791
|
-
return path30.join(getPromptQueuesDirectory(), `${queueStateFileSlug(queueKey)}.json`);
|
|
34792
|
-
}
|
|
34793
|
-
|
|
34794
34992
|
// src/prompt-turn-queue/disk-store.ts
|
|
34795
34993
|
var MERGEABLE_SERVER_STATES = /* @__PURE__ */ new Set([
|
|
34796
34994
|
"queued",
|
|
@@ -34800,28 +34998,27 @@ var MERGEABLE_SERVER_STATES = /* @__PURE__ */ new Set([
|
|
|
34800
34998
|
"stopping",
|
|
34801
34999
|
"discarded"
|
|
34802
35000
|
]);
|
|
34803
|
-
function parsePersistedQueueFile(raw) {
|
|
34804
|
-
try {
|
|
34805
|
-
const o = JSON.parse(raw);
|
|
34806
|
-
const queueKey = typeof o.queueKey === "string" ? o.queueKey : typeof o.queueKeyHash === "string" ? o.queueKeyHash : null;
|
|
34807
|
-
if (!queueKey || typeof o.updatedAt !== "string" || !Array.isArray(o.turns)) return null;
|
|
34808
|
-
return { queueKey, updatedAt: o.updatedAt, turns: o.turns };
|
|
34809
|
-
} catch {
|
|
34810
|
-
return null;
|
|
34811
|
-
}
|
|
34812
|
-
}
|
|
34813
35001
|
function readPersistedQueue(queueKey) {
|
|
34814
|
-
const
|
|
35002
|
+
const db = getCliDatabase();
|
|
35003
|
+
const row = db.get("SELECT queue_key, updated_at, turns_json FROM prompt_queue WHERE queue_key = ?", [
|
|
35004
|
+
queueKey
|
|
35005
|
+
]);
|
|
35006
|
+
if (!row) return null;
|
|
34815
35007
|
try {
|
|
34816
|
-
|
|
35008
|
+
const turns = JSON.parse(row.turns_json);
|
|
35009
|
+
if (!Array.isArray(turns)) return null;
|
|
35010
|
+
return { queueKey: row.queue_key, updatedAt: row.updated_at, turns };
|
|
34817
35011
|
} catch {
|
|
34818
35012
|
return null;
|
|
34819
35013
|
}
|
|
34820
35014
|
}
|
|
34821
35015
|
function writePersistedQueue(file2) {
|
|
34822
|
-
|
|
34823
|
-
|
|
34824
|
-
|
|
35016
|
+
const db = getCliDatabase();
|
|
35017
|
+
db.run(
|
|
35018
|
+
`INSERT INTO prompt_queue (queue_key, updated_at, turns_json) VALUES (?, ?, ?)
|
|
35019
|
+
ON CONFLICT(queue_key) DO UPDATE SET updated_at = excluded.updated_at, turns_json = excluded.turns_json`,
|
|
35020
|
+
[file2.queueKey, file2.updatedAt, JSON.stringify(file2.turns)]
|
|
35021
|
+
);
|
|
34825
35022
|
}
|
|
34826
35023
|
function mergeServerQueueSnapshot(queueKey, serverTurns) {
|
|
34827
35024
|
const prev = readPersistedQueue(queueKey);
|
|
@@ -34879,7 +35076,7 @@ async function runLocalRevertBeforeQueuedPrompt(next, deps) {
|
|
|
34879
35076
|
const tid = typeof pl.snapshotRevertTurnId === "string" && pl.snapshotRevertTurnId.trim() !== "" ? pl.snapshotRevertTurnId.trim() : next.turnId;
|
|
34880
35077
|
const agentBase = deps.sessionWorktreeManager.getSessionWorktreeRootForSession(sid) ?? getBridgeRoot();
|
|
34881
35078
|
const file2 = snapshotFilePath(agentBase, tid);
|
|
34882
|
-
if (!
|
|
35079
|
+
if (!fs31.existsSync(file2)) {
|
|
34883
35080
|
deps.log(
|
|
34884
35081
|
`[Queue] requeued_with_revert: no pre-turn snapshot for ${tid.slice(0, 8)}\u2026; continuing without revert.`
|
|
34885
35082
|
);
|
|
@@ -35103,9 +35300,9 @@ function parseChangeSummarySnapshots(raw) {
|
|
|
35103
35300
|
for (const item of raw) {
|
|
35104
35301
|
if (!item || typeof item !== "object") continue;
|
|
35105
35302
|
const o = item;
|
|
35106
|
-
const
|
|
35107
|
-
if (!
|
|
35108
|
-
const row = { path:
|
|
35303
|
+
const path39 = typeof o.path === "string" && o.path.trim() !== "" ? o.path.trim() : "";
|
|
35304
|
+
if (!path39) continue;
|
|
35305
|
+
const row = { path: path39 };
|
|
35109
35306
|
if (typeof o.patchContent === "string") row.patchContent = o.patchContent;
|
|
35110
35307
|
if (typeof o.oldText === "string") row.oldText = o.oldText;
|
|
35111
35308
|
if (typeof o.newText === "string") row.newText = o.newText;
|
|
@@ -35326,15 +35523,15 @@ var handleSkillCallMessage = (msg, { getWs, log: log2 }) => {
|
|
|
35326
35523
|
};
|
|
35327
35524
|
|
|
35328
35525
|
// src/files/list-dir.ts
|
|
35329
|
-
import
|
|
35330
|
-
import
|
|
35526
|
+
import fs32 from "node:fs";
|
|
35527
|
+
import path35 from "node:path";
|
|
35331
35528
|
|
|
35332
35529
|
// src/files/ensure-under-cwd.ts
|
|
35333
|
-
import
|
|
35530
|
+
import path34 from "node:path";
|
|
35334
35531
|
function ensureUnderCwd(relativePath, cwd = getBridgeRoot()) {
|
|
35335
|
-
const normalized =
|
|
35336
|
-
const resolved =
|
|
35337
|
-
if (!resolved.startsWith(cwd +
|
|
35532
|
+
const normalized = path34.normalize(relativePath).replace(/^(\.\/)+/, "");
|
|
35533
|
+
const resolved = path34.resolve(cwd, normalized);
|
|
35534
|
+
if (!resolved.startsWith(cwd + path34.sep) && resolved !== cwd) {
|
|
35338
35535
|
return null;
|
|
35339
35536
|
}
|
|
35340
35537
|
return resolved;
|
|
@@ -35348,7 +35545,7 @@ async function listDirAsync(relativePath) {
|
|
|
35348
35545
|
return { error: "Path is outside working directory" };
|
|
35349
35546
|
}
|
|
35350
35547
|
try {
|
|
35351
|
-
const names = await
|
|
35548
|
+
const names = await fs32.promises.readdir(resolved, { withFileTypes: true });
|
|
35352
35549
|
const visible = names.filter((d) => !d.name.startsWith("."));
|
|
35353
35550
|
const entries = [];
|
|
35354
35551
|
for (let i = 0; i < visible.length; i++) {
|
|
@@ -35356,12 +35553,12 @@ async function listDirAsync(relativePath) {
|
|
|
35356
35553
|
await yieldToEventLoop();
|
|
35357
35554
|
}
|
|
35358
35555
|
const d = visible[i];
|
|
35359
|
-
const entryPath =
|
|
35360
|
-
const fullPath =
|
|
35556
|
+
const entryPath = path35.join(relativePath || ".", d.name).replace(/\\/g, "/");
|
|
35557
|
+
const fullPath = path35.join(resolved, d.name);
|
|
35361
35558
|
let isDir = d.isDirectory();
|
|
35362
35559
|
if (d.isSymbolicLink()) {
|
|
35363
35560
|
try {
|
|
35364
|
-
const targetStat = await
|
|
35561
|
+
const targetStat = await fs32.promises.stat(fullPath);
|
|
35365
35562
|
isDir = targetStat.isDirectory();
|
|
35366
35563
|
} catch {
|
|
35367
35564
|
isDir = false;
|
|
@@ -35386,25 +35583,25 @@ async function listDirAsync(relativePath) {
|
|
|
35386
35583
|
}
|
|
35387
35584
|
|
|
35388
35585
|
// src/files/read-file.ts
|
|
35389
|
-
import
|
|
35586
|
+
import fs33 from "node:fs";
|
|
35390
35587
|
import { StringDecoder } from "node:string_decoder";
|
|
35391
35588
|
function resolveFilePath(relativePath) {
|
|
35392
35589
|
const resolved = ensureUnderCwd(relativePath, getBridgeRoot());
|
|
35393
35590
|
if (!resolved) return { error: "Path is outside working directory" };
|
|
35394
35591
|
let real;
|
|
35395
35592
|
try {
|
|
35396
|
-
real =
|
|
35593
|
+
real = fs33.realpathSync(resolved);
|
|
35397
35594
|
} catch {
|
|
35398
35595
|
real = resolved;
|
|
35399
35596
|
}
|
|
35400
|
-
const stat2 =
|
|
35597
|
+
const stat2 = fs33.statSync(real);
|
|
35401
35598
|
if (!stat2.isFile()) return { error: "Not a file" };
|
|
35402
35599
|
return real;
|
|
35403
35600
|
}
|
|
35404
35601
|
var LINE_CHUNK_SIZE = 64 * 1024;
|
|
35405
35602
|
function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize = LINE_CHUNK_SIZE) {
|
|
35406
|
-
const fileSize =
|
|
35407
|
-
const fd =
|
|
35603
|
+
const fileSize = fs33.statSync(filePath).size;
|
|
35604
|
+
const fd = fs33.openSync(filePath, "r");
|
|
35408
35605
|
const bufSize = 64 * 1024;
|
|
35409
35606
|
const buf = Buffer.alloc(bufSize);
|
|
35410
35607
|
const decoder = new StringDecoder("utf8");
|
|
@@ -35417,7 +35614,7 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
|
|
|
35417
35614
|
let line0Accum = "";
|
|
35418
35615
|
try {
|
|
35419
35616
|
let bytesRead;
|
|
35420
|
-
while (!done && (bytesRead =
|
|
35617
|
+
while (!done && (bytesRead = fs33.readSync(fd, buf, 0, bufSize, null)) > 0) {
|
|
35421
35618
|
const text = partial2 + decoder.write(buf.subarray(0, bytesRead));
|
|
35422
35619
|
partial2 = "";
|
|
35423
35620
|
let lineStart = 0;
|
|
@@ -35552,7 +35749,7 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
|
|
|
35552
35749
|
}
|
|
35553
35750
|
return { content: resultLines.join("\n"), size: fileSize };
|
|
35554
35751
|
} finally {
|
|
35555
|
-
|
|
35752
|
+
fs33.closeSync(fd);
|
|
35556
35753
|
}
|
|
35557
35754
|
}
|
|
35558
35755
|
function readFile2(relativePath, startLine, endLine, lineOffset, lineChunkSize = LINE_CHUNK_SIZE) {
|
|
@@ -35563,8 +35760,8 @@ function readFile2(relativePath, startLine, endLine, lineOffset, lineChunkSize =
|
|
|
35563
35760
|
if (hasRange) {
|
|
35564
35761
|
return readFileRange(result, startLine, endLine, lineOffset, lineChunkSize);
|
|
35565
35762
|
}
|
|
35566
|
-
const stat2 =
|
|
35567
|
-
const raw =
|
|
35763
|
+
const stat2 = fs33.statSync(result);
|
|
35764
|
+
const raw = fs33.readFileSync(result, "utf8");
|
|
35568
35765
|
const lines = raw.split(/\r?\n/);
|
|
35569
35766
|
return { content: raw, totalLines: lines.length, size: stat2.size };
|
|
35570
35767
|
} catch (err) {
|
|
@@ -35577,14 +35774,14 @@ async function readFileAsync(relativePath, startLine, endLine, lineOffset, lineC
|
|
|
35577
35774
|
}
|
|
35578
35775
|
|
|
35579
35776
|
// src/files/handle-file-browser-search.ts
|
|
35777
|
+
import path36 from "node:path";
|
|
35580
35778
|
var SEARCH_LIMIT = 100;
|
|
35581
35779
|
function handleFileBrowserSearch(msg, socket, e2ee) {
|
|
35582
35780
|
void (async () => {
|
|
35583
35781
|
await yieldToEventLoop();
|
|
35584
35782
|
const q = typeof msg.q === "string" ? msg.q : "";
|
|
35585
|
-
const cwd = getBridgeRoot();
|
|
35586
|
-
|
|
35587
|
-
if (index === null) {
|
|
35783
|
+
const cwd = path36.resolve(getBridgeRoot());
|
|
35784
|
+
if (!bridgeFileIndexIsPopulated(cwd)) {
|
|
35588
35785
|
const payload2 = {
|
|
35589
35786
|
type: "file_browser_search_response",
|
|
35590
35787
|
id: msg.id,
|
|
@@ -35594,7 +35791,7 @@ function handleFileBrowserSearch(msg, socket, e2ee) {
|
|
|
35594
35791
|
sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload2, ["paths"]) : payload2);
|
|
35595
35792
|
return;
|
|
35596
35793
|
}
|
|
35597
|
-
const results = await
|
|
35794
|
+
const results = await searchBridgeFilePathsAsync(cwd, q, SEARCH_LIMIT);
|
|
35598
35795
|
const payload = {
|
|
35599
35796
|
type: "file_browser_search_response",
|
|
35600
35797
|
id: msg.id,
|
|
@@ -35682,8 +35879,8 @@ function handleSkillLayoutRequest(msg, deps) {
|
|
|
35682
35879
|
}
|
|
35683
35880
|
|
|
35684
35881
|
// src/skills/install-remote-skills.ts
|
|
35685
|
-
import
|
|
35686
|
-
import
|
|
35882
|
+
import fs34 from "node:fs";
|
|
35883
|
+
import path37 from "node:path";
|
|
35687
35884
|
function installRemoteSkills(cwd, targetDir, items) {
|
|
35688
35885
|
const installed2 = [];
|
|
35689
35886
|
if (!Array.isArray(items)) {
|
|
@@ -35694,15 +35891,15 @@ function installRemoteSkills(cwd, targetDir, items) {
|
|
|
35694
35891
|
if (typeof item.sourceId !== "string" || typeof item.skillName !== "string" || typeof item.versionHash !== "string" || !Array.isArray(item.files)) {
|
|
35695
35892
|
continue;
|
|
35696
35893
|
}
|
|
35697
|
-
const skillDir =
|
|
35894
|
+
const skillDir = path37.join(cwd, targetDir, item.skillName);
|
|
35698
35895
|
for (const f of item.files) {
|
|
35699
35896
|
if (typeof f.path !== "string" || !f.text && !f.base64) continue;
|
|
35700
|
-
const dest =
|
|
35701
|
-
|
|
35897
|
+
const dest = path37.join(skillDir, f.path);
|
|
35898
|
+
fs34.mkdirSync(path37.dirname(dest), { recursive: true });
|
|
35702
35899
|
if (f.text !== void 0) {
|
|
35703
|
-
|
|
35900
|
+
fs34.writeFileSync(dest, f.text, "utf8");
|
|
35704
35901
|
} else if (f.base64) {
|
|
35705
|
-
|
|
35902
|
+
fs34.writeFileSync(dest, Buffer.from(f.base64, "base64"));
|
|
35706
35903
|
}
|
|
35707
35904
|
}
|
|
35708
35905
|
installed2.push({
|
|
@@ -35852,7 +36049,7 @@ var handleSessionDiscardedMessage = (msg, deps) => {
|
|
|
35852
36049
|
};
|
|
35853
36050
|
|
|
35854
36051
|
// src/routing/handlers/revert-turn-snapshot.ts
|
|
35855
|
-
import * as
|
|
36052
|
+
import * as fs35 from "node:fs";
|
|
35856
36053
|
var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
35857
36054
|
const id = typeof msg.id === "string" ? msg.id : "";
|
|
35858
36055
|
const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
|
|
@@ -35864,7 +36061,7 @@ var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
|
35864
36061
|
if (!s) return;
|
|
35865
36062
|
const agentBase = sessionWorktreeManager.getSessionWorktreeRootForSession(sessionId) ?? getBridgeRoot();
|
|
35866
36063
|
const file2 = snapshotFilePath(agentBase, turnId);
|
|
35867
|
-
if (!
|
|
36064
|
+
if (!fs35.existsSync(file2)) {
|
|
35868
36065
|
sendWsMessage(s, {
|
|
35869
36066
|
type: "revert_turn_snapshot_result",
|
|
35870
36067
|
id,
|
|
@@ -36359,6 +36556,7 @@ async function createBridgeConnection(options) {
|
|
|
36359
36556
|
const { apiUrl, workspaceId, justAuthenticated, onAuthInvalid, persistTokens } = options;
|
|
36360
36557
|
const firehoseServerUrl = options.firehoseServerUrl ?? options.proxyServerUrl;
|
|
36361
36558
|
const logFn = options.log ?? log;
|
|
36559
|
+
getCliDatabase({ logLegacyMigration: logFn });
|
|
36362
36560
|
const tokens = {
|
|
36363
36561
|
accessToken: options.authToken,
|
|
36364
36562
|
refreshToken: options.refreshToken
|
|
@@ -36424,8 +36622,8 @@ async function createBridgeConnection(options) {
|
|
|
36424
36622
|
getCloudAccessToken: () => tokens.accessToken
|
|
36425
36623
|
};
|
|
36426
36624
|
const identifyReportedPaths = {
|
|
36427
|
-
bridgeRootPath:
|
|
36428
|
-
worktreesRootPath:
|
|
36625
|
+
bridgeRootPath: path38.resolve(getBridgeRoot()),
|
|
36626
|
+
worktreesRootPath: path38.resolve(worktreesRootPath)
|
|
36429
36627
|
};
|
|
36430
36628
|
const { connect } = createMainBridgeWebSocketLifecycle({
|
|
36431
36629
|
state,
|