@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/cli.js +262 -175
- package/dist/cli.js.map +4 -4
- package/dist/index.js +262 -175
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -25064,7 +25064,7 @@ var {
|
|
|
25064
25064
|
} = import_index.default;
|
|
25065
25065
|
|
|
25066
25066
|
// src/cli-version.ts
|
|
25067
|
-
var CLI_VERSION = "0.1.
|
|
25067
|
+
var CLI_VERSION = "0.1.32".length > 0 ? "0.1.32" : "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";
|
|
@@ -26699,6 +26699,11 @@ function runPendingAuth(options) {
|
|
|
26699
26699
|
// src/sqlite/cli-database.ts
|
|
26700
26700
|
import sqliteWasm from "node-sqlite3-wasm";
|
|
26701
26701
|
|
|
26702
|
+
// src/runtime/yield-to-event-loop.ts
|
|
26703
|
+
function yieldToEventLoop() {
|
|
26704
|
+
return new Promise((resolve20) => setImmediate(resolve20));
|
|
26705
|
+
}
|
|
26706
|
+
|
|
26702
26707
|
// src/sqlite/cli-sqlite-paths.ts
|
|
26703
26708
|
import fs8 from "node:fs";
|
|
26704
26709
|
import path5 from "node:path";
|
|
@@ -26991,6 +26996,23 @@ function migrateCliSqlite(db) {
|
|
|
26991
26996
|
|
|
26992
26997
|
// src/sqlite/cli-database.ts
|
|
26993
26998
|
var { Database: SqliteDatabase } = sqliteWasm;
|
|
26999
|
+
var CLI_SQLITE_SYNC_RETRY_MAX = 40;
|
|
27000
|
+
var CLI_SQLITE_ASYNC_RETRY_MAX = 60;
|
|
27001
|
+
var CLI_SQLITE_ASYNC_BASE_DELAY_MS = 20;
|
|
27002
|
+
function applyCliSqliteConcurrencyPragmas(db) {
|
|
27003
|
+
try {
|
|
27004
|
+
db.exec("PRAGMA journal_mode = WAL");
|
|
27005
|
+
} catch {
|
|
27006
|
+
}
|
|
27007
|
+
try {
|
|
27008
|
+
db.run("PRAGMA synchronous = NORMAL");
|
|
27009
|
+
} catch {
|
|
27010
|
+
}
|
|
27011
|
+
try {
|
|
27012
|
+
db.run("PRAGMA busy_timeout = 8000");
|
|
27013
|
+
} catch {
|
|
27014
|
+
}
|
|
27015
|
+
}
|
|
26994
27016
|
function applyCliSqliteMemoryPragmas(db) {
|
|
26995
27017
|
try {
|
|
26996
27018
|
db.run("PRAGMA cache_size = -8192");
|
|
@@ -26998,18 +27020,6 @@ function applyCliSqliteMemoryPragmas(db) {
|
|
|
26998
27020
|
} catch {
|
|
26999
27021
|
}
|
|
27000
27022
|
}
|
|
27001
|
-
var openDatabases = /* @__PURE__ */ new Map();
|
|
27002
|
-
var processExitCloseRegistered = false;
|
|
27003
|
-
function registerProcessExitSqliteClose() {
|
|
27004
|
-
if (processExitCloseRegistered) return;
|
|
27005
|
-
processExitCloseRegistered = true;
|
|
27006
|
-
process.once("exit", () => {
|
|
27007
|
-
for (const db of openDatabases.values()) {
|
|
27008
|
-
safeCloseCliSqliteDatabase(db);
|
|
27009
|
-
}
|
|
27010
|
-
openDatabases.clear();
|
|
27011
|
-
});
|
|
27012
|
-
}
|
|
27013
27023
|
function safeCloseCliSqliteDatabase(db) {
|
|
27014
27024
|
if (db == null) return;
|
|
27015
27025
|
try {
|
|
@@ -27018,22 +27028,33 @@ function safeCloseCliSqliteDatabase(db) {
|
|
|
27018
27028
|
}
|
|
27019
27029
|
}
|
|
27020
27030
|
function closeAllCliSqliteConnections() {
|
|
27021
|
-
|
|
27022
|
-
|
|
27031
|
+
}
|
|
27032
|
+
function isCliSqliteLockError(e) {
|
|
27033
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
27034
|
+
const lower = msg.toLowerCase();
|
|
27035
|
+
return lower.includes("database is locked") || lower.includes("sqlite_busy") || lower.includes("sqlite3_busy") || lower.includes("database") && lower.includes("locked");
|
|
27036
|
+
}
|
|
27037
|
+
function syncSleepMs(ms) {
|
|
27038
|
+
if (ms <= 0) return;
|
|
27039
|
+
try {
|
|
27040
|
+
const sab = new SharedArrayBuffer(4);
|
|
27041
|
+
const ia = new Int32Array(sab);
|
|
27042
|
+
Atomics.wait(ia, 0, 0, Math.min(ms, 1e4));
|
|
27043
|
+
} catch {
|
|
27044
|
+
const end = Date.now() + ms;
|
|
27045
|
+
while (Date.now() < end) {
|
|
27046
|
+
}
|
|
27023
27047
|
}
|
|
27024
|
-
openDatabases.clear();
|
|
27025
27048
|
}
|
|
27026
|
-
function
|
|
27049
|
+
function asyncDelayMs(ms) {
|
|
27050
|
+
return new Promise((resolve20) => setTimeout(resolve20, ms));
|
|
27051
|
+
}
|
|
27052
|
+
function openCliSqliteConnection(options) {
|
|
27027
27053
|
const sqlitePath = getCliSqlitePath();
|
|
27028
|
-
const existing = openDatabases.get(sqlitePath);
|
|
27029
|
-
if (existing?.isOpen) return existing;
|
|
27030
|
-
if (existing && !existing.isOpen) {
|
|
27031
|
-
safeCloseCliSqliteDatabase(existing);
|
|
27032
|
-
openDatabases.delete(sqlitePath);
|
|
27033
|
-
}
|
|
27034
27054
|
ensureCliSqliteParentDir(sqlitePath);
|
|
27035
27055
|
const db = new SqliteDatabase(sqlitePath);
|
|
27036
27056
|
try {
|
|
27057
|
+
applyCliSqliteConcurrencyPragmas(db);
|
|
27037
27058
|
applyCliSqliteMemoryPragmas(db);
|
|
27038
27059
|
migrateCliSqlite(db);
|
|
27039
27060
|
importCliSqliteLegacyDiskData(db, options?.logLegacyMigration);
|
|
@@ -27041,10 +27062,52 @@ function getCliDatabase(options) {
|
|
|
27041
27062
|
safeCloseCliSqliteDatabase(db);
|
|
27042
27063
|
throw e;
|
|
27043
27064
|
}
|
|
27044
|
-
openDatabases.set(sqlitePath, db);
|
|
27045
|
-
registerProcessExitSqliteClose();
|
|
27046
27065
|
return db;
|
|
27047
27066
|
}
|
|
27067
|
+
function withCliSqliteSync(fn, options) {
|
|
27068
|
+
for (let attempt = 1; attempt <= CLI_SQLITE_SYNC_RETRY_MAX; attempt++) {
|
|
27069
|
+
let db;
|
|
27070
|
+
try {
|
|
27071
|
+
db = openCliSqliteConnection(options);
|
|
27072
|
+
try {
|
|
27073
|
+
return fn(db);
|
|
27074
|
+
} finally {
|
|
27075
|
+
safeCloseCliSqliteDatabase(db);
|
|
27076
|
+
}
|
|
27077
|
+
} catch (e) {
|
|
27078
|
+
safeCloseCliSqliteDatabase(db);
|
|
27079
|
+
if (!isCliSqliteLockError(e) || attempt === CLI_SQLITE_SYNC_RETRY_MAX) throw e;
|
|
27080
|
+
syncSleepMs(Math.min(500, 12 * attempt));
|
|
27081
|
+
}
|
|
27082
|
+
}
|
|
27083
|
+
throw new Error("withCliSqliteSync: exhausted retries");
|
|
27084
|
+
}
|
|
27085
|
+
async function withCliSqlite(fn, options) {
|
|
27086
|
+
let lastError;
|
|
27087
|
+
for (let attempt = 1; attempt <= CLI_SQLITE_ASYNC_RETRY_MAX; attempt++) {
|
|
27088
|
+
let db;
|
|
27089
|
+
try {
|
|
27090
|
+
db = openCliSqliteConnection(options);
|
|
27091
|
+
try {
|
|
27092
|
+
return await Promise.resolve(fn(db));
|
|
27093
|
+
} finally {
|
|
27094
|
+
safeCloseCliSqliteDatabase(db);
|
|
27095
|
+
}
|
|
27096
|
+
} catch (e) {
|
|
27097
|
+
lastError = e;
|
|
27098
|
+
safeCloseCliSqliteDatabase(db);
|
|
27099
|
+
if (!isCliSqliteLockError(e) || attempt === CLI_SQLITE_ASYNC_RETRY_MAX) throw e;
|
|
27100
|
+
const delayMs = Math.min(600, CLI_SQLITE_ASYNC_BASE_DELAY_MS * attempt);
|
|
27101
|
+
await asyncDelayMs(delayMs);
|
|
27102
|
+
await yieldToEventLoop();
|
|
27103
|
+
}
|
|
27104
|
+
}
|
|
27105
|
+
if (lastError instanceof Error) throw lastError;
|
|
27106
|
+
throw new Error(String(lastError));
|
|
27107
|
+
}
|
|
27108
|
+
async function ensureCliSqliteInitialized(options) {
|
|
27109
|
+
await withCliSqlite(() => void 0, options);
|
|
27110
|
+
}
|
|
27048
27111
|
|
|
27049
27112
|
// src/connection/close-bridge-connection.ts
|
|
27050
27113
|
async function closeBridgeConnection(state, acpManager, devServerManager, log2) {
|
|
@@ -34812,56 +34875,80 @@ function sessionKeyForCloudSessionId(cloudSessionId) {
|
|
|
34812
34875
|
}
|
|
34813
34876
|
function readLocalAgentSessionFile(cloudSessionId) {
|
|
34814
34877
|
try {
|
|
34815
|
-
|
|
34816
|
-
|
|
34817
|
-
|
|
34818
|
-
|
|
34819
|
-
|
|
34820
|
-
|
|
34821
|
-
|
|
34822
|
-
|
|
34823
|
-
|
|
34824
|
-
|
|
34825
|
-
|
|
34826
|
-
|
|
34827
|
-
|
|
34828
|
-
|
|
34878
|
+
return withCliSqliteSync((db) => {
|
|
34879
|
+
const key = sessionKeyForCloudSessionId(cloudSessionId);
|
|
34880
|
+
const row = db.get(
|
|
34881
|
+
"SELECT acp_session_id, backend_agent_type, config_options_json, updated_at FROM agent_session WHERE session_key = ?",
|
|
34882
|
+
[key]
|
|
34883
|
+
);
|
|
34884
|
+
if (!row) return null;
|
|
34885
|
+
let configOptions = null;
|
|
34886
|
+
if (row.config_options_json != null && row.config_options_json !== "") {
|
|
34887
|
+
try {
|
|
34888
|
+
const parsed = JSON.parse(row.config_options_json);
|
|
34889
|
+
configOptions = Array.isArray(parsed) ? parsed : null;
|
|
34890
|
+
} catch {
|
|
34891
|
+
configOptions = null;
|
|
34892
|
+
}
|
|
34829
34893
|
}
|
|
34830
|
-
|
|
34831
|
-
|
|
34832
|
-
|
|
34833
|
-
|
|
34834
|
-
|
|
34835
|
-
|
|
34836
|
-
|
|
34837
|
-
};
|
|
34894
|
+
return {
|
|
34895
|
+
v: 1,
|
|
34896
|
+
acpSessionId: row.acp_session_id,
|
|
34897
|
+
backendAgentType: row.backend_agent_type,
|
|
34898
|
+
configOptions,
|
|
34899
|
+
updatedAt: row.updated_at
|
|
34900
|
+
};
|
|
34901
|
+
});
|
|
34838
34902
|
} catch {
|
|
34839
34903
|
return null;
|
|
34840
34904
|
}
|
|
34841
34905
|
}
|
|
34842
34906
|
function writeLocalAgentSessionFile(cloudSessionId, patch) {
|
|
34843
34907
|
try {
|
|
34844
|
-
|
|
34845
|
-
|
|
34846
|
-
|
|
34847
|
-
|
|
34848
|
-
|
|
34849
|
-
|
|
34850
|
-
|
|
34851
|
-
|
|
34852
|
-
|
|
34853
|
-
|
|
34854
|
-
|
|
34855
|
-
|
|
34856
|
-
|
|
34857
|
-
|
|
34858
|
-
|
|
34859
|
-
|
|
34860
|
-
|
|
34861
|
-
|
|
34862
|
-
|
|
34863
|
-
|
|
34864
|
-
|
|
34908
|
+
withCliSqliteSync((db) => {
|
|
34909
|
+
const key = sessionKeyForCloudSessionId(cloudSessionId);
|
|
34910
|
+
const prevRow = db.get(
|
|
34911
|
+
"SELECT acp_session_id, backend_agent_type, config_options_json, updated_at FROM agent_session WHERE session_key = ?",
|
|
34912
|
+
[key]
|
|
34913
|
+
);
|
|
34914
|
+
let prev = null;
|
|
34915
|
+
if (prevRow) {
|
|
34916
|
+
let configOptions = null;
|
|
34917
|
+
if (prevRow.config_options_json != null && prevRow.config_options_json !== "") {
|
|
34918
|
+
try {
|
|
34919
|
+
const parsed = JSON.parse(prevRow.config_options_json);
|
|
34920
|
+
configOptions = Array.isArray(parsed) ? parsed : null;
|
|
34921
|
+
} catch {
|
|
34922
|
+
configOptions = null;
|
|
34923
|
+
}
|
|
34924
|
+
}
|
|
34925
|
+
prev = {
|
|
34926
|
+
v: 1,
|
|
34927
|
+
acpSessionId: prevRow.acp_session_id,
|
|
34928
|
+
backendAgentType: prevRow.backend_agent_type,
|
|
34929
|
+
configOptions,
|
|
34930
|
+
updatedAt: prevRow.updated_at
|
|
34931
|
+
};
|
|
34932
|
+
}
|
|
34933
|
+
const next = {
|
|
34934
|
+
v: 1,
|
|
34935
|
+
acpSessionId: patch.acpSessionId !== void 0 ? patch.acpSessionId : prev?.acpSessionId ?? null,
|
|
34936
|
+
backendAgentType: patch.backendAgentType !== void 0 ? patch.backendAgentType : prev?.backendAgentType ?? null,
|
|
34937
|
+
configOptions: patch.configOptions !== void 0 ? patch.configOptions : prev?.configOptions ?? null,
|
|
34938
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
34939
|
+
};
|
|
34940
|
+
const configJson = next.configOptions != null ? JSON.stringify(next.configOptions) : null;
|
|
34941
|
+
db.run(
|
|
34942
|
+
`INSERT INTO agent_session (session_key, acp_session_id, backend_agent_type, config_options_json, updated_at)
|
|
34943
|
+
VALUES (?, ?, ?, ?, ?)
|
|
34944
|
+
ON CONFLICT(session_key) DO UPDATE SET
|
|
34945
|
+
acp_session_id = excluded.acp_session_id,
|
|
34946
|
+
backend_agent_type = excluded.backend_agent_type,
|
|
34947
|
+
config_options_json = excluded.config_options_json,
|
|
34948
|
+
updated_at = excluded.updated_at`,
|
|
34949
|
+
[key, next.acpSessionId, next.backendAgentType, configJson, next.updatedAt]
|
|
34950
|
+
);
|
|
34951
|
+
});
|
|
34865
34952
|
} catch {
|
|
34866
34953
|
}
|
|
34867
34954
|
}
|
|
@@ -36444,11 +36531,6 @@ function getCwdHashForFileIndex(resolvedCwd) {
|
|
|
36444
36531
|
// src/files/index/build-file-index.ts
|
|
36445
36532
|
import path29 from "node:path";
|
|
36446
36533
|
|
|
36447
|
-
// src/runtime/yield-to-event-loop.ts
|
|
36448
|
-
function yieldToEventLoop() {
|
|
36449
|
-
return new Promise((resolve20) => setImmediate(resolve20));
|
|
36450
|
-
}
|
|
36451
|
-
|
|
36452
36534
|
// src/files/index/walk-workspace-tree.ts
|
|
36453
36535
|
import fs25 from "node:fs";
|
|
36454
36536
|
import path28 from "node:path";
|
|
@@ -36513,39 +36595,40 @@ function withFileIndexSqliteLock(fn) {
|
|
|
36513
36595
|
// src/files/index/build-file-index.ts
|
|
36514
36596
|
var FILE_INDEX_INSERT_BUFFER = 2048;
|
|
36515
36597
|
function persistFileIndexForResolvedCwd(resolved) {
|
|
36516
|
-
|
|
36517
|
-
|
|
36518
|
-
|
|
36519
|
-
|
|
36520
|
-
|
|
36521
|
-
try {
|
|
36522
|
-
db.run("DELETE FROM file_index_path WHERE cwd_hash = ?", [h]);
|
|
36523
|
-
const ins = db.prepare("INSERT INTO file_index_path (cwd_hash, path) VALUES (?, ?)");
|
|
36598
|
+
return withCliSqliteSync((db) => {
|
|
36599
|
+
const h = getCwdHashForFileIndex(resolved);
|
|
36600
|
+
const buf = [];
|
|
36601
|
+
let pathCount = 0;
|
|
36602
|
+
db.run("BEGIN IMMEDIATE");
|
|
36524
36603
|
try {
|
|
36525
|
-
|
|
36526
|
-
|
|
36527
|
-
|
|
36528
|
-
|
|
36529
|
-
|
|
36530
|
-
|
|
36531
|
-
|
|
36532
|
-
|
|
36533
|
-
|
|
36534
|
-
|
|
36535
|
-
|
|
36536
|
-
|
|
36537
|
-
|
|
36538
|
-
|
|
36539
|
-
|
|
36540
|
-
|
|
36541
|
-
|
|
36542
|
-
|
|
36543
|
-
db.run("
|
|
36544
|
-
} catch {
|
|
36604
|
+
db.run("DELETE FROM file_index_path WHERE cwd_hash = ?", [h]);
|
|
36605
|
+
const ins = db.prepare("INSERT INTO file_index_path (cwd_hash, path) VALUES (?, ?)");
|
|
36606
|
+
try {
|
|
36607
|
+
const flushBuf = () => {
|
|
36608
|
+
for (const rel of buf) {
|
|
36609
|
+
ins.run([h, rel]);
|
|
36610
|
+
}
|
|
36611
|
+
pathCount += buf.length;
|
|
36612
|
+
buf.length = 0;
|
|
36613
|
+
};
|
|
36614
|
+
walkWorkspaceTreeSync(resolved, resolved, (rel) => {
|
|
36615
|
+
buf.push(rel);
|
|
36616
|
+
if (buf.length >= FILE_INDEX_INSERT_BUFFER) flushBuf();
|
|
36617
|
+
});
|
|
36618
|
+
flushBuf();
|
|
36619
|
+
} finally {
|
|
36620
|
+
ins.finalize();
|
|
36621
|
+
}
|
|
36622
|
+
db.run("COMMIT");
|
|
36623
|
+
} catch (e) {
|
|
36624
|
+
try {
|
|
36625
|
+
db.run("ROLLBACK");
|
|
36626
|
+
} catch {
|
|
36627
|
+
}
|
|
36628
|
+
throw e;
|
|
36545
36629
|
}
|
|
36546
|
-
|
|
36547
|
-
}
|
|
36548
|
-
return pathCount;
|
|
36630
|
+
return pathCount;
|
|
36631
|
+
});
|
|
36549
36632
|
}
|
|
36550
36633
|
async function buildFileIndexAsync(cwd) {
|
|
36551
36634
|
return withFileIndexSqliteLock(async () => {
|
|
@@ -36569,23 +36652,20 @@ function sqliteExprBridgeFileIndexDependencyRank() {
|
|
|
36569
36652
|
function escapeLikePattern(fragment) {
|
|
36570
36653
|
return fragment.replace(/\\/g, "\\\\").replace(/%/g, "\\%").replace(/_/g, "\\_");
|
|
36571
36654
|
}
|
|
36572
|
-
function
|
|
36573
|
-
const db = getCliDatabase();
|
|
36655
|
+
function bridgeFileIndexIsPopulatedWithDb(resolvedCwd, db) {
|
|
36574
36656
|
const h = getCwdHashForFileIndex(resolvedCwd);
|
|
36575
36657
|
const row = db.get("SELECT 1 as ok FROM file_index_path WHERE cwd_hash = ? LIMIT 1", [h]);
|
|
36576
36658
|
return row != null;
|
|
36577
36659
|
}
|
|
36578
|
-
function
|
|
36579
|
-
const db = getCliDatabase();
|
|
36660
|
+
function bridgeFileIndexPathCountWithDb(resolvedCwd, db) {
|
|
36580
36661
|
const h = getCwdHashForFileIndex(resolvedCwd);
|
|
36581
36662
|
const row = db.get("SELECT COUNT(*) as c FROM file_index_path WHERE cwd_hash = ?", [h]);
|
|
36582
36663
|
const c = row?.c ?? 0;
|
|
36583
36664
|
return Number(c);
|
|
36584
36665
|
}
|
|
36585
|
-
function
|
|
36666
|
+
function searchBridgeFilePathsWithDb(resolvedCwd, query, limit, db) {
|
|
36586
36667
|
const q = query.trim().toLowerCase();
|
|
36587
36668
|
if (!q) return [];
|
|
36588
|
-
const db = getCliDatabase();
|
|
36589
36669
|
const h = getCwdHashForFileIndex(resolvedCwd);
|
|
36590
36670
|
const pattern = `%${escapeLikePattern(q)}%`;
|
|
36591
36671
|
const lim = Math.max(0, Math.min(1e4, Math.floor(limit)));
|
|
@@ -36596,9 +36676,15 @@ function searchBridgeFilePaths(resolvedCwd, query, limit = 100) {
|
|
|
36596
36676
|
);
|
|
36597
36677
|
return rows.map((r) => String(r.path));
|
|
36598
36678
|
}
|
|
36679
|
+
async function bridgeFileIndexIsPopulated(resolvedCwd) {
|
|
36680
|
+
return withCliSqlite((db) => bridgeFileIndexIsPopulatedWithDb(resolvedCwd, db));
|
|
36681
|
+
}
|
|
36682
|
+
async function bridgeFileIndexPathCount(resolvedCwd) {
|
|
36683
|
+
return withCliSqlite((db) => bridgeFileIndexPathCountWithDb(resolvedCwd, db));
|
|
36684
|
+
}
|
|
36599
36685
|
async function searchBridgeFilePathsAsync(resolvedCwd, query, limit = 100) {
|
|
36600
36686
|
await yieldToEventLoop();
|
|
36601
|
-
const out =
|
|
36687
|
+
const out = await withCliSqlite((db) => searchBridgeFilePathsWithDb(resolvedCwd, query, limit, db));
|
|
36602
36688
|
if (out.length >= INDEX_WORK_YIELD_EVERY) await yieldToEventLoop();
|
|
36603
36689
|
return out;
|
|
36604
36690
|
}
|
|
@@ -36606,8 +36692,8 @@ async function searchBridgeFilePathsAsync(resolvedCwd, query, limit = 100) {
|
|
|
36606
36692
|
// src/files/index/ensure-file-index.ts
|
|
36607
36693
|
async function ensureFileIndexAsync(cwd) {
|
|
36608
36694
|
const resolved = path30.resolve(cwd);
|
|
36609
|
-
if (bridgeFileIndexIsPopulated(resolved)) {
|
|
36610
|
-
return { fromCache: true, pathCount: bridgeFileIndexPathCount(resolved) };
|
|
36695
|
+
if (await bridgeFileIndexIsPopulated(resolved)) {
|
|
36696
|
+
return { fromCache: true, pathCount: await bridgeFileIndexPathCount(resolved) };
|
|
36611
36697
|
}
|
|
36612
36698
|
return { ...await buildFileIndexAsync(resolved), fromCache: false };
|
|
36613
36699
|
}
|
|
@@ -38288,30 +38374,32 @@ var MERGEABLE_SERVER_STATES = /* @__PURE__ */ new Set([
|
|
|
38288
38374
|
"stopping",
|
|
38289
38375
|
"discarded"
|
|
38290
38376
|
]);
|
|
38291
|
-
function readPersistedQueue(queueKey) {
|
|
38292
|
-
|
|
38293
|
-
|
|
38294
|
-
|
|
38295
|
-
|
|
38296
|
-
|
|
38297
|
-
|
|
38298
|
-
|
|
38299
|
-
|
|
38300
|
-
|
|
38301
|
-
|
|
38302
|
-
|
|
38303
|
-
|
|
38377
|
+
async function readPersistedQueue(queueKey) {
|
|
38378
|
+
return withCliSqlite((db) => {
|
|
38379
|
+
const row = db.get("SELECT queue_key, updated_at, turns_json FROM prompt_queue WHERE queue_key = ?", [
|
|
38380
|
+
queueKey
|
|
38381
|
+
]);
|
|
38382
|
+
if (!row) return null;
|
|
38383
|
+
try {
|
|
38384
|
+
const turns = JSON.parse(row.turns_json);
|
|
38385
|
+
if (!Array.isArray(turns)) return null;
|
|
38386
|
+
return { queueKey: row.queue_key, updatedAt: row.updated_at, turns };
|
|
38387
|
+
} catch {
|
|
38388
|
+
return null;
|
|
38389
|
+
}
|
|
38390
|
+
});
|
|
38304
38391
|
}
|
|
38305
|
-
function writePersistedQueue(file2) {
|
|
38306
|
-
|
|
38307
|
-
|
|
38308
|
-
|
|
38309
|
-
|
|
38310
|
-
|
|
38311
|
-
|
|
38392
|
+
async function writePersistedQueue(file2) {
|
|
38393
|
+
await withCliSqlite((db) => {
|
|
38394
|
+
db.run(
|
|
38395
|
+
`INSERT INTO prompt_queue (queue_key, updated_at, turns_json) VALUES (?, ?, ?)
|
|
38396
|
+
ON CONFLICT(queue_key) DO UPDATE SET updated_at = excluded.updated_at, turns_json = excluded.turns_json`,
|
|
38397
|
+
[file2.queueKey, file2.updatedAt, JSON.stringify(file2.turns)]
|
|
38398
|
+
);
|
|
38399
|
+
});
|
|
38312
38400
|
}
|
|
38313
|
-
function mergeServerQueueSnapshot(queueKey, serverTurns) {
|
|
38314
|
-
const prev = readPersistedQueue(queueKey);
|
|
38401
|
+
async function mergeServerQueueSnapshot(queueKey, serverTurns) {
|
|
38402
|
+
const prev = await readPersistedQueue(queueKey);
|
|
38315
38403
|
const turns = [];
|
|
38316
38404
|
for (const raw of serverTurns) {
|
|
38317
38405
|
if (!raw || typeof raw !== "object") continue;
|
|
@@ -38408,12 +38496,12 @@ async function applyPromptQueueStateFromServer(msg, deps) {
|
|
|
38408
38496
|
const getWs = deps.getWs;
|
|
38409
38497
|
for (const [queueKey, serverTurns] of Object.entries(raw)) {
|
|
38410
38498
|
if (!Array.isArray(serverTurns)) continue;
|
|
38411
|
-
const file2 = mergeServerQueueSnapshot(queueKey, serverTurns);
|
|
38412
|
-
writePersistedQueue(file2);
|
|
38499
|
+
const file2 = await mergeServerQueueSnapshot(queueKey, serverTurns);
|
|
38500
|
+
await writePersistedQueue(file2);
|
|
38413
38501
|
}
|
|
38414
38502
|
for (const [queueKey, serverTurns] of Object.entries(raw)) {
|
|
38415
38503
|
if (!Array.isArray(serverTurns)) continue;
|
|
38416
|
-
const file2 = readPersistedQueue(queueKey);
|
|
38504
|
+
const file2 = await readPersistedQueue(queueKey);
|
|
38417
38505
|
if (!file2) continue;
|
|
38418
38506
|
for (const running of file2.turns.filter((t) => t.lastClientState === "running")) {
|
|
38419
38507
|
runIdToQueueKey.set(running.turnId, queueKey);
|
|
@@ -38421,7 +38509,7 @@ async function applyPromptQueueStateFromServer(msg, deps) {
|
|
|
38421
38509
|
}
|
|
38422
38510
|
for (const [queueKey, serverTurns] of Object.entries(raw)) {
|
|
38423
38511
|
if (!Array.isArray(serverTurns)) continue;
|
|
38424
|
-
const file2 = readPersistedQueue(queueKey);
|
|
38512
|
+
const file2 = await readPersistedQueue(queueKey);
|
|
38425
38513
|
if (!file2) continue;
|
|
38426
38514
|
const cancelRow = file2.turns.find((t) => t.serverState === "cancel_requested" && t.lastClientState === "running");
|
|
38427
38515
|
if (cancelRow) {
|
|
@@ -38430,7 +38518,7 @@ async function applyPromptQueueStateFromServer(msg, deps) {
|
|
|
38430
38518
|
deps.log(
|
|
38431
38519
|
`[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.`
|
|
38432
38520
|
);
|
|
38433
|
-
finalizePromptTurnOnBridge(deps.getWs, cancelRow.turnId, false, { terminalClientState: "cancelled" });
|
|
38521
|
+
await finalizePromptTurnOnBridge(deps.getWs, cancelRow.turnId, false, { terminalClientState: "cancelled" });
|
|
38434
38522
|
const ws = deps.getWs();
|
|
38435
38523
|
if (ws && cancelRow.sessionId) {
|
|
38436
38524
|
sendWsMessage(ws, {
|
|
@@ -38449,19 +38537,19 @@ async function applyPromptQueueStateFromServer(msg, deps) {
|
|
|
38449
38537
|
const startedThisTick = /* @__PURE__ */ new Set();
|
|
38450
38538
|
for (const [queueKey, serverTurns] of Object.entries(raw)) {
|
|
38451
38539
|
if (!Array.isArray(serverTurns)) continue;
|
|
38452
|
-
const file2 = readPersistedQueue(queueKey);
|
|
38540
|
+
const file2 = await readPersistedQueue(queueKey);
|
|
38453
38541
|
if (!file2) continue;
|
|
38454
38542
|
if (hasRunningTurn(file2.turns)) continue;
|
|
38455
38543
|
const next = pickNextRunnableTurn(file2.turns);
|
|
38456
38544
|
if (!next) continue;
|
|
38457
38545
|
if (!await runLocalRevertBeforeQueuedPrompt(next, deps)) {
|
|
38458
38546
|
next.lastClientState = "failed";
|
|
38459
|
-
writePersistedQueue(file2);
|
|
38547
|
+
await writePersistedQueue(file2);
|
|
38460
38548
|
sendPromptQueueClientReport(getWs(), { [queueKey]: [{ turnId: next.turnId, clientState: "failed" }] });
|
|
38461
38549
|
continue;
|
|
38462
38550
|
}
|
|
38463
38551
|
next.lastClientState = "running";
|
|
38464
|
-
writePersistedQueue(file2);
|
|
38552
|
+
await writePersistedQueue(file2);
|
|
38465
38553
|
runIdToQueueKey.set(next.turnId, queueKey);
|
|
38466
38554
|
startedThisTick.add(next.turnId);
|
|
38467
38555
|
report[queueKey] = [{ turnId: next.turnId, clientState: "running" }];
|
|
@@ -38471,7 +38559,7 @@ async function applyPromptQueueStateFromServer(msg, deps) {
|
|
|
38471
38559
|
}
|
|
38472
38560
|
for (const [queueKey, serverTurns] of Object.entries(raw)) {
|
|
38473
38561
|
if (!Array.isArray(serverTurns)) continue;
|
|
38474
|
-
const file2 = readPersistedQueue(queueKey);
|
|
38562
|
+
const file2 = await readPersistedQueue(queueKey);
|
|
38475
38563
|
if (!file2) continue;
|
|
38476
38564
|
const running = file2.turns.find((t) => t.lastClientState === "running");
|
|
38477
38565
|
if (!running || !startedThisTick.has(running.turnId)) continue;
|
|
@@ -38479,17 +38567,17 @@ async function applyPromptQueueStateFromServer(msg, deps) {
|
|
|
38479
38567
|
dispatchLocalPrompt(running, deps);
|
|
38480
38568
|
}
|
|
38481
38569
|
}
|
|
38482
|
-
function finalizePromptTurnOnBridge(getWs, runId, success2, opts) {
|
|
38570
|
+
async function finalizePromptTurnOnBridge(getWs, runId, success2, opts) {
|
|
38483
38571
|
if (!runId) return false;
|
|
38484
38572
|
const queueKey = runIdToQueueKey.get(runId);
|
|
38485
38573
|
runIdToQueueKey.delete(runId);
|
|
38486
38574
|
if (!queueKey) return false;
|
|
38487
|
-
const f = readPersistedQueue(queueKey);
|
|
38575
|
+
const f = await readPersistedQueue(queueKey);
|
|
38488
38576
|
if (!f) return false;
|
|
38489
38577
|
const t = f.turns.find((x) => x.turnId === runId);
|
|
38490
38578
|
if (!t) return false;
|
|
38491
38579
|
t.lastClientState = opts?.terminalClientState ?? (success2 ? "stopped" : "failed");
|
|
38492
|
-
writePersistedQueue(f);
|
|
38580
|
+
await writePersistedQueue(f);
|
|
38493
38581
|
sendPromptQueueClientReport(getWs(), { [queueKey]: [{ turnId: runId, clientState: t.lastClientState }] });
|
|
38494
38582
|
return true;
|
|
38495
38583
|
}
|
|
@@ -38510,12 +38598,13 @@ function createBridgePromptSenders(deps, getWs) {
|
|
|
38510
38598
|
if (result.type === "prompt_result") {
|
|
38511
38599
|
const pr = result;
|
|
38512
38600
|
const cancelled = pr.stopReason === "cancelled";
|
|
38513
|
-
finalizePromptTurnOnBridge(
|
|
38601
|
+
void finalizePromptTurnOnBridge(
|
|
38514
38602
|
getWs,
|
|
38515
38603
|
typeof pr.runId === "string" ? pr.runId : void 0,
|
|
38516
38604
|
pr.success === true,
|
|
38517
38605
|
cancelled ? { terminalClientState: "cancelled" } : void 0
|
|
38518
|
-
)
|
|
38606
|
+
).catch(() => {
|
|
38607
|
+
});
|
|
38519
38608
|
}
|
|
38520
38609
|
};
|
|
38521
38610
|
const sendSessionUpdate = (payload) => {
|
|
@@ -39248,7 +39337,7 @@ function handleFileBrowserSearch(msg, socket, e2ee) {
|
|
|
39248
39337
|
await yieldToEventLoop();
|
|
39249
39338
|
const q = typeof msg.q === "string" ? msg.q : "";
|
|
39250
39339
|
const cwd = path37.resolve(getBridgeRoot());
|
|
39251
|
-
if (!bridgeFileIndexIsPopulated(cwd)) {
|
|
39340
|
+
if (!await bridgeFileIndexIsPopulated(cwd)) {
|
|
39252
39341
|
const payload2 = {
|
|
39253
39342
|
type: "file_browser_search_response",
|
|
39254
39343
|
id: msg.id,
|
|
@@ -40009,7 +40098,7 @@ import * as path40 from "node:path";
|
|
|
40009
40098
|
// src/agents/capabilities/probe-one-agent-type-for-capabilities.ts
|
|
40010
40099
|
import * as path39 from "node:path";
|
|
40011
40100
|
async function probeOneAgentTypeForCapabilities(params) {
|
|
40012
|
-
const { agentType, cwd, workspaceId, log: log2,
|
|
40101
|
+
const { agentType, cwd, workspaceId, log: log2, reportAgentCapabilities, bridgeReport = true } = params;
|
|
40013
40102
|
const resolved = resolveAgentCommand(agentType);
|
|
40014
40103
|
if (!resolved) return false;
|
|
40015
40104
|
let sqliteChanged = false;
|
|
@@ -40020,11 +40109,13 @@ async function probeOneAgentTypeForCapabilities(params) {
|
|
|
40020
40109
|
reportedRef.done = true;
|
|
40021
40110
|
let changed = false;
|
|
40022
40111
|
try {
|
|
40023
|
-
changed =
|
|
40024
|
-
|
|
40025
|
-
|
|
40026
|
-
|
|
40027
|
-
|
|
40112
|
+
changed = withCliSqliteSync(
|
|
40113
|
+
(db) => upsertCliAgentCapabilityCache(db, {
|
|
40114
|
+
workspaceId,
|
|
40115
|
+
agentType,
|
|
40116
|
+
configOptions: co
|
|
40117
|
+
})
|
|
40118
|
+
);
|
|
40028
40119
|
} catch {
|
|
40029
40120
|
}
|
|
40030
40121
|
sqliteChanged ||= changed;
|
|
@@ -40082,7 +40173,6 @@ async function probeAgentCapabilitiesForDetectedTypes(params) {
|
|
|
40082
40173
|
cwd,
|
|
40083
40174
|
workspaceId,
|
|
40084
40175
|
log: log2,
|
|
40085
|
-
getDb,
|
|
40086
40176
|
reportAgentCapabilities,
|
|
40087
40177
|
bridgeReport = true,
|
|
40088
40178
|
forceAllTypes = false
|
|
@@ -40094,7 +40184,7 @@ async function probeAgentCapabilitiesForDetectedTypes(params) {
|
|
|
40094
40184
|
if (!agentType.trim()) continue;
|
|
40095
40185
|
if (!forceAllTypes) {
|
|
40096
40186
|
try {
|
|
40097
|
-
if (process.env.BUILDAUTOMATON_FORCE_PROBE_ACP_CAPABILITIES !== "1" &&
|
|
40187
|
+
if (process.env.BUILDAUTOMATON_FORCE_PROBE_ACP_CAPABILITIES !== "1" && await withCliSqlite((db) => hasNonEmptyAgentCapabilityCache(db, workspaceId, agentType))) {
|
|
40098
40188
|
continue;
|
|
40099
40189
|
}
|
|
40100
40190
|
} catch {
|
|
@@ -40105,7 +40195,6 @@ async function probeAgentCapabilitiesForDetectedTypes(params) {
|
|
|
40105
40195
|
cwd,
|
|
40106
40196
|
workspaceId,
|
|
40107
40197
|
log: log2,
|
|
40108
|
-
getDb,
|
|
40109
40198
|
reportAgentCapabilities,
|
|
40110
40199
|
bridgeReport
|
|
40111
40200
|
});
|
|
@@ -40116,14 +40205,13 @@ async function probeAgentCapabilitiesForDetectedTypes(params) {
|
|
|
40116
40205
|
|
|
40117
40206
|
// src/agents/capabilities/warmup-agent-capabilities-on-connect.ts
|
|
40118
40207
|
async function warmupAgentCapabilitiesOnConnect(params) {
|
|
40119
|
-
const { workspaceId, log: log2,
|
|
40208
|
+
const { workspaceId, log: log2, getWs } = params;
|
|
40120
40209
|
const cwd = path40.resolve(getBridgeRoot());
|
|
40121
|
-
|
|
40122
|
-
function sendBatchFromCache() {
|
|
40210
|
+
async function sendBatchFromCache() {
|
|
40123
40211
|
const socket = getWs();
|
|
40124
40212
|
if (!socket || socket.readyState !== wrapper_default.OPEN) return;
|
|
40125
40213
|
try {
|
|
40126
|
-
const rows = listCliAgentCapabilityCacheForWorkspace(db, workspaceId);
|
|
40214
|
+
const rows = await withCliSqlite((db) => listCliAgentCapabilityCacheForWorkspace(db, workspaceId));
|
|
40127
40215
|
if (rows.length === 0) return;
|
|
40128
40216
|
sendWsMessage(socket, {
|
|
40129
40217
|
type: "agent_capabilities_batch",
|
|
@@ -40135,7 +40223,7 @@ async function warmupAgentCapabilitiesOnConnect(params) {
|
|
|
40135
40223
|
);
|
|
40136
40224
|
}
|
|
40137
40225
|
}
|
|
40138
|
-
sendBatchFromCache();
|
|
40226
|
+
await sendBatchFromCache();
|
|
40139
40227
|
let types = [];
|
|
40140
40228
|
try {
|
|
40141
40229
|
types = [...await detectLocalAgentTypes()];
|
|
@@ -40148,11 +40236,10 @@ async function warmupAgentCapabilitiesOnConnect(params) {
|
|
|
40148
40236
|
cwd,
|
|
40149
40237
|
workspaceId,
|
|
40150
40238
|
log: log2,
|
|
40151
|
-
getDb,
|
|
40152
40239
|
bridgeReport: false,
|
|
40153
40240
|
forceAllTypes: false
|
|
40154
40241
|
});
|
|
40155
|
-
if (n > 0) sendBatchFromCache();
|
|
40242
|
+
if (n > 0) await sendBatchFromCache();
|
|
40156
40243
|
} catch (e) {
|
|
40157
40244
|
log2(`[Bridge service] Agent capability probe (missing cache) failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
40158
40245
|
}
|
|
@@ -40164,11 +40251,10 @@ async function warmupAgentCapabilitiesOnConnect(params) {
|
|
|
40164
40251
|
cwd,
|
|
40165
40252
|
workspaceId,
|
|
40166
40253
|
log: log2,
|
|
40167
|
-
getDb,
|
|
40168
40254
|
bridgeReport: false,
|
|
40169
40255
|
forceAllTypes: true
|
|
40170
40256
|
});
|
|
40171
|
-
if (n > 0) sendBatchFromCache();
|
|
40257
|
+
if (n > 0) await sendBatchFromCache();
|
|
40172
40258
|
} catch (e) {
|
|
40173
40259
|
log2(`[Bridge service] Agent capability lazy refresh failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
40174
40260
|
}
|
|
@@ -40180,7 +40266,7 @@ async function createBridgeConnection(options) {
|
|
|
40180
40266
|
const { apiUrl, workspaceId, justAuthenticated, onAuthInvalid, persistTokens } = options;
|
|
40181
40267
|
const firehoseServerUrl = options.firehoseServerUrl ?? options.proxyServerUrl;
|
|
40182
40268
|
const logFn = options.log ?? log;
|
|
40183
|
-
|
|
40269
|
+
await ensureCliSqliteInitialized({ logLegacyMigration: logFn });
|
|
40184
40270
|
const tokens = {
|
|
40185
40271
|
accessToken: options.authToken,
|
|
40186
40272
|
refreshToken: options.refreshToken
|
|
@@ -40210,11 +40296,13 @@ async function createBridgeConnection(options) {
|
|
|
40210
40296
|
if (!Array.isArray(info.configOptions) || info.configOptions.length === 0) return;
|
|
40211
40297
|
let changed = false;
|
|
40212
40298
|
try {
|
|
40213
|
-
changed =
|
|
40214
|
-
|
|
40215
|
-
|
|
40216
|
-
|
|
40217
|
-
|
|
40299
|
+
changed = withCliSqliteSync(
|
|
40300
|
+
(db) => upsertCliAgentCapabilityCache(db, {
|
|
40301
|
+
workspaceId,
|
|
40302
|
+
agentType: info.agentType,
|
|
40303
|
+
configOptions: info.configOptions
|
|
40304
|
+
})
|
|
40305
|
+
);
|
|
40218
40306
|
} catch {
|
|
40219
40307
|
}
|
|
40220
40308
|
if (!changed) return;
|
|
@@ -40267,7 +40355,6 @@ async function createBridgeConnection(options) {
|
|
|
40267
40355
|
await warmupAgentCapabilitiesOnConnect({
|
|
40268
40356
|
workspaceId,
|
|
40269
40357
|
log: logFn,
|
|
40270
|
-
getDb: getCliDatabase,
|
|
40271
40358
|
getWs
|
|
40272
40359
|
});
|
|
40273
40360
|
},
|