@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/cli.js +315 -185
- package/dist/cli.js.map +4 -4
- package/dist/index.js +315 -185
- 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,17 +26996,29 @@ function migrateCliSqlite(db) {
|
|
|
26991
26996
|
|
|
26992
26997
|
// src/sqlite/cli-database.ts
|
|
26993
26998
|
var { Database: SqliteDatabase } = sqliteWasm;
|
|
26994
|
-
var
|
|
26995
|
-
var
|
|
26996
|
-
|
|
26997
|
-
|
|
26998
|
-
|
|
26999
|
-
|
|
27000
|
-
|
|
27001
|
-
|
|
27002
|
-
|
|
27003
|
-
|
|
27004
|
-
}
|
|
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
|
+
}
|
|
27016
|
+
function applyCliSqliteMemoryPragmas(db) {
|
|
27017
|
+
try {
|
|
27018
|
+
db.run("PRAGMA cache_size = -8192");
|
|
27019
|
+
db.run("PRAGMA temp_store = FILE");
|
|
27020
|
+
} catch {
|
|
27021
|
+
}
|
|
27005
27022
|
}
|
|
27006
27023
|
function safeCloseCliSqliteDatabase(db) {
|
|
27007
27024
|
if (db == null) return;
|
|
@@ -27011,32 +27028,86 @@ function safeCloseCliSqliteDatabase(db) {
|
|
|
27011
27028
|
}
|
|
27012
27029
|
}
|
|
27013
27030
|
function closeAllCliSqliteConnections() {
|
|
27014
|
-
|
|
27015
|
-
|
|
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
|
+
}
|
|
27016
27047
|
}
|
|
27017
|
-
openDatabases.clear();
|
|
27018
27048
|
}
|
|
27019
|
-
function
|
|
27049
|
+
function asyncDelayMs(ms) {
|
|
27050
|
+
return new Promise((resolve20) => setTimeout(resolve20, ms));
|
|
27051
|
+
}
|
|
27052
|
+
function openCliSqliteConnection(options) {
|
|
27020
27053
|
const sqlitePath = getCliSqlitePath();
|
|
27021
|
-
const existing = openDatabases.get(sqlitePath);
|
|
27022
|
-
if (existing?.isOpen) return existing;
|
|
27023
|
-
if (existing && !existing.isOpen) {
|
|
27024
|
-
safeCloseCliSqliteDatabase(existing);
|
|
27025
|
-
openDatabases.delete(sqlitePath);
|
|
27026
|
-
}
|
|
27027
27054
|
ensureCliSqliteParentDir(sqlitePath);
|
|
27028
27055
|
const db = new SqliteDatabase(sqlitePath);
|
|
27029
27056
|
try {
|
|
27057
|
+
applyCliSqliteConcurrencyPragmas(db);
|
|
27058
|
+
applyCliSqliteMemoryPragmas(db);
|
|
27030
27059
|
migrateCliSqlite(db);
|
|
27031
27060
|
importCliSqliteLegacyDiskData(db, options?.logLegacyMigration);
|
|
27032
27061
|
} catch (e) {
|
|
27033
27062
|
safeCloseCliSqliteDatabase(db);
|
|
27034
27063
|
throw e;
|
|
27035
27064
|
}
|
|
27036
|
-
openDatabases.set(sqlitePath, db);
|
|
27037
|
-
registerProcessExitSqliteClose();
|
|
27038
27065
|
return db;
|
|
27039
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
|
+
}
|
|
27040
27111
|
|
|
27041
27112
|
// src/connection/close-bridge-connection.ts
|
|
27042
27113
|
async function closeBridgeConnection(state, acpManager, devServerManager, log2) {
|
|
@@ -34670,6 +34741,28 @@ function sendGitHeadVsWorkspaceForToolPaths(mergedPaths, sentPaths, send, sessio
|
|
|
34670
34741
|
}
|
|
34671
34742
|
}
|
|
34672
34743
|
|
|
34744
|
+
// src/agents/acp/hooks/bridge-on-session-update/send-session-info-title-update.ts
|
|
34745
|
+
function extractSessionInfoTitle(params) {
|
|
34746
|
+
if (!params || typeof params !== "object") return null;
|
|
34747
|
+
const p = params;
|
|
34748
|
+
const title = typeof p.title === "string" ? p.title.trim() : "";
|
|
34749
|
+
return title ? title : null;
|
|
34750
|
+
}
|
|
34751
|
+
function sendSessionInfoTitleUpdate(params) {
|
|
34752
|
+
const title = extractSessionInfoTitle(params.payload);
|
|
34753
|
+
if (!title || !params.runId || !params.send) return;
|
|
34754
|
+
try {
|
|
34755
|
+
params.send({
|
|
34756
|
+
type: "session_title_update",
|
|
34757
|
+
...params.sessionId ? { sessionId: params.sessionId } : {},
|
|
34758
|
+
runId: params.runId,
|
|
34759
|
+
title
|
|
34760
|
+
});
|
|
34761
|
+
} catch (err) {
|
|
34762
|
+
params.log(`[Bridge service] Session title update send failed: ${errorMessage(err)}`);
|
|
34763
|
+
}
|
|
34764
|
+
}
|
|
34765
|
+
|
|
34673
34766
|
// src/agents/acp/hooks/bridge-on-session-update/create-bridge-on-session-update.ts
|
|
34674
34767
|
function createBridgeOnSessionUpdate(opts) {
|
|
34675
34768
|
const { routing, getSendSessionUpdate, log: log2, sessionParentPath } = opts;
|
|
@@ -34685,6 +34778,10 @@ function createBridgeOnSessionUpdate(opts) {
|
|
|
34685
34778
|
if (updateKind === "config_option_update") {
|
|
34686
34779
|
return;
|
|
34687
34780
|
}
|
|
34781
|
+
if (updateKind === "session_info_update") {
|
|
34782
|
+
sendSessionInfoTitleUpdate({ payload: params, runId, sessionId, send, log: log2 });
|
|
34783
|
+
return;
|
|
34784
|
+
}
|
|
34688
34785
|
const isCompletedToolCallUpdate = updateKind === "tool_call_update" && isCompletedToolStatus(p.status);
|
|
34689
34786
|
const toolName = p.toolCall?.name ?? p.tool_call?.name ?? "";
|
|
34690
34787
|
const isToolUpdate = updateKind === "tool_call" || updateKind === "tool_call_update" || typeof toolName === "string" && toolName.length > 0;
|
|
@@ -34778,56 +34875,80 @@ function sessionKeyForCloudSessionId(cloudSessionId) {
|
|
|
34778
34875
|
}
|
|
34779
34876
|
function readLocalAgentSessionFile(cloudSessionId) {
|
|
34780
34877
|
try {
|
|
34781
|
-
|
|
34782
|
-
|
|
34783
|
-
|
|
34784
|
-
|
|
34785
|
-
|
|
34786
|
-
|
|
34787
|
-
|
|
34788
|
-
|
|
34789
|
-
|
|
34790
|
-
|
|
34791
|
-
|
|
34792
|
-
|
|
34793
|
-
|
|
34794
|
-
|
|
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
|
+
}
|
|
34795
34893
|
}
|
|
34796
|
-
|
|
34797
|
-
|
|
34798
|
-
|
|
34799
|
-
|
|
34800
|
-
|
|
34801
|
-
|
|
34802
|
-
|
|
34803
|
-
};
|
|
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
|
+
});
|
|
34804
34902
|
} catch {
|
|
34805
34903
|
return null;
|
|
34806
34904
|
}
|
|
34807
34905
|
}
|
|
34808
34906
|
function writeLocalAgentSessionFile(cloudSessionId, patch) {
|
|
34809
34907
|
try {
|
|
34810
|
-
|
|
34811
|
-
|
|
34812
|
-
|
|
34813
|
-
|
|
34814
|
-
|
|
34815
|
-
|
|
34816
|
-
|
|
34817
|
-
|
|
34818
|
-
|
|
34819
|
-
|
|
34820
|
-
|
|
34821
|
-
|
|
34822
|
-
|
|
34823
|
-
|
|
34824
|
-
|
|
34825
|
-
|
|
34826
|
-
|
|
34827
|
-
|
|
34828
|
-
|
|
34829
|
-
|
|
34830
|
-
|
|
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
|
+
});
|
|
34831
34952
|
} catch {
|
|
34832
34953
|
}
|
|
34833
34954
|
}
|
|
@@ -36410,45 +36531,36 @@ function getCwdHashForFileIndex(resolvedCwd) {
|
|
|
36410
36531
|
// src/files/index/build-file-index.ts
|
|
36411
36532
|
import path29 from "node:path";
|
|
36412
36533
|
|
|
36413
|
-
// src/runtime/yield-to-event-loop.ts
|
|
36414
|
-
function yieldToEventLoop() {
|
|
36415
|
-
return new Promise((resolve20) => setImmediate(resolve20));
|
|
36416
|
-
}
|
|
36417
|
-
|
|
36418
36534
|
// src/files/index/walk-workspace-tree.ts
|
|
36419
36535
|
import fs25 from "node:fs";
|
|
36420
36536
|
import path28 from "node:path";
|
|
36421
|
-
|
|
36537
|
+
function shouldSkipWorkspaceWalkEntry(name) {
|
|
36538
|
+
return name.startsWith(".");
|
|
36539
|
+
}
|
|
36540
|
+
function walkWorkspaceTreeSync(dir, baseDir, onFile) {
|
|
36422
36541
|
let names;
|
|
36423
36542
|
try {
|
|
36424
|
-
names =
|
|
36543
|
+
names = fs25.readdirSync(dir);
|
|
36425
36544
|
} catch {
|
|
36426
36545
|
return;
|
|
36427
36546
|
}
|
|
36428
36547
|
for (const name of names) {
|
|
36429
|
-
if (name
|
|
36430
|
-
if (state.n > 0 && state.n % INDEX_WORK_YIELD_EVERY === 0) {
|
|
36431
|
-
await yieldToEventLoop();
|
|
36432
|
-
}
|
|
36433
|
-
state.n++;
|
|
36548
|
+
if (shouldSkipWorkspaceWalkEntry(name)) continue;
|
|
36434
36549
|
const full = path28.join(dir, name);
|
|
36435
36550
|
let stat3;
|
|
36436
36551
|
try {
|
|
36437
|
-
stat3 =
|
|
36552
|
+
stat3 = fs25.statSync(full);
|
|
36438
36553
|
} catch {
|
|
36439
36554
|
continue;
|
|
36440
36555
|
}
|
|
36441
36556
|
const relative5 = path28.relative(baseDir, full).replace(/\\/g, "/");
|
|
36442
36557
|
if (stat3.isDirectory()) {
|
|
36443
|
-
|
|
36558
|
+
walkWorkspaceTreeSync(full, baseDir, onFile);
|
|
36444
36559
|
} else if (stat3.isFile()) {
|
|
36445
|
-
|
|
36560
|
+
onFile(relative5);
|
|
36446
36561
|
}
|
|
36447
36562
|
}
|
|
36448
36563
|
}
|
|
36449
|
-
function createWalkYieldState() {
|
|
36450
|
-
return { n: 0 };
|
|
36451
|
-
}
|
|
36452
36564
|
|
|
36453
36565
|
// src/files/index/file-index-sqlite-lock.ts
|
|
36454
36566
|
import fs26 from "node:fs";
|
|
@@ -36481,80 +36593,98 @@ function withFileIndexSqliteLock(fn) {
|
|
|
36481
36593
|
}
|
|
36482
36594
|
|
|
36483
36595
|
// src/files/index/build-file-index.ts
|
|
36484
|
-
|
|
36485
|
-
|
|
36486
|
-
|
|
36487
|
-
|
|
36488
|
-
|
|
36489
|
-
|
|
36490
|
-
|
|
36491
|
-
try {
|
|
36492
|
-
db.run("DELETE FROM file_index_path WHERE cwd_hash = ?", [h]);
|
|
36493
|
-
const ins = db.prepare("INSERT INTO file_index_path (cwd_hash, path) VALUES (?, ?)");
|
|
36596
|
+
var FILE_INDEX_INSERT_BUFFER = 2048;
|
|
36597
|
+
function persistFileIndexForResolvedCwd(resolved) {
|
|
36598
|
+
return withCliSqliteSync((db) => {
|
|
36599
|
+
const h = getCwdHashForFileIndex(resolved);
|
|
36600
|
+
const buf = [];
|
|
36601
|
+
let pathCount = 0;
|
|
36602
|
+
db.run("BEGIN IMMEDIATE");
|
|
36494
36603
|
try {
|
|
36495
|
-
|
|
36496
|
-
|
|
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();
|
|
36497
36621
|
}
|
|
36498
|
-
|
|
36499
|
-
|
|
36500
|
-
|
|
36501
|
-
|
|
36502
|
-
|
|
36503
|
-
|
|
36504
|
-
|
|
36505
|
-
} catch {
|
|
36622
|
+
db.run("COMMIT");
|
|
36623
|
+
} catch (e) {
|
|
36624
|
+
try {
|
|
36625
|
+
db.run("ROLLBACK");
|
|
36626
|
+
} catch {
|
|
36627
|
+
}
|
|
36628
|
+
throw e;
|
|
36506
36629
|
}
|
|
36507
|
-
|
|
36508
|
-
}
|
|
36630
|
+
return pathCount;
|
|
36631
|
+
});
|
|
36509
36632
|
}
|
|
36510
36633
|
async function buildFileIndexAsync(cwd) {
|
|
36511
36634
|
return withFileIndexSqliteLock(async () => {
|
|
36512
36635
|
const resolved = path29.resolve(cwd);
|
|
36513
|
-
const paths = [];
|
|
36514
|
-
await walkWorkspaceTreeAsync(resolved, resolved, paths, createWalkYieldState());
|
|
36515
36636
|
await yieldToEventLoop();
|
|
36516
|
-
|
|
36517
|
-
|
|
36518
|
-
return { pathCount
|
|
36637
|
+
const pathCount = persistFileIndexForResolvedCwd(resolved);
|
|
36638
|
+
await yieldToEventLoop();
|
|
36639
|
+
return { pathCount };
|
|
36519
36640
|
});
|
|
36520
36641
|
}
|
|
36521
36642
|
|
|
36522
36643
|
// src/files/index/ensure-file-index.ts
|
|
36523
36644
|
import path30 from "node:path";
|
|
36524
36645
|
|
|
36646
|
+
// src/files/index/file-index-dependency-path.ts
|
|
36647
|
+
function sqliteExprBridgeFileIndexDependencyRank() {
|
|
36648
|
+
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`;
|
|
36649
|
+
}
|
|
36650
|
+
|
|
36525
36651
|
// src/files/index/search-file-index.ts
|
|
36526
36652
|
function escapeLikePattern(fragment) {
|
|
36527
36653
|
return fragment.replace(/\\/g, "\\\\").replace(/%/g, "\\%").replace(/_/g, "\\_");
|
|
36528
36654
|
}
|
|
36529
|
-
function
|
|
36530
|
-
const db = getCliDatabase();
|
|
36655
|
+
function bridgeFileIndexIsPopulatedWithDb(resolvedCwd, db) {
|
|
36531
36656
|
const h = getCwdHashForFileIndex(resolvedCwd);
|
|
36532
36657
|
const row = db.get("SELECT 1 as ok FROM file_index_path WHERE cwd_hash = ? LIMIT 1", [h]);
|
|
36533
36658
|
return row != null;
|
|
36534
36659
|
}
|
|
36535
|
-
function
|
|
36536
|
-
const db = getCliDatabase();
|
|
36660
|
+
function bridgeFileIndexPathCountWithDb(resolvedCwd, db) {
|
|
36537
36661
|
const h = getCwdHashForFileIndex(resolvedCwd);
|
|
36538
36662
|
const row = db.get("SELECT COUNT(*) as c FROM file_index_path WHERE cwd_hash = ?", [h]);
|
|
36539
36663
|
const c = row?.c ?? 0;
|
|
36540
36664
|
return Number(c);
|
|
36541
36665
|
}
|
|
36542
|
-
function
|
|
36666
|
+
function searchBridgeFilePathsWithDb(resolvedCwd, query, limit, db) {
|
|
36543
36667
|
const q = query.trim().toLowerCase();
|
|
36544
36668
|
if (!q) return [];
|
|
36545
|
-
const db = getCliDatabase();
|
|
36546
36669
|
const h = getCwdHashForFileIndex(resolvedCwd);
|
|
36547
36670
|
const pattern = `%${escapeLikePattern(q)}%`;
|
|
36548
36671
|
const lim = Math.max(0, Math.min(1e4, Math.floor(limit)));
|
|
36672
|
+
const depRank = sqliteExprBridgeFileIndexDependencyRank();
|
|
36549
36673
|
const rows = db.all(
|
|
36550
|
-
`SELECT path FROM file_index_path WHERE cwd_hash = ? AND lower(path) LIKE ? ESCAPE '\\' LIMIT ?`,
|
|
36674
|
+
`SELECT path FROM file_index_path WHERE cwd_hash = ? AND lower(path) LIKE ? ESCAPE '\\' ORDER BY ${depRank}, path LIMIT ?`,
|
|
36551
36675
|
[h, pattern, lim]
|
|
36552
36676
|
);
|
|
36553
36677
|
return rows.map((r) => String(r.path));
|
|
36554
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
|
+
}
|
|
36555
36685
|
async function searchBridgeFilePathsAsync(resolvedCwd, query, limit = 100) {
|
|
36556
36686
|
await yieldToEventLoop();
|
|
36557
|
-
const out =
|
|
36687
|
+
const out = await withCliSqlite((db) => searchBridgeFilePathsWithDb(resolvedCwd, query, limit, db));
|
|
36558
36688
|
if (out.length >= INDEX_WORK_YIELD_EVERY) await yieldToEventLoop();
|
|
36559
36689
|
return out;
|
|
36560
36690
|
}
|
|
@@ -36562,8 +36692,8 @@ async function searchBridgeFilePathsAsync(resolvedCwd, query, limit = 100) {
|
|
|
36562
36692
|
// src/files/index/ensure-file-index.ts
|
|
36563
36693
|
async function ensureFileIndexAsync(cwd) {
|
|
36564
36694
|
const resolved = path30.resolve(cwd);
|
|
36565
|
-
if (bridgeFileIndexIsPopulated(resolved)) {
|
|
36566
|
-
return { fromCache: true, pathCount: bridgeFileIndexPathCount(resolved) };
|
|
36695
|
+
if (await bridgeFileIndexIsPopulated(resolved)) {
|
|
36696
|
+
return { fromCache: true, pathCount: await bridgeFileIndexPathCount(resolved) };
|
|
36567
36697
|
}
|
|
36568
36698
|
return { ...await buildFileIndexAsync(resolved), fromCache: false };
|
|
36569
36699
|
}
|
|
@@ -36572,7 +36702,6 @@ async function ensureFileIndexAsync(cwd) {
|
|
|
36572
36702
|
var DEBOUNCE_MS = 900;
|
|
36573
36703
|
function shouldIgnoreRelative(rel) {
|
|
36574
36704
|
const n = rel.replace(/\\/g, "/");
|
|
36575
|
-
if (n.includes("/node_modules/") || n.startsWith("node_modules/")) return true;
|
|
36576
36705
|
if (n.includes("/.git/") || n === ".git" || n.startsWith(".git/")) return true;
|
|
36577
36706
|
if (n.includes("/.buildautomaton/") || n.startsWith(".buildautomaton/")) return true;
|
|
36578
36707
|
return false;
|
|
@@ -38245,30 +38374,32 @@ var MERGEABLE_SERVER_STATES = /* @__PURE__ */ new Set([
|
|
|
38245
38374
|
"stopping",
|
|
38246
38375
|
"discarded"
|
|
38247
38376
|
]);
|
|
38248
|
-
function readPersistedQueue(queueKey) {
|
|
38249
|
-
|
|
38250
|
-
|
|
38251
|
-
|
|
38252
|
-
|
|
38253
|
-
|
|
38254
|
-
|
|
38255
|
-
|
|
38256
|
-
|
|
38257
|
-
|
|
38258
|
-
|
|
38259
|
-
|
|
38260
|
-
|
|
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
|
+
});
|
|
38261
38391
|
}
|
|
38262
|
-
function writePersistedQueue(file2) {
|
|
38263
|
-
|
|
38264
|
-
|
|
38265
|
-
|
|
38266
|
-
|
|
38267
|
-
|
|
38268
|
-
|
|
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
|
+
});
|
|
38269
38400
|
}
|
|
38270
|
-
function mergeServerQueueSnapshot(queueKey, serverTurns) {
|
|
38271
|
-
const prev = readPersistedQueue(queueKey);
|
|
38401
|
+
async function mergeServerQueueSnapshot(queueKey, serverTurns) {
|
|
38402
|
+
const prev = await readPersistedQueue(queueKey);
|
|
38272
38403
|
const turns = [];
|
|
38273
38404
|
for (const raw of serverTurns) {
|
|
38274
38405
|
if (!raw || typeof raw !== "object") continue;
|
|
@@ -38365,12 +38496,12 @@ async function applyPromptQueueStateFromServer(msg, deps) {
|
|
|
38365
38496
|
const getWs = deps.getWs;
|
|
38366
38497
|
for (const [queueKey, serverTurns] of Object.entries(raw)) {
|
|
38367
38498
|
if (!Array.isArray(serverTurns)) continue;
|
|
38368
|
-
const file2 = mergeServerQueueSnapshot(queueKey, serverTurns);
|
|
38369
|
-
writePersistedQueue(file2);
|
|
38499
|
+
const file2 = await mergeServerQueueSnapshot(queueKey, serverTurns);
|
|
38500
|
+
await writePersistedQueue(file2);
|
|
38370
38501
|
}
|
|
38371
38502
|
for (const [queueKey, serverTurns] of Object.entries(raw)) {
|
|
38372
38503
|
if (!Array.isArray(serverTurns)) continue;
|
|
38373
|
-
const file2 = readPersistedQueue(queueKey);
|
|
38504
|
+
const file2 = await readPersistedQueue(queueKey);
|
|
38374
38505
|
if (!file2) continue;
|
|
38375
38506
|
for (const running of file2.turns.filter((t) => t.lastClientState === "running")) {
|
|
38376
38507
|
runIdToQueueKey.set(running.turnId, queueKey);
|
|
@@ -38378,7 +38509,7 @@ async function applyPromptQueueStateFromServer(msg, deps) {
|
|
|
38378
38509
|
}
|
|
38379
38510
|
for (const [queueKey, serverTurns] of Object.entries(raw)) {
|
|
38380
38511
|
if (!Array.isArray(serverTurns)) continue;
|
|
38381
|
-
const file2 = readPersistedQueue(queueKey);
|
|
38512
|
+
const file2 = await readPersistedQueue(queueKey);
|
|
38382
38513
|
if (!file2) continue;
|
|
38383
38514
|
const cancelRow = file2.turns.find((t) => t.serverState === "cancel_requested" && t.lastClientState === "running");
|
|
38384
38515
|
if (cancelRow) {
|
|
@@ -38387,7 +38518,7 @@ async function applyPromptQueueStateFromServer(msg, deps) {
|
|
|
38387
38518
|
deps.log(
|
|
38388
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.`
|
|
38389
38520
|
);
|
|
38390
|
-
finalizePromptTurnOnBridge(deps.getWs, cancelRow.turnId, false, { terminalClientState: "cancelled" });
|
|
38521
|
+
await finalizePromptTurnOnBridge(deps.getWs, cancelRow.turnId, false, { terminalClientState: "cancelled" });
|
|
38391
38522
|
const ws = deps.getWs();
|
|
38392
38523
|
if (ws && cancelRow.sessionId) {
|
|
38393
38524
|
sendWsMessage(ws, {
|
|
@@ -38406,19 +38537,19 @@ async function applyPromptQueueStateFromServer(msg, deps) {
|
|
|
38406
38537
|
const startedThisTick = /* @__PURE__ */ new Set();
|
|
38407
38538
|
for (const [queueKey, serverTurns] of Object.entries(raw)) {
|
|
38408
38539
|
if (!Array.isArray(serverTurns)) continue;
|
|
38409
|
-
const file2 = readPersistedQueue(queueKey);
|
|
38540
|
+
const file2 = await readPersistedQueue(queueKey);
|
|
38410
38541
|
if (!file2) continue;
|
|
38411
38542
|
if (hasRunningTurn(file2.turns)) continue;
|
|
38412
38543
|
const next = pickNextRunnableTurn(file2.turns);
|
|
38413
38544
|
if (!next) continue;
|
|
38414
38545
|
if (!await runLocalRevertBeforeQueuedPrompt(next, deps)) {
|
|
38415
38546
|
next.lastClientState = "failed";
|
|
38416
|
-
writePersistedQueue(file2);
|
|
38547
|
+
await writePersistedQueue(file2);
|
|
38417
38548
|
sendPromptQueueClientReport(getWs(), { [queueKey]: [{ turnId: next.turnId, clientState: "failed" }] });
|
|
38418
38549
|
continue;
|
|
38419
38550
|
}
|
|
38420
38551
|
next.lastClientState = "running";
|
|
38421
|
-
writePersistedQueue(file2);
|
|
38552
|
+
await writePersistedQueue(file2);
|
|
38422
38553
|
runIdToQueueKey.set(next.turnId, queueKey);
|
|
38423
38554
|
startedThisTick.add(next.turnId);
|
|
38424
38555
|
report[queueKey] = [{ turnId: next.turnId, clientState: "running" }];
|
|
@@ -38428,7 +38559,7 @@ async function applyPromptQueueStateFromServer(msg, deps) {
|
|
|
38428
38559
|
}
|
|
38429
38560
|
for (const [queueKey, serverTurns] of Object.entries(raw)) {
|
|
38430
38561
|
if (!Array.isArray(serverTurns)) continue;
|
|
38431
|
-
const file2 = readPersistedQueue(queueKey);
|
|
38562
|
+
const file2 = await readPersistedQueue(queueKey);
|
|
38432
38563
|
if (!file2) continue;
|
|
38433
38564
|
const running = file2.turns.find((t) => t.lastClientState === "running");
|
|
38434
38565
|
if (!running || !startedThisTick.has(running.turnId)) continue;
|
|
@@ -38436,17 +38567,17 @@ async function applyPromptQueueStateFromServer(msg, deps) {
|
|
|
38436
38567
|
dispatchLocalPrompt(running, deps);
|
|
38437
38568
|
}
|
|
38438
38569
|
}
|
|
38439
|
-
function finalizePromptTurnOnBridge(getWs, runId, success2, opts) {
|
|
38570
|
+
async function finalizePromptTurnOnBridge(getWs, runId, success2, opts) {
|
|
38440
38571
|
if (!runId) return false;
|
|
38441
38572
|
const queueKey = runIdToQueueKey.get(runId);
|
|
38442
38573
|
runIdToQueueKey.delete(runId);
|
|
38443
38574
|
if (!queueKey) return false;
|
|
38444
|
-
const f = readPersistedQueue(queueKey);
|
|
38575
|
+
const f = await readPersistedQueue(queueKey);
|
|
38445
38576
|
if (!f) return false;
|
|
38446
38577
|
const t = f.turns.find((x) => x.turnId === runId);
|
|
38447
38578
|
if (!t) return false;
|
|
38448
38579
|
t.lastClientState = opts?.terminalClientState ?? (success2 ? "stopped" : "failed");
|
|
38449
|
-
writePersistedQueue(f);
|
|
38580
|
+
await writePersistedQueue(f);
|
|
38450
38581
|
sendPromptQueueClientReport(getWs(), { [queueKey]: [{ turnId: runId, clientState: t.lastClientState }] });
|
|
38451
38582
|
return true;
|
|
38452
38583
|
}
|
|
@@ -38467,12 +38598,13 @@ function createBridgePromptSenders(deps, getWs) {
|
|
|
38467
38598
|
if (result.type === "prompt_result") {
|
|
38468
38599
|
const pr = result;
|
|
38469
38600
|
const cancelled = pr.stopReason === "cancelled";
|
|
38470
|
-
finalizePromptTurnOnBridge(
|
|
38601
|
+
void finalizePromptTurnOnBridge(
|
|
38471
38602
|
getWs,
|
|
38472
38603
|
typeof pr.runId === "string" ? pr.runId : void 0,
|
|
38473
38604
|
pr.success === true,
|
|
38474
38605
|
cancelled ? { terminalClientState: "cancelled" } : void 0
|
|
38475
|
-
)
|
|
38606
|
+
).catch(() => {
|
|
38607
|
+
});
|
|
38476
38608
|
}
|
|
38477
38609
|
};
|
|
38478
38610
|
const sendSessionUpdate = (payload) => {
|
|
@@ -39205,7 +39337,7 @@ function handleFileBrowserSearch(msg, socket, e2ee) {
|
|
|
39205
39337
|
await yieldToEventLoop();
|
|
39206
39338
|
const q = typeof msg.q === "string" ? msg.q : "";
|
|
39207
39339
|
const cwd = path37.resolve(getBridgeRoot());
|
|
39208
|
-
if (!bridgeFileIndexIsPopulated(cwd)) {
|
|
39340
|
+
if (!await bridgeFileIndexIsPopulated(cwd)) {
|
|
39209
39341
|
const payload2 = {
|
|
39210
39342
|
type: "file_browser_search_response",
|
|
39211
39343
|
id: msg.id,
|
|
@@ -39966,7 +40098,7 @@ import * as path40 from "node:path";
|
|
|
39966
40098
|
// src/agents/capabilities/probe-one-agent-type-for-capabilities.ts
|
|
39967
40099
|
import * as path39 from "node:path";
|
|
39968
40100
|
async function probeOneAgentTypeForCapabilities(params) {
|
|
39969
|
-
const { agentType, cwd, workspaceId, log: log2,
|
|
40101
|
+
const { agentType, cwd, workspaceId, log: log2, reportAgentCapabilities, bridgeReport = true } = params;
|
|
39970
40102
|
const resolved = resolveAgentCommand(agentType);
|
|
39971
40103
|
if (!resolved) return false;
|
|
39972
40104
|
let sqliteChanged = false;
|
|
@@ -39977,11 +40109,13 @@ async function probeOneAgentTypeForCapabilities(params) {
|
|
|
39977
40109
|
reportedRef.done = true;
|
|
39978
40110
|
let changed = false;
|
|
39979
40111
|
try {
|
|
39980
|
-
changed =
|
|
39981
|
-
|
|
39982
|
-
|
|
39983
|
-
|
|
39984
|
-
|
|
40112
|
+
changed = withCliSqliteSync(
|
|
40113
|
+
(db) => upsertCliAgentCapabilityCache(db, {
|
|
40114
|
+
workspaceId,
|
|
40115
|
+
agentType,
|
|
40116
|
+
configOptions: co
|
|
40117
|
+
})
|
|
40118
|
+
);
|
|
39985
40119
|
} catch {
|
|
39986
40120
|
}
|
|
39987
40121
|
sqliteChanged ||= changed;
|
|
@@ -40039,7 +40173,6 @@ async function probeAgentCapabilitiesForDetectedTypes(params) {
|
|
|
40039
40173
|
cwd,
|
|
40040
40174
|
workspaceId,
|
|
40041
40175
|
log: log2,
|
|
40042
|
-
getDb,
|
|
40043
40176
|
reportAgentCapabilities,
|
|
40044
40177
|
bridgeReport = true,
|
|
40045
40178
|
forceAllTypes = false
|
|
@@ -40051,7 +40184,7 @@ async function probeAgentCapabilitiesForDetectedTypes(params) {
|
|
|
40051
40184
|
if (!agentType.trim()) continue;
|
|
40052
40185
|
if (!forceAllTypes) {
|
|
40053
40186
|
try {
|
|
40054
|
-
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))) {
|
|
40055
40188
|
continue;
|
|
40056
40189
|
}
|
|
40057
40190
|
} catch {
|
|
@@ -40062,7 +40195,6 @@ async function probeAgentCapabilitiesForDetectedTypes(params) {
|
|
|
40062
40195
|
cwd,
|
|
40063
40196
|
workspaceId,
|
|
40064
40197
|
log: log2,
|
|
40065
|
-
getDb,
|
|
40066
40198
|
reportAgentCapabilities,
|
|
40067
40199
|
bridgeReport
|
|
40068
40200
|
});
|
|
@@ -40073,14 +40205,13 @@ async function probeAgentCapabilitiesForDetectedTypes(params) {
|
|
|
40073
40205
|
|
|
40074
40206
|
// src/agents/capabilities/warmup-agent-capabilities-on-connect.ts
|
|
40075
40207
|
async function warmupAgentCapabilitiesOnConnect(params) {
|
|
40076
|
-
const { workspaceId, log: log2,
|
|
40208
|
+
const { workspaceId, log: log2, getWs } = params;
|
|
40077
40209
|
const cwd = path40.resolve(getBridgeRoot());
|
|
40078
|
-
|
|
40079
|
-
function sendBatchFromCache() {
|
|
40210
|
+
async function sendBatchFromCache() {
|
|
40080
40211
|
const socket = getWs();
|
|
40081
40212
|
if (!socket || socket.readyState !== wrapper_default.OPEN) return;
|
|
40082
40213
|
try {
|
|
40083
|
-
const rows = listCliAgentCapabilityCacheForWorkspace(db, workspaceId);
|
|
40214
|
+
const rows = await withCliSqlite((db) => listCliAgentCapabilityCacheForWorkspace(db, workspaceId));
|
|
40084
40215
|
if (rows.length === 0) return;
|
|
40085
40216
|
sendWsMessage(socket, {
|
|
40086
40217
|
type: "agent_capabilities_batch",
|
|
@@ -40092,7 +40223,7 @@ async function warmupAgentCapabilitiesOnConnect(params) {
|
|
|
40092
40223
|
);
|
|
40093
40224
|
}
|
|
40094
40225
|
}
|
|
40095
|
-
sendBatchFromCache();
|
|
40226
|
+
await sendBatchFromCache();
|
|
40096
40227
|
let types = [];
|
|
40097
40228
|
try {
|
|
40098
40229
|
types = [...await detectLocalAgentTypes()];
|
|
@@ -40105,11 +40236,10 @@ async function warmupAgentCapabilitiesOnConnect(params) {
|
|
|
40105
40236
|
cwd,
|
|
40106
40237
|
workspaceId,
|
|
40107
40238
|
log: log2,
|
|
40108
|
-
getDb,
|
|
40109
40239
|
bridgeReport: false,
|
|
40110
40240
|
forceAllTypes: false
|
|
40111
40241
|
});
|
|
40112
|
-
if (n > 0) sendBatchFromCache();
|
|
40242
|
+
if (n > 0) await sendBatchFromCache();
|
|
40113
40243
|
} catch (e) {
|
|
40114
40244
|
log2(`[Bridge service] Agent capability probe (missing cache) failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
40115
40245
|
}
|
|
@@ -40121,11 +40251,10 @@ async function warmupAgentCapabilitiesOnConnect(params) {
|
|
|
40121
40251
|
cwd,
|
|
40122
40252
|
workspaceId,
|
|
40123
40253
|
log: log2,
|
|
40124
|
-
getDb,
|
|
40125
40254
|
bridgeReport: false,
|
|
40126
40255
|
forceAllTypes: true
|
|
40127
40256
|
});
|
|
40128
|
-
if (n > 0) sendBatchFromCache();
|
|
40257
|
+
if (n > 0) await sendBatchFromCache();
|
|
40129
40258
|
} catch (e) {
|
|
40130
40259
|
log2(`[Bridge service] Agent capability lazy refresh failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
40131
40260
|
}
|
|
@@ -40137,7 +40266,7 @@ async function createBridgeConnection(options) {
|
|
|
40137
40266
|
const { apiUrl, workspaceId, justAuthenticated, onAuthInvalid, persistTokens } = options;
|
|
40138
40267
|
const firehoseServerUrl = options.firehoseServerUrl ?? options.proxyServerUrl;
|
|
40139
40268
|
const logFn = options.log ?? log;
|
|
40140
|
-
|
|
40269
|
+
await ensureCliSqliteInitialized({ logLegacyMigration: logFn });
|
|
40141
40270
|
const tokens = {
|
|
40142
40271
|
accessToken: options.authToken,
|
|
40143
40272
|
refreshToken: options.refreshToken
|
|
@@ -40167,11 +40296,13 @@ async function createBridgeConnection(options) {
|
|
|
40167
40296
|
if (!Array.isArray(info.configOptions) || info.configOptions.length === 0) return;
|
|
40168
40297
|
let changed = false;
|
|
40169
40298
|
try {
|
|
40170
|
-
changed =
|
|
40171
|
-
|
|
40172
|
-
|
|
40173
|
-
|
|
40174
|
-
|
|
40299
|
+
changed = withCliSqliteSync(
|
|
40300
|
+
(db) => upsertCliAgentCapabilityCache(db, {
|
|
40301
|
+
workspaceId,
|
|
40302
|
+
agentType: info.agentType,
|
|
40303
|
+
configOptions: info.configOptions
|
|
40304
|
+
})
|
|
40305
|
+
);
|
|
40175
40306
|
} catch {
|
|
40176
40307
|
}
|
|
40177
40308
|
if (!changed) return;
|
|
@@ -40224,7 +40355,6 @@ async function createBridgeConnection(options) {
|
|
|
40224
40355
|
await warmupAgentCapabilitiesOnConnect({
|
|
40225
40356
|
workspaceId,
|
|
40226
40357
|
log: logFn,
|
|
40227
|
-
getDb: getCliDatabase,
|
|
40228
40358
|
getWs
|
|
40229
40359
|
});
|
|
40230
40360
|
},
|