@buildautomaton/cli 0.1.29 → 0.1.31
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 +579 -147
- package/dist/cli.js.map +4 -4
- package/dist/index.js +564 -132
- package/dist/index.js.map +4 -4
- package/dist/migrations/002_acp_capability_cache.sql +10 -0
- package/dist/migrations/002_agent_capabilities.sql +10 -0
- package/dist/migrations/002_agent_capability_cache.sql +10 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -973,7 +973,7 @@ var require_command = __commonJS({
|
|
|
973
973
|
"../../node_modules/.pnpm/commander@12.1.0/node_modules/commander/lib/command.js"(exports) {
|
|
974
974
|
var EventEmitter2 = __require("node:events").EventEmitter;
|
|
975
975
|
var childProcess2 = __require("node:child_process");
|
|
976
|
-
var
|
|
976
|
+
var path43 = __require("node:path");
|
|
977
977
|
var fs38 = __require("node:fs");
|
|
978
978
|
var process8 = __require("node:process");
|
|
979
979
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
@@ -1906,9 +1906,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1906
1906
|
let launchWithNode = false;
|
|
1907
1907
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
1908
1908
|
function findFile(baseDir, baseName) {
|
|
1909
|
-
const localBin =
|
|
1909
|
+
const localBin = path43.resolve(baseDir, baseName);
|
|
1910
1910
|
if (fs38.existsSync(localBin)) return localBin;
|
|
1911
|
-
if (sourceExt.includes(
|
|
1911
|
+
if (sourceExt.includes(path43.extname(baseName))) return void 0;
|
|
1912
1912
|
const foundExt = sourceExt.find(
|
|
1913
1913
|
(ext) => fs38.existsSync(`${localBin}${ext}`)
|
|
1914
1914
|
);
|
|
@@ -1926,17 +1926,17 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1926
1926
|
} catch (err) {
|
|
1927
1927
|
resolvedScriptPath = this._scriptPath;
|
|
1928
1928
|
}
|
|
1929
|
-
executableDir =
|
|
1930
|
-
|
|
1929
|
+
executableDir = path43.resolve(
|
|
1930
|
+
path43.dirname(resolvedScriptPath),
|
|
1931
1931
|
executableDir
|
|
1932
1932
|
);
|
|
1933
1933
|
}
|
|
1934
1934
|
if (executableDir) {
|
|
1935
1935
|
let localFile = findFile(executableDir, executableFile);
|
|
1936
1936
|
if (!localFile && !subcommand._executableFile && this._scriptPath) {
|
|
1937
|
-
const legacyName =
|
|
1937
|
+
const legacyName = path43.basename(
|
|
1938
1938
|
this._scriptPath,
|
|
1939
|
-
|
|
1939
|
+
path43.extname(this._scriptPath)
|
|
1940
1940
|
);
|
|
1941
1941
|
if (legacyName !== this._name) {
|
|
1942
1942
|
localFile = findFile(
|
|
@@ -1947,7 +1947,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1947
1947
|
}
|
|
1948
1948
|
executableFile = localFile || executableFile;
|
|
1949
1949
|
}
|
|
1950
|
-
launchWithNode = sourceExt.includes(
|
|
1950
|
+
launchWithNode = sourceExt.includes(path43.extname(executableFile));
|
|
1951
1951
|
let proc;
|
|
1952
1952
|
if (process8.platform !== "win32") {
|
|
1953
1953
|
if (launchWithNode) {
|
|
@@ -2787,7 +2787,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2787
2787
|
* @return {Command}
|
|
2788
2788
|
*/
|
|
2789
2789
|
nameFromFilename(filename) {
|
|
2790
|
-
this._name =
|
|
2790
|
+
this._name = path43.basename(filename, path43.extname(filename));
|
|
2791
2791
|
return this;
|
|
2792
2792
|
}
|
|
2793
2793
|
/**
|
|
@@ -2801,9 +2801,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2801
2801
|
* @param {string} [path]
|
|
2802
2802
|
* @return {(string|null|Command)}
|
|
2803
2803
|
*/
|
|
2804
|
-
executableDir(
|
|
2805
|
-
if (
|
|
2806
|
-
this._executableDir =
|
|
2804
|
+
executableDir(path44) {
|
|
2805
|
+
if (path44 === void 0) return this._executableDir;
|
|
2806
|
+
this._executableDir = path44;
|
|
2807
2807
|
return this;
|
|
2808
2808
|
}
|
|
2809
2809
|
/**
|
|
@@ -5236,7 +5236,7 @@ var require_websocket = __commonJS({
|
|
|
5236
5236
|
var http = __require("http");
|
|
5237
5237
|
var net = __require("net");
|
|
5238
5238
|
var tls = __require("tls");
|
|
5239
|
-
var { randomBytes: randomBytes3, createHash:
|
|
5239
|
+
var { randomBytes: randomBytes3, createHash: createHash3 } = __require("crypto");
|
|
5240
5240
|
var { Duplex, Readable: Readable2 } = __require("stream");
|
|
5241
5241
|
var { URL: URL2 } = __require("url");
|
|
5242
5242
|
var PerMessageDeflate = require_permessage_deflate();
|
|
@@ -5896,7 +5896,7 @@ var require_websocket = __commonJS({
|
|
|
5896
5896
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
5897
5897
|
return;
|
|
5898
5898
|
}
|
|
5899
|
-
const digest =
|
|
5899
|
+
const digest = createHash3("sha1").update(key + GUID).digest("base64");
|
|
5900
5900
|
if (res.headers["sec-websocket-accept"] !== digest) {
|
|
5901
5901
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
5902
5902
|
return;
|
|
@@ -6263,7 +6263,7 @@ var require_websocket_server = __commonJS({
|
|
|
6263
6263
|
var EventEmitter2 = __require("events");
|
|
6264
6264
|
var http = __require("http");
|
|
6265
6265
|
var { Duplex } = __require("stream");
|
|
6266
|
-
var { createHash:
|
|
6266
|
+
var { createHash: createHash3 } = __require("crypto");
|
|
6267
6267
|
var extension = require_extension();
|
|
6268
6268
|
var PerMessageDeflate = require_permessage_deflate();
|
|
6269
6269
|
var subprotocol = require_subprotocol();
|
|
@@ -6564,7 +6564,7 @@ var require_websocket_server = __commonJS({
|
|
|
6564
6564
|
);
|
|
6565
6565
|
}
|
|
6566
6566
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
6567
|
-
const digest =
|
|
6567
|
+
const digest = createHash3("sha1").update(key + GUID).digest("base64");
|
|
6568
6568
|
const headers = [
|
|
6569
6569
|
"HTTP/1.1 101 Switching Protocols",
|
|
6570
6570
|
"Upgrade: websocket",
|
|
@@ -7061,8 +7061,8 @@ var init_parseUtil = __esm({
|
|
|
7061
7061
|
init_errors();
|
|
7062
7062
|
init_en();
|
|
7063
7063
|
makeIssue = (params) => {
|
|
7064
|
-
const { data, path:
|
|
7065
|
-
const fullPath = [...
|
|
7064
|
+
const { data, path: path43, errorMaps, issueData } = params;
|
|
7065
|
+
const fullPath = [...path43, ...issueData.path || []];
|
|
7066
7066
|
const fullIssue = {
|
|
7067
7067
|
...issueData,
|
|
7068
7068
|
path: fullPath
|
|
@@ -7370,11 +7370,11 @@ var init_types = __esm({
|
|
|
7370
7370
|
init_parseUtil();
|
|
7371
7371
|
init_util();
|
|
7372
7372
|
ParseInputLazyPath = class {
|
|
7373
|
-
constructor(parent, value,
|
|
7373
|
+
constructor(parent, value, path43, key) {
|
|
7374
7374
|
this._cachedPath = [];
|
|
7375
7375
|
this.parent = parent;
|
|
7376
7376
|
this.data = value;
|
|
7377
|
-
this._path =
|
|
7377
|
+
this._path = path43;
|
|
7378
7378
|
this._key = key;
|
|
7379
7379
|
}
|
|
7380
7380
|
get path() {
|
|
@@ -11529,10 +11529,10 @@ var require_src2 = __commonJS({
|
|
|
11529
11529
|
var fs_1 = __require("fs");
|
|
11530
11530
|
var debug_1 = __importDefault(require_src());
|
|
11531
11531
|
var log2 = debug_1.default("@kwsites/file-exists");
|
|
11532
|
-
function check2(
|
|
11533
|
-
log2(`checking %s`,
|
|
11532
|
+
function check2(path43, isFile, isDirectory) {
|
|
11533
|
+
log2(`checking %s`, path43);
|
|
11534
11534
|
try {
|
|
11535
|
-
const stat3 = fs_1.statSync(
|
|
11535
|
+
const stat3 = fs_1.statSync(path43);
|
|
11536
11536
|
if (stat3.isFile() && isFile) {
|
|
11537
11537
|
log2(`[OK] path represents a file`);
|
|
11538
11538
|
return true;
|
|
@@ -11552,8 +11552,8 @@ var require_src2 = __commonJS({
|
|
|
11552
11552
|
throw e;
|
|
11553
11553
|
}
|
|
11554
11554
|
}
|
|
11555
|
-
function exists2(
|
|
11556
|
-
return check2(
|
|
11555
|
+
function exists2(path43, type = exports.READABLE) {
|
|
11556
|
+
return check2(path43, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
|
|
11557
11557
|
}
|
|
11558
11558
|
exports.exists = exists2;
|
|
11559
11559
|
exports.FILE = 1;
|
|
@@ -11850,10 +11850,10 @@ function assignProp(target, prop, value) {
|
|
|
11850
11850
|
configurable: true
|
|
11851
11851
|
});
|
|
11852
11852
|
}
|
|
11853
|
-
function getElementAtPath(obj,
|
|
11854
|
-
if (!
|
|
11853
|
+
function getElementAtPath(obj, path43) {
|
|
11854
|
+
if (!path43)
|
|
11855
11855
|
return obj;
|
|
11856
|
-
return
|
|
11856
|
+
return path43.reduce((acc, key) => acc?.[key], obj);
|
|
11857
11857
|
}
|
|
11858
11858
|
function promiseAllObject(promisesObj) {
|
|
11859
11859
|
const keys = Object.keys(promisesObj);
|
|
@@ -12102,11 +12102,11 @@ function aborted(x, startIndex = 0) {
|
|
|
12102
12102
|
}
|
|
12103
12103
|
return false;
|
|
12104
12104
|
}
|
|
12105
|
-
function prefixIssues(
|
|
12105
|
+
function prefixIssues(path43, issues) {
|
|
12106
12106
|
return issues.map((iss) => {
|
|
12107
12107
|
var _a2;
|
|
12108
12108
|
(_a2 = iss).path ?? (_a2.path = []);
|
|
12109
|
-
iss.path.unshift(
|
|
12109
|
+
iss.path.unshift(path43);
|
|
12110
12110
|
return iss;
|
|
12111
12111
|
});
|
|
12112
12112
|
}
|
|
@@ -12295,7 +12295,7 @@ function treeifyError(error40, _mapper) {
|
|
|
12295
12295
|
return issue2.message;
|
|
12296
12296
|
};
|
|
12297
12297
|
const result = { errors: [] };
|
|
12298
|
-
const processError = (error41,
|
|
12298
|
+
const processError = (error41, path43 = []) => {
|
|
12299
12299
|
var _a2, _b;
|
|
12300
12300
|
for (const issue2 of error41.issues) {
|
|
12301
12301
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -12305,7 +12305,7 @@ function treeifyError(error40, _mapper) {
|
|
|
12305
12305
|
} else if (issue2.code === "invalid_element") {
|
|
12306
12306
|
processError({ issues: issue2.issues }, issue2.path);
|
|
12307
12307
|
} else {
|
|
12308
|
-
const fullpath = [...
|
|
12308
|
+
const fullpath = [...path43, ...issue2.path];
|
|
12309
12309
|
if (fullpath.length === 0) {
|
|
12310
12310
|
result.errors.push(mapper(issue2));
|
|
12311
12311
|
continue;
|
|
@@ -12335,9 +12335,9 @@ function treeifyError(error40, _mapper) {
|
|
|
12335
12335
|
processError(error40);
|
|
12336
12336
|
return result;
|
|
12337
12337
|
}
|
|
12338
|
-
function toDotPath(
|
|
12338
|
+
function toDotPath(path43) {
|
|
12339
12339
|
const segs = [];
|
|
12340
|
-
for (const seg of
|
|
12340
|
+
for (const seg of path43) {
|
|
12341
12341
|
if (typeof seg === "number")
|
|
12342
12342
|
segs.push(`[${seg}]`);
|
|
12343
12343
|
else if (typeof seg === "symbol")
|
|
@@ -24800,8 +24800,8 @@ var init_acp = __esm({
|
|
|
24800
24800
|
this.#requestHandler = requestHandler;
|
|
24801
24801
|
this.#notificationHandler = notificationHandler;
|
|
24802
24802
|
this.#stream = stream;
|
|
24803
|
-
this.#closedPromise = new Promise((
|
|
24804
|
-
this.#abortController.signal.addEventListener("abort", () =>
|
|
24803
|
+
this.#closedPromise = new Promise((resolve20) => {
|
|
24804
|
+
this.#abortController.signal.addEventListener("abort", () => resolve20());
|
|
24805
24805
|
});
|
|
24806
24806
|
this.#receive();
|
|
24807
24807
|
}
|
|
@@ -24950,8 +24950,8 @@ var init_acp = __esm({
|
|
|
24950
24950
|
}
|
|
24951
24951
|
async sendRequest(method, params) {
|
|
24952
24952
|
const id = this.#nextRequestId++;
|
|
24953
|
-
const responsePromise = new Promise((
|
|
24954
|
-
this.#pendingResponses.set(id, { resolve:
|
|
24953
|
+
const responsePromise = new Promise((resolve20, reject) => {
|
|
24954
|
+
this.#pendingResponses.set(id, { resolve: resolve20, reject });
|
|
24955
24955
|
});
|
|
24956
24956
|
await this.#sendMessage({ jsonrpc: "2.0", id, method, params });
|
|
24957
24957
|
return responsePromise;
|
|
@@ -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.31".length > 0 ? "0.1.31" : "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";
|
|
@@ -25072,7 +25072,7 @@ var DEFAULT_FIREHOSE_URL = "https://buildautomaton-firehose.fly.dev";
|
|
|
25072
25072
|
|
|
25073
25073
|
// src/cli/run-cli-action.ts
|
|
25074
25074
|
import * as fs37 from "node:fs";
|
|
25075
|
-
import * as
|
|
25075
|
+
import * as path42 from "node:path";
|
|
25076
25076
|
|
|
25077
25077
|
// src/cli-log-level.ts
|
|
25078
25078
|
var verbosity = "info";
|
|
@@ -26077,14 +26077,14 @@ var baseOpen = async (options) => {
|
|
|
26077
26077
|
}
|
|
26078
26078
|
const subprocess = childProcess.spawn(command, cliArguments, childProcessOptions);
|
|
26079
26079
|
if (options.wait) {
|
|
26080
|
-
return new Promise((
|
|
26080
|
+
return new Promise((resolve20, reject) => {
|
|
26081
26081
|
subprocess.once("error", reject);
|
|
26082
26082
|
subprocess.once("close", (exitCode) => {
|
|
26083
26083
|
if (!options.allowNonzeroExitCode && exitCode > 0) {
|
|
26084
26084
|
reject(new Error(`Exited with code ${exitCode}`));
|
|
26085
26085
|
return;
|
|
26086
26086
|
}
|
|
26087
|
-
|
|
26087
|
+
resolve20(subprocess);
|
|
26088
26088
|
});
|
|
26089
26089
|
});
|
|
26090
26090
|
}
|
|
@@ -26573,8 +26573,8 @@ function runPendingAuth(options) {
|
|
|
26573
26573
|
let hasOpenedBrowser = false;
|
|
26574
26574
|
let resolved = false;
|
|
26575
26575
|
let resolveAuth;
|
|
26576
|
-
const authPromise = new Promise((
|
|
26577
|
-
resolveAuth =
|
|
26576
|
+
const authPromise = new Promise((resolve20) => {
|
|
26577
|
+
resolveAuth = resolve20;
|
|
26578
26578
|
});
|
|
26579
26579
|
let reconnectAttempt = 0;
|
|
26580
26580
|
const signInQuiet = createEmptyReconnectQuietSlot();
|
|
@@ -26929,6 +26929,16 @@ function recordMigrationAndPruneCheckpointLegacy(db, migration, applied2) {
|
|
|
26929
26929
|
}
|
|
26930
26930
|
var CHECKPOINT_V1 = "001_cli_sqlite_checkpoint_v1";
|
|
26931
26931
|
var CHECKPOINT_V1_SQL = readCliSqliteMigrationSql("001_cli_sqlite_checkpoint_v1.sql");
|
|
26932
|
+
var AGENT_CAPABILITIES_SQL = readCliSqliteMigrationSql("002_agent_capabilities.sql");
|
|
26933
|
+
function agentCapabilitiesTableState(db) {
|
|
26934
|
+
const rows = db.all(
|
|
26935
|
+
`SELECT name FROM sqlite_master WHERE type='table' AND name IN ('agent_capabilities', 'agent_capability_cache')`
|
|
26936
|
+
);
|
|
26937
|
+
const names = new Set(rows.map((r) => r.name));
|
|
26938
|
+
if (names.has("agent_capabilities")) return "current";
|
|
26939
|
+
if (names.has("agent_capability_cache")) return "legacy";
|
|
26940
|
+
return "new";
|
|
26941
|
+
}
|
|
26932
26942
|
var CLI_SQLITE_MIGRATIONS = [
|
|
26933
26943
|
{
|
|
26934
26944
|
name: CHECKPOINT_V1,
|
|
@@ -26936,6 +26946,23 @@ var CLI_SQLITE_MIGRATIONS = [
|
|
|
26936
26946
|
migrate: (db) => {
|
|
26937
26947
|
db.exec(CHECKPOINT_V1_SQL);
|
|
26938
26948
|
}
|
|
26949
|
+
},
|
|
26950
|
+
{
|
|
26951
|
+
name: "002_agent_capabilities",
|
|
26952
|
+
migrate: (db) => {
|
|
26953
|
+
const state = agentCapabilitiesTableState(db);
|
|
26954
|
+
if (state === "current") return;
|
|
26955
|
+
if (state === "legacy") {
|
|
26956
|
+
db.exec(`
|
|
26957
|
+
ALTER TABLE agent_capability_cache RENAME TO agent_capabilities;
|
|
26958
|
+
DROP INDEX IF EXISTS idx_agent_capability_cache_workspace;
|
|
26959
|
+
CREATE INDEX IF NOT EXISTS idx_agent_capabilities_workspace ON agent_capabilities(workspace_id);
|
|
26960
|
+
`);
|
|
26961
|
+
return;
|
|
26962
|
+
}
|
|
26963
|
+
db.exec(AGENT_CAPABILITIES_SQL);
|
|
26964
|
+
},
|
|
26965
|
+
alreadyApplied: (db) => agentCapabilitiesTableState(db) === "current"
|
|
26939
26966
|
}
|
|
26940
26967
|
];
|
|
26941
26968
|
function migrateCliSqlite(db) {
|
|
@@ -26964,6 +26991,13 @@ function migrateCliSqlite(db) {
|
|
|
26964
26991
|
|
|
26965
26992
|
// src/sqlite/cli-database.ts
|
|
26966
26993
|
var { Database: SqliteDatabase } = sqliteWasm;
|
|
26994
|
+
function applyCliSqliteMemoryPragmas(db) {
|
|
26995
|
+
try {
|
|
26996
|
+
db.run("PRAGMA cache_size = -8192");
|
|
26997
|
+
db.run("PRAGMA temp_store = FILE");
|
|
26998
|
+
} catch {
|
|
26999
|
+
}
|
|
27000
|
+
}
|
|
26967
27001
|
var openDatabases = /* @__PURE__ */ new Map();
|
|
26968
27002
|
var processExitCloseRegistered = false;
|
|
26969
27003
|
function registerProcessExitSqliteClose() {
|
|
@@ -27000,6 +27034,7 @@ function getCliDatabase(options) {
|
|
|
27000
27034
|
ensureCliSqliteParentDir(sqlitePath);
|
|
27001
27035
|
const db = new SqliteDatabase(sqlitePath);
|
|
27002
27036
|
try {
|
|
27037
|
+
applyCliSqliteMemoryPragmas(db);
|
|
27003
27038
|
migrateCliSqlite(db);
|
|
27004
27039
|
importCliSqliteLegacyDiskData(db, options?.logLegacyMigration);
|
|
27005
27040
|
} catch (e) {
|
|
@@ -27015,7 +27050,7 @@ function getCliDatabase(options) {
|
|
|
27015
27050
|
async function closeBridgeConnection(state, acpManager, devServerManager, log2) {
|
|
27016
27051
|
const say = log2 ?? logImmediate;
|
|
27017
27052
|
say("Cleaning up connections\u2026");
|
|
27018
|
-
await new Promise((
|
|
27053
|
+
await new Promise((resolve20) => setImmediate(resolve20));
|
|
27019
27054
|
state.closedByUser = true;
|
|
27020
27055
|
clearReconnectQuietTimer(state.mainQuiet);
|
|
27021
27056
|
clearReconnectQuietTimer(state.firehoseQuiet);
|
|
@@ -27403,9 +27438,9 @@ function parseChangeSummaryJson(raw, allowedPaths, options) {
|
|
|
27403
27438
|
const rawPath = typeof o.path === "string" ? o.path.trim() : "";
|
|
27404
27439
|
const summary = typeof o.summary === "string" ? o.summary.trim() : "";
|
|
27405
27440
|
if (!rawPath || !summary) continue;
|
|
27406
|
-
const
|
|
27407
|
-
if (!
|
|
27408
|
-
rows.push({ path:
|
|
27441
|
+
const path43 = skip ? normalizeRepoRelativePath(rawPath) || rawPath : resolveChangeSummaryPathAgainstAllowed(rawPath, allowedPaths);
|
|
27442
|
+
if (!path43) continue;
|
|
27443
|
+
rows.push({ path: path43, summary: clampSummaryToAtMostTwoLines(summary) });
|
|
27409
27444
|
}
|
|
27410
27445
|
return rows;
|
|
27411
27446
|
}
|
|
@@ -27615,6 +27650,7 @@ function buildCliAutoApprovedPermissionRpcResult(requestParams) {
|
|
|
27615
27650
|
// ../types/src/agent-config.ts
|
|
27616
27651
|
var AGENT_CONFIG_CLAUDE_PERMISSION_MODE_KEY = "claude_permission_mode";
|
|
27617
27652
|
var AGENT_CONFIG_CLI_PERMISSION_MODE_KEY = "cli_permission_mode";
|
|
27653
|
+
var AGENT_CONFIG_AGENT_MODEL_KEY = "agent_model";
|
|
27618
27654
|
function getClaudePermissionModeFromAgentConfig(config2) {
|
|
27619
27655
|
if (!config2) return null;
|
|
27620
27656
|
const raw = config2[AGENT_CONFIG_CLAUDE_PERMISSION_MODE_KEY];
|
|
@@ -27626,6 +27662,13 @@ function getCliPermissionModeFromAgentConfig(config2) {
|
|
|
27626
27662
|
if (!config2) return CLI_PERMISSION_MODE_DEFAULT;
|
|
27627
27663
|
return normalizeCliPermissionModeInput(config2[AGENT_CONFIG_CLI_PERMISSION_MODE_KEY]);
|
|
27628
27664
|
}
|
|
27665
|
+
function getAgentModelFromAgentConfig(config2) {
|
|
27666
|
+
if (!config2) return null;
|
|
27667
|
+
const cur = config2[AGENT_CONFIG_AGENT_MODEL_KEY];
|
|
27668
|
+
if (typeof cur !== "string") return null;
|
|
27669
|
+
const t = cur.trim();
|
|
27670
|
+
return t !== "" ? t : null;
|
|
27671
|
+
}
|
|
27629
27672
|
|
|
27630
27673
|
// src/git/session-git-queue.ts
|
|
27631
27674
|
import { execFile as execFile7 } from "node:child_process";
|
|
@@ -27680,8 +27723,8 @@ function pathspec(...paths) {
|
|
|
27680
27723
|
cache.set(key, paths);
|
|
27681
27724
|
return key;
|
|
27682
27725
|
}
|
|
27683
|
-
function isPathSpec(
|
|
27684
|
-
return
|
|
27726
|
+
function isPathSpec(path43) {
|
|
27727
|
+
return path43 instanceof String && cache.has(path43);
|
|
27685
27728
|
}
|
|
27686
27729
|
function toPaths(pathSpec) {
|
|
27687
27730
|
return cache.get(pathSpec) || [];
|
|
@@ -27770,8 +27813,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
|
|
|
27770
27813
|
function forEachLineWithContent(input, callback) {
|
|
27771
27814
|
return toLinesWithContent(input, true).map((line) => callback(line));
|
|
27772
27815
|
}
|
|
27773
|
-
function folderExists(
|
|
27774
|
-
return (0, import_file_exists.exists)(
|
|
27816
|
+
function folderExists(path43) {
|
|
27817
|
+
return (0, import_file_exists.exists)(path43, import_file_exists.FOLDER);
|
|
27775
27818
|
}
|
|
27776
27819
|
function append(target, item) {
|
|
27777
27820
|
if (Array.isArray(target)) {
|
|
@@ -28175,8 +28218,8 @@ function checkIsRepoRootTask() {
|
|
|
28175
28218
|
commands,
|
|
28176
28219
|
format: "utf-8",
|
|
28177
28220
|
onError,
|
|
28178
|
-
parser(
|
|
28179
|
-
return /^\.(git)?$/.test(
|
|
28221
|
+
parser(path43) {
|
|
28222
|
+
return /^\.(git)?$/.test(path43.trim());
|
|
28180
28223
|
}
|
|
28181
28224
|
};
|
|
28182
28225
|
}
|
|
@@ -28610,11 +28653,11 @@ function parseGrep(grep) {
|
|
|
28610
28653
|
const paths = /* @__PURE__ */ new Set();
|
|
28611
28654
|
const results = {};
|
|
28612
28655
|
forEachLineWithContent(grep, (input) => {
|
|
28613
|
-
const [
|
|
28614
|
-
paths.add(
|
|
28615
|
-
(results[
|
|
28656
|
+
const [path43, line, preview] = input.split(NULL);
|
|
28657
|
+
paths.add(path43);
|
|
28658
|
+
(results[path43] = results[path43] || []).push({
|
|
28616
28659
|
line: asNumber(line),
|
|
28617
|
-
path:
|
|
28660
|
+
path: path43,
|
|
28618
28661
|
preview
|
|
28619
28662
|
});
|
|
28620
28663
|
});
|
|
@@ -29379,14 +29422,14 @@ var init_hash_object = __esm2({
|
|
|
29379
29422
|
init_task();
|
|
29380
29423
|
}
|
|
29381
29424
|
});
|
|
29382
|
-
function parseInit(bare,
|
|
29425
|
+
function parseInit(bare, path43, text) {
|
|
29383
29426
|
const response = String(text).trim();
|
|
29384
29427
|
let result;
|
|
29385
29428
|
if (result = initResponseRegex.exec(response)) {
|
|
29386
|
-
return new InitSummary(bare,
|
|
29429
|
+
return new InitSummary(bare, path43, false, result[1]);
|
|
29387
29430
|
}
|
|
29388
29431
|
if (result = reInitResponseRegex.exec(response)) {
|
|
29389
|
-
return new InitSummary(bare,
|
|
29432
|
+
return new InitSummary(bare, path43, true, result[1]);
|
|
29390
29433
|
}
|
|
29391
29434
|
let gitDir = "";
|
|
29392
29435
|
const tokens = response.split(" ");
|
|
@@ -29397,7 +29440,7 @@ function parseInit(bare, path41, text) {
|
|
|
29397
29440
|
break;
|
|
29398
29441
|
}
|
|
29399
29442
|
}
|
|
29400
|
-
return new InitSummary(bare,
|
|
29443
|
+
return new InitSummary(bare, path43, /^re/i.test(response), gitDir);
|
|
29401
29444
|
}
|
|
29402
29445
|
var InitSummary;
|
|
29403
29446
|
var initResponseRegex;
|
|
@@ -29406,9 +29449,9 @@ var init_InitSummary = __esm2({
|
|
|
29406
29449
|
"src/lib/responses/InitSummary.ts"() {
|
|
29407
29450
|
"use strict";
|
|
29408
29451
|
InitSummary = class {
|
|
29409
|
-
constructor(bare,
|
|
29452
|
+
constructor(bare, path43, existing, gitDir) {
|
|
29410
29453
|
this.bare = bare;
|
|
29411
|
-
this.path =
|
|
29454
|
+
this.path = path43;
|
|
29412
29455
|
this.existing = existing;
|
|
29413
29456
|
this.gitDir = gitDir;
|
|
29414
29457
|
}
|
|
@@ -29420,7 +29463,7 @@ var init_InitSummary = __esm2({
|
|
|
29420
29463
|
function hasBareCommand(command) {
|
|
29421
29464
|
return command.includes(bareCommand);
|
|
29422
29465
|
}
|
|
29423
|
-
function initTask(bare = false,
|
|
29466
|
+
function initTask(bare = false, path43, customArgs) {
|
|
29424
29467
|
const commands = ["init", ...customArgs];
|
|
29425
29468
|
if (bare && !hasBareCommand(commands)) {
|
|
29426
29469
|
commands.splice(1, 0, bareCommand);
|
|
@@ -29429,7 +29472,7 @@ function initTask(bare = false, path41, customArgs) {
|
|
|
29429
29472
|
commands,
|
|
29430
29473
|
format: "utf-8",
|
|
29431
29474
|
parser(text) {
|
|
29432
|
-
return parseInit(commands.includes("--bare"),
|
|
29475
|
+
return parseInit(commands.includes("--bare"), path43, text);
|
|
29433
29476
|
}
|
|
29434
29477
|
};
|
|
29435
29478
|
}
|
|
@@ -30245,12 +30288,12 @@ var init_FileStatusSummary = __esm2({
|
|
|
30245
30288
|
"use strict";
|
|
30246
30289
|
fromPathRegex = /^(.+)\0(.+)$/;
|
|
30247
30290
|
FileStatusSummary = class {
|
|
30248
|
-
constructor(
|
|
30249
|
-
this.path =
|
|
30291
|
+
constructor(path43, index, working_dir) {
|
|
30292
|
+
this.path = path43;
|
|
30250
30293
|
this.index = index;
|
|
30251
30294
|
this.working_dir = working_dir;
|
|
30252
30295
|
if (index === "R" || working_dir === "R") {
|
|
30253
|
-
const detail = fromPathRegex.exec(
|
|
30296
|
+
const detail = fromPathRegex.exec(path43) || [null, path43, path43];
|
|
30254
30297
|
this.from = detail[2] || "";
|
|
30255
30298
|
this.path = detail[1] || "";
|
|
30256
30299
|
}
|
|
@@ -30281,14 +30324,14 @@ function splitLine(result, lineStr) {
|
|
|
30281
30324
|
default:
|
|
30282
30325
|
return;
|
|
30283
30326
|
}
|
|
30284
|
-
function data(index, workingDir,
|
|
30327
|
+
function data(index, workingDir, path43) {
|
|
30285
30328
|
const raw = `${index}${workingDir}`;
|
|
30286
30329
|
const handler = parsers6.get(raw);
|
|
30287
30330
|
if (handler) {
|
|
30288
|
-
handler(result,
|
|
30331
|
+
handler(result, path43);
|
|
30289
30332
|
}
|
|
30290
30333
|
if (raw !== "##" && raw !== "!!") {
|
|
30291
|
-
result.files.push(new FileStatusSummary(
|
|
30334
|
+
result.files.push(new FileStatusSummary(path43, index, workingDir));
|
|
30292
30335
|
}
|
|
30293
30336
|
}
|
|
30294
30337
|
}
|
|
@@ -30597,9 +30640,9 @@ var init_simple_git_api = __esm2({
|
|
|
30597
30640
|
next
|
|
30598
30641
|
);
|
|
30599
30642
|
}
|
|
30600
|
-
hashObject(
|
|
30643
|
+
hashObject(path43, write) {
|
|
30601
30644
|
return this._runTask(
|
|
30602
|
-
hashObjectTask(
|
|
30645
|
+
hashObjectTask(path43, write === true),
|
|
30603
30646
|
trailingFunctionArgument(arguments)
|
|
30604
30647
|
);
|
|
30605
30648
|
}
|
|
@@ -30952,8 +30995,8 @@ var init_branch = __esm2({
|
|
|
30952
30995
|
}
|
|
30953
30996
|
});
|
|
30954
30997
|
function toPath(input) {
|
|
30955
|
-
const
|
|
30956
|
-
return
|
|
30998
|
+
const path43 = input.trim().replace(/^["']|["']$/g, "");
|
|
30999
|
+
return path43 && normalize(path43);
|
|
30957
31000
|
}
|
|
30958
31001
|
var parseCheckIgnore;
|
|
30959
31002
|
var init_CheckIgnore = __esm2({
|
|
@@ -31267,8 +31310,8 @@ __export2(sub_module_exports, {
|
|
|
31267
31310
|
subModuleTask: () => subModuleTask,
|
|
31268
31311
|
updateSubModuleTask: () => updateSubModuleTask
|
|
31269
31312
|
});
|
|
31270
|
-
function addSubModuleTask(repo,
|
|
31271
|
-
return subModuleTask(["add", repo,
|
|
31313
|
+
function addSubModuleTask(repo, path43) {
|
|
31314
|
+
return subModuleTask(["add", repo, path43]);
|
|
31272
31315
|
}
|
|
31273
31316
|
function initSubModuleTask(customArgs) {
|
|
31274
31317
|
return subModuleTask(["init", ...customArgs]);
|
|
@@ -31601,8 +31644,8 @@ var require_git = __commonJS2({
|
|
|
31601
31644
|
}
|
|
31602
31645
|
return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
|
|
31603
31646
|
};
|
|
31604
|
-
Git2.prototype.submoduleAdd = function(repo,
|
|
31605
|
-
return this._runTask(addSubModuleTask2(repo,
|
|
31647
|
+
Git2.prototype.submoduleAdd = function(repo, path43, then) {
|
|
31648
|
+
return this._runTask(addSubModuleTask2(repo, path43), trailingFunctionArgument2(arguments));
|
|
31606
31649
|
};
|
|
31607
31650
|
Git2.prototype.submoduleUpdate = function(args, then) {
|
|
31608
31651
|
return this._runTask(
|
|
@@ -32489,9 +32532,9 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
|
|
|
32489
32532
|
// src/agents/acp/put-summarize-change-summaries.ts
|
|
32490
32533
|
async function putEncryptedChangeSummaryRows(params) {
|
|
32491
32534
|
const base = params.apiBaseUrl.replace(/\/+$/, "");
|
|
32492
|
-
const entries = params.rows.map(({ path:
|
|
32535
|
+
const entries = params.rows.map(({ path: path43, summary }) => {
|
|
32493
32536
|
const enc = params.e2ee.encryptFields({ summary }, ["summary"]);
|
|
32494
|
-
return { path:
|
|
32537
|
+
return { path: path43, summary: JSON.stringify(enc) };
|
|
32495
32538
|
});
|
|
32496
32539
|
const res = await fetch(
|
|
32497
32540
|
`${base}/api/sessions/${encodeURIComponent(params.sessionId)}/follow-ups/summarize-changes`,
|
|
@@ -33125,6 +33168,48 @@ async function applyClaudePermissionFromAcpSession(params) {
|
|
|
33125
33168
|
}
|
|
33126
33169
|
}
|
|
33127
33170
|
|
|
33171
|
+
// src/agents/acp/apply-acp-model-from-agent-session.ts
|
|
33172
|
+
function flattenSelectOptions2(options) {
|
|
33173
|
+
if (options == null || options.length === 0) return [];
|
|
33174
|
+
const first2 = options[0];
|
|
33175
|
+
if (first2 != null && typeof first2 === "object" && "group" in first2 && first2.group != null) {
|
|
33176
|
+
return options.flatMap((g) => Array.isArray(g.options) ? g.options : []);
|
|
33177
|
+
}
|
|
33178
|
+
return options;
|
|
33179
|
+
}
|
|
33180
|
+
function looksLikeModelOption(o) {
|
|
33181
|
+
if (o.category === "model" || o.category === "models") return true;
|
|
33182
|
+
const id = typeof o.id === "string" ? o.id.toLowerCase() : "";
|
|
33183
|
+
if (id === "model" || id.endsWith("_model") || id.includes("model")) return true;
|
|
33184
|
+
const name = typeof o.name === "string" ? o.name.toLowerCase() : "";
|
|
33185
|
+
return name.includes("model") && !name.includes("mode");
|
|
33186
|
+
}
|
|
33187
|
+
function pickModelConfigOption(configOptions) {
|
|
33188
|
+
if (configOptions == null || configOptions.length === 0) return null;
|
|
33189
|
+
return configOptions.find(looksLikeModelOption) ?? null;
|
|
33190
|
+
}
|
|
33191
|
+
async function applyAcpModelFromAcpSession(params) {
|
|
33192
|
+
const { sessionId, agentConfig, configOptions, setSessionConfigOption, logDebug: logDebug2 } = params;
|
|
33193
|
+
const desired = getAgentModelFromAgentConfig(agentConfig);
|
|
33194
|
+
if (desired == null) return;
|
|
33195
|
+
const modelOpt = pickModelConfigOption(configOptions ?? null);
|
|
33196
|
+
if (modelOpt == null) return;
|
|
33197
|
+
const flat = flattenSelectOptions2(modelOpt.options);
|
|
33198
|
+
const allowed = flat.some((o) => o.value === desired);
|
|
33199
|
+
if (!allowed) return;
|
|
33200
|
+
if (modelOpt.currentValue === desired) return;
|
|
33201
|
+
try {
|
|
33202
|
+
logDebug2(
|
|
33203
|
+
`[Agent] ACP session/set_config_option (model) configId=${JSON.stringify(modelOpt.id)} value=${JSON.stringify(desired)} was=${JSON.stringify(modelOpt.currentValue)} sessionId=${sessionId.slice(0, 8)}\u2026`
|
|
33204
|
+
);
|
|
33205
|
+
await setSessionConfigOption({ sessionId, configId: modelOpt.id, value: desired });
|
|
33206
|
+
} catch (e) {
|
|
33207
|
+
logDebug2(
|
|
33208
|
+
`[Agent] ACP session/set_config_option (model) failed: ${e instanceof Error ? e.message : String(e)}`
|
|
33209
|
+
);
|
|
33210
|
+
}
|
|
33211
|
+
}
|
|
33212
|
+
|
|
33128
33213
|
// src/agents/acp/clients/shared/config-options-for-permission.ts
|
|
33129
33214
|
function configOptionsForPermission(getActive, established) {
|
|
33130
33215
|
const mem = getActive?.();
|
|
@@ -33217,6 +33302,17 @@ async function bootstrapAcpWireSession(transport, ctx, initializeRequest) {
|
|
|
33217
33302
|
logDebug: ctx.logDebug
|
|
33218
33303
|
});
|
|
33219
33304
|
}
|
|
33305
|
+
const cfgAll = ctx.agentConfig != null && typeof ctx.agentConfig === "object" && !Array.isArray(ctx.agentConfig) ? ctx.agentConfig : null;
|
|
33306
|
+
const configOptionsForModel = established.configOptions;
|
|
33307
|
+
if (transport.setSessionConfigOption) {
|
|
33308
|
+
await applyAcpModelFromAcpSession({
|
|
33309
|
+
sessionId,
|
|
33310
|
+
agentConfig: cfgAll,
|
|
33311
|
+
configOptions: configOptionsForPermission(ctx.getActiveConfigOptions, configOptionsForModel),
|
|
33312
|
+
setSessionConfigOption: (p) => transport.setSessionConfigOption(p),
|
|
33313
|
+
logDebug: ctx.logDebug
|
|
33314
|
+
});
|
|
33315
|
+
}
|
|
33220
33316
|
return established;
|
|
33221
33317
|
}
|
|
33222
33318
|
|
|
@@ -33322,10 +33418,15 @@ async function sendAcpPromptViaTransport(transport, ctx, sessionId, promptText,
|
|
|
33322
33418
|
// src/agents/acp/clients/sdk/sdk-stdio-permission-request-handshake.ts
|
|
33323
33419
|
function awaitSdkStdioPermissionRequestHandshake(params) {
|
|
33324
33420
|
const { requestId, paramsRecord, pending, onRequest } = params;
|
|
33325
|
-
return new Promise((
|
|
33326
|
-
pending.set(requestId, { resolve:
|
|
33421
|
+
return new Promise((resolve20) => {
|
|
33422
|
+
pending.set(requestId, { resolve: resolve20, params: paramsRecord });
|
|
33423
|
+
if (onRequest == null) {
|
|
33424
|
+
pending.delete(requestId);
|
|
33425
|
+
resolve20({ outcome: { outcome: "denied" } });
|
|
33426
|
+
return;
|
|
33427
|
+
}
|
|
33327
33428
|
try {
|
|
33328
|
-
onRequest
|
|
33429
|
+
onRequest({
|
|
33329
33430
|
requestId,
|
|
33330
33431
|
method: "session/request_permission",
|
|
33331
33432
|
params: paramsRecord
|
|
@@ -33387,7 +33488,7 @@ async function createSdkStdioAcpClient(options) {
|
|
|
33387
33488
|
child.once("close", (code, signal) => {
|
|
33388
33489
|
onAgentSubprocessExit?.({ code, signal });
|
|
33389
33490
|
});
|
|
33390
|
-
return new Promise((
|
|
33491
|
+
return new Promise((resolve20, reject) => {
|
|
33391
33492
|
let initSettled = false;
|
|
33392
33493
|
const settleReject = (err) => {
|
|
33393
33494
|
if (initSettled) return;
|
|
@@ -33401,7 +33502,7 @@ async function createSdkStdioAcpClient(options) {
|
|
|
33401
33502
|
const settleResolve = (handle) => {
|
|
33402
33503
|
if (initSettled) return;
|
|
33403
33504
|
initSettled = true;
|
|
33404
|
-
|
|
33505
|
+
resolve20(handle);
|
|
33405
33506
|
};
|
|
33406
33507
|
child.on("error", (err) => {
|
|
33407
33508
|
settleReject(new Error(formatSpawnError(err, command[0])));
|
|
@@ -33693,7 +33794,7 @@ async function createCursorAcpClient(options) {
|
|
|
33693
33794
|
logDebug,
|
|
33694
33795
|
getStderrText: () => stderrCapture.getText()
|
|
33695
33796
|
};
|
|
33696
|
-
return new Promise((
|
|
33797
|
+
return new Promise((resolve20, reject) => {
|
|
33697
33798
|
child.on("error", (err) => {
|
|
33698
33799
|
child.kill();
|
|
33699
33800
|
reject(new Error(formatSpawnError2(err, command[0])));
|
|
@@ -33772,12 +33873,16 @@ async function createCursorAcpClient(options) {
|
|
|
33772
33873
|
}
|
|
33773
33874
|
if (method === "session/request_permission" && typeof id === "number") {
|
|
33774
33875
|
const params = msg.params ?? {};
|
|
33775
|
-
|
|
33776
|
-
|
|
33777
|
-
|
|
33778
|
-
|
|
33779
|
-
|
|
33780
|
-
|
|
33876
|
+
if (onRequest) {
|
|
33877
|
+
pendingRequests.set(id, { method, params });
|
|
33878
|
+
onRequest({
|
|
33879
|
+
requestId: String(id),
|
|
33880
|
+
method,
|
|
33881
|
+
params
|
|
33882
|
+
});
|
|
33883
|
+
} else {
|
|
33884
|
+
respond(id, { outcome: { outcome: "denied" } });
|
|
33885
|
+
}
|
|
33781
33886
|
return;
|
|
33782
33887
|
}
|
|
33783
33888
|
if (typeof id === "number" && method) {
|
|
@@ -33865,7 +33970,7 @@ async function createCursorAcpClient(options) {
|
|
|
33865
33970
|
clientInfo: { name: "buildautomaton-cli", version: "0.1.0" }
|
|
33866
33971
|
});
|
|
33867
33972
|
const sessionId = established.sessionId;
|
|
33868
|
-
|
|
33973
|
+
resolve20({
|
|
33869
33974
|
sessionId,
|
|
33870
33975
|
async sendPrompt(prompt, options2) {
|
|
33871
33976
|
const imgs = options2?.images?.map((im) => ({ type: "image", mimeType: im.mimeType, data: im.dataBase64 }));
|
|
@@ -34573,6 +34678,28 @@ function sendGitHeadVsWorkspaceForToolPaths(mergedPaths, sentPaths, send, sessio
|
|
|
34573
34678
|
}
|
|
34574
34679
|
}
|
|
34575
34680
|
|
|
34681
|
+
// src/agents/acp/hooks/bridge-on-session-update/send-session-info-title-update.ts
|
|
34682
|
+
function extractSessionInfoTitle(params) {
|
|
34683
|
+
if (!params || typeof params !== "object") return null;
|
|
34684
|
+
const p = params;
|
|
34685
|
+
const title = typeof p.title === "string" ? p.title.trim() : "";
|
|
34686
|
+
return title ? title : null;
|
|
34687
|
+
}
|
|
34688
|
+
function sendSessionInfoTitleUpdate(params) {
|
|
34689
|
+
const title = extractSessionInfoTitle(params.payload);
|
|
34690
|
+
if (!title || !params.runId || !params.send) return;
|
|
34691
|
+
try {
|
|
34692
|
+
params.send({
|
|
34693
|
+
type: "session_title_update",
|
|
34694
|
+
...params.sessionId ? { sessionId: params.sessionId } : {},
|
|
34695
|
+
runId: params.runId,
|
|
34696
|
+
title
|
|
34697
|
+
});
|
|
34698
|
+
} catch (err) {
|
|
34699
|
+
params.log(`[Bridge service] Session title update send failed: ${errorMessage(err)}`);
|
|
34700
|
+
}
|
|
34701
|
+
}
|
|
34702
|
+
|
|
34576
34703
|
// src/agents/acp/hooks/bridge-on-session-update/create-bridge-on-session-update.ts
|
|
34577
34704
|
function createBridgeOnSessionUpdate(opts) {
|
|
34578
34705
|
const { routing, getSendSessionUpdate, log: log2, sessionParentPath } = opts;
|
|
@@ -34588,6 +34715,10 @@ function createBridgeOnSessionUpdate(opts) {
|
|
|
34588
34715
|
if (updateKind === "config_option_update") {
|
|
34589
34716
|
return;
|
|
34590
34717
|
}
|
|
34718
|
+
if (updateKind === "session_info_update") {
|
|
34719
|
+
sendSessionInfoTitleUpdate({ payload: params, runId, sessionId, send, log: log2 });
|
|
34720
|
+
return;
|
|
34721
|
+
}
|
|
34591
34722
|
const isCompletedToolCallUpdate = updateKind === "tool_call_update" && isCompletedToolStatus(p.status);
|
|
34592
34723
|
const toolName = p.toolCall?.name ?? p.tool_call?.name ?? "";
|
|
34593
34724
|
const isToolUpdate = updateKind === "tool_call" || updateKind === "tool_call_update" || typeof toolName === "string" && toolName.length > 0;
|
|
@@ -34745,6 +34876,7 @@ async function ensureAcpClient(options) {
|
|
|
34745
34876
|
sessionParentPath,
|
|
34746
34877
|
routing,
|
|
34747
34878
|
cloudSessionId,
|
|
34879
|
+
reportAgentCapabilities,
|
|
34748
34880
|
sendSessionUpdate,
|
|
34749
34881
|
sendRequest,
|
|
34750
34882
|
log: log2
|
|
@@ -34832,6 +34964,12 @@ async function ensureAcpClient(options) {
|
|
|
34832
34964
|
backendAgentType: preferredAgentType
|
|
34833
34965
|
});
|
|
34834
34966
|
}
|
|
34967
|
+
if (reportAgentCapabilities && preferredAgentType && Array.isArray(info.configOptions) && info.configOptions.length > 0) {
|
|
34968
|
+
reportAgentCapabilities({
|
|
34969
|
+
agentType: preferredAgentType,
|
|
34970
|
+
configOptions: info.configOptions
|
|
34971
|
+
});
|
|
34972
|
+
}
|
|
34835
34973
|
},
|
|
34836
34974
|
onAcpConfigOptionsUpdated: (configOptions) => {
|
|
34837
34975
|
state.activeSessionConfigOptions = configOptions;
|
|
@@ -34841,6 +34979,12 @@ async function ensureAcpClient(options) {
|
|
|
34841
34979
|
backendAgentType: preferredAgentType
|
|
34842
34980
|
});
|
|
34843
34981
|
}
|
|
34982
|
+
if (reportAgentCapabilities && preferredAgentType && Array.isArray(configOptions) && configOptions.length > 0) {
|
|
34983
|
+
reportAgentCapabilities({
|
|
34984
|
+
agentType: preferredAgentType,
|
|
34985
|
+
configOptions
|
|
34986
|
+
});
|
|
34987
|
+
}
|
|
34844
34988
|
},
|
|
34845
34989
|
onAgentSubprocessExit: () => {
|
|
34846
34990
|
state.acpHandle = null;
|
|
@@ -34871,7 +35015,7 @@ async function ensureAcpClient(options) {
|
|
|
34871
35015
|
|
|
34872
35016
|
// src/agents/acp/create-acp-manager.ts
|
|
34873
35017
|
async function createAcpManager(options) {
|
|
34874
|
-
const { log: log2 } = options;
|
|
35018
|
+
const { log: log2, reportAgentCapabilities } = options;
|
|
34875
35019
|
const state = {
|
|
34876
35020
|
acpHandle: null,
|
|
34877
35021
|
acpStartPromise: null,
|
|
@@ -34915,7 +35059,8 @@ async function createAcpManager(options) {
|
|
|
34915
35059
|
cloudApiBaseUrl,
|
|
34916
35060
|
getCloudAccessToken,
|
|
34917
35061
|
e2ee,
|
|
34918
|
-
attachments
|
|
35062
|
+
attachments,
|
|
35063
|
+
agentId
|
|
34919
35064
|
} = opts;
|
|
34920
35065
|
const preferredForPrompt = agentType ?? backendFallbackAgentType ?? null;
|
|
34921
35066
|
pendingCancelRunId = void 0;
|
|
@@ -34933,7 +35078,8 @@ async function createAcpManager(options) {
|
|
|
34933
35078
|
cloudSessionId: sessionId,
|
|
34934
35079
|
sendSessionUpdate,
|
|
34935
35080
|
sendRequest: sendSessionUpdate,
|
|
34936
|
-
log: log2
|
|
35081
|
+
log: log2,
|
|
35082
|
+
reportAgentCapabilities
|
|
34937
35083
|
});
|
|
34938
35084
|
if (!handle) {
|
|
34939
35085
|
const errMsg = state.lastAcpStartError || "No agent configured. Register local agents on this bridge in the app.";
|
|
@@ -36300,43 +36446,39 @@ import path29 from "node:path";
|
|
|
36300
36446
|
|
|
36301
36447
|
// src/runtime/yield-to-event-loop.ts
|
|
36302
36448
|
function yieldToEventLoop() {
|
|
36303
|
-
return new Promise((
|
|
36449
|
+
return new Promise((resolve20) => setImmediate(resolve20));
|
|
36304
36450
|
}
|
|
36305
36451
|
|
|
36306
36452
|
// src/files/index/walk-workspace-tree.ts
|
|
36307
36453
|
import fs25 from "node:fs";
|
|
36308
36454
|
import path28 from "node:path";
|
|
36309
|
-
|
|
36455
|
+
function shouldSkipWorkspaceWalkEntry(name) {
|
|
36456
|
+
return name.startsWith(".");
|
|
36457
|
+
}
|
|
36458
|
+
function walkWorkspaceTreeSync(dir, baseDir, onFile) {
|
|
36310
36459
|
let names;
|
|
36311
36460
|
try {
|
|
36312
|
-
names =
|
|
36461
|
+
names = fs25.readdirSync(dir);
|
|
36313
36462
|
} catch {
|
|
36314
36463
|
return;
|
|
36315
36464
|
}
|
|
36316
36465
|
for (const name of names) {
|
|
36317
|
-
if (name
|
|
36318
|
-
if (state.n > 0 && state.n % INDEX_WORK_YIELD_EVERY === 0) {
|
|
36319
|
-
await yieldToEventLoop();
|
|
36320
|
-
}
|
|
36321
|
-
state.n++;
|
|
36466
|
+
if (shouldSkipWorkspaceWalkEntry(name)) continue;
|
|
36322
36467
|
const full = path28.join(dir, name);
|
|
36323
36468
|
let stat3;
|
|
36324
36469
|
try {
|
|
36325
|
-
stat3 =
|
|
36470
|
+
stat3 = fs25.statSync(full);
|
|
36326
36471
|
} catch {
|
|
36327
36472
|
continue;
|
|
36328
36473
|
}
|
|
36329
36474
|
const relative5 = path28.relative(baseDir, full).replace(/\\/g, "/");
|
|
36330
36475
|
if (stat3.isDirectory()) {
|
|
36331
|
-
|
|
36476
|
+
walkWorkspaceTreeSync(full, baseDir, onFile);
|
|
36332
36477
|
} else if (stat3.isFile()) {
|
|
36333
|
-
|
|
36478
|
+
onFile(relative5);
|
|
36334
36479
|
}
|
|
36335
36480
|
}
|
|
36336
36481
|
}
|
|
36337
|
-
function createWalkYieldState() {
|
|
36338
|
-
return { n: 0 };
|
|
36339
|
-
}
|
|
36340
36482
|
|
|
36341
36483
|
// src/files/index/file-index-sqlite-lock.ts
|
|
36342
36484
|
import fs26 from "node:fs";
|
|
@@ -36369,20 +36511,29 @@ function withFileIndexSqliteLock(fn) {
|
|
|
36369
36511
|
}
|
|
36370
36512
|
|
|
36371
36513
|
// src/files/index/build-file-index.ts
|
|
36372
|
-
|
|
36373
|
-
|
|
36374
|
-
}
|
|
36375
|
-
function persistPathsToSqlite(resolved, paths) {
|
|
36514
|
+
var FILE_INDEX_INSERT_BUFFER = 2048;
|
|
36515
|
+
function persistFileIndexForResolvedCwd(resolved) {
|
|
36376
36516
|
const db = getCliDatabase();
|
|
36377
36517
|
const h = getCwdHashForFileIndex(resolved);
|
|
36518
|
+
const buf = [];
|
|
36519
|
+
let pathCount = 0;
|
|
36378
36520
|
db.run("BEGIN IMMEDIATE");
|
|
36379
36521
|
try {
|
|
36380
36522
|
db.run("DELETE FROM file_index_path WHERE cwd_hash = ?", [h]);
|
|
36381
36523
|
const ins = db.prepare("INSERT INTO file_index_path (cwd_hash, path) VALUES (?, ?)");
|
|
36382
36524
|
try {
|
|
36383
|
-
|
|
36384
|
-
|
|
36385
|
-
|
|
36525
|
+
const flushBuf = () => {
|
|
36526
|
+
for (const rel of buf) {
|
|
36527
|
+
ins.run([h, rel]);
|
|
36528
|
+
}
|
|
36529
|
+
pathCount += buf.length;
|
|
36530
|
+
buf.length = 0;
|
|
36531
|
+
};
|
|
36532
|
+
walkWorkspaceTreeSync(resolved, resolved, (rel) => {
|
|
36533
|
+
buf.push(rel);
|
|
36534
|
+
if (buf.length >= FILE_INDEX_INSERT_BUFFER) flushBuf();
|
|
36535
|
+
});
|
|
36536
|
+
flushBuf();
|
|
36386
36537
|
} finally {
|
|
36387
36538
|
ins.finalize();
|
|
36388
36539
|
}
|
|
@@ -36394,22 +36545,26 @@ function persistPathsToSqlite(resolved, paths) {
|
|
|
36394
36545
|
}
|
|
36395
36546
|
throw e;
|
|
36396
36547
|
}
|
|
36548
|
+
return pathCount;
|
|
36397
36549
|
}
|
|
36398
36550
|
async function buildFileIndexAsync(cwd) {
|
|
36399
36551
|
return withFileIndexSqliteLock(async () => {
|
|
36400
36552
|
const resolved = path29.resolve(cwd);
|
|
36401
|
-
const paths = [];
|
|
36402
|
-
await walkWorkspaceTreeAsync(resolved, resolved, paths, createWalkYieldState());
|
|
36403
36553
|
await yieldToEventLoop();
|
|
36404
|
-
|
|
36405
|
-
|
|
36406
|
-
return { pathCount
|
|
36554
|
+
const pathCount = persistFileIndexForResolvedCwd(resolved);
|
|
36555
|
+
await yieldToEventLoop();
|
|
36556
|
+
return { pathCount };
|
|
36407
36557
|
});
|
|
36408
36558
|
}
|
|
36409
36559
|
|
|
36410
36560
|
// src/files/index/ensure-file-index.ts
|
|
36411
36561
|
import path30 from "node:path";
|
|
36412
36562
|
|
|
36563
|
+
// src/files/index/file-index-dependency-path.ts
|
|
36564
|
+
function sqliteExprBridgeFileIndexDependencyRank() {
|
|
36565
|
+
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`;
|
|
36566
|
+
}
|
|
36567
|
+
|
|
36413
36568
|
// src/files/index/search-file-index.ts
|
|
36414
36569
|
function escapeLikePattern(fragment) {
|
|
36415
36570
|
return fragment.replace(/\\/g, "\\\\").replace(/%/g, "\\%").replace(/_/g, "\\_");
|
|
@@ -36434,8 +36589,9 @@ function searchBridgeFilePaths(resolvedCwd, query, limit = 100) {
|
|
|
36434
36589
|
const h = getCwdHashForFileIndex(resolvedCwd);
|
|
36435
36590
|
const pattern = `%${escapeLikePattern(q)}%`;
|
|
36436
36591
|
const lim = Math.max(0, Math.min(1e4, Math.floor(limit)));
|
|
36592
|
+
const depRank = sqliteExprBridgeFileIndexDependencyRank();
|
|
36437
36593
|
const rows = db.all(
|
|
36438
|
-
`SELECT path FROM file_index_path WHERE cwd_hash = ? AND lower(path) LIKE ? ESCAPE '\\' LIMIT ?`,
|
|
36594
|
+
`SELECT path FROM file_index_path WHERE cwd_hash = ? AND lower(path) LIKE ? ESCAPE '\\' ORDER BY ${depRank}, path LIMIT ?`,
|
|
36439
36595
|
[h, pattern, lim]
|
|
36440
36596
|
);
|
|
36441
36597
|
return rows.map((r) => String(r.path));
|
|
@@ -36460,7 +36616,6 @@ async function ensureFileIndexAsync(cwd) {
|
|
|
36460
36616
|
var DEBOUNCE_MS = 900;
|
|
36461
36617
|
function shouldIgnoreRelative(rel) {
|
|
36462
36618
|
const n = rel.replace(/\\/g, "/");
|
|
36463
|
-
if (n.includes("/node_modules/") || n.startsWith("node_modules/")) return true;
|
|
36464
36619
|
if (n.includes("/.git/") || n === ".git" || n.startsWith(".git/")) return true;
|
|
36465
36620
|
if (n.includes("/.buildautomaton/") || n.startsWith(".buildautomaton/")) return true;
|
|
36466
36621
|
return false;
|
|
@@ -36524,7 +36679,7 @@ function startFileIndexWatcher(cwd = getBridgeRoot()) {
|
|
|
36524
36679
|
}
|
|
36525
36680
|
|
|
36526
36681
|
// src/connection/create-bridge-connection.ts
|
|
36527
|
-
import * as
|
|
36682
|
+
import * as path41 from "node:path";
|
|
36528
36683
|
|
|
36529
36684
|
// src/dev-servers/manager/dev-server-manager.ts
|
|
36530
36685
|
import { rm as rm2 } from "node:fs/promises";
|
|
@@ -36546,15 +36701,15 @@ function sendDevServerStatus(getWs, serverId, status, options) {
|
|
|
36546
36701
|
|
|
36547
36702
|
// src/dev-servers/process/terminate-child-process.ts
|
|
36548
36703
|
async function sigtermAndWaitForExit(proc, graceMs, log2, shortId) {
|
|
36549
|
-
const exited = new Promise((
|
|
36550
|
-
proc.once("exit", () =>
|
|
36704
|
+
const exited = new Promise((resolve20) => {
|
|
36705
|
+
proc.once("exit", () => resolve20());
|
|
36551
36706
|
});
|
|
36552
36707
|
log2(`[dev-server] Sending SIGTERM to ${shortId} (pid=${proc.pid ?? "?"}).`);
|
|
36553
36708
|
try {
|
|
36554
36709
|
proc.kill("SIGTERM");
|
|
36555
36710
|
} catch {
|
|
36556
36711
|
}
|
|
36557
|
-
await Promise.race([exited, new Promise((
|
|
36712
|
+
await Promise.race([exited, new Promise((resolve20) => setTimeout(resolve20, graceMs))]);
|
|
36558
36713
|
}
|
|
36559
36714
|
function forceKillChild(proc, log2, shortId, graceMs) {
|
|
36560
36715
|
log2(
|
|
@@ -37437,7 +37592,7 @@ async function proxyToLocal(request) {
|
|
|
37437
37592
|
};
|
|
37438
37593
|
const maxAttempts = isIdempotentProxyMethod(request.method) ? LOCAL_PREVIEW_FETCH_RETRY_DELAYS_MS.length + 1 : 1;
|
|
37439
37594
|
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
|
|
37440
|
-
const once = await new Promise((
|
|
37595
|
+
const once = await new Promise((resolve20) => {
|
|
37441
37596
|
const req = mod.request(opts, (res) => {
|
|
37442
37597
|
const chunks = [];
|
|
37443
37598
|
res.on("data", (c) => chunks.push(c));
|
|
@@ -37448,7 +37603,7 @@ async function proxyToLocal(request) {
|
|
|
37448
37603
|
if (typeof v === "string") headers[k] = v;
|
|
37449
37604
|
else if (Array.isArray(v) && v[0]) headers[k] = v[0];
|
|
37450
37605
|
}
|
|
37451
|
-
|
|
37606
|
+
resolve20({
|
|
37452
37607
|
id: request.id,
|
|
37453
37608
|
statusCode: res.statusCode ?? 0,
|
|
37454
37609
|
headers,
|
|
@@ -37457,7 +37612,7 @@ async function proxyToLocal(request) {
|
|
|
37457
37612
|
});
|
|
37458
37613
|
});
|
|
37459
37614
|
req.on("error", (err) => {
|
|
37460
|
-
|
|
37615
|
+
resolve20({
|
|
37461
37616
|
id: request.id,
|
|
37462
37617
|
statusCode: 0,
|
|
37463
37618
|
headers: {},
|
|
@@ -38076,6 +38231,13 @@ var handleBridgeIdentified = (msg, deps) => {
|
|
|
38076
38231
|
`[Bridge service] Auto-detect agents failed: ${e instanceof Error ? e.message : String(e)}`
|
|
38077
38232
|
);
|
|
38078
38233
|
}
|
|
38234
|
+
try {
|
|
38235
|
+
await deps.warmupAgentCapabilitiesOnConnect?.();
|
|
38236
|
+
} catch (e) {
|
|
38237
|
+
deps.log(
|
|
38238
|
+
`[Bridge service] Agent capability warmup failed: ${e instanceof Error ? e.message : String(e)}`
|
|
38239
|
+
);
|
|
38240
|
+
}
|
|
38079
38241
|
})();
|
|
38080
38242
|
});
|
|
38081
38243
|
setImmediate(() => {
|
|
@@ -38428,9 +38590,9 @@ function parseChangeSummarySnapshots(raw) {
|
|
|
38428
38590
|
for (const item of raw) {
|
|
38429
38591
|
if (!item || typeof item !== "object") continue;
|
|
38430
38592
|
const o = item;
|
|
38431
|
-
const
|
|
38432
|
-
if (!
|
|
38433
|
-
const row = { path:
|
|
38593
|
+
const path43 = typeof o.path === "string" && o.path.trim() !== "" ? o.path.trim() : "";
|
|
38594
|
+
if (!path43) continue;
|
|
38595
|
+
const row = { path: path43 };
|
|
38434
38596
|
if (typeof o.patchContent === "string") row.patchContent = o.patchContent;
|
|
38435
38597
|
if (typeof o.oldText === "string") row.oldText = o.oldText;
|
|
38436
38598
|
if (typeof o.newText === "string") row.newText = o.newText;
|
|
@@ -38548,6 +38710,8 @@ function handleBridgePrompt(msg, deps) {
|
|
|
38548
38710
|
const sessionParent = rawParent === "bridge_root" || rawParent === "worktrees_root" ? rawParent : rawParent === "session_worktrees_root" ? "worktrees_root" : null;
|
|
38549
38711
|
const sessionParentPath = typeof msg.sessionParentPath === "string" && msg.sessionParentPath.trim() ? msg.sessionParentPath.trim() : null;
|
|
38550
38712
|
const agentType = typeof msg.agentType === "string" && msg.agentType.trim() ? msg.agentType.trim() : void 0;
|
|
38713
|
+
const rawAgentId = msg.agentId;
|
|
38714
|
+
const agentId = typeof rawAgentId === "string" && rawAgentId.trim() !== "" ? rawAgentId.trim() : null;
|
|
38551
38715
|
const mode = typeof msg.mode === "string" && msg.mode.trim() ? msg.mode.trim() : void 0;
|
|
38552
38716
|
const agentConfig = msg.agentConfig != null && typeof msg.agentConfig === "object" && !Array.isArray(msg.agentConfig) ? msg.agentConfig : void 0;
|
|
38553
38717
|
acpManager.logPromptReceivedFromBridge({ agentType, mode });
|
|
@@ -38585,6 +38749,7 @@ function handleBridgePrompt(msg, deps) {
|
|
|
38585
38749
|
runId,
|
|
38586
38750
|
mode,
|
|
38587
38751
|
agentType,
|
|
38752
|
+
agentId,
|
|
38588
38753
|
agentConfig,
|
|
38589
38754
|
sessionParentPath: effectiveCwd,
|
|
38590
38755
|
sendResult: sendResult2,
|
|
@@ -38647,8 +38812,8 @@ function randomSecret() {
|
|
|
38647
38812
|
}
|
|
38648
38813
|
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
38649
38814
|
}
|
|
38650
|
-
async function requestPreviewApi(port, secret, method,
|
|
38651
|
-
const url2 = `http://127.0.0.1:${port}${
|
|
38815
|
+
async function requestPreviewApi(port, secret, method, path43, body) {
|
|
38816
|
+
const url2 = `http://127.0.0.1:${port}${path43}`;
|
|
38652
38817
|
const headers = {
|
|
38653
38818
|
[PREVIEW_SECRET_HEADER]: secret,
|
|
38654
38819
|
"Content-Type": "application/json"
|
|
@@ -38660,7 +38825,7 @@ async function requestPreviewApi(port, secret, method, path41, body) {
|
|
|
38660
38825
|
});
|
|
38661
38826
|
const data = await res.json().catch(() => ({}));
|
|
38662
38827
|
if (!res.ok) {
|
|
38663
|
-
throw new Error(data?.error ?? `Preview API ${method} ${
|
|
38828
|
+
throw new Error(data?.error ?? `Preview API ${method} ${path43}: ${res.status}`);
|
|
38664
38829
|
}
|
|
38665
38830
|
return data;
|
|
38666
38831
|
}
|
|
@@ -39774,6 +39939,242 @@ function createBridgeHeartbeatController(params) {
|
|
|
39774
39939
|
};
|
|
39775
39940
|
}
|
|
39776
39941
|
|
|
39942
|
+
// src/sqlite/hash-json-sha256.ts
|
|
39943
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
39944
|
+
function hashJsonUtf8Sha256(value) {
|
|
39945
|
+
return createHash2("sha256").update(JSON.stringify(value), "utf8").digest("hex");
|
|
39946
|
+
}
|
|
39947
|
+
|
|
39948
|
+
// src/sqlite/agent-capability-cache.ts
|
|
39949
|
+
function hasNonEmptyAgentCapabilityCache(db, workspaceId, agentType) {
|
|
39950
|
+
const t = agentType.trim();
|
|
39951
|
+
if (!t) return false;
|
|
39952
|
+
try {
|
|
39953
|
+
const row = db.get(
|
|
39954
|
+
`SELECT config_options_json FROM agent_capabilities WHERE workspace_id = ? AND agent_type = ?`,
|
|
39955
|
+
[workspaceId, t]
|
|
39956
|
+
);
|
|
39957
|
+
if (row?.config_options_json == null || row.config_options_json === "") return false;
|
|
39958
|
+
const parsed = JSON.parse(row.config_options_json);
|
|
39959
|
+
return Array.isArray(parsed) && parsed.length > 0;
|
|
39960
|
+
} catch {
|
|
39961
|
+
return false;
|
|
39962
|
+
}
|
|
39963
|
+
}
|
|
39964
|
+
function upsertCliAgentCapabilityCache(db, row) {
|
|
39965
|
+
const t = row.agentType.trim();
|
|
39966
|
+
if (!t) return false;
|
|
39967
|
+
const hash = hashJsonUtf8Sha256(row.configOptions);
|
|
39968
|
+
try {
|
|
39969
|
+
const prev = db.get(
|
|
39970
|
+
`SELECT content_hash FROM agent_capabilities WHERE workspace_id = ? AND agent_type = ?`,
|
|
39971
|
+
[row.workspaceId, t]
|
|
39972
|
+
);
|
|
39973
|
+
if (prev?.content_hash === hash) return false;
|
|
39974
|
+
} catch {
|
|
39975
|
+
}
|
|
39976
|
+
const json2 = JSON.stringify(row.configOptions);
|
|
39977
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
39978
|
+
db.run(
|
|
39979
|
+
`INSERT INTO agent_capabilities (workspace_id, agent_type, config_options_json, content_hash, updated_at)
|
|
39980
|
+
VALUES (?, ?, ?, ?, ?)
|
|
39981
|
+
ON CONFLICT(workspace_id, agent_type) DO UPDATE SET
|
|
39982
|
+
config_options_json = excluded.config_options_json,
|
|
39983
|
+
content_hash = excluded.content_hash,
|
|
39984
|
+
updated_at = excluded.updated_at`,
|
|
39985
|
+
[row.workspaceId, t, json2, hash, now]
|
|
39986
|
+
);
|
|
39987
|
+
return true;
|
|
39988
|
+
}
|
|
39989
|
+
function listCliAgentCapabilityCacheForWorkspace(db, workspaceId) {
|
|
39990
|
+
const rows = db.all(
|
|
39991
|
+
`SELECT agent_type, config_options_json FROM agent_capabilities WHERE workspace_id = ?`,
|
|
39992
|
+
[workspaceId]
|
|
39993
|
+
);
|
|
39994
|
+
const out = [];
|
|
39995
|
+
for (const r of rows) {
|
|
39996
|
+
try {
|
|
39997
|
+
const parsed = JSON.parse(r.config_options_json);
|
|
39998
|
+
if (!Array.isArray(parsed) || parsed.length === 0) continue;
|
|
39999
|
+
out.push({ agentType: r.agent_type, configOptions: parsed });
|
|
40000
|
+
} catch {
|
|
40001
|
+
}
|
|
40002
|
+
}
|
|
40003
|
+
return out;
|
|
40004
|
+
}
|
|
40005
|
+
|
|
40006
|
+
// src/agents/capabilities/warmup-agent-capabilities-on-connect.ts
|
|
40007
|
+
import * as path40 from "node:path";
|
|
40008
|
+
|
|
40009
|
+
// src/agents/capabilities/probe-one-agent-type-for-capabilities.ts
|
|
40010
|
+
import * as path39 from "node:path";
|
|
40011
|
+
async function probeOneAgentTypeForCapabilities(params) {
|
|
40012
|
+
const { agentType, cwd, workspaceId, log: log2, getDb, reportAgentCapabilities, bridgeReport = true } = params;
|
|
40013
|
+
const resolved = resolveAgentCommand(agentType);
|
|
40014
|
+
if (!resolved) return false;
|
|
40015
|
+
let sqliteChanged = false;
|
|
40016
|
+
const reportedRef = { done: false };
|
|
40017
|
+
const tryReport = (co) => {
|
|
40018
|
+
if (reportedRef.done) return;
|
|
40019
|
+
if (!Array.isArray(co) || co.length === 0) return;
|
|
40020
|
+
reportedRef.done = true;
|
|
40021
|
+
let changed = false;
|
|
40022
|
+
try {
|
|
40023
|
+
changed = upsertCliAgentCapabilityCache(getDb(), {
|
|
40024
|
+
workspaceId,
|
|
40025
|
+
agentType,
|
|
40026
|
+
configOptions: co
|
|
40027
|
+
});
|
|
40028
|
+
} catch {
|
|
40029
|
+
}
|
|
40030
|
+
sqliteChanged ||= changed;
|
|
40031
|
+
if (bridgeReport && changed) {
|
|
40032
|
+
reportAgentCapabilities?.({ agentType, configOptions: co });
|
|
40033
|
+
}
|
|
40034
|
+
};
|
|
40035
|
+
let handle = null;
|
|
40036
|
+
const killTimer = setTimeout(() => {
|
|
40037
|
+
try {
|
|
40038
|
+
handle?.disconnect();
|
|
40039
|
+
} catch {
|
|
40040
|
+
}
|
|
40041
|
+
}, 28e3);
|
|
40042
|
+
killTimer.unref?.();
|
|
40043
|
+
try {
|
|
40044
|
+
handle = await resolved.createClient({
|
|
40045
|
+
command: resolved.command,
|
|
40046
|
+
cwd: path39.resolve(cwd),
|
|
40047
|
+
backendAgentType: agentType,
|
|
40048
|
+
sessionMode: "agent",
|
|
40049
|
+
persistedAcpSessionId: null,
|
|
40050
|
+
agentConfig: null,
|
|
40051
|
+
getActiveConfigOptions: () => null,
|
|
40052
|
+
onAcpSessionEstablished: (info) => {
|
|
40053
|
+
tryReport(info.configOptions ?? null);
|
|
40054
|
+
},
|
|
40055
|
+
onAcpConfigOptionsUpdated: (co) => {
|
|
40056
|
+
tryReport(co);
|
|
40057
|
+
},
|
|
40058
|
+
onAgentSubprocessExit: () => {
|
|
40059
|
+
},
|
|
40060
|
+
onSessionUpdate: () => {
|
|
40061
|
+
}
|
|
40062
|
+
});
|
|
40063
|
+
await new Promise((r) => setTimeout(r, 1200));
|
|
40064
|
+
} catch (e) {
|
|
40065
|
+
log2(
|
|
40066
|
+
`[Bridge service] Agent capability probe (${agentType}): ${e instanceof Error ? e.message : String(e)}`
|
|
40067
|
+
);
|
|
40068
|
+
} finally {
|
|
40069
|
+
clearTimeout(killTimer);
|
|
40070
|
+
try {
|
|
40071
|
+
handle?.disconnect();
|
|
40072
|
+
} catch {
|
|
40073
|
+
}
|
|
40074
|
+
}
|
|
40075
|
+
return sqliteChanged;
|
|
40076
|
+
}
|
|
40077
|
+
|
|
40078
|
+
// src/agents/capabilities/probe-agent-capabilities-for-types.ts
|
|
40079
|
+
async function probeAgentCapabilitiesForDetectedTypes(params) {
|
|
40080
|
+
const {
|
|
40081
|
+
agentTypes,
|
|
40082
|
+
cwd,
|
|
40083
|
+
workspaceId,
|
|
40084
|
+
log: log2,
|
|
40085
|
+
getDb,
|
|
40086
|
+
reportAgentCapabilities,
|
|
40087
|
+
bridgeReport = true,
|
|
40088
|
+
forceAllTypes = false
|
|
40089
|
+
} = params;
|
|
40090
|
+
let changedCount = 0;
|
|
40091
|
+
for (let i = 0; i < agentTypes.length; i++) {
|
|
40092
|
+
if (i > 0) await yieldToEventLoop();
|
|
40093
|
+
const agentType = agentTypes[i];
|
|
40094
|
+
if (!agentType.trim()) continue;
|
|
40095
|
+
if (!forceAllTypes) {
|
|
40096
|
+
try {
|
|
40097
|
+
if (process.env.BUILDAUTOMATON_FORCE_PROBE_ACP_CAPABILITIES !== "1" && hasNonEmptyAgentCapabilityCache(getDb(), workspaceId, agentType)) {
|
|
40098
|
+
continue;
|
|
40099
|
+
}
|
|
40100
|
+
} catch {
|
|
40101
|
+
}
|
|
40102
|
+
}
|
|
40103
|
+
const changed = await probeOneAgentTypeForCapabilities({
|
|
40104
|
+
agentType,
|
|
40105
|
+
cwd,
|
|
40106
|
+
workspaceId,
|
|
40107
|
+
log: log2,
|
|
40108
|
+
getDb,
|
|
40109
|
+
reportAgentCapabilities,
|
|
40110
|
+
bridgeReport
|
|
40111
|
+
});
|
|
40112
|
+
if (changed) changedCount += 1;
|
|
40113
|
+
}
|
|
40114
|
+
return changedCount;
|
|
40115
|
+
}
|
|
40116
|
+
|
|
40117
|
+
// src/agents/capabilities/warmup-agent-capabilities-on-connect.ts
|
|
40118
|
+
async function warmupAgentCapabilitiesOnConnect(params) {
|
|
40119
|
+
const { workspaceId, log: log2, getDb, getWs } = params;
|
|
40120
|
+
const cwd = path40.resolve(getBridgeRoot());
|
|
40121
|
+
const db = getDb();
|
|
40122
|
+
function sendBatchFromCache() {
|
|
40123
|
+
const socket = getWs();
|
|
40124
|
+
if (!socket || socket.readyState !== wrapper_default.OPEN) return;
|
|
40125
|
+
try {
|
|
40126
|
+
const rows = listCliAgentCapabilityCacheForWorkspace(db, workspaceId);
|
|
40127
|
+
if (rows.length === 0) return;
|
|
40128
|
+
sendWsMessage(socket, {
|
|
40129
|
+
type: "agent_capabilities_batch",
|
|
40130
|
+
items: rows.map((r) => ({ agentType: r.agentType, configOptions: r.configOptions }))
|
|
40131
|
+
});
|
|
40132
|
+
} catch (e) {
|
|
40133
|
+
log2(
|
|
40134
|
+
`[Bridge service] Agent capability batch to bridge failed: ${e instanceof Error ? e.message : String(e)}`
|
|
40135
|
+
);
|
|
40136
|
+
}
|
|
40137
|
+
}
|
|
40138
|
+
sendBatchFromCache();
|
|
40139
|
+
let types = [];
|
|
40140
|
+
try {
|
|
40141
|
+
types = [...await detectLocalAgentTypes()];
|
|
40142
|
+
} catch (e) {
|
|
40143
|
+
log2(`[Bridge service] detectLocalAgentTypes failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
40144
|
+
}
|
|
40145
|
+
try {
|
|
40146
|
+
const n = await probeAgentCapabilitiesForDetectedTypes({
|
|
40147
|
+
agentTypes: types,
|
|
40148
|
+
cwd,
|
|
40149
|
+
workspaceId,
|
|
40150
|
+
log: log2,
|
|
40151
|
+
getDb,
|
|
40152
|
+
bridgeReport: false,
|
|
40153
|
+
forceAllTypes: false
|
|
40154
|
+
});
|
|
40155
|
+
if (n > 0) sendBatchFromCache();
|
|
40156
|
+
} catch (e) {
|
|
40157
|
+
log2(`[Bridge service] Agent capability probe (missing cache) failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
40158
|
+
}
|
|
40159
|
+
void (async () => {
|
|
40160
|
+
try {
|
|
40161
|
+
await yieldToEventLoop();
|
|
40162
|
+
const n = await probeAgentCapabilitiesForDetectedTypes({
|
|
40163
|
+
agentTypes: types,
|
|
40164
|
+
cwd,
|
|
40165
|
+
workspaceId,
|
|
40166
|
+
log: log2,
|
|
40167
|
+
getDb,
|
|
40168
|
+
bridgeReport: false,
|
|
40169
|
+
forceAllTypes: true
|
|
40170
|
+
});
|
|
40171
|
+
if (n > 0) sendBatchFromCache();
|
|
40172
|
+
} catch (e) {
|
|
40173
|
+
log2(`[Bridge service] Agent capability lazy refresh failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
40174
|
+
}
|
|
40175
|
+
})();
|
|
40176
|
+
}
|
|
40177
|
+
|
|
39777
40178
|
// src/connection/create-bridge-connection.ts
|
|
39778
40179
|
async function createBridgeConnection(options) {
|
|
39779
40180
|
const { apiUrl, workspaceId, justAuthenticated, onAuthInvalid, persistTokens } = options;
|
|
@@ -39802,16 +40203,39 @@ async function createBridgeConnection(options) {
|
|
|
39802
40203
|
firehoseOutage: createEmptyReconnectOutageTracker(),
|
|
39803
40204
|
lastFirehoseReconnectCloseMeta: null
|
|
39804
40205
|
};
|
|
40206
|
+
function getWs() {
|
|
40207
|
+
return state.currentWs;
|
|
40208
|
+
}
|
|
40209
|
+
function sendAgentCapabilitiesToBridge(info) {
|
|
40210
|
+
if (!Array.isArray(info.configOptions) || info.configOptions.length === 0) return;
|
|
40211
|
+
let changed = false;
|
|
40212
|
+
try {
|
|
40213
|
+
changed = upsertCliAgentCapabilityCache(getCliDatabase(), {
|
|
40214
|
+
workspaceId,
|
|
40215
|
+
agentType: info.agentType,
|
|
40216
|
+
configOptions: info.configOptions
|
|
40217
|
+
});
|
|
40218
|
+
} catch {
|
|
40219
|
+
}
|
|
40220
|
+
if (!changed) return;
|
|
40221
|
+
const socket = getWs();
|
|
40222
|
+
if (!socket || socket.readyState !== wrapper_default.OPEN) return;
|
|
40223
|
+
sendWsMessage(socket, {
|
|
40224
|
+
type: "agent_capabilities",
|
|
40225
|
+
agentType: info.agentType,
|
|
40226
|
+
configOptions: info.configOptions
|
|
40227
|
+
});
|
|
40228
|
+
}
|
|
39805
40229
|
const worktreesRootPath = options.worktreesRootPath ?? defaultWorktreesRootPath();
|
|
39806
40230
|
const sessionWorktreeManager = new SessionWorktreeManager({
|
|
39807
40231
|
worktreesRootPath,
|
|
39808
40232
|
log: logFn
|
|
39809
40233
|
});
|
|
39810
|
-
const acpManager = await createAcpManager({
|
|
40234
|
+
const acpManager = await createAcpManager({
|
|
40235
|
+
log: logFn,
|
|
40236
|
+
reportAgentCapabilities: sendAgentCapabilitiesToBridge
|
|
40237
|
+
});
|
|
39811
40238
|
logFn("CLI running. Press Ctrl+C to exit.");
|
|
39812
|
-
function getWs() {
|
|
39813
|
-
return state.currentWs;
|
|
39814
|
-
}
|
|
39815
40239
|
const e2ee = options.e2eCertificate ? createCliE2eeRuntime(options.e2eCertificate) : void 0;
|
|
39816
40240
|
const devServerManager = new DevServerManager({ getWs, log: logFn, getBridgeRoot, e2ee });
|
|
39817
40241
|
const bridgeHeartbeat = createBridgeHeartbeatController({ getWs, log: logFn });
|
|
@@ -39839,14 +40263,22 @@ async function createBridgeConnection(options) {
|
|
|
39839
40263
|
},
|
|
39840
40264
|
sendLocalSkillsReport,
|
|
39841
40265
|
reportAutoDetectedAgents,
|
|
40266
|
+
warmupAgentCapabilitiesOnConnect: async () => {
|
|
40267
|
+
await warmupAgentCapabilitiesOnConnect({
|
|
40268
|
+
workspaceId,
|
|
40269
|
+
log: logFn,
|
|
40270
|
+
getDb: getCliDatabase,
|
|
40271
|
+
getWs
|
|
40272
|
+
});
|
|
40273
|
+
},
|
|
39842
40274
|
devServerManager,
|
|
39843
40275
|
e2ee,
|
|
39844
40276
|
cloudApiBaseUrl: apiUrl,
|
|
39845
40277
|
getCloudAccessToken: () => tokens.accessToken
|
|
39846
40278
|
};
|
|
39847
40279
|
const identifyReportedPaths = {
|
|
39848
|
-
bridgeRootPath:
|
|
39849
|
-
worktreesRootPath:
|
|
40280
|
+
bridgeRootPath: path41.resolve(getBridgeRoot()),
|
|
40281
|
+
worktreesRootPath: path41.resolve(worktreesRootPath)
|
|
39850
40282
|
};
|
|
39851
40283
|
const { connect } = createMainBridgeWebSocketLifecycle({
|
|
39852
40284
|
state,
|
|
@@ -40084,7 +40516,7 @@ async function runCliAction(program2, opts) {
|
|
|
40084
40516
|
const firehoseServerUrl = opts.firehoseUrl ?? opts.proxyUrl ?? process.env.BUILDAUTOMATON_FIREHOSE_URL ?? process.env.BUILDAUTOMATON_PROXY_URL ?? DEFAULT_FIREHOSE_URL;
|
|
40085
40517
|
const bridgeRootOpt = (opts.bridgeRoot && typeof opts.bridgeRoot === "string" && opts.bridgeRoot.trim() ? opts.bridgeRoot.trim() : null) ?? (opts.cwd && typeof opts.cwd === "string" && opts.cwd.trim() ? opts.cwd.trim() : null);
|
|
40086
40518
|
if (bridgeRootOpt) {
|
|
40087
|
-
const resolvedBridgeRoot =
|
|
40519
|
+
const resolvedBridgeRoot = path42.resolve(process.cwd(), bridgeRootOpt);
|
|
40088
40520
|
try {
|
|
40089
40521
|
const st = fs37.statSync(resolvedBridgeRoot);
|
|
40090
40522
|
if (!st.isDirectory()) {
|
|
@@ -40106,7 +40538,7 @@ async function runCliAction(program2, opts) {
|
|
|
40106
40538
|
);
|
|
40107
40539
|
let worktreesRootPath;
|
|
40108
40540
|
if (opts.worktreesRoot && opts.worktreesRoot.trim()) {
|
|
40109
|
-
worktreesRootPath =
|
|
40541
|
+
worktreesRootPath = path42.resolve(opts.worktreesRoot.trim());
|
|
40110
40542
|
}
|
|
40111
40543
|
const e2eCertificates = opts.e2eeCertificatesDir?.trim() ? await loadOrCreateE2eCertificates(opts.e2eeCertificatesDir.trim()) : void 0;
|
|
40112
40544
|
if (e2eCertificates) {
|