@buildautomaton/cli 0.1.30 → 0.1.32

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/index.js CHANGED
@@ -23962,7 +23962,7 @@ function installBridgeProcessResilience() {
23962
23962
  }
23963
23963
 
23964
23964
  // src/cli-version.ts
23965
- var CLI_VERSION = "0.1.30".length > 0 ? "0.1.30" : "0.0.0-dev";
23965
+ var CLI_VERSION = "0.1.32".length > 0 ? "0.1.32" : "0.0.0-dev";
23966
23966
 
23967
23967
  // src/connection/heartbeat/constants.ts
23968
23968
  var BRIDGE_APP_HEARTBEAT_INTERVAL_MS = 1e4;
@@ -25025,6 +25025,11 @@ function runPendingAuth(options) {
25025
25025
  // src/sqlite/cli-database.ts
25026
25026
  import sqliteWasm from "node-sqlite3-wasm";
25027
25027
 
25028
+ // src/runtime/yield-to-event-loop.ts
25029
+ function yieldToEventLoop() {
25030
+ return new Promise((resolve18) => setImmediate(resolve18));
25031
+ }
25032
+
25028
25033
  // src/sqlite/cli-sqlite-paths.ts
25029
25034
  import fs7 from "node:fs";
25030
25035
  import path5 from "node:path";
@@ -25317,17 +25322,29 @@ function migrateCliSqlite(db) {
25317
25322
 
25318
25323
  // src/sqlite/cli-database.ts
25319
25324
  var { Database: SqliteDatabase } = sqliteWasm;
25320
- var openDatabases = /* @__PURE__ */ new Map();
25321
- var processExitCloseRegistered = false;
25322
- function registerProcessExitSqliteClose() {
25323
- if (processExitCloseRegistered) return;
25324
- processExitCloseRegistered = true;
25325
- process.once("exit", () => {
25326
- for (const db of openDatabases.values()) {
25327
- safeCloseCliSqliteDatabase(db);
25328
- }
25329
- openDatabases.clear();
25330
- });
25325
+ var CLI_SQLITE_SYNC_RETRY_MAX = 40;
25326
+ var CLI_SQLITE_ASYNC_RETRY_MAX = 60;
25327
+ var CLI_SQLITE_ASYNC_BASE_DELAY_MS = 20;
25328
+ function applyCliSqliteConcurrencyPragmas(db) {
25329
+ try {
25330
+ db.exec("PRAGMA journal_mode = WAL");
25331
+ } catch {
25332
+ }
25333
+ try {
25334
+ db.run("PRAGMA synchronous = NORMAL");
25335
+ } catch {
25336
+ }
25337
+ try {
25338
+ db.run("PRAGMA busy_timeout = 8000");
25339
+ } catch {
25340
+ }
25341
+ }
25342
+ function applyCliSqliteMemoryPragmas(db) {
25343
+ try {
25344
+ db.run("PRAGMA cache_size = -8192");
25345
+ db.run("PRAGMA temp_store = FILE");
25346
+ } catch {
25347
+ }
25331
25348
  }
25332
25349
  function safeCloseCliSqliteDatabase(db) {
25333
25350
  if (db == null) return;
@@ -25337,32 +25354,86 @@ function safeCloseCliSqliteDatabase(db) {
25337
25354
  }
25338
25355
  }
25339
25356
  function closeAllCliSqliteConnections() {
25340
- for (const db of openDatabases.values()) {
25341
- safeCloseCliSqliteDatabase(db);
25357
+ }
25358
+ function isCliSqliteLockError(e) {
25359
+ const msg = e instanceof Error ? e.message : String(e);
25360
+ const lower = msg.toLowerCase();
25361
+ return lower.includes("database is locked") || lower.includes("sqlite_busy") || lower.includes("sqlite3_busy") || lower.includes("database") && lower.includes("locked");
25362
+ }
25363
+ function syncSleepMs(ms) {
25364
+ if (ms <= 0) return;
25365
+ try {
25366
+ const sab = new SharedArrayBuffer(4);
25367
+ const ia = new Int32Array(sab);
25368
+ Atomics.wait(ia, 0, 0, Math.min(ms, 1e4));
25369
+ } catch {
25370
+ const end = Date.now() + ms;
25371
+ while (Date.now() < end) {
25372
+ }
25342
25373
  }
25343
- openDatabases.clear();
25344
25374
  }
25345
- function getCliDatabase(options) {
25375
+ function asyncDelayMs(ms) {
25376
+ return new Promise((resolve18) => setTimeout(resolve18, ms));
25377
+ }
25378
+ function openCliSqliteConnection(options) {
25346
25379
  const sqlitePath = getCliSqlitePath();
25347
- const existing = openDatabases.get(sqlitePath);
25348
- if (existing?.isOpen) return existing;
25349
- if (existing && !existing.isOpen) {
25350
- safeCloseCliSqliteDatabase(existing);
25351
- openDatabases.delete(sqlitePath);
25352
- }
25353
25380
  ensureCliSqliteParentDir(sqlitePath);
25354
25381
  const db = new SqliteDatabase(sqlitePath);
25355
25382
  try {
25383
+ applyCliSqliteConcurrencyPragmas(db);
25384
+ applyCliSqliteMemoryPragmas(db);
25356
25385
  migrateCliSqlite(db);
25357
25386
  importCliSqliteLegacyDiskData(db, options?.logLegacyMigration);
25358
25387
  } catch (e) {
25359
25388
  safeCloseCliSqliteDatabase(db);
25360
25389
  throw e;
25361
25390
  }
25362
- openDatabases.set(sqlitePath, db);
25363
- registerProcessExitSqliteClose();
25364
25391
  return db;
25365
25392
  }
25393
+ function withCliSqliteSync(fn, options) {
25394
+ for (let attempt = 1; attempt <= CLI_SQLITE_SYNC_RETRY_MAX; attempt++) {
25395
+ let db;
25396
+ try {
25397
+ db = openCliSqliteConnection(options);
25398
+ try {
25399
+ return fn(db);
25400
+ } finally {
25401
+ safeCloseCliSqliteDatabase(db);
25402
+ }
25403
+ } catch (e) {
25404
+ safeCloseCliSqliteDatabase(db);
25405
+ if (!isCliSqliteLockError(e) || attempt === CLI_SQLITE_SYNC_RETRY_MAX) throw e;
25406
+ syncSleepMs(Math.min(500, 12 * attempt));
25407
+ }
25408
+ }
25409
+ throw new Error("withCliSqliteSync: exhausted retries");
25410
+ }
25411
+ async function withCliSqlite(fn, options) {
25412
+ let lastError;
25413
+ for (let attempt = 1; attempt <= CLI_SQLITE_ASYNC_RETRY_MAX; attempt++) {
25414
+ let db;
25415
+ try {
25416
+ db = openCliSqliteConnection(options);
25417
+ try {
25418
+ return await Promise.resolve(fn(db));
25419
+ } finally {
25420
+ safeCloseCliSqliteDatabase(db);
25421
+ }
25422
+ } catch (e) {
25423
+ lastError = e;
25424
+ safeCloseCliSqliteDatabase(db);
25425
+ if (!isCliSqliteLockError(e) || attempt === CLI_SQLITE_ASYNC_RETRY_MAX) throw e;
25426
+ const delayMs = Math.min(600, CLI_SQLITE_ASYNC_BASE_DELAY_MS * attempt);
25427
+ await asyncDelayMs(delayMs);
25428
+ await yieldToEventLoop();
25429
+ }
25430
+ }
25431
+ if (lastError instanceof Error) throw lastError;
25432
+ throw new Error(String(lastError));
25433
+ }
25434
+ async function ensureCliSqliteInitialized(options) {
25435
+ await withCliSqlite(() => void 0, options);
25436
+ }
25366
25437
 
25367
25438
  // src/connection/close-bridge-connection.ts
25368
25439
  async function closeBridgeConnection(state, acpManager, devServerManager, log2) {
@@ -31710,6 +31781,28 @@ function sendGitHeadVsWorkspaceForToolPaths(mergedPaths, sentPaths, send, sessio
31710
31781
  }
31711
31782
  }
31712
31783
 
31784
+ // src/agents/acp/hooks/bridge-on-session-update/send-session-info-title-update.ts
31785
+ function extractSessionInfoTitle(params) {
31786
+ if (!params || typeof params !== "object") return null;
31787
+ const p = params;
31788
+ const title = typeof p.title === "string" ? p.title.trim() : "";
31789
+ return title ? title : null;
31790
+ }
31791
+ function sendSessionInfoTitleUpdate(params) {
31792
+ const title = extractSessionInfoTitle(params.payload);
31793
+ if (!title || !params.runId || !params.send) return;
31794
+ try {
31795
+ params.send({
31796
+ type: "session_title_update",
31797
+ ...params.sessionId ? { sessionId: params.sessionId } : {},
31798
+ runId: params.runId,
31799
+ title
31800
+ });
31801
+ } catch (err) {
31802
+ params.log(`[Bridge service] Session title update send failed: ${errorMessage(err)}`);
31803
+ }
31804
+ }
31805
+
31713
31806
  // src/agents/acp/hooks/bridge-on-session-update/create-bridge-on-session-update.ts
31714
31807
  function createBridgeOnSessionUpdate(opts) {
31715
31808
  const { routing, getSendSessionUpdate, log: log2, sessionParentPath } = opts;
@@ -31725,6 +31818,10 @@ function createBridgeOnSessionUpdate(opts) {
31725
31818
  if (updateKind === "config_option_update") {
31726
31819
  return;
31727
31820
  }
31821
+ if (updateKind === "session_info_update") {
31822
+ sendSessionInfoTitleUpdate({ payload: params, runId, sessionId, send, log: log2 });
31823
+ return;
31824
+ }
31728
31825
  const isCompletedToolCallUpdate = updateKind === "tool_call_update" && isCompletedToolStatus(p.status);
31729
31826
  const toolName = p.toolCall?.name ?? p.tool_call?.name ?? "";
31730
31827
  const isToolUpdate = updateKind === "tool_call" || updateKind === "tool_call_update" || typeof toolName === "string" && toolName.length > 0;
@@ -31818,56 +31915,80 @@ function sessionKeyForCloudSessionId(cloudSessionId) {
31818
31915
  }
31819
31916
  function readLocalAgentSessionFile(cloudSessionId) {
31820
31917
  try {
31821
- const db = getCliDatabase();
31822
- const key = sessionKeyForCloudSessionId(cloudSessionId);
31823
- const row = db.get(
31824
- "SELECT acp_session_id, backend_agent_type, config_options_json, updated_at FROM agent_session WHERE session_key = ?",
31825
- [key]
31826
- );
31827
- if (!row) return null;
31828
- let configOptions = null;
31829
- if (row.config_options_json != null && row.config_options_json !== "") {
31830
- try {
31831
- const parsed = JSON.parse(row.config_options_json);
31832
- configOptions = Array.isArray(parsed) ? parsed : null;
31833
- } catch {
31834
- configOptions = null;
31918
+ return withCliSqliteSync((db) => {
31919
+ const key = sessionKeyForCloudSessionId(cloudSessionId);
31920
+ const row = db.get(
31921
+ "SELECT acp_session_id, backend_agent_type, config_options_json, updated_at FROM agent_session WHERE session_key = ?",
31922
+ [key]
31923
+ );
31924
+ if (!row) return null;
31925
+ let configOptions = null;
31926
+ if (row.config_options_json != null && row.config_options_json !== "") {
31927
+ try {
31928
+ const parsed = JSON.parse(row.config_options_json);
31929
+ configOptions = Array.isArray(parsed) ? parsed : null;
31930
+ } catch {
31931
+ configOptions = null;
31932
+ }
31835
31933
  }
31836
- }
31837
- return {
31838
- v: 1,
31839
- acpSessionId: row.acp_session_id,
31840
- backendAgentType: row.backend_agent_type,
31841
- configOptions,
31842
- updatedAt: row.updated_at
31843
- };
31934
+ return {
31935
+ v: 1,
31936
+ acpSessionId: row.acp_session_id,
31937
+ backendAgentType: row.backend_agent_type,
31938
+ configOptions,
31939
+ updatedAt: row.updated_at
31940
+ };
31941
+ });
31844
31942
  } catch {
31845
31943
  return null;
31846
31944
  }
31847
31945
  }
31848
31946
  function writeLocalAgentSessionFile(cloudSessionId, patch) {
31849
31947
  try {
31850
- const db = getCliDatabase();
31851
- const key = sessionKeyForCloudSessionId(cloudSessionId);
31852
- const prev = readLocalAgentSessionFile(cloudSessionId);
31853
- const next = {
31854
- v: 1,
31855
- acpSessionId: patch.acpSessionId !== void 0 ? patch.acpSessionId : prev?.acpSessionId ?? null,
31856
- backendAgentType: patch.backendAgentType !== void 0 ? patch.backendAgentType : prev?.backendAgentType ?? null,
31857
- configOptions: patch.configOptions !== void 0 ? patch.configOptions : prev?.configOptions ?? null,
31858
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
31859
- };
31860
- const configJson = next.configOptions != null ? JSON.stringify(next.configOptions) : null;
31861
- db.run(
31862
- `INSERT INTO agent_session (session_key, acp_session_id, backend_agent_type, config_options_json, updated_at)
31863
- VALUES (?, ?, ?, ?, ?)
31864
- ON CONFLICT(session_key) DO UPDATE SET
31865
- acp_session_id = excluded.acp_session_id,
31866
- backend_agent_type = excluded.backend_agent_type,
31867
- config_options_json = excluded.config_options_json,
31868
- updated_at = excluded.updated_at`,
31869
- [key, next.acpSessionId, next.backendAgentType, configJson, next.updatedAt]
31870
- );
31948
+ withCliSqliteSync((db) => {
31949
+ const key = sessionKeyForCloudSessionId(cloudSessionId);
31950
+ const prevRow = db.get(
31951
+ "SELECT acp_session_id, backend_agent_type, config_options_json, updated_at FROM agent_session WHERE session_key = ?",
31952
+ [key]
31953
+ );
31954
+ let prev = null;
31955
+ if (prevRow) {
31956
+ let configOptions = null;
31957
+ if (prevRow.config_options_json != null && prevRow.config_options_json !== "") {
31958
+ try {
31959
+ const parsed = JSON.parse(prevRow.config_options_json);
31960
+ configOptions = Array.isArray(parsed) ? parsed : null;
31961
+ } catch {
31962
+ configOptions = null;
31963
+ }
31964
+ }
31965
+ prev = {
31966
+ v: 1,
31967
+ acpSessionId: prevRow.acp_session_id,
31968
+ backendAgentType: prevRow.backend_agent_type,
31969
+ configOptions,
31970
+ updatedAt: prevRow.updated_at
31971
+ };
31972
+ }
31973
+ const next = {
31974
+ v: 1,
31975
+ acpSessionId: patch.acpSessionId !== void 0 ? patch.acpSessionId : prev?.acpSessionId ?? null,
31976
+ backendAgentType: patch.backendAgentType !== void 0 ? patch.backendAgentType : prev?.backendAgentType ?? null,
31977
+ configOptions: patch.configOptions !== void 0 ? patch.configOptions : prev?.configOptions ?? null,
31978
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
31979
+ };
31980
+ const configJson = next.configOptions != null ? JSON.stringify(next.configOptions) : null;
31981
+ db.run(
31982
+ `INSERT INTO agent_session (session_key, acp_session_id, backend_agent_type, config_options_json, updated_at)
31983
+ VALUES (?, ?, ?, ?, ?)
31984
+ ON CONFLICT(session_key) DO UPDATE SET
31985
+ acp_session_id = excluded.acp_session_id,
31986
+ backend_agent_type = excluded.backend_agent_type,
31987
+ config_options_json = excluded.config_options_json,
31988
+ updated_at = excluded.updated_at`,
31989
+ [key, next.acpSessionId, next.backendAgentType, configJson, next.updatedAt]
31990
+ );
31991
+ });
31871
31992
  } catch {
31872
31993
  }
31873
31994
  }
@@ -33450,45 +33571,36 @@ function getCwdHashForFileIndex(resolvedCwd) {
33450
33571
  // src/files/index/build-file-index.ts
33451
33572
  import path28 from "node:path";
33452
33573
 
33453
- // src/runtime/yield-to-event-loop.ts
33454
- function yieldToEventLoop() {
33455
- return new Promise((resolve18) => setImmediate(resolve18));
33456
- }
33457
-
33458
33574
  // src/files/index/walk-workspace-tree.ts
33459
33575
  import fs24 from "node:fs";
33460
33576
  import path27 from "node:path";
33461
- async function walkWorkspaceTreeAsync(dir, baseDir, out, state) {
33577
+ function shouldSkipWorkspaceWalkEntry(name) {
33578
+ return name.startsWith(".");
33579
+ }
33580
+ function walkWorkspaceTreeSync(dir, baseDir, onFile) {
33462
33581
  let names;
33463
33582
  try {
33464
- names = await fs24.promises.readdir(dir);
33583
+ names = fs24.readdirSync(dir);
33465
33584
  } catch {
33466
33585
  return;
33467
33586
  }
33468
33587
  for (const name of names) {
33469
- if (name.startsWith(".")) continue;
33470
- if (state.n > 0 && state.n % INDEX_WORK_YIELD_EVERY === 0) {
33471
- await yieldToEventLoop();
33472
- }
33473
- state.n++;
33588
+ if (shouldSkipWorkspaceWalkEntry(name)) continue;
33474
33589
  const full = path27.join(dir, name);
33475
33590
  let stat2;
33476
33591
  try {
33477
- stat2 = await fs24.promises.stat(full);
33592
+ stat2 = fs24.statSync(full);
33478
33593
  } catch {
33479
33594
  continue;
33480
33595
  }
33481
33596
  const relative5 = path27.relative(baseDir, full).replace(/\\/g, "/");
33482
33597
  if (stat2.isDirectory()) {
33483
- await walkWorkspaceTreeAsync(full, baseDir, out, state);
33598
+ walkWorkspaceTreeSync(full, baseDir, onFile);
33484
33599
  } else if (stat2.isFile()) {
33485
- out.push(relative5);
33600
+ onFile(relative5);
33486
33601
  }
33487
33602
  }
33488
33603
  }
33489
- function createWalkYieldState() {
33490
- return { n: 0 };
33491
- }
33492
33604
 
33493
33605
  // src/files/index/file-index-sqlite-lock.ts
33494
33606
  import fs25 from "node:fs";
@@ -33521,80 +33633,98 @@ function withFileIndexSqliteLock(fn) {
33521
33633
  }
33522
33634
 
33523
33635
  // src/files/index/build-file-index.ts
33524
- function sortPaths(paths) {
33525
- paths.sort((a, b) => a.localeCompare(b, void 0, { sensitivity: "base" }));
33526
- }
33527
- function persistPathsToSqlite(resolved, paths) {
33528
- const db = getCliDatabase();
33529
- const h = getCwdHashForFileIndex(resolved);
33530
- db.run("BEGIN IMMEDIATE");
33531
- try {
33532
- db.run("DELETE FROM file_index_path WHERE cwd_hash = ?", [h]);
33533
- const ins = db.prepare("INSERT INTO file_index_path (cwd_hash, path) VALUES (?, ?)");
33636
+ var FILE_INDEX_INSERT_BUFFER = 2048;
33637
+ function persistFileIndexForResolvedCwd(resolved) {
33638
+ return withCliSqliteSync((db) => {
33639
+ const h = getCwdHashForFileIndex(resolved);
33640
+ const buf = [];
33641
+ let pathCount = 0;
33642
+ db.run("BEGIN IMMEDIATE");
33534
33643
  try {
33535
- for (const rel of paths) {
33536
- ins.run([h, rel]);
33644
+ db.run("DELETE FROM file_index_path WHERE cwd_hash = ?", [h]);
33645
+ const ins = db.prepare("INSERT INTO file_index_path (cwd_hash, path) VALUES (?, ?)");
33646
+ try {
33647
+ const flushBuf = () => {
33648
+ for (const rel of buf) {
33649
+ ins.run([h, rel]);
33650
+ }
33651
+ pathCount += buf.length;
33652
+ buf.length = 0;
33653
+ };
33654
+ walkWorkspaceTreeSync(resolved, resolved, (rel) => {
33655
+ buf.push(rel);
33656
+ if (buf.length >= FILE_INDEX_INSERT_BUFFER) flushBuf();
33657
+ });
33658
+ flushBuf();
33659
+ } finally {
33660
+ ins.finalize();
33537
33661
  }
33538
- } finally {
33539
- ins.finalize();
33540
- }
33541
- db.run("COMMIT");
33542
- } catch (e) {
33543
- try {
33544
- db.run("ROLLBACK");
33545
- } catch {
33662
+ db.run("COMMIT");
33663
+ } catch (e) {
33664
+ try {
33665
+ db.run("ROLLBACK");
33666
+ } catch {
33667
+ }
33668
+ throw e;
33546
33669
  }
33547
- throw e;
33548
- }
33670
+ return pathCount;
33671
+ });
33549
33672
  }
33550
33673
  async function buildFileIndexAsync(cwd) {
33551
33674
  return withFileIndexSqliteLock(async () => {
33552
33675
  const resolved = path28.resolve(cwd);
33553
- const paths = [];
33554
- await walkWorkspaceTreeAsync(resolved, resolved, paths, createWalkYieldState());
33555
33676
  await yieldToEventLoop();
33556
- sortPaths(paths);
33557
- persistPathsToSqlite(resolved, paths);
33558
- return { pathCount: paths.length };
33677
+ const pathCount = persistFileIndexForResolvedCwd(resolved);
33678
+ await yieldToEventLoop();
33679
+ return { pathCount };
33559
33680
  });
33560
33681
  }
33561
33682
 
33562
33683
  // src/files/index/ensure-file-index.ts
33563
33684
  import path29 from "node:path";
33564
33685
 
33686
+ // src/files/index/file-index-dependency-path.ts
33687
+ function sqliteExprBridgeFileIndexDependencyRank() {
33688
+ return `CASE WHEN lower(path) = 'node_modules' OR lower(path) LIKE 'node_modules/%' OR lower(path) LIKE '%/node_modules/%' OR lower(path) = 'bower_components' OR lower(path) LIKE 'bower_components/%' OR lower(path) LIKE '%/bower_components/%' THEN 1 ELSE 0 END`;
33689
+ }
33690
+
33565
33691
  // src/files/index/search-file-index.ts
33566
33692
  function escapeLikePattern(fragment) {
33567
33693
  return fragment.replace(/\\/g, "\\\\").replace(/%/g, "\\%").replace(/_/g, "\\_");
33568
33694
  }
33569
- function bridgeFileIndexIsPopulated(resolvedCwd) {
33570
- const db = getCliDatabase();
33695
+ function bridgeFileIndexIsPopulatedWithDb(resolvedCwd, db) {
33571
33696
  const h = getCwdHashForFileIndex(resolvedCwd);
33572
33697
  const row = db.get("SELECT 1 as ok FROM file_index_path WHERE cwd_hash = ? LIMIT 1", [h]);
33573
33698
  return row != null;
33574
33699
  }
33575
- function bridgeFileIndexPathCount(resolvedCwd) {
33576
- const db = getCliDatabase();
33700
+ function bridgeFileIndexPathCountWithDb(resolvedCwd, db) {
33577
33701
  const h = getCwdHashForFileIndex(resolvedCwd);
33578
33702
  const row = db.get("SELECT COUNT(*) as c FROM file_index_path WHERE cwd_hash = ?", [h]);
33579
33703
  const c = row?.c ?? 0;
33580
33704
  return Number(c);
33581
33705
  }
33582
- function searchBridgeFilePaths(resolvedCwd, query, limit = 100) {
33706
+ function searchBridgeFilePathsWithDb(resolvedCwd, query, limit, db) {
33583
33707
  const q = query.trim().toLowerCase();
33584
33708
  if (!q) return [];
33585
- const db = getCliDatabase();
33586
33709
  const h = getCwdHashForFileIndex(resolvedCwd);
33587
33710
  const pattern = `%${escapeLikePattern(q)}%`;
33588
33711
  const lim = Math.max(0, Math.min(1e4, Math.floor(limit)));
33712
+ const depRank = sqliteExprBridgeFileIndexDependencyRank();
33589
33713
  const rows = db.all(
33590
- `SELECT path FROM file_index_path WHERE cwd_hash = ? AND lower(path) LIKE ? ESCAPE '\\' LIMIT ?`,
33714
+ `SELECT path FROM file_index_path WHERE cwd_hash = ? AND lower(path) LIKE ? ESCAPE '\\' ORDER BY ${depRank}, path LIMIT ?`,
33591
33715
  [h, pattern, lim]
33592
33716
  );
33593
33717
  return rows.map((r) => String(r.path));
33594
33718
  }
33719
+ async function bridgeFileIndexIsPopulated(resolvedCwd) {
33720
+ return withCliSqlite((db) => bridgeFileIndexIsPopulatedWithDb(resolvedCwd, db));
33721
+ }
33722
+ async function bridgeFileIndexPathCount(resolvedCwd) {
33723
+ return withCliSqlite((db) => bridgeFileIndexPathCountWithDb(resolvedCwd, db));
33724
+ }
33595
33725
  async function searchBridgeFilePathsAsync(resolvedCwd, query, limit = 100) {
33596
33726
  await yieldToEventLoop();
33597
- const out = searchBridgeFilePaths(resolvedCwd, query, limit);
33727
+ const out = await withCliSqlite((db) => searchBridgeFilePathsWithDb(resolvedCwd, query, limit, db));
33598
33728
  if (out.length >= INDEX_WORK_YIELD_EVERY) await yieldToEventLoop();
33599
33729
  return out;
33600
33730
  }
@@ -33602,8 +33732,8 @@ async function searchBridgeFilePathsAsync(resolvedCwd, query, limit = 100) {
33602
33732
  // src/files/index/ensure-file-index.ts
33603
33733
  async function ensureFileIndexAsync(cwd) {
33604
33734
  const resolved = path29.resolve(cwd);
33605
- if (bridgeFileIndexIsPopulated(resolved)) {
33606
- return { fromCache: true, pathCount: bridgeFileIndexPathCount(resolved) };
33735
+ if (await bridgeFileIndexIsPopulated(resolved)) {
33736
+ return { fromCache: true, pathCount: await bridgeFileIndexPathCount(resolved) };
33607
33737
  }
33608
33738
  return { ...await buildFileIndexAsync(resolved), fromCache: false };
33609
33739
  }
@@ -33612,7 +33742,6 @@ async function ensureFileIndexAsync(cwd) {
33612
33742
  var DEBOUNCE_MS = 900;
33613
33743
  function shouldIgnoreRelative(rel) {
33614
33744
  const n = rel.replace(/\\/g, "/");
33615
- if (n.includes("/node_modules/") || n.startsWith("node_modules/")) return true;
33616
33745
  if (n.includes("/.git/") || n === ".git" || n.startsWith(".git/")) return true;
33617
33746
  if (n.includes("/.buildautomaton/") || n.startsWith(".buildautomaton/")) return true;
33618
33747
  return false;
@@ -35117,30 +35246,32 @@ var MERGEABLE_SERVER_STATES = /* @__PURE__ */ new Set([
35117
35246
  "stopping",
35118
35247
  "discarded"
35119
35248
  ]);
35120
- function readPersistedQueue(queueKey) {
35121
- const db = getCliDatabase();
35122
- const row = db.get("SELECT queue_key, updated_at, turns_json FROM prompt_queue WHERE queue_key = ?", [
35123
- queueKey
35124
- ]);
35125
- if (!row) return null;
35126
- try {
35127
- const turns = JSON.parse(row.turns_json);
35128
- if (!Array.isArray(turns)) return null;
35129
- return { queueKey: row.queue_key, updatedAt: row.updated_at, turns };
35130
- } catch {
35131
- return null;
35132
- }
35249
+ async function readPersistedQueue(queueKey) {
35250
+ return withCliSqlite((db) => {
35251
+ const row = db.get("SELECT queue_key, updated_at, turns_json FROM prompt_queue WHERE queue_key = ?", [
35252
+ queueKey
35253
+ ]);
35254
+ if (!row) return null;
35255
+ try {
35256
+ const turns = JSON.parse(row.turns_json);
35257
+ if (!Array.isArray(turns)) return null;
35258
+ return { queueKey: row.queue_key, updatedAt: row.updated_at, turns };
35259
+ } catch {
35260
+ return null;
35261
+ }
35262
+ });
35133
35263
  }
35134
- function writePersistedQueue(file2) {
35135
- const db = getCliDatabase();
35136
- db.run(
35137
- `INSERT INTO prompt_queue (queue_key, updated_at, turns_json) VALUES (?, ?, ?)
35138
- ON CONFLICT(queue_key) DO UPDATE SET updated_at = excluded.updated_at, turns_json = excluded.turns_json`,
35139
- [file2.queueKey, file2.updatedAt, JSON.stringify(file2.turns)]
35140
- );
35264
+ async function writePersistedQueue(file2) {
35265
+ await withCliSqlite((db) => {
35266
+ db.run(
35267
+ `INSERT INTO prompt_queue (queue_key, updated_at, turns_json) VALUES (?, ?, ?)
35268
+ ON CONFLICT(queue_key) DO UPDATE SET updated_at = excluded.updated_at, turns_json = excluded.turns_json`,
35269
+ [file2.queueKey, file2.updatedAt, JSON.stringify(file2.turns)]
35270
+ );
35271
+ });
35141
35272
  }
35142
- function mergeServerQueueSnapshot(queueKey, serverTurns) {
35143
- const prev = readPersistedQueue(queueKey);
35273
+ async function mergeServerQueueSnapshot(queueKey, serverTurns) {
35274
+ const prev = await readPersistedQueue(queueKey);
35144
35275
  const turns = [];
35145
35276
  for (const raw of serverTurns) {
35146
35277
  if (!raw || typeof raw !== "object") continue;
@@ -35237,12 +35368,12 @@ async function applyPromptQueueStateFromServer(msg, deps) {
35237
35368
  const getWs = deps.getWs;
35238
35369
  for (const [queueKey, serverTurns] of Object.entries(raw)) {
35239
35370
  if (!Array.isArray(serverTurns)) continue;
35240
- const file2 = mergeServerQueueSnapshot(queueKey, serverTurns);
35241
- writePersistedQueue(file2);
35371
+ const file2 = await mergeServerQueueSnapshot(queueKey, serverTurns);
35372
+ await writePersistedQueue(file2);
35242
35373
  }
35243
35374
  for (const [queueKey, serverTurns] of Object.entries(raw)) {
35244
35375
  if (!Array.isArray(serverTurns)) continue;
35245
- const file2 = readPersistedQueue(queueKey);
35376
+ const file2 = await readPersistedQueue(queueKey);
35246
35377
  if (!file2) continue;
35247
35378
  for (const running of file2.turns.filter((t) => t.lastClientState === "running")) {
35248
35379
  runIdToQueueKey.set(running.turnId, queueKey);
@@ -35250,7 +35381,7 @@ async function applyPromptQueueStateFromServer(msg, deps) {
35250
35381
  }
35251
35382
  for (const [queueKey, serverTurns] of Object.entries(raw)) {
35252
35383
  if (!Array.isArray(serverTurns)) continue;
35253
- const file2 = readPersistedQueue(queueKey);
35384
+ const file2 = await readPersistedQueue(queueKey);
35254
35385
  if (!file2) continue;
35255
35386
  const cancelRow = file2.turns.find((t) => t.serverState === "cancel_requested" && t.lastClientState === "running");
35256
35387
  if (cancelRow) {
@@ -35259,7 +35390,7 @@ async function applyPromptQueueStateFromServer(msg, deps) {
35259
35390
  deps.log(
35260
35391
  `[Queue] server cancel_requested for ${cancelRow.turnId.slice(0, 8)}\u2026 but no local agent run is active (e.g. after CLI restart); marking cancelled and notifying bridge.`
35261
35392
  );
35262
- finalizePromptTurnOnBridge(deps.getWs, cancelRow.turnId, false, { terminalClientState: "cancelled" });
35393
+ await finalizePromptTurnOnBridge(deps.getWs, cancelRow.turnId, false, { terminalClientState: "cancelled" });
35263
35394
  const ws = deps.getWs();
35264
35395
  if (ws && cancelRow.sessionId) {
35265
35396
  sendWsMessage(ws, {
@@ -35278,19 +35409,19 @@ async function applyPromptQueueStateFromServer(msg, deps) {
35278
35409
  const startedThisTick = /* @__PURE__ */ new Set();
35279
35410
  for (const [queueKey, serverTurns] of Object.entries(raw)) {
35280
35411
  if (!Array.isArray(serverTurns)) continue;
35281
- const file2 = readPersistedQueue(queueKey);
35412
+ const file2 = await readPersistedQueue(queueKey);
35282
35413
  if (!file2) continue;
35283
35414
  if (hasRunningTurn(file2.turns)) continue;
35284
35415
  const next = pickNextRunnableTurn(file2.turns);
35285
35416
  if (!next) continue;
35286
35417
  if (!await runLocalRevertBeforeQueuedPrompt(next, deps)) {
35287
35418
  next.lastClientState = "failed";
35288
- writePersistedQueue(file2);
35419
+ await writePersistedQueue(file2);
35289
35420
  sendPromptQueueClientReport(getWs(), { [queueKey]: [{ turnId: next.turnId, clientState: "failed" }] });
35290
35421
  continue;
35291
35422
  }
35292
35423
  next.lastClientState = "running";
35293
- writePersistedQueue(file2);
35424
+ await writePersistedQueue(file2);
35294
35425
  runIdToQueueKey.set(next.turnId, queueKey);
35295
35426
  startedThisTick.add(next.turnId);
35296
35427
  report[queueKey] = [{ turnId: next.turnId, clientState: "running" }];
@@ -35300,7 +35431,7 @@ async function applyPromptQueueStateFromServer(msg, deps) {
35300
35431
  }
35301
35432
  for (const [queueKey, serverTurns] of Object.entries(raw)) {
35302
35433
  if (!Array.isArray(serverTurns)) continue;
35303
- const file2 = readPersistedQueue(queueKey);
35434
+ const file2 = await readPersistedQueue(queueKey);
35304
35435
  if (!file2) continue;
35305
35436
  const running = file2.turns.find((t) => t.lastClientState === "running");
35306
35437
  if (!running || !startedThisTick.has(running.turnId)) continue;
@@ -35308,17 +35439,17 @@ async function applyPromptQueueStateFromServer(msg, deps) {
35308
35439
  dispatchLocalPrompt(running, deps);
35309
35440
  }
35310
35441
  }
35311
- function finalizePromptTurnOnBridge(getWs, runId, success2, opts) {
35442
+ async function finalizePromptTurnOnBridge(getWs, runId, success2, opts) {
35312
35443
  if (!runId) return false;
35313
35444
  const queueKey = runIdToQueueKey.get(runId);
35314
35445
  runIdToQueueKey.delete(runId);
35315
35446
  if (!queueKey) return false;
35316
- const f = readPersistedQueue(queueKey);
35447
+ const f = await readPersistedQueue(queueKey);
35317
35448
  if (!f) return false;
35318
35449
  const t = f.turns.find((x) => x.turnId === runId);
35319
35450
  if (!t) return false;
35320
35451
  t.lastClientState = opts?.terminalClientState ?? (success2 ? "stopped" : "failed");
35321
- writePersistedQueue(f);
35452
+ await writePersistedQueue(f);
35322
35453
  sendPromptQueueClientReport(getWs(), { [queueKey]: [{ turnId: runId, clientState: t.lastClientState }] });
35323
35454
  return true;
35324
35455
  }
@@ -35339,12 +35470,13 @@ function createBridgePromptSenders(deps, getWs) {
35339
35470
  if (result.type === "prompt_result") {
35340
35471
  const pr = result;
35341
35472
  const cancelled = pr.stopReason === "cancelled";
35342
- finalizePromptTurnOnBridge(
35473
+ void finalizePromptTurnOnBridge(
35343
35474
  getWs,
35344
35475
  typeof pr.runId === "string" ? pr.runId : void 0,
35345
35476
  pr.success === true,
35346
35477
  cancelled ? { terminalClientState: "cancelled" } : void 0
35347
- );
35478
+ ).catch(() => {
35479
+ });
35348
35480
  }
35349
35481
  };
35350
35482
  const sendSessionUpdate = (payload) => {
@@ -35903,7 +36035,7 @@ function handleFileBrowserSearch(msg, socket, e2ee) {
35903
36035
  await yieldToEventLoop();
35904
36036
  const q = typeof msg.q === "string" ? msg.q : "";
35905
36037
  const cwd = path36.resolve(getBridgeRoot());
35906
- if (!bridgeFileIndexIsPopulated(cwd)) {
36038
+ if (!await bridgeFileIndexIsPopulated(cwd)) {
35907
36039
  const payload2 = {
35908
36040
  type: "file_browser_search_response",
35909
36041
  id: msg.id,
@@ -36743,7 +36875,7 @@ import * as path39 from "node:path";
36743
36875
  // src/agents/capabilities/probe-one-agent-type-for-capabilities.ts
36744
36876
  import * as path38 from "node:path";
36745
36877
  async function probeOneAgentTypeForCapabilities(params) {
36746
- const { agentType, cwd, workspaceId, log: log2, getDb, reportAgentCapabilities, bridgeReport = true } = params;
36878
+ const { agentType, cwd, workspaceId, log: log2, reportAgentCapabilities, bridgeReport = true } = params;
36747
36879
  const resolved = resolveAgentCommand(agentType);
36748
36880
  if (!resolved) return false;
36749
36881
  let sqliteChanged = false;
@@ -36754,11 +36886,13 @@ async function probeOneAgentTypeForCapabilities(params) {
36754
36886
  reportedRef.done = true;
36755
36887
  let changed = false;
36756
36888
  try {
36757
- changed = upsertCliAgentCapabilityCache(getDb(), {
36758
- workspaceId,
36759
- agentType,
36760
- configOptions: co
36761
- });
36889
+ changed = withCliSqliteSync(
36890
+ (db) => upsertCliAgentCapabilityCache(db, {
36891
+ workspaceId,
36892
+ agentType,
36893
+ configOptions: co
36894
+ })
36895
+ );
36762
36896
  } catch {
36763
36897
  }
36764
36898
  sqliteChanged ||= changed;
@@ -36816,7 +36950,6 @@ async function probeAgentCapabilitiesForDetectedTypes(params) {
36816
36950
  cwd,
36817
36951
  workspaceId,
36818
36952
  log: log2,
36819
- getDb,
36820
36953
  reportAgentCapabilities,
36821
36954
  bridgeReport = true,
36822
36955
  forceAllTypes = false
@@ -36828,7 +36961,7 @@ async function probeAgentCapabilitiesForDetectedTypes(params) {
36828
36961
  if (!agentType.trim()) continue;
36829
36962
  if (!forceAllTypes) {
36830
36963
  try {
36831
- if (process.env.BUILDAUTOMATON_FORCE_PROBE_ACP_CAPABILITIES !== "1" && hasNonEmptyAgentCapabilityCache(getDb(), workspaceId, agentType)) {
36964
+ if (process.env.BUILDAUTOMATON_FORCE_PROBE_ACP_CAPABILITIES !== "1" && await withCliSqlite((db) => hasNonEmptyAgentCapabilityCache(db, workspaceId, agentType))) {
36832
36965
  continue;
36833
36966
  }
36834
36967
  } catch {
@@ -36839,7 +36972,6 @@ async function probeAgentCapabilitiesForDetectedTypes(params) {
36839
36972
  cwd,
36840
36973
  workspaceId,
36841
36974
  log: log2,
36842
- getDb,
36843
36975
  reportAgentCapabilities,
36844
36976
  bridgeReport
36845
36977
  });
@@ -36850,14 +36982,13 @@ async function probeAgentCapabilitiesForDetectedTypes(params) {
36850
36982
 
36851
36983
  // src/agents/capabilities/warmup-agent-capabilities-on-connect.ts
36852
36984
  async function warmupAgentCapabilitiesOnConnect(params) {
36853
- const { workspaceId, log: log2, getDb, getWs } = params;
36985
+ const { workspaceId, log: log2, getWs } = params;
36854
36986
  const cwd = path39.resolve(getBridgeRoot());
36855
- const db = getDb();
36856
- function sendBatchFromCache() {
36987
+ async function sendBatchFromCache() {
36857
36988
  const socket = getWs();
36858
36989
  if (!socket || socket.readyState !== wrapper_default.OPEN) return;
36859
36990
  try {
36860
- const rows = listCliAgentCapabilityCacheForWorkspace(db, workspaceId);
36991
+ const rows = await withCliSqlite((db) => listCliAgentCapabilityCacheForWorkspace(db, workspaceId));
36861
36992
  if (rows.length === 0) return;
36862
36993
  sendWsMessage(socket, {
36863
36994
  type: "agent_capabilities_batch",
@@ -36869,7 +37000,7 @@ async function warmupAgentCapabilitiesOnConnect(params) {
36869
37000
  );
36870
37001
  }
36871
37002
  }
36872
- sendBatchFromCache();
37003
+ await sendBatchFromCache();
36873
37004
  let types = [];
36874
37005
  try {
36875
37006
  types = [...await detectLocalAgentTypes()];
@@ -36882,11 +37013,10 @@ async function warmupAgentCapabilitiesOnConnect(params) {
36882
37013
  cwd,
36883
37014
  workspaceId,
36884
37015
  log: log2,
36885
- getDb,
36886
37016
  bridgeReport: false,
36887
37017
  forceAllTypes: false
36888
37018
  });
36889
- if (n > 0) sendBatchFromCache();
37019
+ if (n > 0) await sendBatchFromCache();
36890
37020
  } catch (e) {
36891
37021
  log2(`[Bridge service] Agent capability probe (missing cache) failed: ${e instanceof Error ? e.message : String(e)}`);
36892
37022
  }
@@ -36898,11 +37028,10 @@ async function warmupAgentCapabilitiesOnConnect(params) {
36898
37028
  cwd,
36899
37029
  workspaceId,
36900
37030
  log: log2,
36901
- getDb,
36902
37031
  bridgeReport: false,
36903
37032
  forceAllTypes: true
36904
37033
  });
36905
- if (n > 0) sendBatchFromCache();
37034
+ if (n > 0) await sendBatchFromCache();
36906
37035
  } catch (e) {
36907
37036
  log2(`[Bridge service] Agent capability lazy refresh failed: ${e instanceof Error ? e.message : String(e)}`);
36908
37037
  }
@@ -36914,7 +37043,7 @@ async function createBridgeConnection(options) {
36914
37043
  const { apiUrl, workspaceId, justAuthenticated, onAuthInvalid, persistTokens } = options;
36915
37044
  const firehoseServerUrl = options.firehoseServerUrl ?? options.proxyServerUrl;
36916
37045
  const logFn = options.log ?? log;
36917
- getCliDatabase({ logLegacyMigration: logFn });
37046
+ await ensureCliSqliteInitialized({ logLegacyMigration: logFn });
36918
37047
  const tokens = {
36919
37048
  accessToken: options.authToken,
36920
37049
  refreshToken: options.refreshToken
@@ -36944,11 +37073,13 @@ async function createBridgeConnection(options) {
36944
37073
  if (!Array.isArray(info.configOptions) || info.configOptions.length === 0) return;
36945
37074
  let changed = false;
36946
37075
  try {
36947
- changed = upsertCliAgentCapabilityCache(getCliDatabase(), {
36948
- workspaceId,
36949
- agentType: info.agentType,
36950
- configOptions: info.configOptions
36951
- });
37076
+ changed = withCliSqliteSync(
37077
+ (db) => upsertCliAgentCapabilityCache(db, {
37078
+ workspaceId,
37079
+ agentType: info.agentType,
37080
+ configOptions: info.configOptions
37081
+ })
37082
+ );
36952
37083
  } catch {
36953
37084
  }
36954
37085
  if (!changed) return;
@@ -37001,7 +37132,6 @@ async function createBridgeConnection(options) {
37001
37132
  await warmupAgentCapabilitiesOnConnect({
37002
37133
  workspaceId,
37003
37134
  log: logFn,
37004
- getDb: getCliDatabase,
37005
37135
  getWs
37006
37136
  });
37007
37137
  },