@buildautomaton/cli 0.1.31 → 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.31".length > 0 ? "0.1.31" : "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,6 +25322,23 @@ function migrateCliSqlite(db) {
25317
25322
 
25318
25323
  // src/sqlite/cli-database.ts
25319
25324
  var { Database: SqliteDatabase } = sqliteWasm;
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
+ }
25320
25342
  function applyCliSqliteMemoryPragmas(db) {
25321
25343
  try {
25322
25344
  db.run("PRAGMA cache_size = -8192");
@@ -25324,18 +25346,6 @@ function applyCliSqliteMemoryPragmas(db) {
25324
25346
  } catch {
25325
25347
  }
25326
25348
  }
25327
- var openDatabases = /* @__PURE__ */ new Map();
25328
- var processExitCloseRegistered = false;
25329
- function registerProcessExitSqliteClose() {
25330
- if (processExitCloseRegistered) return;
25331
- processExitCloseRegistered = true;
25332
- process.once("exit", () => {
25333
- for (const db of openDatabases.values()) {
25334
- safeCloseCliSqliteDatabase(db);
25335
- }
25336
- openDatabases.clear();
25337
- });
25338
- }
25339
25349
  function safeCloseCliSqliteDatabase(db) {
25340
25350
  if (db == null) return;
25341
25351
  try {
@@ -25344,22 +25354,33 @@ function safeCloseCliSqliteDatabase(db) {
25344
25354
  }
25345
25355
  }
25346
25356
  function closeAllCliSqliteConnections() {
25347
- for (const db of openDatabases.values()) {
25348
- 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
+ }
25349
25373
  }
25350
- openDatabases.clear();
25351
25374
  }
25352
- function getCliDatabase(options) {
25375
+ function asyncDelayMs(ms) {
25376
+ return new Promise((resolve18) => setTimeout(resolve18, ms));
25377
+ }
25378
+ function openCliSqliteConnection(options) {
25353
25379
  const sqlitePath = getCliSqlitePath();
25354
- const existing = openDatabases.get(sqlitePath);
25355
- if (existing?.isOpen) return existing;
25356
- if (existing && !existing.isOpen) {
25357
- safeCloseCliSqliteDatabase(existing);
25358
- openDatabases.delete(sqlitePath);
25359
- }
25360
25380
  ensureCliSqliteParentDir(sqlitePath);
25361
25381
  const db = new SqliteDatabase(sqlitePath);
25362
25382
  try {
25383
+ applyCliSqliteConcurrencyPragmas(db);
25363
25384
  applyCliSqliteMemoryPragmas(db);
25364
25385
  migrateCliSqlite(db);
25365
25386
  importCliSqliteLegacyDiskData(db, options?.logLegacyMigration);
@@ -25367,10 +25388,52 @@ function getCliDatabase(options) {
25367
25388
  safeCloseCliSqliteDatabase(db);
25368
25389
  throw e;
25369
25390
  }
25370
- openDatabases.set(sqlitePath, db);
25371
- registerProcessExitSqliteClose();
25372
25391
  return db;
25373
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
+ }
25374
25437
 
25375
25438
  // src/connection/close-bridge-connection.ts
25376
25439
  async function closeBridgeConnection(state, acpManager, devServerManager, log2) {
@@ -31852,56 +31915,80 @@ function sessionKeyForCloudSessionId(cloudSessionId) {
31852
31915
  }
31853
31916
  function readLocalAgentSessionFile(cloudSessionId) {
31854
31917
  try {
31855
- const db = getCliDatabase();
31856
- const key = sessionKeyForCloudSessionId(cloudSessionId);
31857
- const row = db.get(
31858
- "SELECT acp_session_id, backend_agent_type, config_options_json, updated_at FROM agent_session WHERE session_key = ?",
31859
- [key]
31860
- );
31861
- if (!row) return null;
31862
- let configOptions = null;
31863
- if (row.config_options_json != null && row.config_options_json !== "") {
31864
- try {
31865
- const parsed = JSON.parse(row.config_options_json);
31866
- configOptions = Array.isArray(parsed) ? parsed : null;
31867
- } catch {
31868
- 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
+ }
31869
31933
  }
31870
- }
31871
- return {
31872
- v: 1,
31873
- acpSessionId: row.acp_session_id,
31874
- backendAgentType: row.backend_agent_type,
31875
- configOptions,
31876
- updatedAt: row.updated_at
31877
- };
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
+ });
31878
31942
  } catch {
31879
31943
  return null;
31880
31944
  }
31881
31945
  }
31882
31946
  function writeLocalAgentSessionFile(cloudSessionId, patch) {
31883
31947
  try {
31884
- const db = getCliDatabase();
31885
- const key = sessionKeyForCloudSessionId(cloudSessionId);
31886
- const prev = readLocalAgentSessionFile(cloudSessionId);
31887
- const next = {
31888
- v: 1,
31889
- acpSessionId: patch.acpSessionId !== void 0 ? patch.acpSessionId : prev?.acpSessionId ?? null,
31890
- backendAgentType: patch.backendAgentType !== void 0 ? patch.backendAgentType : prev?.backendAgentType ?? null,
31891
- configOptions: patch.configOptions !== void 0 ? patch.configOptions : prev?.configOptions ?? null,
31892
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
31893
- };
31894
- const configJson = next.configOptions != null ? JSON.stringify(next.configOptions) : null;
31895
- db.run(
31896
- `INSERT INTO agent_session (session_key, acp_session_id, backend_agent_type, config_options_json, updated_at)
31897
- VALUES (?, ?, ?, ?, ?)
31898
- ON CONFLICT(session_key) DO UPDATE SET
31899
- acp_session_id = excluded.acp_session_id,
31900
- backend_agent_type = excluded.backend_agent_type,
31901
- config_options_json = excluded.config_options_json,
31902
- updated_at = excluded.updated_at`,
31903
- [key, next.acpSessionId, next.backendAgentType, configJson, next.updatedAt]
31904
- );
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
+ });
31905
31992
  } catch {
31906
31993
  }
31907
31994
  }
@@ -33484,11 +33571,6 @@ function getCwdHashForFileIndex(resolvedCwd) {
33484
33571
  // src/files/index/build-file-index.ts
33485
33572
  import path28 from "node:path";
33486
33573
 
33487
- // src/runtime/yield-to-event-loop.ts
33488
- function yieldToEventLoop() {
33489
- return new Promise((resolve18) => setImmediate(resolve18));
33490
- }
33491
-
33492
33574
  // src/files/index/walk-workspace-tree.ts
33493
33575
  import fs24 from "node:fs";
33494
33576
  import path27 from "node:path";
@@ -33553,39 +33635,40 @@ function withFileIndexSqliteLock(fn) {
33553
33635
  // src/files/index/build-file-index.ts
33554
33636
  var FILE_INDEX_INSERT_BUFFER = 2048;
33555
33637
  function persistFileIndexForResolvedCwd(resolved) {
33556
- const db = getCliDatabase();
33557
- const h = getCwdHashForFileIndex(resolved);
33558
- const buf = [];
33559
- let pathCount = 0;
33560
- db.run("BEGIN IMMEDIATE");
33561
- try {
33562
- db.run("DELETE FROM file_index_path WHERE cwd_hash = ?", [h]);
33563
- const ins = db.prepare("INSERT INTO file_index_path (cwd_hash, path) VALUES (?, ?)");
33638
+ return withCliSqliteSync((db) => {
33639
+ const h = getCwdHashForFileIndex(resolved);
33640
+ const buf = [];
33641
+ let pathCount = 0;
33642
+ db.run("BEGIN IMMEDIATE");
33564
33643
  try {
33565
- const flushBuf = () => {
33566
- for (const rel of buf) {
33567
- ins.run([h, rel]);
33568
- }
33569
- pathCount += buf.length;
33570
- buf.length = 0;
33571
- };
33572
- walkWorkspaceTreeSync(resolved, resolved, (rel) => {
33573
- buf.push(rel);
33574
- if (buf.length >= FILE_INDEX_INSERT_BUFFER) flushBuf();
33575
- });
33576
- flushBuf();
33577
- } finally {
33578
- ins.finalize();
33579
- }
33580
- db.run("COMMIT");
33581
- } catch (e) {
33582
- try {
33583
- db.run("ROLLBACK");
33584
- } catch {
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();
33661
+ }
33662
+ db.run("COMMIT");
33663
+ } catch (e) {
33664
+ try {
33665
+ db.run("ROLLBACK");
33666
+ } catch {
33667
+ }
33668
+ throw e;
33585
33669
  }
33586
- throw e;
33587
- }
33588
- return pathCount;
33670
+ return pathCount;
33671
+ });
33589
33672
  }
33590
33673
  async function buildFileIndexAsync(cwd) {
33591
33674
  return withFileIndexSqliteLock(async () => {
@@ -33609,23 +33692,20 @@ function sqliteExprBridgeFileIndexDependencyRank() {
33609
33692
  function escapeLikePattern(fragment) {
33610
33693
  return fragment.replace(/\\/g, "\\\\").replace(/%/g, "\\%").replace(/_/g, "\\_");
33611
33694
  }
33612
- function bridgeFileIndexIsPopulated(resolvedCwd) {
33613
- const db = getCliDatabase();
33695
+ function bridgeFileIndexIsPopulatedWithDb(resolvedCwd, db) {
33614
33696
  const h = getCwdHashForFileIndex(resolvedCwd);
33615
33697
  const row = db.get("SELECT 1 as ok FROM file_index_path WHERE cwd_hash = ? LIMIT 1", [h]);
33616
33698
  return row != null;
33617
33699
  }
33618
- function bridgeFileIndexPathCount(resolvedCwd) {
33619
- const db = getCliDatabase();
33700
+ function bridgeFileIndexPathCountWithDb(resolvedCwd, db) {
33620
33701
  const h = getCwdHashForFileIndex(resolvedCwd);
33621
33702
  const row = db.get("SELECT COUNT(*) as c FROM file_index_path WHERE cwd_hash = ?", [h]);
33622
33703
  const c = row?.c ?? 0;
33623
33704
  return Number(c);
33624
33705
  }
33625
- function searchBridgeFilePaths(resolvedCwd, query, limit = 100) {
33706
+ function searchBridgeFilePathsWithDb(resolvedCwd, query, limit, db) {
33626
33707
  const q = query.trim().toLowerCase();
33627
33708
  if (!q) return [];
33628
- const db = getCliDatabase();
33629
33709
  const h = getCwdHashForFileIndex(resolvedCwd);
33630
33710
  const pattern = `%${escapeLikePattern(q)}%`;
33631
33711
  const lim = Math.max(0, Math.min(1e4, Math.floor(limit)));
@@ -33636,9 +33716,15 @@ function searchBridgeFilePaths(resolvedCwd, query, limit = 100) {
33636
33716
  );
33637
33717
  return rows.map((r) => String(r.path));
33638
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
+ }
33639
33725
  async function searchBridgeFilePathsAsync(resolvedCwd, query, limit = 100) {
33640
33726
  await yieldToEventLoop();
33641
- const out = searchBridgeFilePaths(resolvedCwd, query, limit);
33727
+ const out = await withCliSqlite((db) => searchBridgeFilePathsWithDb(resolvedCwd, query, limit, db));
33642
33728
  if (out.length >= INDEX_WORK_YIELD_EVERY) await yieldToEventLoop();
33643
33729
  return out;
33644
33730
  }
@@ -33646,8 +33732,8 @@ async function searchBridgeFilePathsAsync(resolvedCwd, query, limit = 100) {
33646
33732
  // src/files/index/ensure-file-index.ts
33647
33733
  async function ensureFileIndexAsync(cwd) {
33648
33734
  const resolved = path29.resolve(cwd);
33649
- if (bridgeFileIndexIsPopulated(resolved)) {
33650
- return { fromCache: true, pathCount: bridgeFileIndexPathCount(resolved) };
33735
+ if (await bridgeFileIndexIsPopulated(resolved)) {
33736
+ return { fromCache: true, pathCount: await bridgeFileIndexPathCount(resolved) };
33651
33737
  }
33652
33738
  return { ...await buildFileIndexAsync(resolved), fromCache: false };
33653
33739
  }
@@ -35160,30 +35246,32 @@ var MERGEABLE_SERVER_STATES = /* @__PURE__ */ new Set([
35160
35246
  "stopping",
35161
35247
  "discarded"
35162
35248
  ]);
35163
- function readPersistedQueue(queueKey) {
35164
- const db = getCliDatabase();
35165
- const row = db.get("SELECT queue_key, updated_at, turns_json FROM prompt_queue WHERE queue_key = ?", [
35166
- queueKey
35167
- ]);
35168
- if (!row) return null;
35169
- try {
35170
- const turns = JSON.parse(row.turns_json);
35171
- if (!Array.isArray(turns)) return null;
35172
- return { queueKey: row.queue_key, updatedAt: row.updated_at, turns };
35173
- } catch {
35174
- return null;
35175
- }
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
+ });
35176
35263
  }
35177
- function writePersistedQueue(file2) {
35178
- const db = getCliDatabase();
35179
- db.run(
35180
- `INSERT INTO prompt_queue (queue_key, updated_at, turns_json) VALUES (?, ?, ?)
35181
- ON CONFLICT(queue_key) DO UPDATE SET updated_at = excluded.updated_at, turns_json = excluded.turns_json`,
35182
- [file2.queueKey, file2.updatedAt, JSON.stringify(file2.turns)]
35183
- );
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
+ });
35184
35272
  }
35185
- function mergeServerQueueSnapshot(queueKey, serverTurns) {
35186
- const prev = readPersistedQueue(queueKey);
35273
+ async function mergeServerQueueSnapshot(queueKey, serverTurns) {
35274
+ const prev = await readPersistedQueue(queueKey);
35187
35275
  const turns = [];
35188
35276
  for (const raw of serverTurns) {
35189
35277
  if (!raw || typeof raw !== "object") continue;
@@ -35280,12 +35368,12 @@ async function applyPromptQueueStateFromServer(msg, deps) {
35280
35368
  const getWs = deps.getWs;
35281
35369
  for (const [queueKey, serverTurns] of Object.entries(raw)) {
35282
35370
  if (!Array.isArray(serverTurns)) continue;
35283
- const file2 = mergeServerQueueSnapshot(queueKey, serverTurns);
35284
- writePersistedQueue(file2);
35371
+ const file2 = await mergeServerQueueSnapshot(queueKey, serverTurns);
35372
+ await writePersistedQueue(file2);
35285
35373
  }
35286
35374
  for (const [queueKey, serverTurns] of Object.entries(raw)) {
35287
35375
  if (!Array.isArray(serverTurns)) continue;
35288
- const file2 = readPersistedQueue(queueKey);
35376
+ const file2 = await readPersistedQueue(queueKey);
35289
35377
  if (!file2) continue;
35290
35378
  for (const running of file2.turns.filter((t) => t.lastClientState === "running")) {
35291
35379
  runIdToQueueKey.set(running.turnId, queueKey);
@@ -35293,7 +35381,7 @@ async function applyPromptQueueStateFromServer(msg, deps) {
35293
35381
  }
35294
35382
  for (const [queueKey, serverTurns] of Object.entries(raw)) {
35295
35383
  if (!Array.isArray(serverTurns)) continue;
35296
- const file2 = readPersistedQueue(queueKey);
35384
+ const file2 = await readPersistedQueue(queueKey);
35297
35385
  if (!file2) continue;
35298
35386
  const cancelRow = file2.turns.find((t) => t.serverState === "cancel_requested" && t.lastClientState === "running");
35299
35387
  if (cancelRow) {
@@ -35302,7 +35390,7 @@ async function applyPromptQueueStateFromServer(msg, deps) {
35302
35390
  deps.log(
35303
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.`
35304
35392
  );
35305
- finalizePromptTurnOnBridge(deps.getWs, cancelRow.turnId, false, { terminalClientState: "cancelled" });
35393
+ await finalizePromptTurnOnBridge(deps.getWs, cancelRow.turnId, false, { terminalClientState: "cancelled" });
35306
35394
  const ws = deps.getWs();
35307
35395
  if (ws && cancelRow.sessionId) {
35308
35396
  sendWsMessage(ws, {
@@ -35321,19 +35409,19 @@ async function applyPromptQueueStateFromServer(msg, deps) {
35321
35409
  const startedThisTick = /* @__PURE__ */ new Set();
35322
35410
  for (const [queueKey, serverTurns] of Object.entries(raw)) {
35323
35411
  if (!Array.isArray(serverTurns)) continue;
35324
- const file2 = readPersistedQueue(queueKey);
35412
+ const file2 = await readPersistedQueue(queueKey);
35325
35413
  if (!file2) continue;
35326
35414
  if (hasRunningTurn(file2.turns)) continue;
35327
35415
  const next = pickNextRunnableTurn(file2.turns);
35328
35416
  if (!next) continue;
35329
35417
  if (!await runLocalRevertBeforeQueuedPrompt(next, deps)) {
35330
35418
  next.lastClientState = "failed";
35331
- writePersistedQueue(file2);
35419
+ await writePersistedQueue(file2);
35332
35420
  sendPromptQueueClientReport(getWs(), { [queueKey]: [{ turnId: next.turnId, clientState: "failed" }] });
35333
35421
  continue;
35334
35422
  }
35335
35423
  next.lastClientState = "running";
35336
- writePersistedQueue(file2);
35424
+ await writePersistedQueue(file2);
35337
35425
  runIdToQueueKey.set(next.turnId, queueKey);
35338
35426
  startedThisTick.add(next.turnId);
35339
35427
  report[queueKey] = [{ turnId: next.turnId, clientState: "running" }];
@@ -35343,7 +35431,7 @@ async function applyPromptQueueStateFromServer(msg, deps) {
35343
35431
  }
35344
35432
  for (const [queueKey, serverTurns] of Object.entries(raw)) {
35345
35433
  if (!Array.isArray(serverTurns)) continue;
35346
- const file2 = readPersistedQueue(queueKey);
35434
+ const file2 = await readPersistedQueue(queueKey);
35347
35435
  if (!file2) continue;
35348
35436
  const running = file2.turns.find((t) => t.lastClientState === "running");
35349
35437
  if (!running || !startedThisTick.has(running.turnId)) continue;
@@ -35351,17 +35439,17 @@ async function applyPromptQueueStateFromServer(msg, deps) {
35351
35439
  dispatchLocalPrompt(running, deps);
35352
35440
  }
35353
35441
  }
35354
- function finalizePromptTurnOnBridge(getWs, runId, success2, opts) {
35442
+ async function finalizePromptTurnOnBridge(getWs, runId, success2, opts) {
35355
35443
  if (!runId) return false;
35356
35444
  const queueKey = runIdToQueueKey.get(runId);
35357
35445
  runIdToQueueKey.delete(runId);
35358
35446
  if (!queueKey) return false;
35359
- const f = readPersistedQueue(queueKey);
35447
+ const f = await readPersistedQueue(queueKey);
35360
35448
  if (!f) return false;
35361
35449
  const t = f.turns.find((x) => x.turnId === runId);
35362
35450
  if (!t) return false;
35363
35451
  t.lastClientState = opts?.terminalClientState ?? (success2 ? "stopped" : "failed");
35364
- writePersistedQueue(f);
35452
+ await writePersistedQueue(f);
35365
35453
  sendPromptQueueClientReport(getWs(), { [queueKey]: [{ turnId: runId, clientState: t.lastClientState }] });
35366
35454
  return true;
35367
35455
  }
@@ -35382,12 +35470,13 @@ function createBridgePromptSenders(deps, getWs) {
35382
35470
  if (result.type === "prompt_result") {
35383
35471
  const pr = result;
35384
35472
  const cancelled = pr.stopReason === "cancelled";
35385
- finalizePromptTurnOnBridge(
35473
+ void finalizePromptTurnOnBridge(
35386
35474
  getWs,
35387
35475
  typeof pr.runId === "string" ? pr.runId : void 0,
35388
35476
  pr.success === true,
35389
35477
  cancelled ? { terminalClientState: "cancelled" } : void 0
35390
- );
35478
+ ).catch(() => {
35479
+ });
35391
35480
  }
35392
35481
  };
35393
35482
  const sendSessionUpdate = (payload) => {
@@ -35946,7 +36035,7 @@ function handleFileBrowserSearch(msg, socket, e2ee) {
35946
36035
  await yieldToEventLoop();
35947
36036
  const q = typeof msg.q === "string" ? msg.q : "";
35948
36037
  const cwd = path36.resolve(getBridgeRoot());
35949
- if (!bridgeFileIndexIsPopulated(cwd)) {
36038
+ if (!await bridgeFileIndexIsPopulated(cwd)) {
35950
36039
  const payload2 = {
35951
36040
  type: "file_browser_search_response",
35952
36041
  id: msg.id,
@@ -36786,7 +36875,7 @@ import * as path39 from "node:path";
36786
36875
  // src/agents/capabilities/probe-one-agent-type-for-capabilities.ts
36787
36876
  import * as path38 from "node:path";
36788
36877
  async function probeOneAgentTypeForCapabilities(params) {
36789
- const { agentType, cwd, workspaceId, log: log2, getDb, reportAgentCapabilities, bridgeReport = true } = params;
36878
+ const { agentType, cwd, workspaceId, log: log2, reportAgentCapabilities, bridgeReport = true } = params;
36790
36879
  const resolved = resolveAgentCommand(agentType);
36791
36880
  if (!resolved) return false;
36792
36881
  let sqliteChanged = false;
@@ -36797,11 +36886,13 @@ async function probeOneAgentTypeForCapabilities(params) {
36797
36886
  reportedRef.done = true;
36798
36887
  let changed = false;
36799
36888
  try {
36800
- changed = upsertCliAgentCapabilityCache(getDb(), {
36801
- workspaceId,
36802
- agentType,
36803
- configOptions: co
36804
- });
36889
+ changed = withCliSqliteSync(
36890
+ (db) => upsertCliAgentCapabilityCache(db, {
36891
+ workspaceId,
36892
+ agentType,
36893
+ configOptions: co
36894
+ })
36895
+ );
36805
36896
  } catch {
36806
36897
  }
36807
36898
  sqliteChanged ||= changed;
@@ -36859,7 +36950,6 @@ async function probeAgentCapabilitiesForDetectedTypes(params) {
36859
36950
  cwd,
36860
36951
  workspaceId,
36861
36952
  log: log2,
36862
- getDb,
36863
36953
  reportAgentCapabilities,
36864
36954
  bridgeReport = true,
36865
36955
  forceAllTypes = false
@@ -36871,7 +36961,7 @@ async function probeAgentCapabilitiesForDetectedTypes(params) {
36871
36961
  if (!agentType.trim()) continue;
36872
36962
  if (!forceAllTypes) {
36873
36963
  try {
36874
- 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))) {
36875
36965
  continue;
36876
36966
  }
36877
36967
  } catch {
@@ -36882,7 +36972,6 @@ async function probeAgentCapabilitiesForDetectedTypes(params) {
36882
36972
  cwd,
36883
36973
  workspaceId,
36884
36974
  log: log2,
36885
- getDb,
36886
36975
  reportAgentCapabilities,
36887
36976
  bridgeReport
36888
36977
  });
@@ -36893,14 +36982,13 @@ async function probeAgentCapabilitiesForDetectedTypes(params) {
36893
36982
 
36894
36983
  // src/agents/capabilities/warmup-agent-capabilities-on-connect.ts
36895
36984
  async function warmupAgentCapabilitiesOnConnect(params) {
36896
- const { workspaceId, log: log2, getDb, getWs } = params;
36985
+ const { workspaceId, log: log2, getWs } = params;
36897
36986
  const cwd = path39.resolve(getBridgeRoot());
36898
- const db = getDb();
36899
- function sendBatchFromCache() {
36987
+ async function sendBatchFromCache() {
36900
36988
  const socket = getWs();
36901
36989
  if (!socket || socket.readyState !== wrapper_default.OPEN) return;
36902
36990
  try {
36903
- const rows = listCliAgentCapabilityCacheForWorkspace(db, workspaceId);
36991
+ const rows = await withCliSqlite((db) => listCliAgentCapabilityCacheForWorkspace(db, workspaceId));
36904
36992
  if (rows.length === 0) return;
36905
36993
  sendWsMessage(socket, {
36906
36994
  type: "agent_capabilities_batch",
@@ -36912,7 +37000,7 @@ async function warmupAgentCapabilitiesOnConnect(params) {
36912
37000
  );
36913
37001
  }
36914
37002
  }
36915
- sendBatchFromCache();
37003
+ await sendBatchFromCache();
36916
37004
  let types = [];
36917
37005
  try {
36918
37006
  types = [...await detectLocalAgentTypes()];
@@ -36925,11 +37013,10 @@ async function warmupAgentCapabilitiesOnConnect(params) {
36925
37013
  cwd,
36926
37014
  workspaceId,
36927
37015
  log: log2,
36928
- getDb,
36929
37016
  bridgeReport: false,
36930
37017
  forceAllTypes: false
36931
37018
  });
36932
- if (n > 0) sendBatchFromCache();
37019
+ if (n > 0) await sendBatchFromCache();
36933
37020
  } catch (e) {
36934
37021
  log2(`[Bridge service] Agent capability probe (missing cache) failed: ${e instanceof Error ? e.message : String(e)}`);
36935
37022
  }
@@ -36941,11 +37028,10 @@ async function warmupAgentCapabilitiesOnConnect(params) {
36941
37028
  cwd,
36942
37029
  workspaceId,
36943
37030
  log: log2,
36944
- getDb,
36945
37031
  bridgeReport: false,
36946
37032
  forceAllTypes: true
36947
37033
  });
36948
- if (n > 0) sendBatchFromCache();
37034
+ if (n > 0) await sendBatchFromCache();
36949
37035
  } catch (e) {
36950
37036
  log2(`[Bridge service] Agent capability lazy refresh failed: ${e instanceof Error ? e.message : String(e)}`);
36951
37037
  }
@@ -36957,7 +37043,7 @@ async function createBridgeConnection(options) {
36957
37043
  const { apiUrl, workspaceId, justAuthenticated, onAuthInvalid, persistTokens } = options;
36958
37044
  const firehoseServerUrl = options.firehoseServerUrl ?? options.proxyServerUrl;
36959
37045
  const logFn = options.log ?? log;
36960
- getCliDatabase({ logLegacyMigration: logFn });
37046
+ await ensureCliSqliteInitialized({ logLegacyMigration: logFn });
36961
37047
  const tokens = {
36962
37048
  accessToken: options.authToken,
36963
37049
  refreshToken: options.refreshToken
@@ -36987,11 +37073,13 @@ async function createBridgeConnection(options) {
36987
37073
  if (!Array.isArray(info.configOptions) || info.configOptions.length === 0) return;
36988
37074
  let changed = false;
36989
37075
  try {
36990
- changed = upsertCliAgentCapabilityCache(getCliDatabase(), {
36991
- workspaceId,
36992
- agentType: info.agentType,
36993
- configOptions: info.configOptions
36994
- });
37076
+ changed = withCliSqliteSync(
37077
+ (db) => upsertCliAgentCapabilityCache(db, {
37078
+ workspaceId,
37079
+ agentType: info.agentType,
37080
+ configOptions: info.configOptions
37081
+ })
37082
+ );
36995
37083
  } catch {
36996
37084
  }
36997
37085
  if (!changed) return;
@@ -37044,7 +37132,6 @@ async function createBridgeConnection(options) {
37044
37132
  await warmupAgentCapabilitiesOnConnect({
37045
37133
  workspaceId,
37046
37134
  log: logFn,
37047
- getDb: getCliDatabase,
37048
37135
  getWs
37049
37136
  });
37050
37137
  },