@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 CHANGED
@@ -973,8 +973,8 @@ var require_command = __commonJS({
973
973
  "../../node_modules/.pnpm/commander@12.1.0/node_modules/commander/lib/command.js"(exports) {
974
974
  var EventEmitter2 = __require("node:events").EventEmitter;
975
975
  var childProcess2 = __require("node:child_process");
976
- var path37 = __require("node:path");
977
- var fs36 = __require("node:fs");
976
+ var path41 = __require("node:path");
977
+ var fs38 = __require("node:fs");
978
978
  var process8 = __require("node:process");
979
979
  var { Argument: Argument2, humanReadableArgName } = require_argument();
980
980
  var { CommanderError: CommanderError2 } = require_error();
@@ -1906,11 +1906,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
1906
1906
  let launchWithNode = false;
1907
1907
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
1908
1908
  function findFile(baseDir, baseName) {
1909
- const localBin = path37.resolve(baseDir, baseName);
1910
- if (fs36.existsSync(localBin)) return localBin;
1911
- if (sourceExt.includes(path37.extname(baseName))) return void 0;
1909
+ const localBin = path41.resolve(baseDir, baseName);
1910
+ if (fs38.existsSync(localBin)) return localBin;
1911
+ if (sourceExt.includes(path41.extname(baseName))) return void 0;
1912
1912
  const foundExt = sourceExt.find(
1913
- (ext) => fs36.existsSync(`${localBin}${ext}`)
1913
+ (ext) => fs38.existsSync(`${localBin}${ext}`)
1914
1914
  );
1915
1915
  if (foundExt) return `${localBin}${foundExt}`;
1916
1916
  return void 0;
@@ -1922,21 +1922,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
1922
1922
  if (this._scriptPath) {
1923
1923
  let resolvedScriptPath;
1924
1924
  try {
1925
- resolvedScriptPath = fs36.realpathSync(this._scriptPath);
1925
+ resolvedScriptPath = fs38.realpathSync(this._scriptPath);
1926
1926
  } catch (err) {
1927
1927
  resolvedScriptPath = this._scriptPath;
1928
1928
  }
1929
- executableDir = path37.resolve(
1930
- path37.dirname(resolvedScriptPath),
1929
+ executableDir = path41.resolve(
1930
+ path41.dirname(resolvedScriptPath),
1931
1931
  executableDir
1932
1932
  );
1933
1933
  }
1934
1934
  if (executableDir) {
1935
1935
  let localFile = findFile(executableDir, executableFile);
1936
1936
  if (!localFile && !subcommand._executableFile && this._scriptPath) {
1937
- const legacyName = path37.basename(
1937
+ const legacyName = path41.basename(
1938
1938
  this._scriptPath,
1939
- path37.extname(this._scriptPath)
1939
+ path41.extname(this._scriptPath)
1940
1940
  );
1941
1941
  if (legacyName !== this._name) {
1942
1942
  localFile = findFile(
@@ -1947,7 +1947,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1947
1947
  }
1948
1948
  executableFile = localFile || executableFile;
1949
1949
  }
1950
- launchWithNode = sourceExt.includes(path37.extname(executableFile));
1950
+ launchWithNode = sourceExt.includes(path41.extname(executableFile));
1951
1951
  let proc;
1952
1952
  if (process8.platform !== "win32") {
1953
1953
  if (launchWithNode) {
@@ -2787,7 +2787,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2787
2787
  * @return {Command}
2788
2788
  */
2789
2789
  nameFromFilename(filename) {
2790
- this._name = path37.basename(filename, path37.extname(filename));
2790
+ this._name = path41.basename(filename, path41.extname(filename));
2791
2791
  return this;
2792
2792
  }
2793
2793
  /**
@@ -2801,9 +2801,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
2801
2801
  * @param {string} [path]
2802
2802
  * @return {(string|null|Command)}
2803
2803
  */
2804
- executableDir(path38) {
2805
- if (path38 === void 0) return this._executableDir;
2806
- this._executableDir = path38;
2804
+ executableDir(path42) {
2805
+ if (path42 === void 0) return this._executableDir;
2806
+ this._executableDir = path42;
2807
2807
  return this;
2808
2808
  }
2809
2809
  /**
@@ -7061,8 +7061,8 @@ var init_parseUtil = __esm({
7061
7061
  init_errors();
7062
7062
  init_en();
7063
7063
  makeIssue = (params) => {
7064
- const { data, path: path37, errorMaps, issueData } = params;
7065
- const fullPath = [...path37, ...issueData.path || []];
7064
+ const { data, path: path41, errorMaps, issueData } = params;
7065
+ const fullPath = [...path41, ...issueData.path || []];
7066
7066
  const fullIssue = {
7067
7067
  ...issueData,
7068
7068
  path: fullPath
@@ -7370,11 +7370,11 @@ var init_types = __esm({
7370
7370
  init_parseUtil();
7371
7371
  init_util();
7372
7372
  ParseInputLazyPath = class {
7373
- constructor(parent, value, path37, key) {
7373
+ constructor(parent, value, path41, key) {
7374
7374
  this._cachedPath = [];
7375
7375
  this.parent = parent;
7376
7376
  this.data = value;
7377
- this._path = path37;
7377
+ this._path = path41;
7378
7378
  this._key = key;
7379
7379
  }
7380
7380
  get path() {
@@ -11235,7 +11235,7 @@ var require_has_flag = __commonJS({
11235
11235
  var require_supports_color = __commonJS({
11236
11236
  "../../node_modules/.pnpm/supports-color@7.2.0/node_modules/supports-color/index.js"(exports, module) {
11237
11237
  "use strict";
11238
- var os8 = __require("os");
11238
+ var os9 = __require("os");
11239
11239
  var tty = __require("tty");
11240
11240
  var hasFlag = require_has_flag();
11241
11241
  var { env } = process;
@@ -11283,7 +11283,7 @@ var require_supports_color = __commonJS({
11283
11283
  return min;
11284
11284
  }
11285
11285
  if (process.platform === "win32") {
11286
- const osRelease = os8.release().split(".");
11286
+ const osRelease = os9.release().split(".");
11287
11287
  if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
11288
11288
  return Number(osRelease[2]) >= 14931 ? 3 : 2;
11289
11289
  }
@@ -11529,10 +11529,10 @@ var require_src2 = __commonJS({
11529
11529
  var fs_1 = __require("fs");
11530
11530
  var debug_1 = __importDefault(require_src());
11531
11531
  var log2 = debug_1.default("@kwsites/file-exists");
11532
- function check2(path37, isFile, isDirectory) {
11533
- log2(`checking %s`, path37);
11532
+ function check2(path41, isFile, isDirectory) {
11533
+ log2(`checking %s`, path41);
11534
11534
  try {
11535
- const stat3 = fs_1.statSync(path37);
11535
+ const stat3 = fs_1.statSync(path41);
11536
11536
  if (stat3.isFile() && isFile) {
11537
11537
  log2(`[OK] path represents a file`);
11538
11538
  return true;
@@ -11552,8 +11552,8 @@ var require_src2 = __commonJS({
11552
11552
  throw e;
11553
11553
  }
11554
11554
  }
11555
- function exists2(path37, type = exports.READABLE) {
11556
- return check2(path37, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
11555
+ function exists2(path41, type = exports.READABLE) {
11556
+ return check2(path41, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
11557
11557
  }
11558
11558
  exports.exists = exists2;
11559
11559
  exports.FILE = 1;
@@ -11850,10 +11850,10 @@ function assignProp(target, prop, value) {
11850
11850
  configurable: true
11851
11851
  });
11852
11852
  }
11853
- function getElementAtPath(obj, path37) {
11854
- if (!path37)
11853
+ function getElementAtPath(obj, path41) {
11854
+ if (!path41)
11855
11855
  return obj;
11856
- return path37.reduce((acc, key) => acc?.[key], obj);
11856
+ return path41.reduce((acc, key) => acc?.[key], obj);
11857
11857
  }
11858
11858
  function promiseAllObject(promisesObj) {
11859
11859
  const keys = Object.keys(promisesObj);
@@ -12102,11 +12102,11 @@ function aborted(x, startIndex = 0) {
12102
12102
  }
12103
12103
  return false;
12104
12104
  }
12105
- function prefixIssues(path37, issues) {
12105
+ function prefixIssues(path41, issues) {
12106
12106
  return issues.map((iss) => {
12107
12107
  var _a2;
12108
12108
  (_a2 = iss).path ?? (_a2.path = []);
12109
- iss.path.unshift(path37);
12109
+ iss.path.unshift(path41);
12110
12110
  return iss;
12111
12111
  });
12112
12112
  }
@@ -12295,7 +12295,7 @@ function treeifyError(error40, _mapper) {
12295
12295
  return issue2.message;
12296
12296
  };
12297
12297
  const result = { errors: [] };
12298
- const processError = (error41, path37 = []) => {
12298
+ const processError = (error41, path41 = []) => {
12299
12299
  var _a2, _b;
12300
12300
  for (const issue2 of error41.issues) {
12301
12301
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -12305,7 +12305,7 @@ function treeifyError(error40, _mapper) {
12305
12305
  } else if (issue2.code === "invalid_element") {
12306
12306
  processError({ issues: issue2.issues }, issue2.path);
12307
12307
  } else {
12308
- const fullpath = [...path37, ...issue2.path];
12308
+ const fullpath = [...path41, ...issue2.path];
12309
12309
  if (fullpath.length === 0) {
12310
12310
  result.errors.push(mapper(issue2));
12311
12311
  continue;
@@ -12335,9 +12335,9 @@ function treeifyError(error40, _mapper) {
12335
12335
  processError(error40);
12336
12336
  return result;
12337
12337
  }
12338
- function toDotPath(path37) {
12338
+ function toDotPath(path41) {
12339
12339
  const segs = [];
12340
- for (const seg of path37) {
12340
+ for (const seg of path41) {
12341
12341
  if (typeof seg === "number")
12342
12342
  segs.push(`[${seg}]`);
12343
12343
  else if (typeof seg === "symbol")
@@ -25064,15 +25064,15 @@ var {
25064
25064
  } = import_index.default;
25065
25065
 
25066
25066
  // src/cli-version.ts
25067
- var CLI_VERSION = "0.1.28".length > 0 ? "0.1.28" : "0.0.0-dev";
25067
+ var CLI_VERSION = "0.1.29".length > 0 ? "0.1.29" : "0.0.0-dev";
25068
25068
 
25069
25069
  // src/cli/defaults.ts
25070
25070
  var DEFAULT_API_URL = process.env.BUILDAUTOMATON_API_URL ?? "https://api.buildautomaton.com";
25071
25071
  var DEFAULT_FIREHOSE_URL = "https://buildautomaton-firehose.fly.dev";
25072
25072
 
25073
25073
  // src/cli/run-cli-action.ts
25074
- import * as fs35 from "node:fs";
25075
- import * as path36 from "node:path";
25074
+ import * as fs37 from "node:fs";
25075
+ import * as path40 from "node:path";
25076
25076
 
25077
25077
  // src/cli-log-level.ts
25078
25078
  var verbosity = "info";
@@ -26696,6 +26696,321 @@ function runPendingAuth(options) {
26696
26696
  };
26697
26697
  }
26698
26698
 
26699
+ // src/sqlite/cli-database.ts
26700
+ import sqliteWasm from "node-sqlite3-wasm";
26701
+
26702
+ // src/sqlite/cli-sqlite-paths.ts
26703
+ import fs8 from "node:fs";
26704
+ import path5 from "node:path";
26705
+ import os3 from "node:os";
26706
+ function getCliSqlitePath() {
26707
+ const override = process.env.BUILDAMATON_CLI_SQLITE_PATH?.trim();
26708
+ if (override) return path5.resolve(override);
26709
+ return path5.join(os3.homedir(), ".buildautomaton", "cli.sqlite");
26710
+ }
26711
+ function ensureCliSqliteParentDir(sqlitePath) {
26712
+ const dir = path5.dirname(sqlitePath);
26713
+ if (!fs8.existsSync(dir)) fs8.mkdirSync(dir, { recursive: true });
26714
+ }
26715
+
26716
+ // src/sqlite/legacy_migration/import-cli-legacy-disk-data.ts
26717
+ import fs13 from "node:fs";
26718
+
26719
+ // src/files/index/constants.ts
26720
+ import path6 from "node:path";
26721
+ import os4 from "node:os";
26722
+ var INDEX_WORK_YIELD_EVERY = 256;
26723
+ var INDEX_DIR = path6.join(os4.homedir(), ".buildautomaton");
26724
+ var INDEX_HASH_LEN = 16;
26725
+
26726
+ // src/prompt-turn-queue/paths.ts
26727
+ import path7 from "node:path";
26728
+ import os5 from "node:os";
26729
+ function getPromptQueuesDirectory() {
26730
+ const override = process.env.BUILDAMATON_PROMPT_QUEUES_DIR?.trim();
26731
+ if (override) return path7.resolve(override);
26732
+ return path7.join(os5.homedir(), ".buildautomaton", "queues");
26733
+ }
26734
+
26735
+ // src/sqlite/legacy_migration/archive-file-index-json.ts
26736
+ import fs10 from "node:fs";
26737
+ import path9 from "node:path";
26738
+
26739
+ // src/sqlite/legacy_migration/archive-to-old-version.ts
26740
+ import fs9 from "node:fs";
26741
+ import path8 from "node:path";
26742
+ var OLD_VERSION_DIR = path8.join(INDEX_DIR, "old-version");
26743
+ function moveLegacyFileToOldVersionBackup(category, sourcePath) {
26744
+ const destDir = path8.join(OLD_VERSION_DIR, category);
26745
+ fs9.mkdirSync(destDir, { recursive: true });
26746
+ const base = path8.basename(sourcePath);
26747
+ let dest = path8.join(destDir, base);
26748
+ if (fs9.existsSync(dest)) {
26749
+ const ext = path8.extname(base);
26750
+ const stem = ext ? base.slice(0, -ext.length) : base;
26751
+ dest = path8.join(destDir, `${stem}-${Date.now()}${ext}`);
26752
+ }
26753
+ fs9.renameSync(sourcePath, dest);
26754
+ }
26755
+
26756
+ // src/sqlite/legacy_migration/archive-file-index-json.ts
26757
+ function archiveLegacyFileIndexJsonFiles() {
26758
+ try {
26759
+ if (!fs10.existsSync(INDEX_DIR)) return;
26760
+ for (const name of fs10.readdirSync(INDEX_DIR)) {
26761
+ if (name.startsWith(".file-index-") && name.endsWith(".json")) {
26762
+ const full = path9.join(INDEX_DIR, name);
26763
+ try {
26764
+ moveLegacyFileToOldVersionBackup("file-index", full);
26765
+ } catch (err) {
26766
+ console.error(`[cli-sqlite] legacy import: could not archive ${name}`, err);
26767
+ }
26768
+ }
26769
+ }
26770
+ } catch (e) {
26771
+ console.error("[cli-sqlite] legacy import: archive file-index json failed", e);
26772
+ }
26773
+ }
26774
+
26775
+ // src/sqlite/legacy_migration/import-agent-sessions-from-disk.ts
26776
+ import fs11 from "node:fs";
26777
+ import path10 from "node:path";
26778
+ import os6 from "node:os";
26779
+ var LEGACY_AGENT_SESSION_DIR = path10.join(os6.homedir(), ".buildautomaton", "agent-sessions");
26780
+ function importLegacyAgentSessionsFromDisk(db) {
26781
+ try {
26782
+ if (!fs11.existsSync(LEGACY_AGENT_SESSION_DIR)) return;
26783
+ const names = fs11.readdirSync(LEGACY_AGENT_SESSION_DIR).filter((n) => n.endsWith(".json"));
26784
+ for (const name of names) {
26785
+ const sessionKey = name.slice(0, -".json".length);
26786
+ const full = path10.join(LEGACY_AGENT_SESSION_DIR, name);
26787
+ let raw;
26788
+ try {
26789
+ raw = fs11.readFileSync(full, "utf8");
26790
+ } catch {
26791
+ continue;
26792
+ }
26793
+ let parsed;
26794
+ try {
26795
+ parsed = JSON.parse(raw);
26796
+ } catch {
26797
+ continue;
26798
+ }
26799
+ if (parsed.v !== 1) continue;
26800
+ const acpSessionId = typeof parsed.acpSessionId === "string" ? parsed.acpSessionId : null;
26801
+ const backendAgentType = typeof parsed.backendAgentType === "string" ? parsed.backendAgentType : null;
26802
+ const configOptionsJson = Array.isArray(parsed.configOptions) ? JSON.stringify(parsed.configOptions) : null;
26803
+ const updatedAt = typeof parsed.updatedAt === "string" ? parsed.updatedAt : (/* @__PURE__ */ new Date()).toISOString();
26804
+ db.run(
26805
+ `INSERT OR REPLACE INTO agent_session (session_key, acp_session_id, backend_agent_type, config_options_json, updated_at)
26806
+ VALUES (?, ?, ?, ?, ?)`,
26807
+ [sessionKey, acpSessionId, backendAgentType, configOptionsJson, updatedAt]
26808
+ );
26809
+ try {
26810
+ moveLegacyFileToOldVersionBackup("agent-sessions", full);
26811
+ } catch {
26812
+ }
26813
+ }
26814
+ } catch (e) {
26815
+ console.error("[cli-sqlite] legacy import: agent_sessions from disk failed", e);
26816
+ }
26817
+ }
26818
+
26819
+ // src/sqlite/legacy_migration/import-prompt-queues-from-disk.ts
26820
+ import fs12 from "node:fs";
26821
+ import path11 from "node:path";
26822
+
26823
+ // src/sqlite/legacy_migration/parse-persisted-queue-json.ts
26824
+ function parsePersistedQueueFromJson(raw) {
26825
+ try {
26826
+ const o = JSON.parse(raw);
26827
+ const queueKey = typeof o.queueKey === "string" ? o.queueKey : typeof o.queueKeyHash === "string" ? o.queueKeyHash : null;
26828
+ if (!queueKey || typeof o.updatedAt !== "string" || !Array.isArray(o.turns)) return null;
26829
+ return { queueKey, updatedAt: o.updatedAt, turns: o.turns };
26830
+ } catch {
26831
+ return null;
26832
+ }
26833
+ }
26834
+
26835
+ // src/sqlite/legacy_migration/import-prompt-queues-from-disk.ts
26836
+ function importLegacyPromptQueuesFromDisk(db) {
26837
+ try {
26838
+ const dir = getPromptQueuesDirectory();
26839
+ if (!fs12.existsSync(dir)) return;
26840
+ for (const name of fs12.readdirSync(dir)) {
26841
+ if (!name.endsWith(".json")) continue;
26842
+ const full = path11.join(dir, name);
26843
+ let raw;
26844
+ try {
26845
+ raw = fs12.readFileSync(full, "utf8");
26846
+ } catch {
26847
+ continue;
26848
+ }
26849
+ const file2 = parsePersistedQueueFromJson(raw);
26850
+ if (!file2) continue;
26851
+ db.run(
26852
+ `INSERT OR REPLACE INTO prompt_queue (queue_key, updated_at, turns_json) VALUES (?, ?, ?)`,
26853
+ [file2.queueKey, file2.updatedAt, JSON.stringify(file2.turns)]
26854
+ );
26855
+ try {
26856
+ moveLegacyFileToOldVersionBackup("queues", full);
26857
+ } catch {
26858
+ }
26859
+ }
26860
+ } catch (e) {
26861
+ console.error("[cli-sqlite] legacy import: prompt queues from disk failed", e);
26862
+ }
26863
+ }
26864
+
26865
+ // src/sqlite/legacy_migration/import-cli-legacy-disk-data.ts
26866
+ function legacyCliDiskMigrationIsPending() {
26867
+ try {
26868
+ if (fs13.existsSync(INDEX_DIR)) {
26869
+ for (const name of fs13.readdirSync(INDEX_DIR)) {
26870
+ if (name.startsWith(".file-index-") && name.endsWith(".json")) return true;
26871
+ }
26872
+ }
26873
+ } catch {
26874
+ }
26875
+ try {
26876
+ if (fs13.existsSync(LEGACY_AGENT_SESSION_DIR)) {
26877
+ if (fs13.readdirSync(LEGACY_AGENT_SESSION_DIR).some((n) => n.endsWith(".json"))) return true;
26878
+ }
26879
+ } catch {
26880
+ }
26881
+ try {
26882
+ const dir = getPromptQueuesDirectory();
26883
+ if (fs13.existsSync(dir) && fs13.readdirSync(dir).some((n) => n.endsWith(".json"))) return true;
26884
+ } catch {
26885
+ }
26886
+ return false;
26887
+ }
26888
+ function importCliSqliteLegacyDiskData(db, log2) {
26889
+ const pending = legacyCliDiskMigrationIsPending();
26890
+ if (pending && log2) {
26891
+ log2("Migrating legacy on-disk CLI data to SQLite\u2026");
26892
+ }
26893
+ archiveLegacyFileIndexJsonFiles();
26894
+ importLegacyAgentSessionsFromDisk(db);
26895
+ importLegacyPromptQueuesFromDisk(db);
26896
+ if (pending && log2) {
26897
+ log2("Legacy on-disk CLI data migration finished.");
26898
+ }
26899
+ }
26900
+
26901
+ // src/sqlite/load-cli-migration-sql.ts
26902
+ import { existsSync, readFileSync } from "node:fs";
26903
+ import { dirname, join as join2 } from "node:path";
26904
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
26905
+ function readCliSqliteMigrationSql(filename) {
26906
+ const dir = dirname(fileURLToPath2(import.meta.url));
26907
+ const resolved = join2(dir, "migrations", filename);
26908
+ if (!existsSync(resolved)) {
26909
+ throw new Error(`Missing CLI SQLite migration SQL: ${resolved}`);
26910
+ }
26911
+ return readFileSync(resolved, "utf8");
26912
+ }
26913
+
26914
+ // src/sqlite/migrate-cli-sqlite.ts
26915
+ function checkpointSatisfiedByLegacyChain(applied2, replacesLegacyMigrations) {
26916
+ return Array.isArray(replacesLegacyMigrations) && replacesLegacyMigrations.length > 0 && replacesLegacyMigrations.every((n) => applied2.has(n));
26917
+ }
26918
+ function recordMigrationAndPruneCheckpointLegacy(db, migration, applied2) {
26919
+ db.run("INSERT INTO __migrations (name) VALUES (?)", [migration.name]);
26920
+ applied2.add(migration.name);
26921
+ if (migration.checkpoint !== true) return;
26922
+ const legacy = migration.replacesLegacyMigrations;
26923
+ if (!legacy?.length) return;
26924
+ for (const legacyName of legacy) {
26925
+ if (legacyName === migration.name) continue;
26926
+ db.run("DELETE FROM __migrations WHERE name = ?", [legacyName]);
26927
+ applied2.delete(legacyName);
26928
+ }
26929
+ }
26930
+ var CHECKPOINT_V1 = "001_cli_sqlite_checkpoint_v1";
26931
+ var CHECKPOINT_V1_SQL = readCliSqliteMigrationSql("001_cli_sqlite_checkpoint_v1.sql");
26932
+ var CLI_SQLITE_MIGRATIONS = [
26933
+ {
26934
+ name: CHECKPOINT_V1,
26935
+ checkpoint: true,
26936
+ migrate: (db) => {
26937
+ db.exec(CHECKPOINT_V1_SQL);
26938
+ }
26939
+ }
26940
+ ];
26941
+ function migrateCliSqlite(db) {
26942
+ db.exec(readCliSqliteMigrationSql("000_bootstrap_migrations_table.sql"));
26943
+ const appliedRows = db.all("SELECT name FROM __migrations");
26944
+ const applied2 = new Set(appliedRows.map((r) => r.name));
26945
+ for (const migration of CLI_SQLITE_MIGRATIONS) {
26946
+ if (applied2.has(migration.name)) continue;
26947
+ if (migration.checkpoint === true && checkpointSatisfiedByLegacyChain(applied2, migration.replacesLegacyMigrations)) {
26948
+ recordMigrationAndPruneCheckpointLegacy(db, migration, applied2);
26949
+ continue;
26950
+ }
26951
+ if (migration.alreadyApplied?.(db)) {
26952
+ recordMigrationAndPruneCheckpointLegacy(db, migration, applied2);
26953
+ continue;
26954
+ }
26955
+ try {
26956
+ migration.migrate(db);
26957
+ recordMigrationAndPruneCheckpointLegacy(db, migration, applied2);
26958
+ } catch (e) {
26959
+ console.error(`[cli-sqlite] Migration failed: ${migration.name}`, e);
26960
+ throw e;
26961
+ }
26962
+ }
26963
+ }
26964
+
26965
+ // src/sqlite/cli-database.ts
26966
+ var { Database: SqliteDatabase } = sqliteWasm;
26967
+ var openDatabases = /* @__PURE__ */ new Map();
26968
+ var processExitCloseRegistered = false;
26969
+ function registerProcessExitSqliteClose() {
26970
+ if (processExitCloseRegistered) return;
26971
+ processExitCloseRegistered = true;
26972
+ process.once("exit", () => {
26973
+ for (const db of openDatabases.values()) {
26974
+ safeCloseCliSqliteDatabase(db);
26975
+ }
26976
+ openDatabases.clear();
26977
+ });
26978
+ }
26979
+ function safeCloseCliSqliteDatabase(db) {
26980
+ if (db == null) return;
26981
+ try {
26982
+ if (db.isOpen) db.close();
26983
+ } catch {
26984
+ }
26985
+ }
26986
+ function closeAllCliSqliteConnections() {
26987
+ for (const db of openDatabases.values()) {
26988
+ safeCloseCliSqliteDatabase(db);
26989
+ }
26990
+ openDatabases.clear();
26991
+ }
26992
+ function getCliDatabase(options) {
26993
+ const sqlitePath = getCliSqlitePath();
26994
+ const existing = openDatabases.get(sqlitePath);
26995
+ if (existing?.isOpen) return existing;
26996
+ if (existing && !existing.isOpen) {
26997
+ safeCloseCliSqliteDatabase(existing);
26998
+ openDatabases.delete(sqlitePath);
26999
+ }
27000
+ ensureCliSqliteParentDir(sqlitePath);
27001
+ const db = new SqliteDatabase(sqlitePath);
27002
+ try {
27003
+ migrateCliSqlite(db);
27004
+ importCliSqliteLegacyDiskData(db, options?.logLegacyMigration);
27005
+ } catch (e) {
27006
+ safeCloseCliSqliteDatabase(db);
27007
+ throw e;
27008
+ }
27009
+ openDatabases.set(sqlitePath, db);
27010
+ registerProcessExitSqliteClose();
27011
+ return db;
27012
+ }
27013
+
26699
27014
  // src/connection/close-bridge-connection.ts
26700
27015
  async function closeBridgeConnection(state, acpManager, devServerManager, log2) {
26701
27016
  const say = log2 ?? logImmediate;
@@ -26739,20 +27054,24 @@ async function closeBridgeConnection(state, acpManager, devServerManager, log2)
26739
27054
  say("Stopping local dev server processes\u2026");
26740
27055
  await devServerManager.shutdownAllGraceful();
26741
27056
  }
27057
+ try {
27058
+ closeAllCliSqliteConnections();
27059
+ } catch {
27060
+ }
26742
27061
  say("Shutdown complete.");
26743
27062
  }
26744
27063
 
26745
27064
  // src/paths/session-layout-paths.ts
26746
- import * as path5 from "node:path";
27065
+ import * as path12 from "node:path";
26747
27066
  function resolveIsolatedSessionParentPathFromCheckouts(worktreePaths) {
26748
- const resolved = worktreePaths.map((p) => path5.resolve(p)).filter(Boolean);
27067
+ const resolved = worktreePaths.map((p) => path12.resolve(p)).filter(Boolean);
26749
27068
  if (resolved.length === 0) return null;
26750
27069
  resolved.sort();
26751
27070
  return resolved[0];
26752
27071
  }
26753
27072
  function resolveSessionParentPathForAgentProcess(resolvedSessionParentPath) {
26754
27073
  if (resolvedSessionParentPath != null && String(resolvedSessionParentPath).trim() !== "") {
26755
- return path5.resolve(String(resolvedSessionParentPath).trim());
27074
+ return path12.resolve(String(resolvedSessionParentPath).trim());
26756
27075
  }
26757
27076
  return getBridgeRoot();
26758
27077
  }
@@ -27084,9 +27403,9 @@ function parseChangeSummaryJson(raw, allowedPaths, options) {
27084
27403
  const rawPath = typeof o.path === "string" ? o.path.trim() : "";
27085
27404
  const summary = typeof o.summary === "string" ? o.summary.trim() : "";
27086
27405
  if (!rawPath || !summary) continue;
27087
- const path37 = skip ? normalizeRepoRelativePath(rawPath) || rawPath : resolveChangeSummaryPathAgainstAllowed(rawPath, allowedPaths);
27088
- if (!path37) continue;
27089
- rows.push({ path: path37, summary: clampSummaryToAtMostTwoLines(summary) });
27406
+ const path41 = skip ? normalizeRepoRelativePath(rawPath) || rawPath : resolveChangeSummaryPathAgainstAllowed(rawPath, allowedPaths);
27407
+ if (!path41) continue;
27408
+ rows.push({ path: path41, summary: clampSummaryToAtMostTwoLines(summary) });
27090
27409
  }
27091
27410
  return rows;
27092
27411
  }
@@ -27312,17 +27631,17 @@ function getCliPermissionModeFromAgentConfig(config2) {
27312
27631
  import { execFile as execFile7 } from "node:child_process";
27313
27632
  import { readFile as readFile2, stat as stat2 } from "node:fs/promises";
27314
27633
  import { promisify as promisify7 } from "node:util";
27315
- import * as path8 from "node:path";
27634
+ import * as path15 from "node:path";
27316
27635
 
27317
27636
  // src/git/pre-turn-snapshot.ts
27318
- import * as fs9 from "node:fs";
27319
- import * as path7 from "node:path";
27637
+ import * as fs15 from "node:fs";
27638
+ import * as path14 from "node:path";
27320
27639
  import { execFile as execFile6 } from "node:child_process";
27321
27640
  import { promisify as promisify6 } from "node:util";
27322
27641
 
27323
27642
  // src/git/discover-repos.ts
27324
- import * as fs8 from "node:fs";
27325
- import * as path6 from "node:path";
27643
+ import * as fs14 from "node:fs";
27644
+ import * as path13 from "node:path";
27326
27645
 
27327
27646
  // ../../node_modules/.pnpm/simple-git@3.32.3/node_modules/simple-git/dist/esm/index.js
27328
27647
  var import_file_exists = __toESM(require_dist(), 1);
@@ -27361,8 +27680,8 @@ function pathspec(...paths) {
27361
27680
  cache.set(key, paths);
27362
27681
  return key;
27363
27682
  }
27364
- function isPathSpec(path37) {
27365
- return path37 instanceof String && cache.has(path37);
27683
+ function isPathSpec(path41) {
27684
+ return path41 instanceof String && cache.has(path41);
27366
27685
  }
27367
27686
  function toPaths(pathSpec) {
27368
27687
  return cache.get(pathSpec) || [];
@@ -27451,8 +27770,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
27451
27770
  function forEachLineWithContent(input, callback) {
27452
27771
  return toLinesWithContent(input, true).map((line) => callback(line));
27453
27772
  }
27454
- function folderExists(path37) {
27455
- return (0, import_file_exists.exists)(path37, import_file_exists.FOLDER);
27773
+ function folderExists(path41) {
27774
+ return (0, import_file_exists.exists)(path41, import_file_exists.FOLDER);
27456
27775
  }
27457
27776
  function append(target, item) {
27458
27777
  if (Array.isArray(target)) {
@@ -27856,8 +28175,8 @@ function checkIsRepoRootTask() {
27856
28175
  commands,
27857
28176
  format: "utf-8",
27858
28177
  onError,
27859
- parser(path37) {
27860
- return /^\.(git)?$/.test(path37.trim());
28178
+ parser(path41) {
28179
+ return /^\.(git)?$/.test(path41.trim());
27861
28180
  }
27862
28181
  };
27863
28182
  }
@@ -28291,11 +28610,11 @@ function parseGrep(grep) {
28291
28610
  const paths = /* @__PURE__ */ new Set();
28292
28611
  const results = {};
28293
28612
  forEachLineWithContent(grep, (input) => {
28294
- const [path37, line, preview] = input.split(NULL);
28295
- paths.add(path37);
28296
- (results[path37] = results[path37] || []).push({
28613
+ const [path41, line, preview] = input.split(NULL);
28614
+ paths.add(path41);
28615
+ (results[path41] = results[path41] || []).push({
28297
28616
  line: asNumber(line),
28298
- path: path37,
28617
+ path: path41,
28299
28618
  preview
28300
28619
  });
28301
28620
  });
@@ -29060,14 +29379,14 @@ var init_hash_object = __esm2({
29060
29379
  init_task();
29061
29380
  }
29062
29381
  });
29063
- function parseInit(bare, path37, text) {
29382
+ function parseInit(bare, path41, text) {
29064
29383
  const response = String(text).trim();
29065
29384
  let result;
29066
29385
  if (result = initResponseRegex.exec(response)) {
29067
- return new InitSummary(bare, path37, false, result[1]);
29386
+ return new InitSummary(bare, path41, false, result[1]);
29068
29387
  }
29069
29388
  if (result = reInitResponseRegex.exec(response)) {
29070
- return new InitSummary(bare, path37, true, result[1]);
29389
+ return new InitSummary(bare, path41, true, result[1]);
29071
29390
  }
29072
29391
  let gitDir = "";
29073
29392
  const tokens = response.split(" ");
@@ -29078,7 +29397,7 @@ function parseInit(bare, path37, text) {
29078
29397
  break;
29079
29398
  }
29080
29399
  }
29081
- return new InitSummary(bare, path37, /^re/i.test(response), gitDir);
29400
+ return new InitSummary(bare, path41, /^re/i.test(response), gitDir);
29082
29401
  }
29083
29402
  var InitSummary;
29084
29403
  var initResponseRegex;
@@ -29087,9 +29406,9 @@ var init_InitSummary = __esm2({
29087
29406
  "src/lib/responses/InitSummary.ts"() {
29088
29407
  "use strict";
29089
29408
  InitSummary = class {
29090
- constructor(bare, path37, existing, gitDir) {
29409
+ constructor(bare, path41, existing, gitDir) {
29091
29410
  this.bare = bare;
29092
- this.path = path37;
29411
+ this.path = path41;
29093
29412
  this.existing = existing;
29094
29413
  this.gitDir = gitDir;
29095
29414
  }
@@ -29101,7 +29420,7 @@ var init_InitSummary = __esm2({
29101
29420
  function hasBareCommand(command) {
29102
29421
  return command.includes(bareCommand);
29103
29422
  }
29104
- function initTask(bare = false, path37, customArgs) {
29423
+ function initTask(bare = false, path41, customArgs) {
29105
29424
  const commands = ["init", ...customArgs];
29106
29425
  if (bare && !hasBareCommand(commands)) {
29107
29426
  commands.splice(1, 0, bareCommand);
@@ -29110,7 +29429,7 @@ function initTask(bare = false, path37, customArgs) {
29110
29429
  commands,
29111
29430
  format: "utf-8",
29112
29431
  parser(text) {
29113
- return parseInit(commands.includes("--bare"), path37, text);
29432
+ return parseInit(commands.includes("--bare"), path41, text);
29114
29433
  }
29115
29434
  };
29116
29435
  }
@@ -29926,12 +30245,12 @@ var init_FileStatusSummary = __esm2({
29926
30245
  "use strict";
29927
30246
  fromPathRegex = /^(.+)\0(.+)$/;
29928
30247
  FileStatusSummary = class {
29929
- constructor(path37, index, working_dir) {
29930
- this.path = path37;
30248
+ constructor(path41, index, working_dir) {
30249
+ this.path = path41;
29931
30250
  this.index = index;
29932
30251
  this.working_dir = working_dir;
29933
30252
  if (index === "R" || working_dir === "R") {
29934
- const detail = fromPathRegex.exec(path37) || [null, path37, path37];
30253
+ const detail = fromPathRegex.exec(path41) || [null, path41, path41];
29935
30254
  this.from = detail[2] || "";
29936
30255
  this.path = detail[1] || "";
29937
30256
  }
@@ -29962,14 +30281,14 @@ function splitLine(result, lineStr) {
29962
30281
  default:
29963
30282
  return;
29964
30283
  }
29965
- function data(index, workingDir, path37) {
30284
+ function data(index, workingDir, path41) {
29966
30285
  const raw = `${index}${workingDir}`;
29967
30286
  const handler = parsers6.get(raw);
29968
30287
  if (handler) {
29969
- handler(result, path37);
30288
+ handler(result, path41);
29970
30289
  }
29971
30290
  if (raw !== "##" && raw !== "!!") {
29972
- result.files.push(new FileStatusSummary(path37, index, workingDir));
30291
+ result.files.push(new FileStatusSummary(path41, index, workingDir));
29973
30292
  }
29974
30293
  }
29975
30294
  }
@@ -30242,15 +30561,15 @@ var init_simple_git_api = __esm2({
30242
30561
  this._executor = _executor;
30243
30562
  }
30244
30563
  _runTask(task, then) {
30245
- const chain = this._executor.chain();
30246
- const promise2 = chain.push(task);
30564
+ const chain2 = this._executor.chain();
30565
+ const promise2 = chain2.push(task);
30247
30566
  if (then) {
30248
30567
  taskCallback(task, promise2, then);
30249
30568
  }
30250
30569
  return Object.create(this, {
30251
30570
  then: { value: promise2.then.bind(promise2) },
30252
30571
  catch: { value: promise2.catch.bind(promise2) },
30253
- _executor: { value: chain }
30572
+ _executor: { value: chain2 }
30254
30573
  });
30255
30574
  }
30256
30575
  add(files) {
@@ -30278,9 +30597,9 @@ var init_simple_git_api = __esm2({
30278
30597
  next
30279
30598
  );
30280
30599
  }
30281
- hashObject(path37, write) {
30600
+ hashObject(path41, write) {
30282
30601
  return this._runTask(
30283
- hashObjectTask(path37, write === true),
30602
+ hashObjectTask(path41, write === true),
30284
30603
  trailingFunctionArgument(arguments)
30285
30604
  );
30286
30605
  }
@@ -30633,8 +30952,8 @@ var init_branch = __esm2({
30633
30952
  }
30634
30953
  });
30635
30954
  function toPath(input) {
30636
- const path37 = input.trim().replace(/^["']|["']$/g, "");
30637
- return path37 && normalize(path37);
30955
+ const path41 = input.trim().replace(/^["']|["']$/g, "");
30956
+ return path41 && normalize(path41);
30638
30957
  }
30639
30958
  var parseCheckIgnore;
30640
30959
  var init_CheckIgnore = __esm2({
@@ -30948,8 +31267,8 @@ __export2(sub_module_exports, {
30948
31267
  subModuleTask: () => subModuleTask,
30949
31268
  updateSubModuleTask: () => updateSubModuleTask
30950
31269
  });
30951
- function addSubModuleTask(repo, path37) {
30952
- return subModuleTask(["add", repo, path37]);
31270
+ function addSubModuleTask(repo, path41) {
31271
+ return subModuleTask(["add", repo, path41]);
30953
31272
  }
30954
31273
  function initSubModuleTask(customArgs) {
30955
31274
  return subModuleTask(["init", ...customArgs]);
@@ -31282,8 +31601,8 @@ var require_git = __commonJS2({
31282
31601
  }
31283
31602
  return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
31284
31603
  };
31285
- Git2.prototype.submoduleAdd = function(repo, path37, then) {
31286
- return this._runTask(addSubModuleTask2(repo, path37), trailingFunctionArgument2(arguments));
31604
+ Git2.prototype.submoduleAdd = function(repo, path41, then) {
31605
+ return this._runTask(addSubModuleTask2(repo, path41), trailingFunctionArgument2(arguments));
31287
31606
  };
31288
31607
  Git2.prototype.submoduleUpdate = function(args, then) {
31289
31608
  return this._runTask(
@@ -31927,20 +32246,20 @@ async function isGitRepoDirectory(dirPath) {
31927
32246
  // src/git/discover-repos.ts
31928
32247
  async function discoverGitRepos(cwd = getBridgeRoot()) {
31929
32248
  const result = [];
31930
- const cwdResolved = path6.resolve(cwd);
32249
+ const cwdResolved = path13.resolve(cwd);
31931
32250
  if (await isGitRepoDirectory(cwdResolved)) {
31932
32251
  const remoteUrl = await getRemoteOriginUrl(cwdResolved);
31933
32252
  result.push({ absolutePath: cwdResolved, remoteUrl });
31934
32253
  }
31935
32254
  let entries;
31936
32255
  try {
31937
- entries = fs8.readdirSync(cwdResolved, { withFileTypes: true });
32256
+ entries = fs14.readdirSync(cwdResolved, { withFileTypes: true });
31938
32257
  } catch {
31939
32258
  return result;
31940
32259
  }
31941
32260
  for (const ent of entries) {
31942
32261
  if (!ent.isDirectory()) continue;
31943
- const childPath = path6.join(cwdResolved, ent.name);
32262
+ const childPath = path13.join(cwdResolved, ent.name);
31944
32263
  if (await isGitRepoDirectory(childPath)) {
31945
32264
  const remoteUrl = await getRemoteOriginUrl(childPath);
31946
32265
  result.push({ absolutePath: childPath, remoteUrl });
@@ -31949,22 +32268,22 @@ async function discoverGitRepos(cwd = getBridgeRoot()) {
31949
32268
  return result;
31950
32269
  }
31951
32270
  async function discoverGitReposUnderRoot(rootPath) {
31952
- const root = path6.resolve(rootPath);
32271
+ const root = path13.resolve(rootPath);
31953
32272
  const roots = [];
31954
32273
  async function walk(dir) {
31955
32274
  if (await isGitRepoDirectory(dir)) {
31956
- roots.push(path6.resolve(dir));
32275
+ roots.push(path13.resolve(dir));
31957
32276
  return;
31958
32277
  }
31959
32278
  let entries;
31960
32279
  try {
31961
- entries = fs8.readdirSync(dir, { withFileTypes: true });
32280
+ entries = fs14.readdirSync(dir, { withFileTypes: true });
31962
32281
  } catch {
31963
32282
  return;
31964
32283
  }
31965
32284
  for (const ent of entries) {
31966
32285
  if (!ent.isDirectory() || ent.name === ".git") continue;
31967
- await walk(path6.join(dir, ent.name));
32286
+ await walk(path13.join(dir, ent.name));
31968
32287
  }
31969
32288
  }
31970
32289
  await walk(root);
@@ -31980,7 +32299,7 @@ async function discoverGitReposUnderRoot(rootPath) {
31980
32299
  // src/git/pre-turn-snapshot.ts
31981
32300
  var execFileAsync5 = promisify6(execFile6);
31982
32301
  function snapshotsDirForCwd(agentCwd) {
31983
- return path7.join(agentCwd, ".buildautomaton", "snapshots");
32302
+ return path14.join(agentCwd, ".buildautomaton", "snapshots");
31984
32303
  }
31985
32304
  async function gitStashCreate(repoRoot, log2) {
31986
32305
  try {
@@ -32009,7 +32328,7 @@ async function gitRun(repoRoot, args, log2, label) {
32009
32328
  async function resolveSnapshotRepoRoots(options) {
32010
32329
  const { worktreePaths, fallbackCwd, sessionId, log: log2 } = options;
32011
32330
  if (worktreePaths?.length) {
32012
- const uniq = [...new Set(worktreePaths.map((p) => path7.resolve(p)))];
32331
+ const uniq = [...new Set(worktreePaths.map((p) => path14.resolve(p)))];
32013
32332
  return uniq;
32014
32333
  }
32015
32334
  try {
@@ -32017,7 +32336,7 @@ async function resolveSnapshotRepoRoots(options) {
32017
32336
  const mapped = repos.map((r) => r.absolutePath);
32018
32337
  const sid = sessionId?.trim();
32019
32338
  if (sid) {
32020
- const filtered = mapped.filter((root) => path7.basename(root) === sid);
32339
+ const filtered = mapped.filter((root) => path14.basename(root) === sid);
32021
32340
  if (filtered.length > 0) return filtered;
32022
32341
  }
32023
32342
  return mapped;
@@ -32038,7 +32357,7 @@ async function capturePreTurnSnapshot(options) {
32038
32357
  }
32039
32358
  const dir = snapshotsDirForCwd(agentCwd);
32040
32359
  try {
32041
- fs9.mkdirSync(dir, { recursive: true });
32360
+ fs15.mkdirSync(dir, { recursive: true });
32042
32361
  } catch (e) {
32043
32362
  return { ok: false, error: e instanceof Error ? e.message : String(e) };
32044
32363
  }
@@ -32047,9 +32366,9 @@ async function capturePreTurnSnapshot(options) {
32047
32366
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
32048
32367
  repos
32049
32368
  };
32050
- const filePath = path7.join(dir, `${runId}.json`);
32369
+ const filePath = path14.join(dir, `${runId}.json`);
32051
32370
  try {
32052
- fs9.writeFileSync(filePath, JSON.stringify(payload, null, 2), "utf8");
32371
+ fs15.writeFileSync(filePath, JSON.stringify(payload, null, 2), "utf8");
32053
32372
  } catch (e) {
32054
32373
  return { ok: false, error: e instanceof Error ? e.message : String(e) };
32055
32374
  }
@@ -32062,7 +32381,7 @@ async function capturePreTurnSnapshot(options) {
32062
32381
  async function applyPreTurnSnapshot(filePath, log2) {
32063
32382
  let data;
32064
32383
  try {
32065
- const raw = fs9.readFileSync(filePath, "utf8");
32384
+ const raw = fs15.readFileSync(filePath, "utf8");
32066
32385
  data = JSON.parse(raw);
32067
32386
  } catch (e) {
32068
32387
  return { ok: false, error: e instanceof Error ? e.message : String(e) };
@@ -32085,7 +32404,7 @@ async function applyPreTurnSnapshot(filePath, log2) {
32085
32404
  return { ok: true };
32086
32405
  }
32087
32406
  function snapshotFilePath(agentCwd, runId) {
32088
- return path7.join(snapshotsDirForCwd(agentCwd), `${runId}.json`);
32407
+ return path14.join(snapshotsDirForCwd(agentCwd), `${runId}.json`);
32089
32408
  }
32090
32409
 
32091
32410
  // src/git/session-git-queue.ts
@@ -32134,7 +32453,7 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
32134
32453
  continue;
32135
32454
  }
32136
32455
  const lines = namesRaw.split("\n").map((l) => l.trim()).filter(Boolean);
32137
- const slug = path8.basename(repo.path).replace(/[^\w.-]+/g, "_") || "repo";
32456
+ const slug = path15.basename(repo.path).replace(/[^\w.-]+/g, "_") || "repo";
32138
32457
  for (const rel of lines) {
32139
32458
  if (rel.includes("..")) continue;
32140
32459
  try {
@@ -32148,7 +32467,7 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
32148
32467
  );
32149
32468
  if (!patchContent.trim()) continue;
32150
32469
  const displayPath = multiRepo ? `${slug}/${rel}` : rel;
32151
- const workspaceFilePath = path8.join(repo.path, rel);
32470
+ const workspaceFilePath = path15.join(repo.path, rel);
32152
32471
  const newText = await readWorkspaceFileAsUtf8(workspaceFilePath);
32153
32472
  sendSessionUpdate({
32154
32473
  type: "session_file_change",
@@ -32170,9 +32489,9 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
32170
32489
  // src/agents/acp/put-summarize-change-summaries.ts
32171
32490
  async function putEncryptedChangeSummaryRows(params) {
32172
32491
  const base = params.apiBaseUrl.replace(/\/+$/, "");
32173
- const entries = params.rows.map(({ path: path37, summary }) => {
32492
+ const entries = params.rows.map(({ path: path41, summary }) => {
32174
32493
  const enc = params.e2ee.encryptFields({ summary }, ["summary"]);
32175
- return { path: path37, summary: JSON.stringify(enc) };
32494
+ return { path: path41, summary: JSON.stringify(enc) };
32176
32495
  });
32177
32496
  const res = await fetch(
32178
32497
  `${base}/api/sessions/${encodeURIComponent(params.sessionId)}/follow-ups/summarize-changes`,
@@ -32483,8 +32802,8 @@ async function sendPromptToAgent(options) {
32483
32802
  }
32484
32803
 
32485
32804
  // src/agents/acp/ensure-acp-client.ts
32486
- import * as fs11 from "node:fs";
32487
- import * as path13 from "node:path";
32805
+ import * as fs16 from "node:fs";
32806
+ import * as path19 from "node:path";
32488
32807
 
32489
32808
  // src/error-message.ts
32490
32809
  function errorMessage(err) {
@@ -32648,8 +32967,8 @@ function enrichAcpPermissionRpcResultFromRequestParams(result, params) {
32648
32967
  }
32649
32968
 
32650
32969
  // src/agents/acp/clients/shared/acp-fs-read-write.ts
32651
- import { mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
32652
- import { dirname as dirname2 } from "node:path";
32970
+ import { mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "node:fs";
32971
+ import { dirname as dirname3 } from "node:path";
32653
32972
 
32654
32973
  // src/files/diff/unified-diff.ts
32655
32974
  function computeLineDiff(oldText, newText) {
@@ -32698,21 +33017,21 @@ function editSnippetToUnifiedDiff(filePath, oldText, newText) {
32698
33017
  }
32699
33018
 
32700
33019
  // src/agents/acp/safe-fs-path.ts
32701
- import * as path9 from "node:path";
33020
+ import * as path16 from "node:path";
32702
33021
  function resolveSafePathUnderCwd(cwd, filePath) {
32703
33022
  const trimmed2 = filePath.trim();
32704
33023
  if (!trimmed2) return null;
32705
- const normalizedCwd = path9.resolve(cwd);
32706
- const resolved = path9.isAbsolute(trimmed2) ? path9.normalize(trimmed2) : path9.resolve(normalizedCwd, trimmed2);
32707
- const rel = path9.relative(normalizedCwd, resolved);
32708
- if (rel.startsWith("..") || path9.isAbsolute(rel)) return null;
33024
+ const normalizedCwd = path16.resolve(cwd);
33025
+ const resolved = path16.isAbsolute(trimmed2) ? path16.normalize(trimmed2) : path16.resolve(normalizedCwd, trimmed2);
33026
+ const rel = path16.relative(normalizedCwd, resolved);
33027
+ if (rel.startsWith("..") || path16.isAbsolute(rel)) return null;
32709
33028
  return resolved;
32710
33029
  }
32711
33030
  function toDisplayPathRelativeToCwd(cwd, absolutePath) {
32712
- const normalizedCwd = path9.resolve(cwd);
32713
- const rel = path9.relative(normalizedCwd, path9.resolve(absolutePath));
32714
- if (!rel || rel === "") return path9.basename(absolutePath);
32715
- return rel.split(path9.sep).join("/");
33031
+ const normalizedCwd = path16.resolve(cwd);
33032
+ const rel = path16.relative(normalizedCwd, path16.resolve(absolutePath));
33033
+ if (!rel || rel === "") return path16.basename(absolutePath);
33034
+ return rel.split(path16.sep).join("/");
32716
33035
  }
32717
33036
 
32718
33037
  // src/agents/acp/clients/shared/acp-fs-read-write.ts
@@ -32727,7 +33046,7 @@ function acpReadTextFileInProcess(ctx, filePath, line, limit) {
32727
33046
  const resolvedPath = resolveSafePathUnderCwd(ctx.cwd, filePath);
32728
33047
  if (!resolvedPath) throw new Error("Invalid or disallowed path");
32729
33048
  try {
32730
- let content = readFileSync2(resolvedPath, "utf8");
33049
+ let content = readFileSync3(resolvedPath, "utf8");
32731
33050
  content = sliceFileContentForAcp(content, line, limit);
32732
33051
  return { content };
32733
33052
  } catch (e) {
@@ -32740,11 +33059,11 @@ function acpWriteTextFileInProcess(ctx, filePath, newText) {
32740
33059
  if (!resolvedPath) throw new Error("Invalid or disallowed path");
32741
33060
  let oldText = "";
32742
33061
  try {
32743
- oldText = readFileSync2(resolvedPath, "utf8");
33062
+ oldText = readFileSync3(resolvedPath, "utf8");
32744
33063
  } catch (e) {
32745
33064
  if (e.code !== "ENOENT") throw e;
32746
33065
  }
32747
- mkdirSync2(dirname2(resolvedPath), { recursive: true });
33066
+ mkdirSync2(dirname3(resolvedPath), { recursive: true });
32748
33067
  writeFileSync2(resolvedPath, newText, "utf8");
32749
33068
  const displayPath = toDisplayPathRelativeToCwd(ctx.cwd, resolvedPath);
32750
33069
  const patchContent = editSnippetToUnifiedDiff(displayPath, oldText, newText);
@@ -33681,20 +34000,20 @@ function resolveAgentCommand(preferredAgentType) {
33681
34000
 
33682
34001
  // src/agents/acp/session-file-change-path-kind.ts
33683
34002
  import { execFileSync as execFileSync4 } from "node:child_process";
33684
- import { existsSync, statSync } from "node:fs";
34003
+ import { existsSync as existsSync2, statSync } from "node:fs";
33685
34004
 
33686
34005
  // src/git/get-git-repo-root-sync.ts
33687
34006
  import { execFileSync as execFileSync2 } from "node:child_process";
33688
- import * as path10 from "node:path";
34007
+ import * as path17 from "node:path";
33689
34008
  function getGitRepoRootSync(startDir) {
33690
34009
  try {
33691
34010
  const out = execFileSync2("git", ["rev-parse", "--show-toplevel"], {
33692
- cwd: path10.resolve(startDir),
34011
+ cwd: path17.resolve(startDir),
33693
34012
  encoding: "utf8",
33694
34013
  stdio: ["ignore", "pipe", "ignore"],
33695
34014
  maxBuffer: 1024 * 1024
33696
34015
  }).trim();
33697
- return out ? path10.resolve(out) : null;
34016
+ return out ? path17.resolve(out) : null;
33698
34017
  } catch {
33699
34018
  return null;
33700
34019
  }
@@ -33702,26 +34021,26 @@ function getGitRepoRootSync(startDir) {
33702
34021
 
33703
34022
  // src/agents/acp/workspace-files.ts
33704
34023
  import { execFileSync as execFileSync3 } from "node:child_process";
33705
- import { readFileSync as readFileSync3 } from "node:fs";
33706
- import * as path11 from "node:path";
34024
+ import { readFileSync as readFileSync4 } from "node:fs";
34025
+ import * as path18 from "node:path";
33707
34026
  function resolveWorkspaceFilePath(sessionParentPath, rawPath) {
33708
34027
  const trimmed2 = rawPath.trim();
33709
34028
  if (!trimmed2) return null;
33710
- const normalizedSessionParent = path11.resolve(sessionParentPath);
34029
+ const normalizedSessionParent = path18.resolve(sessionParentPath);
33711
34030
  let resolvedPath = resolveSafePathUnderCwd(sessionParentPath, trimmed2);
33712
34031
  if (!resolvedPath) {
33713
- const candidate = path11.isAbsolute(trimmed2) ? path11.normalize(trimmed2) : path11.normalize(path11.resolve(normalizedSessionParent, trimmed2));
34032
+ const candidate = path18.isAbsolute(trimmed2) ? path18.normalize(trimmed2) : path18.normalize(path18.resolve(normalizedSessionParent, trimmed2));
33714
34033
  const gitRoot2 = getGitRepoRootSync(sessionParentPath);
33715
34034
  if (!gitRoot2) return null;
33716
- const rel = path11.relative(gitRoot2, candidate);
33717
- if (rel.startsWith("..") || path11.isAbsolute(rel)) return null;
34035
+ const rel = path18.relative(gitRoot2, candidate);
34036
+ if (rel.startsWith("..") || path18.isAbsolute(rel)) return null;
33718
34037
  resolvedPath = candidate;
33719
34038
  }
33720
34039
  const gitRoot = getGitRepoRootSync(sessionParentPath);
33721
34040
  if (gitRoot) {
33722
- const relFromRoot = path11.relative(gitRoot, resolvedPath);
33723
- if (!relFromRoot.startsWith("..") && !path11.isAbsolute(relFromRoot)) {
33724
- return { resolvedPath, display: relFromRoot.split(path11.sep).join("/") };
34041
+ const relFromRoot = path18.relative(gitRoot, resolvedPath);
34042
+ if (!relFromRoot.startsWith("..") && !path18.isAbsolute(relFromRoot)) {
34043
+ return { resolvedPath, display: relFromRoot.split(path18.sep).join("/") };
33725
34044
  }
33726
34045
  }
33727
34046
  return { resolvedPath, display: toDisplayPathRelativeToCwd(sessionParentPath, resolvedPath) };
@@ -33730,11 +34049,11 @@ function readUtf8WorkspaceFile(sessionParentPath, displayPath) {
33730
34049
  if (!displayPath || displayPath.includes("..")) return "";
33731
34050
  const gitRoot = getGitRepoRootSync(sessionParentPath);
33732
34051
  if (gitRoot) {
33733
- const resolvedPath2 = path11.resolve(gitRoot, displayPath);
33734
- const rel = path11.relative(gitRoot, resolvedPath2);
33735
- if (!rel.startsWith("..") && !path11.isAbsolute(rel)) {
34052
+ const resolvedPath2 = path18.resolve(gitRoot, displayPath);
34053
+ const rel = path18.relative(gitRoot, resolvedPath2);
34054
+ if (!rel.startsWith("..") && !path18.isAbsolute(rel)) {
33736
34055
  try {
33737
- return readFileSync3(resolvedPath2, "utf8");
34056
+ return readFileSync4(resolvedPath2, "utf8");
33738
34057
  } catch {
33739
34058
  }
33740
34059
  }
@@ -33742,7 +34061,7 @@ function readUtf8WorkspaceFile(sessionParentPath, displayPath) {
33742
34061
  const resolvedPath = resolveSafePathUnderCwd(sessionParentPath, displayPath);
33743
34062
  if (!resolvedPath) return "";
33744
34063
  try {
33745
- return readFileSync3(resolvedPath, "utf8");
34064
+ return readFileSync4(resolvedPath, "utf8");
33746
34065
  } catch {
33747
34066
  return "";
33748
34067
  }
@@ -33751,9 +34070,9 @@ function tryWorkspaceDisplayToPath(sessionParentPath, displayPath) {
33751
34070
  if (!displayPath || displayPath.includes("..")) return null;
33752
34071
  const gitRoot = getGitRepoRootSync(sessionParentPath);
33753
34072
  if (gitRoot) {
33754
- const resolvedPath = path11.resolve(gitRoot, displayPath);
33755
- const rel = path11.relative(gitRoot, resolvedPath);
33756
- if (!rel.startsWith("..") && !path11.isAbsolute(rel)) return resolvedPath;
34073
+ const resolvedPath = path18.resolve(gitRoot, displayPath);
34074
+ const rel = path18.relative(gitRoot, resolvedPath);
34075
+ if (!rel.startsWith("..") && !path18.isAbsolute(rel)) return resolvedPath;
33757
34076
  }
33758
34077
  return resolveSafePathUnderCwd(sessionParentPath, displayPath);
33759
34078
  }
@@ -33788,7 +34107,7 @@ function gitHeadPathObjectType(sessionParentPath, displayPath) {
33788
34107
  }
33789
34108
  function getSessionFileChangeDirectoryFlags(sessionParentPath, displayPath) {
33790
34109
  const resolvedPath = tryWorkspaceDisplayToPath(sessionParentPath, displayPath);
33791
- if (resolvedPath && existsSync(resolvedPath)) {
34110
+ if (resolvedPath && existsSync2(resolvedPath)) {
33792
34111
  try {
33793
34112
  if (statSync(resolvedPath).isDirectory()) {
33794
34113
  return { isDirectory: true, directoryRemoved: false };
@@ -33888,7 +34207,7 @@ function createBridgeOnRequest(opts) {
33888
34207
  }
33889
34208
 
33890
34209
  // src/agents/acp/hooks/extract-acp-file-diffs-from-update/paths-and-text.ts
33891
- import { fileURLToPath as fileURLToPath2 } from "node:url";
34210
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
33892
34211
  function readOptionalTextField(v) {
33893
34212
  if (v === null || v === void 0) return "";
33894
34213
  if (typeof v === "string") return v;
@@ -33898,7 +34217,7 @@ function normalizePathField(raw) {
33898
34217
  const t = raw.trim();
33899
34218
  if (t.startsWith("file://")) {
33900
34219
  try {
33901
- return fileURLToPath2(t);
34220
+ return fileURLToPath3(t);
33902
34221
  } catch {
33903
34222
  return t;
33904
34223
  }
@@ -34356,29 +34675,34 @@ function buildAcpSessionBridgeHooks(opts) {
34356
34675
  }
34357
34676
 
34358
34677
  // src/agents/acp/local-agent-session-file.ts
34359
- import fs10 from "node:fs";
34360
- import os3 from "node:os";
34361
- import path12 from "node:path";
34362
- var LOCAL_AGENT_SESSION_DIR = path12.join(os3.homedir(), ".buildautomaton", "agent-sessions");
34363
- function safeFileSlug(cloudSessionId) {
34678
+ function sessionKeyForCloudSessionId(cloudSessionId) {
34364
34679
  const t = cloudSessionId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 220);
34365
34680
  return t.length > 0 ? t : "session";
34366
34681
  }
34367
- function localAgentSessionFilePath(cloudSessionId) {
34368
- return path12.join(LOCAL_AGENT_SESSION_DIR, `${safeFileSlug(cloudSessionId)}.json`);
34369
- }
34370
34682
  function readLocalAgentSessionFile(cloudSessionId) {
34371
34683
  try {
34372
- const p = localAgentSessionFilePath(cloudSessionId);
34373
- const raw = fs10.readFileSync(p, "utf8");
34374
- const parsed = JSON.parse(raw);
34375
- if (parsed.v !== 1) return null;
34684
+ const db = getCliDatabase();
34685
+ const key = sessionKeyForCloudSessionId(cloudSessionId);
34686
+ const row = db.get(
34687
+ "SELECT acp_session_id, backend_agent_type, config_options_json, updated_at FROM agent_session WHERE session_key = ?",
34688
+ [key]
34689
+ );
34690
+ if (!row) return null;
34691
+ let configOptions = null;
34692
+ if (row.config_options_json != null && row.config_options_json !== "") {
34693
+ try {
34694
+ const parsed = JSON.parse(row.config_options_json);
34695
+ configOptions = Array.isArray(parsed) ? parsed : null;
34696
+ } catch {
34697
+ configOptions = null;
34698
+ }
34699
+ }
34376
34700
  return {
34377
34701
  v: 1,
34378
- acpSessionId: typeof parsed.acpSessionId === "string" ? parsed.acpSessionId : null,
34379
- backendAgentType: typeof parsed.backendAgentType === "string" ? parsed.backendAgentType : null,
34380
- configOptions: Array.isArray(parsed.configOptions) ? parsed.configOptions : null,
34381
- updatedAt: typeof parsed.updatedAt === "string" ? parsed.updatedAt : (/* @__PURE__ */ new Date()).toISOString()
34702
+ acpSessionId: row.acp_session_id,
34703
+ backendAgentType: row.backend_agent_type,
34704
+ configOptions,
34705
+ updatedAt: row.updated_at
34382
34706
  };
34383
34707
  } catch {
34384
34708
  return null;
@@ -34386,9 +34710,8 @@ function readLocalAgentSessionFile(cloudSessionId) {
34386
34710
  }
34387
34711
  function writeLocalAgentSessionFile(cloudSessionId, patch) {
34388
34712
  try {
34389
- const dir = LOCAL_AGENT_SESSION_DIR;
34390
- if (!fs10.existsSync(dir)) fs10.mkdirSync(dir, { recursive: true });
34391
- const p = localAgentSessionFilePath(cloudSessionId);
34713
+ const db = getCliDatabase();
34714
+ const key = sessionKeyForCloudSessionId(cloudSessionId);
34392
34715
  const prev = readLocalAgentSessionFile(cloudSessionId);
34393
34716
  const next = {
34394
34717
  v: 1,
@@ -34397,7 +34720,17 @@ function writeLocalAgentSessionFile(cloudSessionId, patch) {
34397
34720
  configOptions: patch.configOptions !== void 0 ? patch.configOptions : prev?.configOptions ?? null,
34398
34721
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
34399
34722
  };
34400
- fs10.writeFileSync(p, JSON.stringify(next, null, 2), "utf8");
34723
+ const configJson = next.configOptions != null ? JSON.stringify(next.configOptions) : null;
34724
+ db.run(
34725
+ `INSERT INTO agent_session (session_key, acp_session_id, backend_agent_type, config_options_json, updated_at)
34726
+ VALUES (?, ?, ?, ?, ?)
34727
+ ON CONFLICT(session_key) DO UPDATE SET
34728
+ acp_session_id = excluded.acp_session_id,
34729
+ backend_agent_type = excluded.backend_agent_type,
34730
+ config_options_json = excluded.config_options_json,
34731
+ updated_at = excluded.updated_at`,
34732
+ [key, next.acpSessionId, next.backendAgentType, configJson, next.updatedAt]
34733
+ );
34401
34734
  } catch {
34402
34735
  }
34403
34736
  }
@@ -34421,7 +34754,7 @@ async function ensureAcpClient(options) {
34421
34754
  if (state.acpStartPromise && !state.acpHandle) {
34422
34755
  await state.acpStartPromise;
34423
34756
  }
34424
- if (state.acpHandle && state.lastAcpCwd != null && path13.resolve(state.lastAcpCwd) !== path13.resolve(targetSessionParentPath)) {
34757
+ if (state.acpHandle && state.lastAcpCwd != null && path19.resolve(state.lastAcpCwd) !== path19.resolve(targetSessionParentPath)) {
34425
34758
  try {
34426
34759
  state.acpHandle.disconnect();
34427
34760
  } catch {
@@ -34456,7 +34789,7 @@ async function ensureAcpClient(options) {
34456
34789
  if (!state.acpStartPromise) {
34457
34790
  let statOk = false;
34458
34791
  try {
34459
- const st = fs11.statSync(targetSessionParentPath);
34792
+ const st = fs16.statSync(targetSessionParentPath);
34460
34793
  statOk = st.isDirectory();
34461
34794
  if (!statOk) {
34462
34795
  state.lastAcpStartError = `Agent cwd is not a directory: ${targetSessionParentPath}`;
@@ -34703,12 +35036,12 @@ async function createAcpManager(options) {
34703
35036
  }
34704
35037
 
34705
35038
  // src/worktrees/session-worktree-manager.ts
34706
- import * as path20 from "node:path";
34707
- import os5 from "node:os";
35039
+ import * as path26 from "node:path";
35040
+ import os8 from "node:os";
34708
35041
 
34709
35042
  // src/worktrees/prepare-new-session-worktrees.ts
34710
- import * as fs13 from "node:fs";
34711
- import * as path15 from "node:path";
35043
+ import * as fs18 from "node:fs";
35044
+ import * as path21 from "node:path";
34712
35045
 
34713
35046
  // src/git/worktree-add.ts
34714
35047
  async function gitWorktreeAddBranch(mainRepoPath, worktreePath, branch) {
@@ -34717,12 +35050,12 @@ async function gitWorktreeAddBranch(mainRepoPath, worktreePath, branch) {
34717
35050
  }
34718
35051
 
34719
35052
  // src/worktrees/worktree-layout-file.ts
34720
- import * as fs12 from "node:fs";
34721
- import * as path14 from "node:path";
34722
- import os4 from "node:os";
35053
+ import * as fs17 from "node:fs";
35054
+ import * as path20 from "node:path";
35055
+ import os7 from "node:os";
34723
35056
  var LAYOUT_FILENAME = "worktree-launcher-layout.json";
34724
35057
  function defaultWorktreeLayoutPath() {
34725
- return path14.join(os4.homedir(), ".buildautomaton", LAYOUT_FILENAME);
35058
+ return path20.join(os7.homedir(), ".buildautomaton", LAYOUT_FILENAME);
34726
35059
  }
34727
35060
  function normalizeLoadedLayout(raw) {
34728
35061
  if (raw && typeof raw === "object" && "launcherCwds" in raw) {
@@ -34734,8 +35067,8 @@ function normalizeLoadedLayout(raw) {
34734
35067
  function loadWorktreeLayout() {
34735
35068
  try {
34736
35069
  const p = defaultWorktreeLayoutPath();
34737
- if (!fs12.existsSync(p)) return { launcherCwds: [] };
34738
- const raw = JSON.parse(fs12.readFileSync(p, "utf8"));
35070
+ if (!fs17.existsSync(p)) return { launcherCwds: [] };
35071
+ const raw = JSON.parse(fs17.readFileSync(p, "utf8"));
34739
35072
  return normalizeLoadedLayout(raw);
34740
35073
  } catch {
34741
35074
  return { launcherCwds: [] };
@@ -34743,24 +35076,24 @@ function loadWorktreeLayout() {
34743
35076
  }
34744
35077
  function saveWorktreeLayout(layout) {
34745
35078
  try {
34746
- const dir = path14.dirname(defaultWorktreeLayoutPath());
34747
- fs12.mkdirSync(dir, { recursive: true });
34748
- fs12.writeFileSync(defaultWorktreeLayoutPath(), JSON.stringify(layout, null, 2), "utf8");
35079
+ const dir = path20.dirname(defaultWorktreeLayoutPath());
35080
+ fs17.mkdirSync(dir, { recursive: true });
35081
+ fs17.writeFileSync(defaultWorktreeLayoutPath(), JSON.stringify(layout, null, 2), "utf8");
34749
35082
  } catch {
34750
35083
  }
34751
35084
  }
34752
35085
  function baseNameSafe(pathString) {
34753
- return path14.basename(pathString).replace(/[^a-zA-Z0-9._-]+/g, "-") || "cwd";
35086
+ return path20.basename(pathString).replace(/[^a-zA-Z0-9._-]+/g, "-") || "cwd";
34754
35087
  }
34755
35088
  function getLauncherDirNameIfPresent(layout, bridgeRootPath2) {
34756
- const norm = path14.resolve(bridgeRootPath2);
34757
- const existing = layout.launcherCwds.find((e) => path14.resolve(e.absolutePath) === norm);
35089
+ const norm = path20.resolve(bridgeRootPath2);
35090
+ const existing = layout.launcherCwds.find((e) => path20.resolve(e.absolutePath) === norm);
34758
35091
  return existing?.dirName;
34759
35092
  }
34760
35093
  function allocateDirNameForLauncherCwd(layout, bridgeRootPath2) {
34761
35094
  const existing = getLauncherDirNameIfPresent(layout, bridgeRootPath2);
34762
35095
  if (existing) return existing;
34763
- const norm = path14.resolve(bridgeRootPath2);
35096
+ const norm = path20.resolve(bridgeRootPath2);
34764
35097
  const base = baseNameSafe(norm);
34765
35098
  const used = new Set(layout.launcherCwds.map((e) => e.dirName));
34766
35099
  let name = base;
@@ -34777,10 +35110,10 @@ function allocateDirNameForLauncherCwd(layout, bridgeRootPath2) {
34777
35110
  // src/worktrees/prepare-new-session-worktrees.ts
34778
35111
  async function prepareNewSessionWorktrees(options) {
34779
35112
  const { worktreesRootPath, bridgeRoot, sessionId, layout, log: log2 } = options;
34780
- const bridgeResolved = path15.resolve(bridgeRoot);
35113
+ const bridgeResolved = path21.resolve(bridgeRoot);
34781
35114
  const cwdKey = allocateDirNameForLauncherCwd(layout, bridgeResolved);
34782
- const bridgeKeyDir = path15.join(worktreesRootPath, cwdKey);
34783
- const sessionDir = path15.join(bridgeKeyDir, sessionId);
35115
+ const bridgeKeyDir = path21.join(worktreesRootPath, cwdKey);
35116
+ const sessionDir = path21.join(bridgeKeyDir, sessionId);
34784
35117
  const repos = await discoverGitReposUnderRoot(bridgeResolved);
34785
35118
  if (repos.length === 0) {
34786
35119
  log2("[worktrees] No Git repositories under bridge root; skipping worktree creation.");
@@ -34788,14 +35121,14 @@ async function prepareNewSessionWorktrees(options) {
34788
35121
  }
34789
35122
  const branch = `session-${sessionId}`;
34790
35123
  const worktreePaths = [];
34791
- fs13.mkdirSync(sessionDir, { recursive: true });
35124
+ fs18.mkdirSync(sessionDir, { recursive: true });
34792
35125
  for (const repo of repos) {
34793
- let rel = path15.relative(bridgeResolved, repo.absolutePath);
34794
- if (rel.startsWith("..") || path15.isAbsolute(rel)) continue;
35126
+ let rel = path21.relative(bridgeResolved, repo.absolutePath);
35127
+ if (rel.startsWith("..") || path21.isAbsolute(rel)) continue;
34795
35128
  const relNorm = rel === "" ? "." : rel;
34796
- const wtPath = relNorm === "." ? sessionDir : path15.join(sessionDir, relNorm);
35129
+ const wtPath = relNorm === "." ? sessionDir : path21.join(sessionDir, relNorm);
34797
35130
  if (relNorm !== ".") {
34798
- fs13.mkdirSync(path15.dirname(wtPath), { recursive: true });
35131
+ fs18.mkdirSync(path21.dirname(wtPath), { recursive: true });
34799
35132
  }
34800
35133
  try {
34801
35134
  await gitWorktreeAddBranch(repo.absolutePath, wtPath, branch);
@@ -34837,23 +35170,23 @@ async function renameSessionWorktreeBranches(paths, newBranch, log2) {
34837
35170
  }
34838
35171
 
34839
35172
  // src/worktrees/remove-session-worktrees.ts
34840
- import * as fs16 from "node:fs";
35173
+ import * as fs21 from "node:fs";
34841
35174
 
34842
35175
  // src/git/worktree-remove.ts
34843
- import * as fs15 from "node:fs";
35176
+ import * as fs20 from "node:fs";
34844
35177
 
34845
35178
  // src/git/resolve-main-repo-from-git-file.ts
34846
- import * as fs14 from "node:fs";
34847
- import * as path16 from "node:path";
35179
+ import * as fs19 from "node:fs";
35180
+ import * as path22 from "node:path";
34848
35181
  function resolveMainRepoFromWorktreeGitFile(wt) {
34849
- const gitDirFile = path16.join(wt, ".git");
34850
- if (!fs14.existsSync(gitDirFile) || !fs14.statSync(gitDirFile).isFile()) return "";
34851
- const first2 = fs14.readFileSync(gitDirFile, "utf8").trim();
35182
+ const gitDirFile = path22.join(wt, ".git");
35183
+ if (!fs19.existsSync(gitDirFile) || !fs19.statSync(gitDirFile).isFile()) return "";
35184
+ const first2 = fs19.readFileSync(gitDirFile, "utf8").trim();
34852
35185
  const m = first2.match(/^gitdir:\s*(.+)$/im);
34853
35186
  if (!m) return "";
34854
- const gitWorktreePath = path16.resolve(wt, m[1].trim());
34855
- const gitDir = path16.dirname(path16.dirname(gitWorktreePath));
34856
- return path16.dirname(gitDir);
35187
+ const gitWorktreePath = path22.resolve(wt, m[1].trim());
35188
+ const gitDir = path22.dirname(path22.dirname(gitWorktreePath));
35189
+ return path22.dirname(gitDir);
34857
35190
  }
34858
35191
 
34859
35192
  // src/git/worktree-remove.ts
@@ -34862,7 +35195,7 @@ async function gitWorktreeRemoveForce(worktreePath) {
34862
35195
  if (mainRepo) {
34863
35196
  await cliSimpleGit(mainRepo).raw(["worktree", "remove", "--force", worktreePath]);
34864
35197
  } else {
34865
- fs15.rmSync(worktreePath, { recursive: true, force: true });
35198
+ fs20.rmSync(worktreePath, { recursive: true, force: true });
34866
35199
  }
34867
35200
  }
34868
35201
 
@@ -34875,7 +35208,7 @@ async function removeSessionWorktrees(paths, log2) {
34875
35208
  } catch (e) {
34876
35209
  log2(`[worktrees] Remove failed for ${wt}: ${e instanceof Error ? e.message : String(e)}`);
34877
35210
  try {
34878
- fs16.rmSync(wt, { recursive: true, force: true });
35211
+ fs21.rmSync(wt, { recursive: true, force: true });
34879
35212
  } catch {
34880
35213
  }
34881
35214
  }
@@ -35095,7 +35428,7 @@ function formatRemoteDisplayLabel(remoteUrl) {
35095
35428
  }
35096
35429
 
35097
35430
  // src/git/working-directory/changes/get-working-tree-change-repo-details.ts
35098
- import * as path18 from "node:path";
35431
+ import * as path24 from "node:path";
35099
35432
 
35100
35433
  // src/git/working-directory/changes/parse-git-status.ts
35101
35434
  function parseNameStatusLines(lines) {
@@ -35215,8 +35548,8 @@ async function listChangedFilesForCommit(repoGitCwd, repoRelPath, commitSha) {
35215
35548
  }
35216
35549
 
35217
35550
  // src/git/working-directory/changes/list-changed-files-for-repo.ts
35218
- import * as fs18 from "node:fs";
35219
- import * as path17 from "node:path";
35551
+ import * as fs23 from "node:fs";
35552
+ import * as path23 from "node:path";
35220
35553
 
35221
35554
  // src/git/working-directory/changes/count-lines.ts
35222
35555
  import { createReadStream } from "node:fs";
@@ -35240,7 +35573,7 @@ async function countTextFileLines(filePath) {
35240
35573
  }
35241
35574
 
35242
35575
  // src/git/working-directory/changes/hydrate-patch.ts
35243
- import * as fs17 from "node:fs";
35576
+ import * as fs22 from "node:fs";
35244
35577
  var UNIFIED_HUNK_HEADER_RE = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/;
35245
35578
  var MAX_HYDRATE_LINES_PER_GAP = 8e3;
35246
35579
  var MAX_HYDRATE_LINES_PER_FILE = 8e4;
@@ -35255,7 +35588,7 @@ async function readGitBlobLines(repoCwd, pathInRepo) {
35255
35588
  }
35256
35589
  async function readWorktreeFileLines(filePath) {
35257
35590
  try {
35258
- const raw = await fs17.promises.readFile(filePath, "utf8");
35591
+ const raw = await fs22.promises.readFile(filePath, "utf8");
35259
35592
  return raw.split(/\r?\n/);
35260
35593
  } catch {
35261
35594
  return null;
@@ -35390,7 +35723,7 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
35390
35723
  const rows = [];
35391
35724
  for (const pathInRepo of paths) {
35392
35725
  const relLauncher = posixJoinDirFile(repoRelPath, pathInRepo.replace(/\\/g, "/"));
35393
- const repoFilePath = path17.join(repoGitCwd, pathInRepo);
35726
+ const repoFilePath = path23.join(repoGitCwd, pathInRepo);
35394
35727
  const nums = numByPath.get(pathInRepo);
35395
35728
  let additions = nums?.additions ?? 0;
35396
35729
  let deletions = nums?.deletions ?? 0;
@@ -35403,7 +35736,7 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
35403
35736
  deletions = fromGit.deletions;
35404
35737
  } else {
35405
35738
  try {
35406
- const st = await fs18.promises.stat(repoFilePath);
35739
+ const st = await fs23.promises.stat(repoFilePath);
35407
35740
  if (st.isFile()) additions = await countTextFileLines(repoFilePath);
35408
35741
  else additions = 0;
35409
35742
  } catch {
@@ -35429,7 +35762,7 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
35429
35762
  } else {
35430
35763
  pathInRepo = row.pathRelLauncher;
35431
35764
  }
35432
- const filePath = path17.join(repoGitCwd, pathInRepo);
35765
+ const filePath = path23.join(repoGitCwd, pathInRepo);
35433
35766
  let patch = await unifiedDiffForFile(repoGitCwd, pathInRepo, row.change);
35434
35767
  if (patch) {
35435
35768
  patch = await hydrateUnifiedPatchWithFileContext(patch, filePath, repoGitCwd, pathInRepo, row.change);
@@ -35445,8 +35778,8 @@ function normRepoRel(p) {
35445
35778
  return x === "" ? "." : x;
35446
35779
  }
35447
35780
  async function getWorkingTreeChangeRepoDetails(options) {
35448
- const bridgeRoot = path18.resolve(getBridgeRoot());
35449
- const sessionWtRoot = options.sessionWorktreeRootPath ? path18.resolve(options.sessionWorktreeRootPath) : null;
35781
+ const bridgeRoot = path24.resolve(getBridgeRoot());
35782
+ const sessionWtRoot = options.sessionWorktreeRootPath ? path24.resolve(options.sessionWorktreeRootPath) : null;
35450
35783
  const legacyNested = options.legacyRepoNestedSessionLayout === true;
35451
35784
  const out = [];
35452
35785
  const filter = options.repoFilterRelPath != null ? normRepoRel(options.repoFilterRelPath) : null;
@@ -35459,7 +35792,7 @@ async function getWorkingTreeChangeRepoDetails(options) {
35459
35792
  }
35460
35793
  const basis = filter == null && basisInput.kind === "commit" ? { kind: "working" } : basisInput;
35461
35794
  for (const target of options.commitTargetPaths) {
35462
- const t = path18.resolve(target);
35795
+ const t = path24.resolve(target);
35463
35796
  if (!await isGitRepoDirectory(t)) continue;
35464
35797
  const g = cliSimpleGit(t);
35465
35798
  let branch = "HEAD";
@@ -35472,8 +35805,8 @@ async function getWorkingTreeChangeRepoDetails(options) {
35472
35805
  const remoteDisplay = formatRemoteDisplayLabel(remoteUrl);
35473
35806
  let repoRelPath;
35474
35807
  if (sessionWtRoot) {
35475
- const anchor = legacyNested ? path18.dirname(t) : t;
35476
- const relNorm = path18.relative(sessionWtRoot, anchor);
35808
+ const anchor = legacyNested ? path24.dirname(t) : t;
35809
+ const relNorm = path24.relative(sessionWtRoot, anchor);
35477
35810
  repoRelPath = relNorm === "" ? "." : relNorm.replace(/\\/g, "/");
35478
35811
  } else {
35479
35812
  let top = t;
@@ -35482,8 +35815,8 @@ async function getWorkingTreeChangeRepoDetails(options) {
35482
35815
  } catch {
35483
35816
  top = t;
35484
35817
  }
35485
- const rel = path18.relative(bridgeRoot, path18.resolve(top)).replace(/\\/g, "/") || ".";
35486
- repoRelPath = rel.startsWith("..") ? path18.basename(path18.resolve(top)) : rel;
35818
+ const rel = path24.relative(bridgeRoot, path24.resolve(top)).replace(/\\/g, "/") || ".";
35819
+ repoRelPath = rel.startsWith("..") ? path24.basename(path24.resolve(top)) : rel;
35487
35820
  }
35488
35821
  const norm = normRepoRel(repoRelPath === "" ? "." : repoRelPath);
35489
35822
  if (filter && norm !== filter) continue;
@@ -35548,11 +35881,11 @@ async function commitSessionWorktrees(options) {
35548
35881
  }
35549
35882
 
35550
35883
  // src/worktrees/discover-session-worktree-on-disk.ts
35551
- import * as fs19 from "node:fs";
35552
- import * as path19 from "node:path";
35884
+ import * as fs24 from "node:fs";
35885
+ import * as path25 from "node:path";
35553
35886
  function isGitDir(dirPath) {
35554
35887
  try {
35555
- return fs19.existsSync(path19.join(dirPath, ".git"));
35888
+ return fs24.existsSync(path25.join(dirPath, ".git"));
35556
35889
  } catch {
35557
35890
  return false;
35558
35891
  }
@@ -35561,23 +35894,23 @@ function collectGitRepoRootsUnderDirectory(rootPath) {
35561
35894
  const out = [];
35562
35895
  const walk = (dir) => {
35563
35896
  if (isGitDir(dir)) {
35564
- out.push(path19.resolve(dir));
35897
+ out.push(path25.resolve(dir));
35565
35898
  return;
35566
35899
  }
35567
35900
  let entries;
35568
35901
  try {
35569
- entries = fs19.readdirSync(dir, { withFileTypes: true });
35902
+ entries = fs24.readdirSync(dir, { withFileTypes: true });
35570
35903
  } catch {
35571
35904
  return;
35572
35905
  }
35573
35906
  for (const e of entries) {
35574
35907
  if (e.name.startsWith(".")) continue;
35575
- const full = path19.join(dir, e.name);
35908
+ const full = path25.join(dir, e.name);
35576
35909
  if (!e.isDirectory()) continue;
35577
35910
  walk(full);
35578
35911
  }
35579
35912
  };
35580
- walk(path19.resolve(rootPath));
35913
+ walk(path25.resolve(rootPath));
35581
35914
  return [...new Set(out)];
35582
35915
  }
35583
35916
  function collectWorktreeRootsNamed(root, sessionId, maxDepth) {
@@ -35586,16 +35919,16 @@ function collectWorktreeRootsNamed(root, sessionId, maxDepth) {
35586
35919
  if (depth > maxDepth) return;
35587
35920
  let entries;
35588
35921
  try {
35589
- entries = fs19.readdirSync(dir, { withFileTypes: true });
35922
+ entries = fs24.readdirSync(dir, { withFileTypes: true });
35590
35923
  } catch {
35591
35924
  return;
35592
35925
  }
35593
35926
  for (const e of entries) {
35594
35927
  if (e.name.startsWith(".")) continue;
35595
- const full = path19.join(dir, e.name);
35928
+ const full = path25.join(dir, e.name);
35596
35929
  if (!e.isDirectory()) continue;
35597
35930
  if (e.name === sessionId) {
35598
- if (isGitDir(full)) out.push(path19.resolve(full));
35931
+ if (isGitDir(full)) out.push(path25.resolve(full));
35599
35932
  } else {
35600
35933
  walk(full, depth + 1);
35601
35934
  }
@@ -35607,14 +35940,14 @@ function collectWorktreeRootsNamed(root, sessionId, maxDepth) {
35607
35940
  function tryBindingFromSessionDirectory(sessionDir) {
35608
35941
  let st;
35609
35942
  try {
35610
- st = fs19.statSync(sessionDir);
35943
+ st = fs24.statSync(sessionDir);
35611
35944
  } catch {
35612
35945
  return null;
35613
35946
  }
35614
35947
  if (!st.isDirectory()) return null;
35615
35948
  const worktreePaths = collectGitRepoRootsUnderDirectory(sessionDir);
35616
35949
  if (worktreePaths.length === 0) return null;
35617
- const abs = path19.resolve(sessionDir);
35950
+ const abs = path25.resolve(sessionDir);
35618
35951
  return {
35619
35952
  sessionParentPath: abs,
35620
35953
  workingTreeRelRoot: abs,
@@ -35624,20 +35957,20 @@ function tryBindingFromSessionDirectory(sessionDir) {
35624
35957
  function discoverLegacyBindingAscendingFromCheckout(sessionId, checkoutPath) {
35625
35958
  const sid = sessionId.trim();
35626
35959
  if (!sid) return null;
35627
- const hintR = path19.resolve(checkoutPath);
35960
+ const hintR = path25.resolve(checkoutPath);
35628
35961
  let best = null;
35629
- let cur = path19.dirname(hintR);
35962
+ let cur = path25.dirname(hintR);
35630
35963
  for (let i = 0; i < 40; i++) {
35631
35964
  const paths = collectWorktreeRootsNamed(cur, sid, 24);
35632
- if (paths.some((p) => path19.resolve(p) === hintR)) {
35633
- const isolated = resolveIsolatedSessionParentPathFromCheckouts(paths) ?? path19.resolve(paths[0]);
35965
+ if (paths.some((p) => path25.resolve(p) === hintR)) {
35966
+ const isolated = resolveIsolatedSessionParentPathFromCheckouts(paths) ?? path25.resolve(paths[0]);
35634
35967
  best = {
35635
- sessionParentPath: path19.resolve(isolated),
35636
- workingTreeRelRoot: path19.resolve(cur),
35637
- repoCheckoutPaths: paths.map((p) => path19.resolve(p))
35968
+ sessionParentPath: path25.resolve(isolated),
35969
+ workingTreeRelRoot: path25.resolve(cur),
35970
+ repoCheckoutPaths: paths.map((p) => path25.resolve(p))
35638
35971
  };
35639
35972
  }
35640
- const next = path19.dirname(cur);
35973
+ const next = path25.dirname(cur);
35641
35974
  if (next === cur) break;
35642
35975
  cur = next;
35643
35976
  }
@@ -35645,33 +35978,33 @@ function discoverLegacyBindingAscendingFromCheckout(sessionId, checkoutPath) {
35645
35978
  }
35646
35979
  function discoverSessionWorktreeOnDisk(options) {
35647
35980
  const { sessionId, worktreesRootPath, layout, bridgeRoot } = options;
35648
- if (!sessionId.trim() || !fs19.existsSync(worktreesRootPath)) return null;
35981
+ if (!sessionId.trim() || !fs24.existsSync(worktreesRootPath)) return null;
35649
35982
  const preferredKey = getLauncherDirNameIfPresent(layout, bridgeRoot);
35650
35983
  const keys = [];
35651
35984
  if (preferredKey) keys.push(preferredKey);
35652
35985
  try {
35653
- for (const name of fs19.readdirSync(worktreesRootPath)) {
35986
+ for (const name of fs24.readdirSync(worktreesRootPath)) {
35654
35987
  if (name.startsWith(".")) continue;
35655
- const p = path19.join(worktreesRootPath, name);
35656
- if (!fs19.statSync(p).isDirectory()) continue;
35988
+ const p = path25.join(worktreesRootPath, name);
35989
+ if (!fs24.statSync(p).isDirectory()) continue;
35657
35990
  if (name !== preferredKey) keys.push(name);
35658
35991
  }
35659
35992
  } catch {
35660
35993
  return null;
35661
35994
  }
35662
35995
  for (const key of keys) {
35663
- const layoutRoot = path19.join(worktreesRootPath, key);
35664
- if (!fs19.existsSync(layoutRoot) || !fs19.statSync(layoutRoot).isDirectory()) continue;
35665
- const sessionDir = path19.join(layoutRoot, sessionId);
35996
+ const layoutRoot = path25.join(worktreesRootPath, key);
35997
+ if (!fs24.existsSync(layoutRoot) || !fs24.statSync(layoutRoot).isDirectory()) continue;
35998
+ const sessionDir = path25.join(layoutRoot, sessionId);
35666
35999
  const nested = tryBindingFromSessionDirectory(sessionDir);
35667
36000
  if (nested) return nested;
35668
36001
  const legacyPaths = collectWorktreeRootsNamed(layoutRoot, sessionId, 24);
35669
36002
  if (legacyPaths.length > 0) {
35670
- const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ?? path19.resolve(legacyPaths[0]);
36003
+ const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ?? path25.resolve(legacyPaths[0]);
35671
36004
  return {
35672
- sessionParentPath: path19.resolve(isolated),
35673
- workingTreeRelRoot: path19.resolve(layoutRoot),
35674
- repoCheckoutPaths: legacyPaths.map((p) => path19.resolve(p))
36005
+ sessionParentPath: path25.resolve(isolated),
36006
+ workingTreeRelRoot: path25.resolve(layoutRoot),
36007
+ repoCheckoutPaths: legacyPaths.map((p) => path25.resolve(p))
35675
36008
  };
35676
36009
  }
35677
36010
  }
@@ -35680,12 +36013,12 @@ function discoverSessionWorktreeOnDisk(options) {
35680
36013
  function discoverSessionWorktreesUnderSessionWorktreeRoot(sessionWorktreeRootPathOrHint, sessionId) {
35681
36014
  const sid = sessionId.trim();
35682
36015
  if (!sid) return null;
35683
- const hint = path19.resolve(sessionWorktreeRootPathOrHint);
35684
- const underHint = tryBindingFromSessionDirectory(path19.join(hint, sid));
36016
+ const hint = path25.resolve(sessionWorktreeRootPathOrHint);
36017
+ const underHint = tryBindingFromSessionDirectory(path25.join(hint, sid));
35685
36018
  if (underHint) return underHint;
35686
36019
  const direct = tryBindingFromSessionDirectory(hint);
35687
36020
  if (direct) {
35688
- if (path19.basename(hint) === sid && isGitDir(hint)) {
36021
+ if (path25.basename(hint) === sid && isGitDir(hint)) {
35689
36022
  const legacyFromCheckout = discoverLegacyBindingAscendingFromCheckout(sid, hint);
35690
36023
  if (legacyFromCheckout && legacyFromCheckout.repoCheckoutPaths.length > direct.repoCheckoutPaths.length) {
35691
36024
  return legacyFromCheckout;
@@ -35693,24 +36026,24 @@ function discoverSessionWorktreesUnderSessionWorktreeRoot(sessionWorktreeRootPat
35693
36026
  }
35694
36027
  return direct;
35695
36028
  }
35696
- if (path19.basename(hint) === sid && isGitDir(hint)) {
36029
+ if (path25.basename(hint) === sid && isGitDir(hint)) {
35697
36030
  const legacyFromCheckout = discoverLegacyBindingAscendingFromCheckout(sid, hint);
35698
36031
  if (legacyFromCheckout) return legacyFromCheckout;
35699
36032
  }
35700
36033
  let st;
35701
36034
  try {
35702
- st = fs19.statSync(hint);
36035
+ st = fs24.statSync(hint);
35703
36036
  } catch {
35704
36037
  return null;
35705
36038
  }
35706
36039
  if (!st.isDirectory()) return null;
35707
36040
  const legacyPaths = collectWorktreeRootsNamed(hint, sid, 24);
35708
36041
  if (legacyPaths.length === 0) return null;
35709
- const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ?? path19.resolve(legacyPaths[0]);
36042
+ const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ?? path25.resolve(legacyPaths[0]);
35710
36043
  return {
35711
- sessionParentPath: path19.resolve(isolated),
36044
+ sessionParentPath: path25.resolve(isolated),
35712
36045
  workingTreeRelRoot: hint,
35713
- repoCheckoutPaths: legacyPaths.map((p) => path19.resolve(p))
36046
+ repoCheckoutPaths: legacyPaths.map((p) => path25.resolve(p))
35714
36047
  };
35715
36048
  }
35716
36049
 
@@ -35733,10 +36066,10 @@ var SessionWorktreeManager = class {
35733
36066
  this.layout = loadWorktreeLayout();
35734
36067
  }
35735
36068
  rememberSessionWorktrees(sessionId, binding) {
35736
- const paths = binding.repoCheckoutPaths.map((p) => path20.resolve(p));
36069
+ const paths = binding.repoCheckoutPaths.map((p) => path26.resolve(p));
35737
36070
  this.sessionRepoCheckoutPaths.set(sessionId, paths);
35738
- this.sessionParentPathBySession.set(sessionId, path20.resolve(binding.sessionParentPath));
35739
- this.sessionWorkingTreeRelRootBySession.set(sessionId, path20.resolve(binding.workingTreeRelRoot));
36071
+ this.sessionParentPathBySession.set(sessionId, path26.resolve(binding.sessionParentPath));
36072
+ this.sessionWorkingTreeRelRootBySession.set(sessionId, path26.resolve(binding.workingTreeRelRoot));
35740
36073
  }
35741
36074
  sessionParentPathAfterRemember(sessionId) {
35742
36075
  return this.sessionParentPathBySession.get(sessionId);
@@ -35753,7 +36086,7 @@ var SessionWorktreeManager = class {
35753
36086
  const parent = this.sessionParentPathBySession.get(sessionId);
35754
36087
  const relRoot = this.sessionWorkingTreeRelRootBySession.get(sessionId);
35755
36088
  if (!parent || !relRoot) return false;
35756
- return path20.resolve(parent) !== path20.resolve(relRoot);
36089
+ return path26.resolve(parent) !== path26.resolve(relRoot);
35757
36090
  }
35758
36091
  /**
35759
36092
  * Session parent path for `worktrees_root`: the per-session directory (new layout) or primary checkout (legacy).
@@ -35762,7 +36095,7 @@ var SessionWorktreeManager = class {
35762
36095
  if (!sessionId) return null;
35763
36096
  const sid = sessionId.trim();
35764
36097
  const cached2 = this.sessionParentPathBySession.get(sid);
35765
- if (cached2) return path20.resolve(cached2);
36098
+ if (cached2) return path26.resolve(cached2);
35766
36099
  const paths = this.ensureRepoCheckoutPathsForSession(sid) ?? this.getRepoCheckoutPathsForSession(sid);
35767
36100
  if (!paths?.length) return null;
35768
36101
  return resolveIsolatedSessionParentPathFromCheckouts(paths);
@@ -35776,7 +36109,7 @@ var SessionWorktreeManager = class {
35776
36109
  const sid = sessionId.trim();
35777
36110
  const parentPathRaw = opts.sessionParentPath?.trim();
35778
36111
  if (parentPathRaw) {
35779
- const resolved = path20.resolve(parentPathRaw);
36112
+ const resolved = path26.resolve(parentPathRaw);
35780
36113
  if (sid && parseSessionParent(opts.sessionParent) === "worktrees_root") {
35781
36114
  const diskFirst = this.tryDiscoverFromDisk(sid);
35782
36115
  if (diskFirst) {
@@ -35795,7 +36128,7 @@ var SessionWorktreeManager = class {
35795
36128
  this.rememberSessionWorktrees(sid, tryRoot);
35796
36129
  return this.sessionParentPathAfterRemember(sid);
35797
36130
  }
35798
- const next = path20.dirname(cur);
36131
+ const next = path26.dirname(cur);
35799
36132
  if (next === cur) break;
35800
36133
  cur = next;
35801
36134
  }
@@ -35948,15 +36281,22 @@ var SessionWorktreeManager = class {
35948
36281
  }
35949
36282
  };
35950
36283
  function defaultWorktreesRootPath() {
35951
- return path20.join(os5.homedir(), ".buildautomaton", "worktrees");
36284
+ return path26.join(os8.homedir(), ".buildautomaton", "worktrees");
35952
36285
  }
35953
36286
 
35954
36287
  // src/files/watch-file-index.ts
35955
36288
  import { watch } from "node:fs";
36289
+ import path31 from "node:path";
36290
+
36291
+ // src/files/index/paths.ts
35956
36292
  import path27 from "node:path";
36293
+ import crypto2 from "node:crypto";
36294
+ function getCwdHashForFileIndex(resolvedCwd) {
36295
+ return crypto2.createHash("sha256").update(path27.resolve(resolvedCwd)).digest("hex").slice(0, INDEX_HASH_LEN);
36296
+ }
35957
36297
 
35958
36298
  // src/files/index/build-file-index.ts
35959
- import path24 from "node:path";
36299
+ import path29 from "node:path";
35960
36300
 
35961
36301
  // src/runtime/yield-to-event-loop.ts
35962
36302
  function yieldToEventLoop() {
@@ -35964,47 +36304,12 @@ function yieldToEventLoop() {
35964
36304
  }
35965
36305
 
35966
36306
  // src/files/index/walk-workspace-tree.ts
35967
- import fs20 from "node:fs";
35968
- import path22 from "node:path";
35969
-
35970
- // src/files/index/constants.ts
35971
- import path21 from "node:path";
35972
- import os6 from "node:os";
35973
- var INDEX_WORK_YIELD_EVERY = 256;
35974
- var INDEX_DIR = path21.join(os6.homedir(), ".buildautomaton");
35975
- var INDEX_HASH_LEN = 16;
35976
- var INDEX_VERSION = 2;
35977
- var INDEX_LOG_PREFIX = "[file-index]";
35978
-
35979
- // src/files/index/walk-workspace-tree.ts
35980
- function walkWorkspaceTreeSync(dir, baseDir, out) {
35981
- let names;
35982
- try {
35983
- names = fs20.readdirSync(dir);
35984
- } catch {
35985
- return;
35986
- }
35987
- for (const name of names) {
35988
- if (name.startsWith(".")) continue;
35989
- const full = path22.join(dir, name);
35990
- let stat3;
35991
- try {
35992
- stat3 = fs20.statSync(full);
35993
- } catch {
35994
- continue;
35995
- }
35996
- const relative5 = path22.relative(baseDir, full).replace(/\\/g, "/");
35997
- if (stat3.isDirectory()) {
35998
- walkWorkspaceTreeSync(full, baseDir, out);
35999
- } else if (stat3.isFile()) {
36000
- out.push(relative5);
36001
- }
36002
- }
36003
- }
36307
+ import fs25 from "node:fs";
36308
+ import path28 from "node:path";
36004
36309
  async function walkWorkspaceTreeAsync(dir, baseDir, out, state) {
36005
36310
  let names;
36006
36311
  try {
36007
- names = await fs20.promises.readdir(dir);
36312
+ names = await fs25.promises.readdir(dir);
36008
36313
  } catch {
36009
36314
  return;
36010
36315
  }
@@ -36014,14 +36319,14 @@ async function walkWorkspaceTreeAsync(dir, baseDir, out, state) {
36014
36319
  await yieldToEventLoop();
36015
36320
  }
36016
36321
  state.n++;
36017
- const full = path22.join(dir, name);
36322
+ const full = path28.join(dir, name);
36018
36323
  let stat3;
36019
36324
  try {
36020
- stat3 = await fs20.promises.stat(full);
36325
+ stat3 = await fs25.promises.stat(full);
36021
36326
  } catch {
36022
36327
  continue;
36023
36328
  }
36024
- const relative5 = path22.relative(baseDir, full).replace(/\\/g, "/");
36329
+ const relative5 = path28.relative(baseDir, full).replace(/\\/g, "/");
36025
36330
  if (stat3.isDirectory()) {
36026
36331
  await walkWorkspaceTreeAsync(full, baseDir, out, state);
36027
36332
  } else if (stat3.isFile()) {
@@ -36033,205 +36338,124 @@ function createWalkYieldState() {
36033
36338
  return { n: 0 };
36034
36339
  }
36035
36340
 
36036
- // src/files/index/trigram-utils.ts
36037
- function getTrigrams(s) {
36038
- const lower = s.toLowerCase();
36039
- const out = [];
36040
- for (let i = 0; i <= lower.length - 3; i++) {
36041
- out.push(lower.slice(i, i + 3));
36042
- }
36043
- return out;
36044
- }
36045
- function binarySearch(arr, x) {
36046
- let lo = 0;
36047
- let hi = arr.length - 1;
36048
- while (lo <= hi) {
36049
- const mid = lo + hi >>> 1;
36050
- if (arr[mid] < x) lo = mid + 1;
36051
- else if (arr[mid] > x) hi = mid - 1;
36052
- else return mid;
36053
- }
36054
- return -1;
36055
- }
36056
- function intersectSortedTrigramSets(arrays) {
36057
- if (arrays.length === 0) return [];
36058
- if (arrays.length === 1) return arrays[0];
36059
- const byLength = arrays.slice().sort((a, b) => a.length - b.length);
36060
- const smallest = byLength[0];
36061
- const rest = byLength.slice(1);
36062
- const result = [];
36063
- for (const idx of smallest) {
36064
- if (rest.every((arr) => binarySearch(arr, idx) >= 0)) {
36065
- result.push(idx);
36066
- }
36067
- }
36068
- return result;
36069
- }
36070
-
36071
- // src/files/index/build-trigram-map.ts
36072
- function buildTrigramMapForPaths(paths) {
36073
- const trigramIndex = {};
36074
- for (let i = 0; i < paths.length; i++) {
36075
- const trigrams = getTrigrams(paths[i]);
36076
- const seen = /* @__PURE__ */ new Set();
36077
- for (const tri of trigrams) {
36078
- if (seen.has(tri)) continue;
36079
- seen.add(tri);
36080
- if (!trigramIndex[tri]) trigramIndex[tri] = [];
36081
- trigramIndex[tri].push(i);
36082
- }
36083
- }
36084
- return trigramIndex;
36341
+ // src/files/index/file-index-sqlite-lock.ts
36342
+ import fs26 from "node:fs";
36343
+ function isSqliteCorruptError(e) {
36344
+ const msg = e instanceof Error ? e.message : String(e);
36345
+ return msg.includes("malformed") || msg.includes("database disk image is malformed") || msg.includes("corrupt");
36085
36346
  }
36086
- async function buildTrigramMapForPathsAsync(paths) {
36087
- const trigramIndex = {};
36088
- for (let i = 0; i < paths.length; i++) {
36089
- if (i > 0 && i % INDEX_WORK_YIELD_EVERY === 0) {
36090
- await yieldToEventLoop();
36091
- }
36092
- const trigrams = getTrigrams(paths[i]);
36093
- const seen = /* @__PURE__ */ new Set();
36094
- for (const tri of trigrams) {
36095
- if (seen.has(tri)) continue;
36096
- seen.add(tri);
36097
- if (!trigramIndex[tri]) trigramIndex[tri] = [];
36098
- trigramIndex[tri].push(i);
36347
+ var chain = Promise.resolve();
36348
+ function withFileIndexSqliteLock(fn) {
36349
+ const run = async () => {
36350
+ try {
36351
+ return await Promise.resolve(fn());
36352
+ } catch (e) {
36353
+ if (!isSqliteCorruptError(e)) throw e;
36354
+ closeAllCliSqliteConnections();
36355
+ try {
36356
+ fs26.unlinkSync(getCliSqlitePath());
36357
+ } catch {
36358
+ }
36359
+ chain = Promise.resolve();
36360
+ return await Promise.resolve(fn());
36099
36361
  }
36100
- }
36101
- return trigramIndex;
36102
- }
36103
-
36104
- // src/files/index/write-index-file.ts
36105
- import fs21 from "node:fs";
36106
-
36107
- // src/files/index/paths.ts
36108
- import path23 from "node:path";
36109
- import crypto2 from "node:crypto";
36110
- function getIndexPathForCwd(resolvedCwd) {
36111
- const hash = crypto2.createHash("sha256").update(resolvedCwd).digest("hex").slice(0, INDEX_HASH_LEN);
36112
- return path23.join(INDEX_DIR, `.file-index-${hash}.json`);
36113
- }
36114
-
36115
- // src/files/index/write-index-file.ts
36116
- function writeIndexFileSync(resolvedCwd, data) {
36117
- const indexPath = getIndexPathForCwd(resolvedCwd);
36118
- try {
36119
- if (!fs21.existsSync(INDEX_DIR)) fs21.mkdirSync(INDEX_DIR, { recursive: true });
36120
- fs21.writeFileSync(indexPath, JSON.stringify(data), "utf8");
36121
- } catch (e) {
36122
- console.error(`${INDEX_LOG_PREFIX} Failed to write index:`, e);
36123
- }
36124
- }
36125
- async function writeIndexFileAsync(resolvedCwd, data) {
36126
- const indexPath = getIndexPathForCwd(resolvedCwd);
36127
- try {
36128
- await fs21.promises.mkdir(INDEX_DIR, { recursive: true });
36129
- await fs21.promises.writeFile(indexPath, JSON.stringify(data), "utf8");
36130
- } catch (e) {
36131
- console.error(`${INDEX_LOG_PREFIX} Failed to write index:`, e);
36132
- }
36133
- }
36134
- function makeTrigramIndexData(paths, trigramIndex) {
36135
- return { version: INDEX_VERSION, paths, trigramIndex };
36362
+ };
36363
+ const next = chain.then(run);
36364
+ chain = next.then(
36365
+ () => void 0,
36366
+ () => void 0
36367
+ );
36368
+ return next;
36136
36369
  }
36137
36370
 
36138
36371
  // src/files/index/build-file-index.ts
36139
36372
  function sortPaths(paths) {
36140
36373
  paths.sort((a, b) => a.localeCompare(b, void 0, { sensitivity: "base" }));
36141
36374
  }
36142
- function buildFileIndex(cwd) {
36143
- const resolved = path24.resolve(cwd);
36144
- const paths = [];
36145
- walkWorkspaceTreeSync(resolved, resolved, paths);
36146
- sortPaths(paths);
36147
- const trigramIndex = buildTrigramMapForPaths(paths);
36148
- const data = makeTrigramIndexData(paths, trigramIndex);
36149
- writeIndexFileSync(resolved, data);
36150
- return data;
36151
- }
36152
- async function buildFileIndexAsync(cwd) {
36153
- const resolved = path24.resolve(cwd);
36154
- const paths = [];
36155
- await walkWorkspaceTreeAsync(resolved, resolved, paths, createWalkYieldState());
36156
- await yieldToEventLoop();
36157
- sortPaths(paths);
36158
- const trigramIndex = await buildTrigramMapForPathsAsync(paths);
36159
- const data = makeTrigramIndexData(paths, trigramIndex);
36160
- await writeIndexFileAsync(resolved, data);
36161
- return data;
36162
- }
36163
-
36164
- // src/files/index/load-file-index.ts
36165
- import fs22 from "node:fs";
36166
- import path25 from "node:path";
36167
- function loadFileIndex(cwd) {
36168
- const resolved = path25.resolve(cwd);
36169
- const indexPath = getIndexPathForCwd(resolved);
36375
+ function persistPathsToSqlite(resolved, paths) {
36376
+ const db = getCliDatabase();
36377
+ const h = getCwdHashForFileIndex(resolved);
36378
+ db.run("BEGIN IMMEDIATE");
36170
36379
  try {
36171
- const raw = fs22.readFileSync(indexPath, "utf8");
36172
- const parsed = JSON.parse(raw);
36173
- if (parsed !== null && typeof parsed === "object" && Array.isArray(parsed.paths)) {
36174
- const obj = parsed;
36175
- if (obj.version === INDEX_VERSION && obj.trigramIndex && typeof obj.trigramIndex === "object") {
36176
- return obj;
36380
+ db.run("DELETE FROM file_index_path WHERE cwd_hash = ?", [h]);
36381
+ const ins = db.prepare("INSERT INTO file_index_path (cwd_hash, path) VALUES (?, ?)");
36382
+ try {
36383
+ for (const rel of paths) {
36384
+ ins.run([h, rel]);
36177
36385
  }
36178
- return buildFileIndex(resolved);
36386
+ } finally {
36387
+ ins.finalize();
36179
36388
  }
36180
- if (Array.isArray(parsed) && parsed.every((p) => typeof p === "string")) {
36181
- return buildFileIndex(resolved);
36389
+ db.run("COMMIT");
36390
+ } catch (e) {
36391
+ try {
36392
+ db.run("ROLLBACK");
36393
+ } catch {
36182
36394
  }
36183
- return null;
36184
- } catch {
36185
- return null;
36395
+ throw e;
36186
36396
  }
36187
36397
  }
36398
+ async function buildFileIndexAsync(cwd) {
36399
+ return withFileIndexSqliteLock(async () => {
36400
+ const resolved = path29.resolve(cwd);
36401
+ const paths = [];
36402
+ await walkWorkspaceTreeAsync(resolved, resolved, paths, createWalkYieldState());
36403
+ await yieldToEventLoop();
36404
+ sortPaths(paths);
36405
+ persistPathsToSqlite(resolved, paths);
36406
+ return { pathCount: paths.length };
36407
+ });
36408
+ }
36188
36409
 
36189
36410
  // src/files/index/ensure-file-index.ts
36190
- import path26 from "node:path";
36191
- async function ensureFileIndexAsync(cwd) {
36192
- const resolved = path26.resolve(cwd);
36193
- const cached2 = loadFileIndex(resolved);
36194
- if (cached2 !== null) return { data: cached2, fromCache: true };
36195
- const data = await buildFileIndexAsync(resolved);
36196
- return { data, fromCache: false };
36197
- }
36411
+ import path30 from "node:path";
36198
36412
 
36199
36413
  // src/files/index/search-file-index.ts
36200
- function candidatePathIndices(index, q) {
36201
- const { paths, trigramIndex } = index;
36202
- if (q.length < 3) {
36203
- return paths.map((_, i) => i).filter((i) => paths[i].toLowerCase().includes(q));
36204
- }
36205
- const trigrams = getTrigrams(q);
36206
- if (trigrams.length === 0) {
36207
- return paths.map((_, i) => i).filter((i) => paths[i].toLowerCase().includes(q));
36208
- }
36209
- const arrays = trigrams.map((tri) => trigramIndex[tri]).filter((arr) => arr != null && arr.length > 0);
36210
- if (arrays.length === 0) return [];
36211
- return intersectSortedTrigramSets(arrays);
36212
- }
36213
- async function searchFileIndexAsync(index, query, limit = 100) {
36214
- await yieldToEventLoop();
36414
+ function escapeLikePattern(fragment) {
36415
+ return fragment.replace(/\\/g, "\\\\").replace(/%/g, "\\%").replace(/_/g, "\\_");
36416
+ }
36417
+ function bridgeFileIndexIsPopulated(resolvedCwd) {
36418
+ const db = getCliDatabase();
36419
+ const h = getCwdHashForFileIndex(resolvedCwd);
36420
+ const row = db.get("SELECT 1 as ok FROM file_index_path WHERE cwd_hash = ? LIMIT 1", [h]);
36421
+ return row != null;
36422
+ }
36423
+ function bridgeFileIndexPathCount(resolvedCwd) {
36424
+ const db = getCliDatabase();
36425
+ const h = getCwdHashForFileIndex(resolvedCwd);
36426
+ const row = db.get("SELECT COUNT(*) as c FROM file_index_path WHERE cwd_hash = ?", [h]);
36427
+ const c = row?.c ?? 0;
36428
+ return Number(c);
36429
+ }
36430
+ function searchBridgeFilePaths(resolvedCwd, query, limit = 100) {
36215
36431
  const q = query.trim().toLowerCase();
36216
36432
  if (!q) return [];
36217
- const { paths } = index;
36218
- const candidateIndices = candidatePathIndices(index, q);
36219
- const out = [];
36220
- let n = 0;
36221
- for (const i of candidateIndices) {
36222
- if (n > 0 && n % INDEX_WORK_YIELD_EVERY === 0) {
36223
- await yieldToEventLoop();
36224
- }
36225
- const p = paths[i];
36226
- if (p.toLowerCase().includes(q)) {
36227
- out.push(p);
36228
- if (out.length >= limit) break;
36229
- }
36230
- n++;
36231
- }
36433
+ const db = getCliDatabase();
36434
+ const h = getCwdHashForFileIndex(resolvedCwd);
36435
+ const pattern = `%${escapeLikePattern(q)}%`;
36436
+ const lim = Math.max(0, Math.min(1e4, Math.floor(limit)));
36437
+ const rows = db.all(
36438
+ `SELECT path FROM file_index_path WHERE cwd_hash = ? AND lower(path) LIKE ? ESCAPE '\\' LIMIT ?`,
36439
+ [h, pattern, lim]
36440
+ );
36441
+ return rows.map((r) => String(r.path));
36442
+ }
36443
+ async function searchBridgeFilePathsAsync(resolvedCwd, query, limit = 100) {
36444
+ await yieldToEventLoop();
36445
+ const out = searchBridgeFilePaths(resolvedCwd, query, limit);
36446
+ if (out.length >= INDEX_WORK_YIELD_EVERY) await yieldToEventLoop();
36232
36447
  return out;
36233
36448
  }
36234
36449
 
36450
+ // src/files/index/ensure-file-index.ts
36451
+ async function ensureFileIndexAsync(cwd) {
36452
+ const resolved = path30.resolve(cwd);
36453
+ if (bridgeFileIndexIsPopulated(resolved)) {
36454
+ return { fromCache: true, pathCount: bridgeFileIndexPathCount(resolved) };
36455
+ }
36456
+ return { ...await buildFileIndexAsync(resolved), fromCache: false };
36457
+ }
36458
+
36235
36459
  // src/files/watch-file-index.ts
36236
36460
  var DEBOUNCE_MS = 900;
36237
36461
  function shouldIgnoreRelative(rel) {
@@ -36272,7 +36496,7 @@ function createFsWatcher(resolved, schedule) {
36272
36496
  }
36273
36497
  }
36274
36498
  function startFileIndexWatcher(cwd = getBridgeRoot()) {
36275
- const resolved = path27.resolve(cwd);
36499
+ const resolved = path31.resolve(cwd);
36276
36500
  void buildFileIndexAsync(resolved).catch((e) => {
36277
36501
  console.error("[file-index] Initial index build failed:", e);
36278
36502
  });
@@ -36300,7 +36524,7 @@ function startFileIndexWatcher(cwd = getBridgeRoot()) {
36300
36524
  }
36301
36525
 
36302
36526
  // src/connection/create-bridge-connection.ts
36303
- import * as path35 from "node:path";
36527
+ import * as path39 from "node:path";
36304
36528
 
36305
36529
  // src/dev-servers/manager/dev-server-manager.ts
36306
36530
  import { rm as rm2 } from "node:fs/promises";
@@ -36344,7 +36568,7 @@ function forceKillChild(proc, log2, shortId, graceMs) {
36344
36568
  }
36345
36569
 
36346
36570
  // src/dev-servers/process/wire-dev-server-child-process.ts
36347
- import fs23 from "node:fs";
36571
+ import fs27 from "node:fs";
36348
36572
 
36349
36573
  // src/dev-servers/manager/forward-pipe.ts
36350
36574
  function forwardChildPipe(childReadable, terminal, onData) {
@@ -36380,7 +36604,7 @@ function wireDevServerChildProcess(d) {
36380
36604
  d.setPollInterval(void 0);
36381
36605
  return;
36382
36606
  }
36383
- fs23.readFile(d.mergedLogPath, (err, buf) => {
36607
+ fs27.readFile(d.mergedLogPath, (err, buf) => {
36384
36608
  if (err || (d.getSpawnGeneration() ?? 0) !== d.scheduledGen) return;
36385
36609
  if (buf.length <= d.mergedReadPos.value) return;
36386
36610
  const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
@@ -36418,7 +36642,7 @@ ${errTail}` : ""}`);
36418
36642
  d.sendStatus(code === 0 || code == null ? "stopped" : "error", detail, tails);
36419
36643
  };
36420
36644
  if (mergedPath) {
36421
- fs23.readFile(mergedPath, (err, buf) => {
36645
+ fs27.readFile(mergedPath, (err, buf) => {
36422
36646
  if (!err && buf.length > d.mergedReadPos.value) {
36423
36647
  const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
36424
36648
  if (chunk.length > 0) {
@@ -36520,13 +36744,13 @@ function parseDevServerDefs(servers) {
36520
36744
  }
36521
36745
 
36522
36746
  // src/dev-servers/manager/shell-spawn/utils.ts
36523
- import fs24 from "node:fs";
36747
+ import fs28 from "node:fs";
36524
36748
  function isSpawnEbadf(e) {
36525
36749
  return typeof e === "object" && e !== null && "code" in e && e.code === "EBADF";
36526
36750
  }
36527
36751
  function rmDirQuiet(dir) {
36528
36752
  try {
36529
- fs24.rmSync(dir, { recursive: true, force: true });
36753
+ fs28.rmSync(dir, { recursive: true, force: true });
36530
36754
  } catch {
36531
36755
  }
36532
36756
  }
@@ -36534,7 +36758,7 @@ var cachedDevNullReadFd;
36534
36758
  function devNullReadFd() {
36535
36759
  if (cachedDevNullReadFd === void 0) {
36536
36760
  const devPath = process.platform === "win32" ? "nul" : "/dev/null";
36537
- cachedDevNullReadFd = fs24.openSync(devPath, "r");
36761
+ cachedDevNullReadFd = fs28.openSync(devPath, "r");
36538
36762
  }
36539
36763
  return cachedDevNullReadFd;
36540
36764
  }
@@ -36608,15 +36832,15 @@ function trySpawnShellTruePiped(command, env, cwd, devNullFd, signal) {
36608
36832
 
36609
36833
  // src/dev-servers/manager/shell-spawn/try-spawn-merged-log-file.ts
36610
36834
  import { spawn as spawn6 } from "node:child_process";
36611
- import fs25 from "node:fs";
36835
+ import fs29 from "node:fs";
36612
36836
  import { tmpdir } from "node:os";
36613
- import path28 from "node:path";
36837
+ import path32 from "node:path";
36614
36838
  function trySpawnMergedLogFile(command, env, cwd, signal) {
36615
- const tmpRoot = fs25.mkdtempSync(path28.join(tmpdir(), "ba-devsrv-log-"));
36616
- const logPath = path28.join(tmpRoot, "combined.log");
36839
+ const tmpRoot = fs29.mkdtempSync(path32.join(tmpdir(), "ba-devsrv-log-"));
36840
+ const logPath = path32.join(tmpRoot, "combined.log");
36617
36841
  let logFd;
36618
36842
  try {
36619
- logFd = fs25.openSync(logPath, "a");
36843
+ logFd = fs29.openSync(logPath, "a");
36620
36844
  } catch {
36621
36845
  rmDirQuiet(tmpRoot);
36622
36846
  return null;
@@ -36635,7 +36859,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
36635
36859
  } else {
36636
36860
  proc = spawn6("/bin/sh", ["-c", command], { env, cwd, stdio, ...signal ? { signal } : {} });
36637
36861
  }
36638
- fs25.closeSync(logFd);
36862
+ fs29.closeSync(logFd);
36639
36863
  return {
36640
36864
  proc,
36641
36865
  pipedStdoutStderr: true,
@@ -36644,7 +36868,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
36644
36868
  };
36645
36869
  } catch (e) {
36646
36870
  try {
36647
- fs25.closeSync(logFd);
36871
+ fs29.closeSync(logFd);
36648
36872
  } catch {
36649
36873
  }
36650
36874
  rmDirQuiet(tmpRoot);
@@ -36655,22 +36879,22 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
36655
36879
 
36656
36880
  // src/dev-servers/manager/shell-spawn/try-spawn-shell-script-log-redirect.ts
36657
36881
  import { spawn as spawn7 } from "node:child_process";
36658
- import fs26 from "node:fs";
36882
+ import fs30 from "node:fs";
36659
36883
  import { tmpdir as tmpdir2 } from "node:os";
36660
- import path29 from "node:path";
36884
+ import path33 from "node:path";
36661
36885
  function shSingleQuote(s) {
36662
36886
  return `'${s.replace(/'/g, `'\\''`)}'`;
36663
36887
  }
36664
36888
  function trySpawnShellScriptLogRedirectUnix(command, env, cwd, signal) {
36665
- const tmpRoot = fs26.mkdtempSync(path29.join(tmpdir2(), "ba-devsrv-sh-"));
36666
- const logPath = path29.join(tmpRoot, "combined.log");
36667
- const innerPath = path29.join(tmpRoot, "_cmd.sh");
36668
- const runnerPath = path29.join(tmpRoot, "_run.sh");
36889
+ const tmpRoot = fs30.mkdtempSync(path33.join(tmpdir2(), "ba-devsrv-sh-"));
36890
+ const logPath = path33.join(tmpRoot, "combined.log");
36891
+ const innerPath = path33.join(tmpRoot, "_cmd.sh");
36892
+ const runnerPath = path33.join(tmpRoot, "_run.sh");
36669
36893
  try {
36670
- fs26.writeFileSync(innerPath, `#!/bin/sh
36894
+ fs30.writeFileSync(innerPath, `#!/bin/sh
36671
36895
  ${command}
36672
36896
  `);
36673
- fs26.writeFileSync(
36897
+ fs30.writeFileSync(
36674
36898
  runnerPath,
36675
36899
  `#!/bin/sh
36676
36900
  cd ${shSingleQuote(cwd)}
@@ -36696,13 +36920,13 @@ cd ${shSingleQuote(cwd)}
36696
36920
  }
36697
36921
  }
36698
36922
  function trySpawnShellScriptLogRedirectWin(command, env, cwd, signal) {
36699
- const tmpRoot = fs26.mkdtempSync(path29.join(tmpdir2(), "ba-devsrv-sh-"));
36700
- const logPath = path29.join(tmpRoot, "combined.log");
36701
- const runnerPath = path29.join(tmpRoot, "_run.bat");
36923
+ const tmpRoot = fs30.mkdtempSync(path33.join(tmpdir2(), "ba-devsrv-sh-"));
36924
+ const logPath = path33.join(tmpRoot, "combined.log");
36925
+ const runnerPath = path33.join(tmpRoot, "_run.bat");
36702
36926
  const q = (p) => `"${p.replace(/"/g, '""')}"`;
36703
36927
  const com = process.env.ComSpec || "cmd.exe";
36704
36928
  try {
36705
- fs26.writeFileSync(
36929
+ fs30.writeFileSync(
36706
36930
  runnerPath,
36707
36931
  `@ECHO OFF\r
36708
36932
  CD /D ${q(cwd)}\r
@@ -37639,30 +37863,30 @@ function createOnBridgeIdentified(opts) {
37639
37863
  }
37640
37864
 
37641
37865
  // src/skills/discover-local-agent-skills.ts
37642
- import fs27 from "node:fs";
37643
- import path30 from "node:path";
37866
+ import fs31 from "node:fs";
37867
+ import path34 from "node:path";
37644
37868
  var SKILL_DISCOVERY_ROOTS = [".agents/skills", ".claude/skills", ".cursor/skills", "skills"];
37645
37869
  function discoverLocalSkills(cwd) {
37646
37870
  const out = [];
37647
37871
  const seenKeys = /* @__PURE__ */ new Set();
37648
37872
  for (const rel of SKILL_DISCOVERY_ROOTS) {
37649
- const base = path30.join(cwd, rel);
37650
- if (!fs27.existsSync(base) || !fs27.statSync(base).isDirectory()) continue;
37873
+ const base = path34.join(cwd, rel);
37874
+ if (!fs31.existsSync(base) || !fs31.statSync(base).isDirectory()) continue;
37651
37875
  let entries = [];
37652
37876
  try {
37653
- entries = fs27.readdirSync(base);
37877
+ entries = fs31.readdirSync(base);
37654
37878
  } catch {
37655
37879
  continue;
37656
37880
  }
37657
37881
  for (const name of entries) {
37658
- const dir = path30.join(base, name);
37882
+ const dir = path34.join(base, name);
37659
37883
  try {
37660
- if (!fs27.statSync(dir).isDirectory()) continue;
37884
+ if (!fs31.statSync(dir).isDirectory()) continue;
37661
37885
  } catch {
37662
37886
  continue;
37663
37887
  }
37664
- const skillMd = path30.join(dir, "SKILL.md");
37665
- if (!fs27.existsSync(skillMd)) continue;
37888
+ const skillMd = path34.join(dir, "SKILL.md");
37889
+ if (!fs31.existsSync(skillMd)) continue;
37666
37890
  const key = `${rel}/${name}`;
37667
37891
  if (seenKeys.has(key)) continue;
37668
37892
  seenKeys.add(key);
@@ -37674,23 +37898,23 @@ function discoverLocalSkills(cwd) {
37674
37898
  function discoverSkillLayoutRoots(cwd) {
37675
37899
  const roots = [];
37676
37900
  for (const rel of SKILL_DISCOVERY_ROOTS) {
37677
- const base = path30.join(cwd, rel);
37678
- if (!fs27.existsSync(base) || !fs27.statSync(base).isDirectory()) continue;
37901
+ const base = path34.join(cwd, rel);
37902
+ if (!fs31.existsSync(base) || !fs31.statSync(base).isDirectory()) continue;
37679
37903
  let entries = [];
37680
37904
  try {
37681
- entries = fs27.readdirSync(base);
37905
+ entries = fs31.readdirSync(base);
37682
37906
  } catch {
37683
37907
  continue;
37684
37908
  }
37685
37909
  const skills2 = [];
37686
37910
  for (const name of entries) {
37687
- const dir = path30.join(base, name);
37911
+ const dir = path34.join(base, name);
37688
37912
  try {
37689
- if (!fs27.statSync(dir).isDirectory()) continue;
37913
+ if (!fs31.statSync(dir).isDirectory()) continue;
37690
37914
  } catch {
37691
37915
  continue;
37692
37916
  }
37693
- if (!fs27.existsSync(path30.join(dir, "SKILL.md"))) continue;
37917
+ if (!fs31.existsSync(path34.join(dir, "SKILL.md"))) continue;
37694
37918
  const relPath = `${rel}/${name}`.replace(/\\/g, "/");
37695
37919
  skills2.push({ name, relPath });
37696
37920
  }
@@ -37884,7 +38108,7 @@ var handleAgentConfigMessage = (msg, deps) => {
37884
38108
  };
37885
38109
 
37886
38110
  // src/prompt-turn-queue/runner.ts
37887
- import fs30 from "node:fs";
38111
+ import fs32 from "node:fs";
37888
38112
 
37889
38113
  // src/prompt-turn-queue/client-report.ts
37890
38114
  function sendPromptQueueClientReport(ws, queues) {
@@ -37893,32 +38117,6 @@ function sendPromptQueueClientReport(ws, queues) {
37893
38117
  return true;
37894
38118
  }
37895
38119
 
37896
- // src/prompt-turn-queue/disk-store.ts
37897
- import fs29 from "node:fs";
37898
-
37899
- // src/prompt-turn-queue/paths.ts
37900
- import crypto3 from "node:crypto";
37901
- import fs28 from "node:fs";
37902
- import path31 from "node:path";
37903
- import os7 from "node:os";
37904
- var QUEUE_KEY_HEX_64 = /^[a-f0-9]{64}$/i;
37905
- function queueStateFileSlug(queueKey) {
37906
- if (QUEUE_KEY_HEX_64.test(queueKey)) return queueKey.toLowerCase();
37907
- return crypto3.createHash("sha256").update(queueKey, "utf8").digest("hex");
37908
- }
37909
- function getPromptQueuesDirectory() {
37910
- const override = process.env.BUILDAMATON_PROMPT_QUEUES_DIR?.trim();
37911
- if (override) return path31.resolve(override);
37912
- return path31.join(os7.homedir(), ".buildautomaton", "queues");
37913
- }
37914
- function ensurePromptQueuesDirectory() {
37915
- const dir = getPromptQueuesDirectory();
37916
- if (!fs28.existsSync(dir)) fs28.mkdirSync(dir, { recursive: true });
37917
- }
37918
- function queueStateFilePath(queueKey) {
37919
- return path31.join(getPromptQueuesDirectory(), `${queueStateFileSlug(queueKey)}.json`);
37920
- }
37921
-
37922
38120
  // src/prompt-turn-queue/disk-store.ts
37923
38121
  var MERGEABLE_SERVER_STATES = /* @__PURE__ */ new Set([
37924
38122
  "queued",
@@ -37928,28 +38126,27 @@ var MERGEABLE_SERVER_STATES = /* @__PURE__ */ new Set([
37928
38126
  "stopping",
37929
38127
  "discarded"
37930
38128
  ]);
37931
- function parsePersistedQueueFile(raw) {
37932
- try {
37933
- const o = JSON.parse(raw);
37934
- const queueKey = typeof o.queueKey === "string" ? o.queueKey : typeof o.queueKeyHash === "string" ? o.queueKeyHash : null;
37935
- if (!queueKey || typeof o.updatedAt !== "string" || !Array.isArray(o.turns)) return null;
37936
- return { queueKey, updatedAt: o.updatedAt, turns: o.turns };
37937
- } catch {
37938
- return null;
37939
- }
37940
- }
37941
38129
  function readPersistedQueue(queueKey) {
37942
- const p = queueStateFilePath(queueKey);
38130
+ const db = getCliDatabase();
38131
+ const row = db.get("SELECT queue_key, updated_at, turns_json FROM prompt_queue WHERE queue_key = ?", [
38132
+ queueKey
38133
+ ]);
38134
+ if (!row) return null;
37943
38135
  try {
37944
- return parsePersistedQueueFile(fs29.readFileSync(p, "utf8"));
38136
+ const turns = JSON.parse(row.turns_json);
38137
+ if (!Array.isArray(turns)) return null;
38138
+ return { queueKey: row.queue_key, updatedAt: row.updated_at, turns };
37945
38139
  } catch {
37946
38140
  return null;
37947
38141
  }
37948
38142
  }
37949
38143
  function writePersistedQueue(file2) {
37950
- ensurePromptQueuesDirectory();
37951
- const p = queueStateFilePath(file2.queueKey);
37952
- fs29.writeFileSync(p, JSON.stringify(file2, null, 2), "utf8");
38144
+ const db = getCliDatabase();
38145
+ db.run(
38146
+ `INSERT INTO prompt_queue (queue_key, updated_at, turns_json) VALUES (?, ?, ?)
38147
+ ON CONFLICT(queue_key) DO UPDATE SET updated_at = excluded.updated_at, turns_json = excluded.turns_json`,
38148
+ [file2.queueKey, file2.updatedAt, JSON.stringify(file2.turns)]
38149
+ );
37953
38150
  }
37954
38151
  function mergeServerQueueSnapshot(queueKey, serverTurns) {
37955
38152
  const prev = readPersistedQueue(queueKey);
@@ -38007,7 +38204,7 @@ async function runLocalRevertBeforeQueuedPrompt(next, deps) {
38007
38204
  const tid = typeof pl.snapshotRevertTurnId === "string" && pl.snapshotRevertTurnId.trim() !== "" ? pl.snapshotRevertTurnId.trim() : next.turnId;
38008
38205
  const agentBase = deps.sessionWorktreeManager.getSessionWorktreeRootForSession(sid) ?? getBridgeRoot();
38009
38206
  const file2 = snapshotFilePath(agentBase, tid);
38010
- if (!fs30.existsSync(file2)) {
38207
+ if (!fs32.existsSync(file2)) {
38011
38208
  deps.log(
38012
38209
  `[Queue] requeued_with_revert: no pre-turn snapshot for ${tid.slice(0, 8)}\u2026; continuing without revert.`
38013
38210
  );
@@ -38231,9 +38428,9 @@ function parseChangeSummarySnapshots(raw) {
38231
38428
  for (const item of raw) {
38232
38429
  if (!item || typeof item !== "object") continue;
38233
38430
  const o = item;
38234
- const path37 = typeof o.path === "string" && o.path.trim() !== "" ? o.path.trim() : "";
38235
- if (!path37) continue;
38236
- const row = { path: path37 };
38431
+ const path41 = typeof o.path === "string" && o.path.trim() !== "" ? o.path.trim() : "";
38432
+ if (!path41) continue;
38433
+ const row = { path: path41 };
38237
38434
  if (typeof o.patchContent === "string") row.patchContent = o.patchContent;
38238
38435
  if (typeof o.oldText === "string") row.oldText = o.oldText;
38239
38436
  if (typeof o.newText === "string") row.newText = o.newText;
@@ -38450,8 +38647,8 @@ function randomSecret() {
38450
38647
  }
38451
38648
  return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
38452
38649
  }
38453
- async function requestPreviewApi(port, secret, method, path37, body) {
38454
- const url2 = `http://127.0.0.1:${port}${path37}`;
38650
+ async function requestPreviewApi(port, secret, method, path41, body) {
38651
+ const url2 = `http://127.0.0.1:${port}${path41}`;
38455
38652
  const headers = {
38456
38653
  [PREVIEW_SECRET_HEADER]: secret,
38457
38654
  "Content-Type": "application/json"
@@ -38463,7 +38660,7 @@ async function requestPreviewApi(port, secret, method, path37, body) {
38463
38660
  });
38464
38661
  const data = await res.json().catch(() => ({}));
38465
38662
  if (!res.ok) {
38466
- throw new Error(data?.error ?? `Preview API ${method} ${path37}: ${res.status}`);
38663
+ throw new Error(data?.error ?? `Preview API ${method} ${path41}: ${res.status}`);
38467
38664
  }
38468
38665
  return data;
38469
38666
  }
@@ -38628,15 +38825,15 @@ var handleSkillCallMessage = (msg, { getWs, log: log2 }) => {
38628
38825
  };
38629
38826
 
38630
38827
  // src/files/list-dir.ts
38631
- import fs31 from "node:fs";
38632
- import path33 from "node:path";
38828
+ import fs33 from "node:fs";
38829
+ import path36 from "node:path";
38633
38830
 
38634
38831
  // src/files/ensure-under-cwd.ts
38635
- import path32 from "node:path";
38832
+ import path35 from "node:path";
38636
38833
  function ensureUnderCwd(relativePath, cwd = getBridgeRoot()) {
38637
- const normalized = path32.normalize(relativePath).replace(/^(\.\/)+/, "");
38638
- const resolved = path32.resolve(cwd, normalized);
38639
- if (!resolved.startsWith(cwd + path32.sep) && resolved !== cwd) {
38834
+ const normalized = path35.normalize(relativePath).replace(/^(\.\/)+/, "");
38835
+ const resolved = path35.resolve(cwd, normalized);
38836
+ if (!resolved.startsWith(cwd + path35.sep) && resolved !== cwd) {
38640
38837
  return null;
38641
38838
  }
38642
38839
  return resolved;
@@ -38650,7 +38847,7 @@ async function listDirAsync(relativePath) {
38650
38847
  return { error: "Path is outside working directory" };
38651
38848
  }
38652
38849
  try {
38653
- const names = await fs31.promises.readdir(resolved, { withFileTypes: true });
38850
+ const names = await fs33.promises.readdir(resolved, { withFileTypes: true });
38654
38851
  const visible = names.filter((d) => !d.name.startsWith("."));
38655
38852
  const entries = [];
38656
38853
  for (let i = 0; i < visible.length; i++) {
@@ -38658,12 +38855,12 @@ async function listDirAsync(relativePath) {
38658
38855
  await yieldToEventLoop();
38659
38856
  }
38660
38857
  const d = visible[i];
38661
- const entryPath = path33.join(relativePath || ".", d.name).replace(/\\/g, "/");
38662
- const fullPath = path33.join(resolved, d.name);
38858
+ const entryPath = path36.join(relativePath || ".", d.name).replace(/\\/g, "/");
38859
+ const fullPath = path36.join(resolved, d.name);
38663
38860
  let isDir = d.isDirectory();
38664
38861
  if (d.isSymbolicLink()) {
38665
38862
  try {
38666
- const targetStat = await fs31.promises.stat(fullPath);
38863
+ const targetStat = await fs33.promises.stat(fullPath);
38667
38864
  isDir = targetStat.isDirectory();
38668
38865
  } catch {
38669
38866
  isDir = false;
@@ -38688,25 +38885,25 @@ async function listDirAsync(relativePath) {
38688
38885
  }
38689
38886
 
38690
38887
  // src/files/read-file.ts
38691
- import fs32 from "node:fs";
38888
+ import fs34 from "node:fs";
38692
38889
  import { StringDecoder } from "node:string_decoder";
38693
38890
  function resolveFilePath(relativePath) {
38694
38891
  const resolved = ensureUnderCwd(relativePath, getBridgeRoot());
38695
38892
  if (!resolved) return { error: "Path is outside working directory" };
38696
38893
  let real;
38697
38894
  try {
38698
- real = fs32.realpathSync(resolved);
38895
+ real = fs34.realpathSync(resolved);
38699
38896
  } catch {
38700
38897
  real = resolved;
38701
38898
  }
38702
- const stat3 = fs32.statSync(real);
38899
+ const stat3 = fs34.statSync(real);
38703
38900
  if (!stat3.isFile()) return { error: "Not a file" };
38704
38901
  return real;
38705
38902
  }
38706
38903
  var LINE_CHUNK_SIZE = 64 * 1024;
38707
38904
  function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize = LINE_CHUNK_SIZE) {
38708
- const fileSize = fs32.statSync(filePath).size;
38709
- const fd = fs32.openSync(filePath, "r");
38905
+ const fileSize = fs34.statSync(filePath).size;
38906
+ const fd = fs34.openSync(filePath, "r");
38710
38907
  const bufSize = 64 * 1024;
38711
38908
  const buf = Buffer.alloc(bufSize);
38712
38909
  const decoder = new StringDecoder("utf8");
@@ -38719,7 +38916,7 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
38719
38916
  let line0Accum = "";
38720
38917
  try {
38721
38918
  let bytesRead;
38722
- while (!done && (bytesRead = fs32.readSync(fd, buf, 0, bufSize, null)) > 0) {
38919
+ while (!done && (bytesRead = fs34.readSync(fd, buf, 0, bufSize, null)) > 0) {
38723
38920
  const text = partial2 + decoder.write(buf.subarray(0, bytesRead));
38724
38921
  partial2 = "";
38725
38922
  let lineStart = 0;
@@ -38854,7 +39051,7 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
38854
39051
  }
38855
39052
  return { content: resultLines.join("\n"), size: fileSize };
38856
39053
  } finally {
38857
- fs32.closeSync(fd);
39054
+ fs34.closeSync(fd);
38858
39055
  }
38859
39056
  }
38860
39057
  function readFile3(relativePath, startLine, endLine, lineOffset, lineChunkSize = LINE_CHUNK_SIZE) {
@@ -38865,8 +39062,8 @@ function readFile3(relativePath, startLine, endLine, lineOffset, lineChunkSize =
38865
39062
  if (hasRange) {
38866
39063
  return readFileRange(result, startLine, endLine, lineOffset, lineChunkSize);
38867
39064
  }
38868
- const stat3 = fs32.statSync(result);
38869
- const raw = fs32.readFileSync(result, "utf8");
39065
+ const stat3 = fs34.statSync(result);
39066
+ const raw = fs34.readFileSync(result, "utf8");
38870
39067
  const lines = raw.split(/\r?\n/);
38871
39068
  return { content: raw, totalLines: lines.length, size: stat3.size };
38872
39069
  } catch (err) {
@@ -38879,14 +39076,14 @@ async function readFileAsync(relativePath, startLine, endLine, lineOffset, lineC
38879
39076
  }
38880
39077
 
38881
39078
  // src/files/handle-file-browser-search.ts
39079
+ import path37 from "node:path";
38882
39080
  var SEARCH_LIMIT = 100;
38883
39081
  function handleFileBrowserSearch(msg, socket, e2ee) {
38884
39082
  void (async () => {
38885
39083
  await yieldToEventLoop();
38886
39084
  const q = typeof msg.q === "string" ? msg.q : "";
38887
- const cwd = getBridgeRoot();
38888
- const index = loadFileIndex(cwd);
38889
- if (index === null) {
39085
+ const cwd = path37.resolve(getBridgeRoot());
39086
+ if (!bridgeFileIndexIsPopulated(cwd)) {
38890
39087
  const payload2 = {
38891
39088
  type: "file_browser_search_response",
38892
39089
  id: msg.id,
@@ -38896,7 +39093,7 @@ function handleFileBrowserSearch(msg, socket, e2ee) {
38896
39093
  sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload2, ["paths"]) : payload2);
38897
39094
  return;
38898
39095
  }
38899
- const results = await searchFileIndexAsync(index, q, SEARCH_LIMIT);
39096
+ const results = await searchBridgeFilePathsAsync(cwd, q, SEARCH_LIMIT);
38900
39097
  const payload = {
38901
39098
  type: "file_browser_search_response",
38902
39099
  id: msg.id,
@@ -38984,8 +39181,8 @@ function handleSkillLayoutRequest(msg, deps) {
38984
39181
  }
38985
39182
 
38986
39183
  // src/skills/install-remote-skills.ts
38987
- import fs33 from "node:fs";
38988
- import path34 from "node:path";
39184
+ import fs35 from "node:fs";
39185
+ import path38 from "node:path";
38989
39186
  function installRemoteSkills(cwd, targetDir, items) {
38990
39187
  const installed2 = [];
38991
39188
  if (!Array.isArray(items)) {
@@ -38996,15 +39193,15 @@ function installRemoteSkills(cwd, targetDir, items) {
38996
39193
  if (typeof item.sourceId !== "string" || typeof item.skillName !== "string" || typeof item.versionHash !== "string" || !Array.isArray(item.files)) {
38997
39194
  continue;
38998
39195
  }
38999
- const skillDir = path34.join(cwd, targetDir, item.skillName);
39196
+ const skillDir = path38.join(cwd, targetDir, item.skillName);
39000
39197
  for (const f of item.files) {
39001
39198
  if (typeof f.path !== "string" || !f.text && !f.base64) continue;
39002
- const dest = path34.join(skillDir, f.path);
39003
- fs33.mkdirSync(path34.dirname(dest), { recursive: true });
39199
+ const dest = path38.join(skillDir, f.path);
39200
+ fs35.mkdirSync(path38.dirname(dest), { recursive: true });
39004
39201
  if (f.text !== void 0) {
39005
- fs33.writeFileSync(dest, f.text, "utf8");
39202
+ fs35.writeFileSync(dest, f.text, "utf8");
39006
39203
  } else if (f.base64) {
39007
- fs33.writeFileSync(dest, Buffer.from(f.base64, "base64"));
39204
+ fs35.writeFileSync(dest, Buffer.from(f.base64, "base64"));
39008
39205
  }
39009
39206
  }
39010
39207
  installed2.push({
@@ -39154,7 +39351,7 @@ var handleSessionDiscardedMessage = (msg, deps) => {
39154
39351
  };
39155
39352
 
39156
39353
  // src/routing/handlers/revert-turn-snapshot.ts
39157
- import * as fs34 from "node:fs";
39354
+ import * as fs36 from "node:fs";
39158
39355
  var handleRevertTurnSnapshotMessage = (msg, deps) => {
39159
39356
  const id = typeof msg.id === "string" ? msg.id : "";
39160
39357
  const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
@@ -39166,7 +39363,7 @@ var handleRevertTurnSnapshotMessage = (msg, deps) => {
39166
39363
  if (!s) return;
39167
39364
  const agentBase = sessionWorktreeManager.getSessionWorktreeRootForSession(sessionId) ?? getBridgeRoot();
39168
39365
  const file2 = snapshotFilePath(agentBase, turnId);
39169
- if (!fs34.existsSync(file2)) {
39366
+ if (!fs36.existsSync(file2)) {
39170
39367
  sendWsMessage(s, {
39171
39368
  type: "revert_turn_snapshot_result",
39172
39369
  id,
@@ -39582,6 +39779,7 @@ async function createBridgeConnection(options) {
39582
39779
  const { apiUrl, workspaceId, justAuthenticated, onAuthInvalid, persistTokens } = options;
39583
39780
  const firehoseServerUrl = options.firehoseServerUrl ?? options.proxyServerUrl;
39584
39781
  const logFn = options.log ?? log;
39782
+ getCliDatabase({ logLegacyMigration: logFn });
39585
39783
  const tokens = {
39586
39784
  accessToken: options.authToken,
39587
39785
  refreshToken: options.refreshToken
@@ -39647,8 +39845,8 @@ async function createBridgeConnection(options) {
39647
39845
  getCloudAccessToken: () => tokens.accessToken
39648
39846
  };
39649
39847
  const identifyReportedPaths = {
39650
- bridgeRootPath: path35.resolve(getBridgeRoot()),
39651
- worktreesRootPath: path35.resolve(worktreesRootPath)
39848
+ bridgeRootPath: path39.resolve(getBridgeRoot()),
39849
+ worktreesRootPath: path39.resolve(worktreesRootPath)
39652
39850
  };
39653
39851
  const { connect } = createMainBridgeWebSocketLifecycle({
39654
39852
  state,
@@ -39886,9 +40084,9 @@ async function runCliAction(program2, opts) {
39886
40084
  const firehoseServerUrl = opts.firehoseUrl ?? opts.proxyUrl ?? process.env.BUILDAUTOMATON_FIREHOSE_URL ?? process.env.BUILDAUTOMATON_PROXY_URL ?? DEFAULT_FIREHOSE_URL;
39887
40085
  const bridgeRootOpt = (opts.bridgeRoot && typeof opts.bridgeRoot === "string" && opts.bridgeRoot.trim() ? opts.bridgeRoot.trim() : null) ?? (opts.cwd && typeof opts.cwd === "string" && opts.cwd.trim() ? opts.cwd.trim() : null);
39888
40086
  if (bridgeRootOpt) {
39889
- const resolvedBridgeRoot = path36.resolve(process.cwd(), bridgeRootOpt);
40087
+ const resolvedBridgeRoot = path40.resolve(process.cwd(), bridgeRootOpt);
39890
40088
  try {
39891
- const st = fs35.statSync(resolvedBridgeRoot);
40089
+ const st = fs37.statSync(resolvedBridgeRoot);
39892
40090
  if (!st.isDirectory()) {
39893
40091
  console.error(`Bridge root is not a directory: ${resolvedBridgeRoot}`);
39894
40092
  process.exit(1);
@@ -39908,7 +40106,7 @@ async function runCliAction(program2, opts) {
39908
40106
  );
39909
40107
  let worktreesRootPath;
39910
40108
  if (opts.worktreesRoot && opts.worktreesRoot.trim()) {
39911
- worktreesRootPath = path36.resolve(opts.worktreesRoot.trim());
40109
+ worktreesRootPath = path40.resolve(opts.worktreesRoot.trim());
39912
40110
  }
39913
40111
  const e2eCertificates = opts.e2eeCertificatesDir?.trim() ? await loadOrCreateE2eCertificates(opts.e2eeCertificatesDir.trim()) : void 0;
39914
40112
  if (e2eCertificates) {