@buildautomaton/cli 0.1.34 → 0.1.36
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 +338 -150
- package/dist/cli.js.map +4 -4
- package/dist/index.js +332 -144
- package/dist/index.js.map +4 -4
- package/dist/migrations/003_file_index_parent_paths.sql +17 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -974,7 +974,7 @@ var require_command = __commonJS({
|
|
|
974
974
|
var EventEmitter2 = __require("node:events").EventEmitter;
|
|
975
975
|
var childProcess2 = __require("node:child_process");
|
|
976
976
|
var path43 = __require("node:path");
|
|
977
|
-
var
|
|
977
|
+
var fs41 = __require("node:fs");
|
|
978
978
|
var process8 = __require("node:process");
|
|
979
979
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
980
980
|
var { CommanderError: CommanderError2 } = require_error();
|
|
@@ -1907,10 +1907,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1907
1907
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
1908
1908
|
function findFile(baseDir, baseName) {
|
|
1909
1909
|
const localBin = path43.resolve(baseDir, baseName);
|
|
1910
|
-
if (
|
|
1910
|
+
if (fs41.existsSync(localBin)) return localBin;
|
|
1911
1911
|
if (sourceExt.includes(path43.extname(baseName))) return void 0;
|
|
1912
1912
|
const foundExt = sourceExt.find(
|
|
1913
|
-
(ext) =>
|
|
1913
|
+
(ext) => fs41.existsSync(`${localBin}${ext}`)
|
|
1914
1914
|
);
|
|
1915
1915
|
if (foundExt) return `${localBin}${foundExt}`;
|
|
1916
1916
|
return void 0;
|
|
@@ -1922,7 +1922,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1922
1922
|
if (this._scriptPath) {
|
|
1923
1923
|
let resolvedScriptPath;
|
|
1924
1924
|
try {
|
|
1925
|
-
resolvedScriptPath =
|
|
1925
|
+
resolvedScriptPath = fs41.realpathSync(this._scriptPath);
|
|
1926
1926
|
} catch (err) {
|
|
1927
1927
|
resolvedScriptPath = this._scriptPath;
|
|
1928
1928
|
}
|
|
@@ -11857,8 +11857,8 @@ function getElementAtPath(obj, path43) {
|
|
|
11857
11857
|
}
|
|
11858
11858
|
function promiseAllObject(promisesObj) {
|
|
11859
11859
|
const keys = Object.keys(promisesObj);
|
|
11860
|
-
const
|
|
11861
|
-
return Promise.all(
|
|
11860
|
+
const promises5 = keys.map((key) => promisesObj[key]);
|
|
11861
|
+
return Promise.all(promises5).then((results) => {
|
|
11862
11862
|
const resolvedObj = {};
|
|
11863
11863
|
for (let i = 0; i < keys.length; i++) {
|
|
11864
11864
|
resolvedObj[keys[i]] = results[i];
|
|
@@ -25064,14 +25064,14 @@ 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.36".length > 0 ? "0.1.36" : "0.0.0-dev";
|
|
25068
25068
|
|
|
25069
25069
|
// src/cli/defaults.ts
|
|
25070
25070
|
var DEFAULT_API_URL = process.env.BUILDAUTOMATON_API_URL ?? "https://api.buildautomaton.com";
|
|
25071
25071
|
var DEFAULT_FIREHOSE_URL = "https://buildautomaton-firehose.fly.dev";
|
|
25072
25072
|
|
|
25073
25073
|
// src/cli/run-cli-action.ts
|
|
25074
|
-
import * as
|
|
25074
|
+
import * as fs40 from "node:fs";
|
|
25075
25075
|
import * as path42 from "node:path";
|
|
25076
25076
|
|
|
25077
25077
|
// src/cli-log-level.ts
|
|
@@ -25607,20 +25607,22 @@ function createWsBridge(options) {
|
|
|
25607
25607
|
onOpen?.();
|
|
25608
25608
|
});
|
|
25609
25609
|
ws.on("message", (raw) => {
|
|
25610
|
-
|
|
25611
|
-
|
|
25612
|
-
|
|
25613
|
-
|
|
25614
|
-
|
|
25615
|
-
|
|
25616
|
-
|
|
25617
|
-
|
|
25618
|
-
|
|
25610
|
+
setImmediate(() => {
|
|
25611
|
+
try {
|
|
25612
|
+
let data;
|
|
25613
|
+
if (typeof raw === "string") {
|
|
25614
|
+
data = JSON.parse(raw);
|
|
25615
|
+
} else if (Buffer.isBuffer(raw) || raw instanceof ArrayBuffer) {
|
|
25616
|
+
const str = Buffer.isBuffer(raw) ? raw.toString("utf8") : Buffer.from(raw).toString("utf8");
|
|
25617
|
+
data = JSON.parse(str);
|
|
25618
|
+
} else {
|
|
25619
|
+
data = raw;
|
|
25620
|
+
}
|
|
25621
|
+
onMessage?.(data);
|
|
25622
|
+
} catch {
|
|
25623
|
+
onMessage?.(raw);
|
|
25619
25624
|
}
|
|
25620
|
-
|
|
25621
|
-
} catch {
|
|
25622
|
-
onMessage?.(raw);
|
|
25623
|
-
}
|
|
25625
|
+
});
|
|
25624
25626
|
});
|
|
25625
25627
|
ws.on("close", (code, reason) => {
|
|
25626
25628
|
disposeClientPing();
|
|
@@ -26959,6 +26961,7 @@ function recordMigrationAndPruneCheckpointLegacy(db, migration, applied2) {
|
|
|
26959
26961
|
var CHECKPOINT_V1 = "001_cli_sqlite_checkpoint_v1";
|
|
26960
26962
|
var CHECKPOINT_V1_SQL = readCliSqliteMigrationSql("001_cli_sqlite_checkpoint_v1.sql");
|
|
26961
26963
|
var AGENT_CAPABILITIES_SQL = readCliSqliteMigrationSql("002_agent_capabilities.sql");
|
|
26964
|
+
var FILE_INDEX_PARENT_PATHS_SQL = readCliSqliteMigrationSql("003_file_index_parent_paths.sql");
|
|
26962
26965
|
function agentCapabilitiesTableState(db) {
|
|
26963
26966
|
const rows = db.all(
|
|
26964
26967
|
`SELECT name FROM sqlite_master WHERE type='table' AND name IN ('agent_capabilities', 'agent_capability_cache')`
|
|
@@ -26992,6 +26995,18 @@ var CLI_SQLITE_MIGRATIONS = [
|
|
|
26992
26995
|
db.exec(AGENT_CAPABILITIES_SQL);
|
|
26993
26996
|
},
|
|
26994
26997
|
alreadyApplied: (db) => agentCapabilitiesTableState(db) === "current"
|
|
26998
|
+
},
|
|
26999
|
+
{
|
|
27000
|
+
name: "003_file_index_parent_paths",
|
|
27001
|
+
migrate: (db) => {
|
|
27002
|
+
db.exec(FILE_INDEX_PARENT_PATHS_SQL);
|
|
27003
|
+
},
|
|
27004
|
+
alreadyApplied: (db) => {
|
|
27005
|
+
const row = db.get(
|
|
27006
|
+
`SELECT 1 as ok FROM sqlite_master WHERE type='table' AND name='file_index_parent_path' LIMIT 1`
|
|
27007
|
+
);
|
|
27008
|
+
return row != null;
|
|
27009
|
+
}
|
|
26995
27010
|
}
|
|
26996
27011
|
];
|
|
26997
27012
|
function migrateCliSqlite(db) {
|
|
@@ -27030,6 +27045,10 @@ var CliSqliteInterrupted = class extends Error {
|
|
|
27030
27045
|
}
|
|
27031
27046
|
};
|
|
27032
27047
|
function applyCliSqliteConcurrencyPragmas(db) {
|
|
27048
|
+
try {
|
|
27049
|
+
db.run("PRAGMA foreign_keys = ON");
|
|
27050
|
+
} catch {
|
|
27051
|
+
}
|
|
27033
27052
|
try {
|
|
27034
27053
|
db.exec("PRAGMA journal_mode = WAL");
|
|
27035
27054
|
} catch {
|
|
@@ -35146,7 +35165,7 @@ async function ensureAcpClient(options) {
|
|
|
35146
35165
|
if (!state.acpStartPromise) {
|
|
35147
35166
|
let statOk = false;
|
|
35148
35167
|
try {
|
|
35149
|
-
const st = fs16.
|
|
35168
|
+
const st = await fs16.promises.stat(targetSessionParentPath);
|
|
35150
35169
|
statOk = st.isDirectory();
|
|
35151
35170
|
if (!statOk) {
|
|
35152
35171
|
state.lastAcpStartError = `Agent cwd is not a directory: ${targetSessionParentPath}`;
|
|
@@ -36741,8 +36760,18 @@ import path29 from "node:path";
|
|
|
36741
36760
|
// src/files/index/walk-workspace-tree.ts
|
|
36742
36761
|
import fs25 from "node:fs";
|
|
36743
36762
|
import path28 from "node:path";
|
|
36763
|
+
var DEPENDENCY_INSTALL_DIR_NAMES = /* @__PURE__ */ new Set([
|
|
36764
|
+
"node_modules",
|
|
36765
|
+
"bower_components",
|
|
36766
|
+
"vendor",
|
|
36767
|
+
"Pods",
|
|
36768
|
+
"Carthage",
|
|
36769
|
+
"DerivedData",
|
|
36770
|
+
".yarn",
|
|
36771
|
+
".pnpm-store"
|
|
36772
|
+
]);
|
|
36744
36773
|
function shouldSkipWorkspaceWalkEntry(name) {
|
|
36745
|
-
return
|
|
36774
|
+
return DEPENDENCY_INSTALL_DIR_NAMES.has(name);
|
|
36746
36775
|
}
|
|
36747
36776
|
async function walkWorkspaceTreeAsync(dir, baseDir, onFile, state) {
|
|
36748
36777
|
let names;
|
|
@@ -36813,14 +36842,26 @@ var FILE_INDEX_INTERRUPT_CHECK_EVERY = 256;
|
|
|
36813
36842
|
function assertNotShutdown() {
|
|
36814
36843
|
if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();
|
|
36815
36844
|
}
|
|
36845
|
+
function upsertFileIndexParentPath(db, resolved) {
|
|
36846
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
36847
|
+
db.run(
|
|
36848
|
+
`INSERT INTO file_index_parent_path (path, path_hash, updated_at)
|
|
36849
|
+
VALUES (?, ?, ?)
|
|
36850
|
+
ON CONFLICT(path) DO UPDATE SET path_hash = excluded.path_hash, updated_at = excluded.updated_at`,
|
|
36851
|
+
[resolved, getCwdHashForFileIndex(resolved), now]
|
|
36852
|
+
);
|
|
36853
|
+
const row = db.get("SELECT id FROM file_index_parent_path WHERE path = ?", [resolved]);
|
|
36854
|
+
if (row == null) throw new Error(`Failed to upsert file index parent path: ${resolved}`);
|
|
36855
|
+
return Number(row.id);
|
|
36856
|
+
}
|
|
36816
36857
|
function persistFileIndexPaths(resolved, paths) {
|
|
36817
36858
|
return withCliSqliteSync((db) => {
|
|
36818
|
-
const h = getCwdHashForFileIndex(resolved);
|
|
36819
36859
|
let pathCount = 0;
|
|
36820
36860
|
db.run("BEGIN IMMEDIATE");
|
|
36821
36861
|
try {
|
|
36822
|
-
|
|
36823
|
-
|
|
36862
|
+
const parentId = upsertFileIndexParentPath(db, resolved);
|
|
36863
|
+
db.run("DELETE FROM file_index_child_path WHERE parent_id = ?", [parentId]);
|
|
36864
|
+
const ins = db.prepare("INSERT INTO file_index_child_path (parent_id, path) VALUES (?, ?)");
|
|
36824
36865
|
try {
|
|
36825
36866
|
let batch = 0;
|
|
36826
36867
|
for (const rel of paths) {
|
|
@@ -36828,7 +36869,7 @@ function persistFileIndexPaths(resolved, paths) {
|
|
|
36828
36869
|
batch = 0;
|
|
36829
36870
|
assertNotShutdown();
|
|
36830
36871
|
}
|
|
36831
|
-
ins.run([
|
|
36872
|
+
ins.run([parentId, rel]);
|
|
36832
36873
|
pathCount += 1;
|
|
36833
36874
|
}
|
|
36834
36875
|
} finally {
|
|
@@ -36870,36 +36911,38 @@ async function buildFileIndexAsync(cwd) {
|
|
|
36870
36911
|
// src/files/index/ensure-file-index.ts
|
|
36871
36912
|
import path30 from "node:path";
|
|
36872
36913
|
|
|
36873
|
-
// src/files/index/file-index-dependency-path.ts
|
|
36874
|
-
function sqliteExprBridgeFileIndexDependencyRank() {
|
|
36875
|
-
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`;
|
|
36876
|
-
}
|
|
36877
|
-
|
|
36878
36914
|
// src/files/index/search-file-index.ts
|
|
36879
36915
|
function escapeLikePattern(fragment) {
|
|
36880
36916
|
return fragment.replace(/\\/g, "\\\\").replace(/%/g, "\\%").replace(/_/g, "\\_");
|
|
36881
36917
|
}
|
|
36882
36918
|
function bridgeFileIndexIsPopulatedWithDb(resolvedCwd, db) {
|
|
36883
|
-
const
|
|
36884
|
-
const row = db.get("SELECT 1 as ok FROM file_index_path WHERE cwd_hash = ? LIMIT 1", [h]);
|
|
36919
|
+
const row = db.get("SELECT 1 as ok FROM file_index_parent_path WHERE path = ? LIMIT 1", [resolvedCwd]);
|
|
36885
36920
|
return row != null;
|
|
36886
36921
|
}
|
|
36887
36922
|
function bridgeFileIndexPathCountWithDb(resolvedCwd, db) {
|
|
36888
|
-
const
|
|
36889
|
-
|
|
36923
|
+
const row = db.get(
|
|
36924
|
+
`SELECT COUNT(*) as c
|
|
36925
|
+
FROM file_index_child_path child
|
|
36926
|
+
JOIN file_index_parent_path parent ON parent.id = child.parent_id
|
|
36927
|
+
WHERE parent.path = ?`,
|
|
36928
|
+
[resolvedCwd]
|
|
36929
|
+
);
|
|
36890
36930
|
const c = row?.c ?? 0;
|
|
36891
36931
|
return Number(c);
|
|
36892
36932
|
}
|
|
36893
36933
|
function searchBridgeFilePathsWithDb(resolvedCwd, query, limit, db) {
|
|
36894
36934
|
const q = query.trim().toLowerCase();
|
|
36895
36935
|
if (!q) return [];
|
|
36896
|
-
const h = getCwdHashForFileIndex(resolvedCwd);
|
|
36897
36936
|
const pattern = `%${escapeLikePattern(q)}%`;
|
|
36898
36937
|
const lim = Math.max(0, Math.min(1e4, Math.floor(limit)));
|
|
36899
|
-
const depRank = sqliteExprBridgeFileIndexDependencyRank();
|
|
36900
36938
|
const rows = db.all(
|
|
36901
|
-
`SELECT path
|
|
36902
|
-
|
|
36939
|
+
`SELECT child.path
|
|
36940
|
+
FROM file_index_child_path child
|
|
36941
|
+
JOIN file_index_parent_path parent ON parent.id = child.parent_id
|
|
36942
|
+
WHERE parent.path = ? AND lower(child.path) LIKE ? ESCAPE '\\'
|
|
36943
|
+
ORDER BY child.path
|
|
36944
|
+
LIMIT ?`,
|
|
36945
|
+
[resolvedCwd, pattern, lim]
|
|
36903
36946
|
);
|
|
36904
36947
|
return rows.map((r) => String(r.path));
|
|
36905
36948
|
}
|
|
@@ -36929,9 +36972,7 @@ async function ensureFileIndexAsync(cwd) {
|
|
|
36929
36972
|
var DEBOUNCE_MS = 900;
|
|
36930
36973
|
function shouldIgnoreRelative(rel) {
|
|
36931
36974
|
const n = rel.replace(/\\/g, "/");
|
|
36932
|
-
|
|
36933
|
-
if (n.includes("/.buildautomaton/") || n.startsWith(".buildautomaton/")) return true;
|
|
36934
|
-
return false;
|
|
36975
|
+
return n.split("/").some((segment) => shouldSkipWorkspaceWalkEntry(segment));
|
|
36935
36976
|
}
|
|
36936
36977
|
function attachWatchErrorLog(w) {
|
|
36937
36978
|
w.on("error", (err) => {
|
|
@@ -38168,11 +38209,13 @@ function connectFirehose(options) {
|
|
|
38168
38209
|
if (Buffer.isBuffer(raw) && tryConsumeBinaryProxyBody(raw, deps)) {
|
|
38169
38210
|
return;
|
|
38170
38211
|
}
|
|
38171
|
-
|
|
38172
|
-
|
|
38173
|
-
|
|
38174
|
-
|
|
38175
|
-
|
|
38212
|
+
setImmediate(() => {
|
|
38213
|
+
try {
|
|
38214
|
+
const text = Buffer.isBuffer(raw) ? raw.toString("utf8") : String(raw);
|
|
38215
|
+
dispatchFirehoseJsonMessage(JSON.parse(text), deps);
|
|
38216
|
+
} catch {
|
|
38217
|
+
}
|
|
38218
|
+
});
|
|
38176
38219
|
});
|
|
38177
38220
|
ws.on("close", (code, reason) => {
|
|
38178
38221
|
disposeClientPing();
|
|
@@ -38688,7 +38731,9 @@ async function runLocalRevertBeforeQueuedPrompt(next, deps) {
|
|
|
38688
38731
|
const tid = typeof pl.snapshotRevertTurnId === "string" && pl.snapshotRevertTurnId.trim() !== "" ? pl.snapshotRevertTurnId.trim() : next.turnId;
|
|
38689
38732
|
const agentBase = deps.sessionWorktreeManager.getSessionWorktreeRootForSession(sid) ?? getBridgeRoot();
|
|
38690
38733
|
const file2 = snapshotFilePath(agentBase, tid);
|
|
38691
|
-
|
|
38734
|
+
try {
|
|
38735
|
+
await fs32.promises.access(file2, fs32.constants.F_OK);
|
|
38736
|
+
} catch {
|
|
38692
38737
|
deps.log(
|
|
38693
38738
|
`[Queue] requeued_with_revert: no pre-turn snapshot for ${tid.slice(0, 8)}\u2026; continuing without revert.`
|
|
38694
38739
|
);
|
|
@@ -39312,9 +39357,8 @@ var handleSkillCallMessage = (msg, { getWs, log: log2 }) => {
|
|
|
39312
39357
|
);
|
|
39313
39358
|
};
|
|
39314
39359
|
|
|
39315
|
-
// src/files/list-dir.ts
|
|
39316
|
-
import
|
|
39317
|
-
import path36 from "node:path";
|
|
39360
|
+
// src/files/list-dir/index.ts
|
|
39361
|
+
import fs34 from "node:fs";
|
|
39318
39362
|
|
|
39319
39363
|
// src/files/ensure-under-cwd.ts
|
|
39320
39364
|
import path35 from "node:path";
|
|
@@ -39327,71 +39371,93 @@ function ensureUnderCwd(relativePath, cwd = getBridgeRoot()) {
|
|
|
39327
39371
|
return resolved;
|
|
39328
39372
|
}
|
|
39329
39373
|
|
|
39330
|
-
// src/files/list-dir.ts
|
|
39374
|
+
// src/files/list-dir/types.ts
|
|
39331
39375
|
var LIST_DIR_YIELD_EVERY = 256;
|
|
39332
|
-
|
|
39333
|
-
|
|
39376
|
+
|
|
39377
|
+
// src/files/list-dir/map-dir-entry.ts
|
|
39378
|
+
import path36 from "node:path";
|
|
39379
|
+
import fs33 from "node:fs";
|
|
39380
|
+
async function mapDirEntry(d, relativePath, resolved) {
|
|
39381
|
+
const entryPath = path36.join(relativePath || ".", d.name).replace(/\\/g, "/");
|
|
39382
|
+
const fullPath = path36.join(resolved, d.name);
|
|
39383
|
+
let isDir = d.isDirectory();
|
|
39384
|
+
if (d.isSymbolicLink()) {
|
|
39385
|
+
try {
|
|
39386
|
+
const targetStat = await fs33.promises.stat(fullPath);
|
|
39387
|
+
isDir = targetStat.isDirectory();
|
|
39388
|
+
} catch {
|
|
39389
|
+
isDir = false;
|
|
39390
|
+
}
|
|
39391
|
+
}
|
|
39392
|
+
return {
|
|
39393
|
+
name: d.name,
|
|
39394
|
+
path: entryPath,
|
|
39395
|
+
isDir,
|
|
39396
|
+
isSymlink: d.isSymbolicLink()
|
|
39397
|
+
};
|
|
39398
|
+
}
|
|
39399
|
+
|
|
39400
|
+
// src/files/list-dir/sort-entries.ts
|
|
39401
|
+
function sortListEntries(entries) {
|
|
39402
|
+
return entries.sort((a, b) => {
|
|
39403
|
+
if (a.isDir !== b.isDir) return a.isDir ? -1 : 1;
|
|
39404
|
+
return a.name.localeCompare(b.name, void 0, { sensitivity: "base" });
|
|
39405
|
+
});
|
|
39406
|
+
}
|
|
39407
|
+
|
|
39408
|
+
// src/files/list-dir/index.ts
|
|
39409
|
+
async function listDirAsync(relativePath, sessionParentPath = getBridgeRoot()) {
|
|
39410
|
+
await yieldToEventLoop();
|
|
39411
|
+
const resolved = ensureUnderCwd(relativePath || ".", sessionParentPath);
|
|
39334
39412
|
if (!resolved) {
|
|
39335
39413
|
return { error: "Path is outside working directory" };
|
|
39336
39414
|
}
|
|
39337
39415
|
try {
|
|
39338
|
-
const names = await
|
|
39339
|
-
const visible = names.filter((d) => !d.name.startsWith("."));
|
|
39416
|
+
const names = await fs34.promises.readdir(resolved, { withFileTypes: true });
|
|
39340
39417
|
const entries = [];
|
|
39341
|
-
for (let i = 0; i <
|
|
39418
|
+
for (let i = 0; i < names.length; i++) {
|
|
39342
39419
|
if (i > 0 && i % LIST_DIR_YIELD_EVERY === 0) {
|
|
39343
39420
|
await yieldToEventLoop();
|
|
39344
39421
|
}
|
|
39345
|
-
|
|
39346
|
-
const entryPath = path36.join(relativePath || ".", d.name).replace(/\\/g, "/");
|
|
39347
|
-
const fullPath = path36.join(resolved, d.name);
|
|
39348
|
-
let isDir = d.isDirectory();
|
|
39349
|
-
if (d.isSymbolicLink()) {
|
|
39350
|
-
try {
|
|
39351
|
-
const targetStat = await fs33.promises.stat(fullPath);
|
|
39352
|
-
isDir = targetStat.isDirectory();
|
|
39353
|
-
} catch {
|
|
39354
|
-
isDir = false;
|
|
39355
|
-
}
|
|
39356
|
-
}
|
|
39357
|
-
entries.push({
|
|
39358
|
-
name: d.name,
|
|
39359
|
-
path: entryPath,
|
|
39360
|
-
isDir,
|
|
39361
|
-
isSymlink: d.isSymbolicLink()
|
|
39362
|
-
});
|
|
39422
|
+
entries.push(await mapDirEntry(names[i], relativePath, resolved));
|
|
39363
39423
|
}
|
|
39364
|
-
entries
|
|
39365
|
-
if (a.isDir !== b.isDir) return a.isDir ? -1 : 1;
|
|
39366
|
-
return a.name.localeCompare(b.name, void 0, { sensitivity: "base" });
|
|
39367
|
-
});
|
|
39368
|
-
return { entries };
|
|
39424
|
+
return { entries: sortListEntries(entries) };
|
|
39369
39425
|
} catch (err) {
|
|
39370
39426
|
const message = err instanceof Error ? err.message : String(err);
|
|
39371
39427
|
return { error: message };
|
|
39372
39428
|
}
|
|
39373
39429
|
}
|
|
39374
39430
|
|
|
39375
|
-
// src/files/read-file.ts
|
|
39376
|
-
|
|
39377
|
-
|
|
39378
|
-
|
|
39379
|
-
|
|
39431
|
+
// src/files/read-file/types.ts
|
|
39432
|
+
var LINE_CHUNK_SIZE = 64 * 1024;
|
|
39433
|
+
var READ_RANGE_YIELD_EVERY_BYTES = 256 * 1024;
|
|
39434
|
+
|
|
39435
|
+
// src/files/read-file/resolve-file-path.ts
|
|
39436
|
+
import fs35 from "node:fs";
|
|
39437
|
+
async function resolveFilePathAsync(relativePath, sessionParentPath = getBridgeRoot()) {
|
|
39438
|
+
const resolved = ensureUnderCwd(relativePath, sessionParentPath);
|
|
39380
39439
|
if (!resolved) return { error: "Path is outside working directory" };
|
|
39381
39440
|
let real;
|
|
39382
39441
|
try {
|
|
39383
|
-
real =
|
|
39442
|
+
real = await fs35.promises.realpath(resolved);
|
|
39384
39443
|
} catch {
|
|
39385
39444
|
real = resolved;
|
|
39386
39445
|
}
|
|
39387
|
-
|
|
39388
|
-
|
|
39389
|
-
|
|
39446
|
+
try {
|
|
39447
|
+
const stat3 = await fs35.promises.stat(real);
|
|
39448
|
+
if (!stat3.isFile()) return { error: "Not a file" };
|
|
39449
|
+
return real;
|
|
39450
|
+
} catch (err) {
|
|
39451
|
+
return { error: err instanceof Error ? err.message : String(err) };
|
|
39452
|
+
}
|
|
39390
39453
|
}
|
|
39391
|
-
|
|
39392
|
-
|
|
39393
|
-
|
|
39394
|
-
|
|
39454
|
+
|
|
39455
|
+
// src/files/read-file/read-file-range-async.ts
|
|
39456
|
+
import fs36 from "node:fs";
|
|
39457
|
+
import { StringDecoder } from "node:string_decoder";
|
|
39458
|
+
async function readFileRangeAsync(filePath, startLine, endLine, lineOffsetIn, lineChunkSize = LINE_CHUNK_SIZE) {
|
|
39459
|
+
const fileSize = (await fs36.promises.stat(filePath)).size;
|
|
39460
|
+
const fd = await fs36.promises.open(filePath, "r");
|
|
39395
39461
|
const bufSize = 64 * 1024;
|
|
39396
39462
|
const buf = Buffer.alloc(bufSize);
|
|
39397
39463
|
const decoder = new StringDecoder("utf8");
|
|
@@ -39402,9 +39468,18 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
|
|
|
39402
39468
|
let skipLine0Chars = typeof lineOffsetIn === "number" ? lineOffsetIn : 0;
|
|
39403
39469
|
let line0CharsReturned = 0;
|
|
39404
39470
|
let line0Accum = "";
|
|
39471
|
+
let bytesSinceYield = 0;
|
|
39405
39472
|
try {
|
|
39406
|
-
let
|
|
39407
|
-
while (!done
|
|
39473
|
+
let position = 0;
|
|
39474
|
+
while (!done) {
|
|
39475
|
+
const { bytesRead } = await fd.read(buf, 0, bufSize, position);
|
|
39476
|
+
if (bytesRead === 0) break;
|
|
39477
|
+
position += bytesRead;
|
|
39478
|
+
bytesSinceYield += bytesRead;
|
|
39479
|
+
if (bytesSinceYield >= READ_RANGE_YIELD_EVERY_BYTES) {
|
|
39480
|
+
await yieldToEventLoop();
|
|
39481
|
+
bytesSinceYield = 0;
|
|
39482
|
+
}
|
|
39408
39483
|
const text = partial2 + decoder.write(buf.subarray(0, bytesRead));
|
|
39409
39484
|
partial2 = "";
|
|
39410
39485
|
let lineStart = 0;
|
|
@@ -39539,39 +39614,132 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
|
|
|
39539
39614
|
}
|
|
39540
39615
|
return { content: resultLines.join("\n"), size: fileSize };
|
|
39541
39616
|
} finally {
|
|
39542
|
-
|
|
39617
|
+
await fd.close();
|
|
39543
39618
|
}
|
|
39544
39619
|
}
|
|
39545
|
-
|
|
39620
|
+
|
|
39621
|
+
// src/files/read-file/read-file-buffer-full-async.ts
|
|
39622
|
+
import fs37 from "node:fs";
|
|
39623
|
+
var READ_CHUNK_BYTES = 256 * 1024;
|
|
39624
|
+
async function readFileBufferFullAsync(filePath) {
|
|
39625
|
+
const stat3 = await fs37.promises.stat(filePath);
|
|
39626
|
+
const fd = await fs37.promises.open(filePath, "r");
|
|
39627
|
+
const chunks = [];
|
|
39628
|
+
let position = 0;
|
|
39629
|
+
let bytesSinceYield = 0;
|
|
39546
39630
|
try {
|
|
39547
|
-
|
|
39631
|
+
while (position < stat3.size) {
|
|
39632
|
+
const buf = Buffer.alloc(Math.min(READ_CHUNK_BYTES, stat3.size - position));
|
|
39633
|
+
const { bytesRead } = await fd.read(buf, 0, buf.length, position);
|
|
39634
|
+
if (bytesRead === 0) break;
|
|
39635
|
+
chunks.push(buf.subarray(0, bytesRead));
|
|
39636
|
+
position += bytesRead;
|
|
39637
|
+
bytesSinceYield += bytesRead;
|
|
39638
|
+
if (bytesSinceYield >= READ_RANGE_YIELD_EVERY_BYTES) {
|
|
39639
|
+
await yieldToEventLoop();
|
|
39640
|
+
bytesSinceYield = 0;
|
|
39641
|
+
}
|
|
39642
|
+
}
|
|
39643
|
+
} finally {
|
|
39644
|
+
await fd.close();
|
|
39645
|
+
}
|
|
39646
|
+
return { buffer: Buffer.concat(chunks), size: stat3.size };
|
|
39647
|
+
}
|
|
39648
|
+
|
|
39649
|
+
// src/files/read-file/read-file-full-async.ts
|
|
39650
|
+
async function readFileFullAsync(filePath) {
|
|
39651
|
+
const { buffer, size } = await readFileBufferFullAsync(filePath);
|
|
39652
|
+
const raw = buffer.toString("utf8");
|
|
39653
|
+
const lines = raw.split(/\r?\n/);
|
|
39654
|
+
return { content: raw, totalLines: lines.length, size };
|
|
39655
|
+
}
|
|
39656
|
+
|
|
39657
|
+
// src/files/read-file/guess-mime-type.ts
|
|
39658
|
+
var MIME_BY_EXT = {
|
|
39659
|
+
png: "image/png",
|
|
39660
|
+
jpg: "image/jpeg",
|
|
39661
|
+
jpeg: "image/jpeg",
|
|
39662
|
+
gif: "image/gif",
|
|
39663
|
+
bmp: "image/bmp",
|
|
39664
|
+
ico: "image/x-icon",
|
|
39665
|
+
webp: "image/webp",
|
|
39666
|
+
avif: "image/avif",
|
|
39667
|
+
svg: "image/svg+xml",
|
|
39668
|
+
pdf: "application/pdf",
|
|
39669
|
+
json: "application/json",
|
|
39670
|
+
html: "text/html",
|
|
39671
|
+
htm: "text/html",
|
|
39672
|
+
css: "text/css",
|
|
39673
|
+
js: "text/javascript",
|
|
39674
|
+
mjs: "text/javascript",
|
|
39675
|
+
ts: "text/typescript",
|
|
39676
|
+
txt: "text/plain",
|
|
39677
|
+
md: "text/markdown",
|
|
39678
|
+
xml: "application/xml",
|
|
39679
|
+
zip: "application/zip",
|
|
39680
|
+
gz: "application/gzip",
|
|
39681
|
+
wasm: "application/wasm"
|
|
39682
|
+
};
|
|
39683
|
+
function guessMimeType(filePath) {
|
|
39684
|
+
const ext = filePath.split(".").pop()?.toLowerCase() ?? "";
|
|
39685
|
+
return MIME_BY_EXT[ext] ?? "application/octet-stream";
|
|
39686
|
+
}
|
|
39687
|
+
|
|
39688
|
+
// src/files/read-file/read-file-binary-full-async.ts
|
|
39689
|
+
async function readFileBinaryFullAsync(filePath) {
|
|
39690
|
+
const { buffer, size } = await readFileBufferFullAsync(filePath);
|
|
39691
|
+
return {
|
|
39692
|
+
content: buffer.toString("base64"),
|
|
39693
|
+
size,
|
|
39694
|
+
mimeType: guessMimeType(filePath)
|
|
39695
|
+
};
|
|
39696
|
+
}
|
|
39697
|
+
|
|
39698
|
+
// src/files/read-file/index.ts
|
|
39699
|
+
async function readFileAsync(relativePath, startLine, endLine, lineOffset, lineChunkSize = LINE_CHUNK_SIZE, sessionParentPath = getBridgeRoot(), encoding = "utf8") {
|
|
39700
|
+
await yieldToEventLoop();
|
|
39701
|
+
try {
|
|
39702
|
+
const result = await resolveFilePathAsync(relativePath, sessionParentPath);
|
|
39548
39703
|
if (typeof result === "object") return result;
|
|
39704
|
+
const resolvedPath = result;
|
|
39549
39705
|
const hasRange = typeof startLine === "number" && typeof endLine === "number";
|
|
39706
|
+
if (encoding === "base64") {
|
|
39707
|
+
if (hasRange) return { error: "base64 encoding requires a full file read (no line range)" };
|
|
39708
|
+
const read2 = await readFileBinaryFullAsync(resolvedPath);
|
|
39709
|
+
return { ...read2, resolvedPath };
|
|
39710
|
+
}
|
|
39550
39711
|
if (hasRange) {
|
|
39551
|
-
return
|
|
39712
|
+
return readFileRangeAsync(resolvedPath, startLine, endLine, lineOffset, lineChunkSize);
|
|
39552
39713
|
}
|
|
39553
|
-
const
|
|
39554
|
-
|
|
39555
|
-
const lines = raw.split(/\r?\n/);
|
|
39556
|
-
return { content: raw, totalLines: lines.length, size: stat3.size };
|
|
39714
|
+
const read = await readFileFullAsync(resolvedPath);
|
|
39715
|
+
return { ...read, resolvedPath };
|
|
39557
39716
|
} catch (err) {
|
|
39558
39717
|
return { error: err instanceof Error ? err.message : String(err) };
|
|
39559
39718
|
}
|
|
39560
39719
|
}
|
|
39561
|
-
|
|
39562
|
-
|
|
39563
|
-
|
|
39720
|
+
|
|
39721
|
+
// src/files/resolve-file-browser-session-parent.ts
|
|
39722
|
+
function resolveFileBrowserSessionParent(sessionWorktreeManager, sessionId) {
|
|
39723
|
+
const sid = sessionId?.trim();
|
|
39724
|
+
if (sid) {
|
|
39725
|
+
sessionWorktreeManager.ensureRepoCheckoutPathsForSession(sid);
|
|
39726
|
+
const worktreeRoot = sessionWorktreeManager.getSessionWorktreeRootForSession(sid);
|
|
39727
|
+
if (worktreeRoot) return worktreeRoot;
|
|
39728
|
+
}
|
|
39729
|
+
return getBridgeRoot();
|
|
39564
39730
|
}
|
|
39565
39731
|
|
|
39566
39732
|
// src/files/handle-file-browser-search.ts
|
|
39567
39733
|
import path37 from "node:path";
|
|
39568
39734
|
var SEARCH_LIMIT = 100;
|
|
39569
|
-
function handleFileBrowserSearch(msg, socket, e2ee) {
|
|
39735
|
+
function handleFileBrowserSearch(msg, socket, e2ee, sessionWorktreeManager) {
|
|
39570
39736
|
void (async () => {
|
|
39571
39737
|
await yieldToEventLoop();
|
|
39572
39738
|
const q = typeof msg.q === "string" ? msg.q : "";
|
|
39573
|
-
const
|
|
39574
|
-
|
|
39739
|
+
const sessionParentPath = path37.resolve(
|
|
39740
|
+
sessionWorktreeManager != null ? resolveFileBrowserSessionParent(sessionWorktreeManager, msg.sessionId) : getBridgeRoot()
|
|
39741
|
+
);
|
|
39742
|
+
if (!await bridgeFileIndexIsPopulated(sessionParentPath)) {
|
|
39575
39743
|
const payload2 = {
|
|
39576
39744
|
type: "file_browser_search_response",
|
|
39577
39745
|
id: msg.id,
|
|
@@ -39581,7 +39749,7 @@ function handleFileBrowserSearch(msg, socket, e2ee) {
|
|
|
39581
39749
|
sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload2, ["paths"]) : payload2);
|
|
39582
39750
|
return;
|
|
39583
39751
|
}
|
|
39584
|
-
const results = await searchBridgeFilePathsAsync(
|
|
39752
|
+
const results = await searchBridgeFilePathsAsync(sessionParentPath, q, SEARCH_LIMIT);
|
|
39585
39753
|
const payload = {
|
|
39586
39754
|
type: "file_browser_search_response",
|
|
39587
39755
|
id: msg.id,
|
|
@@ -39591,9 +39759,9 @@ function handleFileBrowserSearch(msg, socket, e2ee) {
|
|
|
39591
39759
|
sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload, ["paths"]) : payload);
|
|
39592
39760
|
})();
|
|
39593
39761
|
}
|
|
39594
|
-
function triggerFileIndexBuild() {
|
|
39762
|
+
function triggerFileIndexBuild(sessionParentPath = getBridgeRoot()) {
|
|
39595
39763
|
setImmediate(() => {
|
|
39596
|
-
void ensureFileIndexAsync(
|
|
39764
|
+
void ensureFileIndexAsync(sessionParentPath).catch((e) => {
|
|
39597
39765
|
console.error("[file-index] Background build failed:", e);
|
|
39598
39766
|
});
|
|
39599
39767
|
});
|
|
@@ -39603,18 +39771,19 @@ function triggerFileIndexBuild() {
|
|
|
39603
39771
|
function sendFileBrowserMessage(socket, e2ee, payload) {
|
|
39604
39772
|
sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload, ["entries", "content", "totalLines", "size", "lineOffset"]) : payload);
|
|
39605
39773
|
}
|
|
39606
|
-
function handleFileBrowserRequest(msg, socket, e2ee) {
|
|
39774
|
+
function handleFileBrowserRequest(msg, socket, e2ee, sessionWorktreeManager) {
|
|
39607
39775
|
void (async () => {
|
|
39608
39776
|
const reqPath = msg.path.replace(/^\/+/, "") || ".";
|
|
39609
39777
|
const op = msg.op === "read" ? "read" : "list";
|
|
39778
|
+
const sessionParentPath = sessionWorktreeManager != null ? resolveFileBrowserSessionParent(sessionWorktreeManager, msg.sessionId) : void 0;
|
|
39610
39779
|
if (op === "list") {
|
|
39611
|
-
const result = await listDirAsync(reqPath);
|
|
39780
|
+
const result = await listDirAsync(reqPath, sessionParentPath);
|
|
39612
39781
|
if ("error" in result) {
|
|
39613
39782
|
sendWsMessage(socket, { type: "file_browser_response", id: msg.id, error: result.error });
|
|
39614
39783
|
} else {
|
|
39615
39784
|
sendFileBrowserMessage(socket, e2ee, { type: "file_browser_response", id: msg.id, entries: result.entries });
|
|
39616
39785
|
if (reqPath === "." || reqPath === "") {
|
|
39617
|
-
triggerFileIndexBuild();
|
|
39786
|
+
triggerFileIndexBuild(sessionParentPath);
|
|
39618
39787
|
}
|
|
39619
39788
|
}
|
|
39620
39789
|
} else {
|
|
@@ -39622,7 +39791,16 @@ function handleFileBrowserRequest(msg, socket, e2ee) {
|
|
|
39622
39791
|
const endLine = typeof msg.endLine === "number" ? msg.endLine : void 0;
|
|
39623
39792
|
const lineOffset = typeof msg.lineOffset === "number" ? msg.lineOffset : void 0;
|
|
39624
39793
|
const lineChunkSize = typeof msg.lineChunkSize === "number" ? msg.lineChunkSize : void 0;
|
|
39625
|
-
const
|
|
39794
|
+
const encoding = msg.encoding === "base64" ? "base64" : "utf8";
|
|
39795
|
+
const result = await readFileAsync(
|
|
39796
|
+
reqPath,
|
|
39797
|
+
startLine,
|
|
39798
|
+
endLine,
|
|
39799
|
+
lineOffset,
|
|
39800
|
+
lineChunkSize,
|
|
39801
|
+
sessionParentPath,
|
|
39802
|
+
encoding
|
|
39803
|
+
);
|
|
39626
39804
|
if ("error" in result) {
|
|
39627
39805
|
sendWsMessage(socket, { type: "file_browser_response", id: msg.id, error: result.error });
|
|
39628
39806
|
} else {
|
|
@@ -39634,6 +39812,8 @@ function handleFileBrowserRequest(msg, socket, e2ee) {
|
|
|
39634
39812
|
size: result.size
|
|
39635
39813
|
};
|
|
39636
39814
|
if (result.lineOffset != null) payload.lineOffset = result.lineOffset;
|
|
39815
|
+
if (result.mimeType != null) payload.mimeType = result.mimeType;
|
|
39816
|
+
if (result.resolvedPath != null) payload.resolvedPath = result.resolvedPath;
|
|
39637
39817
|
sendFileBrowserMessage(socket, e2ee, payload);
|
|
39638
39818
|
}
|
|
39639
39819
|
}
|
|
@@ -39641,21 +39821,27 @@ function handleFileBrowserRequest(msg, socket, e2ee) {
|
|
|
39641
39821
|
}
|
|
39642
39822
|
|
|
39643
39823
|
// src/routing/handlers/file-browser-messages.ts
|
|
39644
|
-
function handleFileBrowserRequestMessage(msg, { getWs, e2ee }) {
|
|
39824
|
+
function handleFileBrowserRequestMessage(msg, { getWs, e2ee, sessionWorktreeManager }) {
|
|
39645
39825
|
if (typeof msg.id !== "string" || typeof msg.path !== "string") return;
|
|
39646
39826
|
const socket = getWs();
|
|
39647
39827
|
if (!socket) return;
|
|
39648
39828
|
handleFileBrowserRequest(
|
|
39649
39829
|
msg,
|
|
39650
39830
|
socket,
|
|
39651
|
-
e2ee
|
|
39831
|
+
e2ee,
|
|
39832
|
+
sessionWorktreeManager
|
|
39652
39833
|
);
|
|
39653
39834
|
}
|
|
39654
|
-
function handleFileBrowserSearchMessage(msg, { getWs, e2ee }) {
|
|
39835
|
+
function handleFileBrowserSearchMessage(msg, { getWs, e2ee, sessionWorktreeManager }) {
|
|
39655
39836
|
if (typeof msg.id !== "string") return;
|
|
39656
39837
|
const socket = getWs();
|
|
39657
39838
|
if (!socket) return;
|
|
39658
|
-
handleFileBrowserSearch(
|
|
39839
|
+
handleFileBrowserSearch(
|
|
39840
|
+
msg,
|
|
39841
|
+
socket,
|
|
39842
|
+
e2ee,
|
|
39843
|
+
sessionWorktreeManager
|
|
39844
|
+
);
|
|
39659
39845
|
}
|
|
39660
39846
|
|
|
39661
39847
|
// src/routing/handlers/skill-layout-request.ts
|
|
@@ -39669,7 +39855,7 @@ function handleSkillLayoutRequest(msg, deps) {
|
|
|
39669
39855
|
}
|
|
39670
39856
|
|
|
39671
39857
|
// src/skills/install-remote-skills.ts
|
|
39672
|
-
import
|
|
39858
|
+
import fs38 from "node:fs";
|
|
39673
39859
|
import path38 from "node:path";
|
|
39674
39860
|
function installRemoteSkills(cwd, targetDir, items) {
|
|
39675
39861
|
const installed2 = [];
|
|
@@ -39685,11 +39871,11 @@ function installRemoteSkills(cwd, targetDir, items) {
|
|
|
39685
39871
|
for (const f of item.files) {
|
|
39686
39872
|
if (typeof f.path !== "string" || !f.text && !f.base64) continue;
|
|
39687
39873
|
const dest = path38.join(skillDir, f.path);
|
|
39688
|
-
|
|
39874
|
+
fs38.mkdirSync(path38.dirname(dest), { recursive: true });
|
|
39689
39875
|
if (f.text !== void 0) {
|
|
39690
|
-
|
|
39876
|
+
fs38.writeFileSync(dest, f.text, "utf8");
|
|
39691
39877
|
} else if (f.base64) {
|
|
39692
|
-
|
|
39878
|
+
fs38.writeFileSync(dest, Buffer.from(f.base64, "base64"));
|
|
39693
39879
|
}
|
|
39694
39880
|
}
|
|
39695
39881
|
installed2.push({
|
|
@@ -39847,7 +40033,7 @@ var handleSessionDiscardedMessage = (msg, deps) => {
|
|
|
39847
40033
|
};
|
|
39848
40034
|
|
|
39849
40035
|
// src/routing/handlers/revert-turn-snapshot.ts
|
|
39850
|
-
import * as
|
|
40036
|
+
import * as fs39 from "node:fs";
|
|
39851
40037
|
var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
39852
40038
|
const id = typeof msg.id === "string" ? msg.id : "";
|
|
39853
40039
|
const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
|
|
@@ -39859,7 +40045,9 @@ var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
|
39859
40045
|
if (!s) return;
|
|
39860
40046
|
const agentBase = sessionWorktreeManager.getSessionWorktreeRootForSession(sessionId) ?? getBridgeRoot();
|
|
39861
40047
|
const file2 = snapshotFilePath(agentBase, turnId);
|
|
39862
|
-
|
|
40048
|
+
try {
|
|
40049
|
+
await fs39.promises.access(file2, fs39.constants.F_OK);
|
|
40050
|
+
} catch {
|
|
39863
40051
|
sendWsMessage(s, {
|
|
39864
40052
|
type: "revert_turn_snapshot_result",
|
|
39865
40053
|
id,
|
|
@@ -39978,9 +40166,7 @@ function handleBridgeMessage(data, deps) {
|
|
|
39978
40166
|
if (!deps.getWs()) return;
|
|
39979
40167
|
const msg = parseApiToBridgeMessage(normalizeInboundBridgeWebSocketJson(data), deps.log);
|
|
39980
40168
|
if (!msg) return;
|
|
39981
|
-
|
|
39982
|
-
dispatchBridgeMessage(msg, deps);
|
|
39983
|
-
});
|
|
40169
|
+
dispatchBridgeMessage(msg, deps);
|
|
39984
40170
|
}
|
|
39985
40171
|
|
|
39986
40172
|
// src/auth/refresh-bridge-tokens.ts
|
|
@@ -40546,25 +40732,27 @@ async function createBridgeConnection(options) {
|
|
|
40546
40732
|
}
|
|
40547
40733
|
function sendAgentCapabilitiesToBridge(info) {
|
|
40548
40734
|
if (!Array.isArray(info.configOptions) || info.configOptions.length === 0) return;
|
|
40549
|
-
|
|
40550
|
-
|
|
40551
|
-
|
|
40552
|
-
|
|
40553
|
-
|
|
40554
|
-
|
|
40555
|
-
|
|
40556
|
-
|
|
40557
|
-
|
|
40558
|
-
|
|
40559
|
-
|
|
40560
|
-
|
|
40561
|
-
|
|
40562
|
-
|
|
40563
|
-
|
|
40564
|
-
|
|
40565
|
-
|
|
40566
|
-
|
|
40567
|
-
|
|
40735
|
+
setImmediate(() => {
|
|
40736
|
+
let changed = false;
|
|
40737
|
+
try {
|
|
40738
|
+
changed = withCliSqliteSync(
|
|
40739
|
+
(db) => upsertCliAgentCapabilityCache(db, {
|
|
40740
|
+
workspaceId,
|
|
40741
|
+
agentType: info.agentType,
|
|
40742
|
+
configOptions: info.configOptions
|
|
40743
|
+
})
|
|
40744
|
+
);
|
|
40745
|
+
} catch (e) {
|
|
40746
|
+
if (e instanceof CliSqliteInterrupted) return;
|
|
40747
|
+
}
|
|
40748
|
+
if (!changed) return;
|
|
40749
|
+
const socket = getWs();
|
|
40750
|
+
if (!socket || socket.readyState !== wrapper_default.OPEN) return;
|
|
40751
|
+
sendWsMessage(socket, {
|
|
40752
|
+
type: "agent_capabilities",
|
|
40753
|
+
agentType: info.agentType,
|
|
40754
|
+
configOptions: info.configOptions
|
|
40755
|
+
});
|
|
40568
40756
|
});
|
|
40569
40757
|
}
|
|
40570
40758
|
const worktreesRootPath = options.worktreesRootPath ?? defaultWorktreesRootPath();
|
|
@@ -40874,7 +41062,7 @@ async function runCliAction(program2, opts) {
|
|
|
40874
41062
|
if (bridgeRootOpt) {
|
|
40875
41063
|
const resolvedBridgeRoot = path42.resolve(process.cwd(), bridgeRootOpt);
|
|
40876
41064
|
try {
|
|
40877
|
-
const st =
|
|
41065
|
+
const st = fs40.statSync(resolvedBridgeRoot);
|
|
40878
41066
|
if (!st.isDirectory()) {
|
|
40879
41067
|
console.error(`Bridge root is not a directory: ${resolvedBridgeRoot}`);
|
|
40880
41068
|
process.exit(1);
|