@buildautomaton/cli 0.1.29 → 0.1.30
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 +509 -120
- package/dist/cli.js.map +4 -4
- package/dist/index.js +494 -105
- 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/index.js
CHANGED
|
@@ -2240,7 +2240,7 @@ var require_websocket = __commonJS({
|
|
|
2240
2240
|
var http = __require("http");
|
|
2241
2241
|
var net = __require("net");
|
|
2242
2242
|
var tls = __require("tls");
|
|
2243
|
-
var { randomBytes: randomBytes2, createHash } = __require("crypto");
|
|
2243
|
+
var { randomBytes: randomBytes2, createHash: createHash2 } = __require("crypto");
|
|
2244
2244
|
var { Duplex, Readable: Readable2 } = __require("stream");
|
|
2245
2245
|
var { URL: URL2 } = __require("url");
|
|
2246
2246
|
var PerMessageDeflate = require_permessage_deflate();
|
|
@@ -2900,7 +2900,7 @@ var require_websocket = __commonJS({
|
|
|
2900
2900
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
2901
2901
|
return;
|
|
2902
2902
|
}
|
|
2903
|
-
const digest =
|
|
2903
|
+
const digest = createHash2("sha1").update(key + GUID).digest("base64");
|
|
2904
2904
|
if (res.headers["sec-websocket-accept"] !== digest) {
|
|
2905
2905
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
2906
2906
|
return;
|
|
@@ -3267,7 +3267,7 @@ var require_websocket_server = __commonJS({
|
|
|
3267
3267
|
var EventEmitter2 = __require("events");
|
|
3268
3268
|
var http = __require("http");
|
|
3269
3269
|
var { Duplex } = __require("stream");
|
|
3270
|
-
var { createHash } = __require("crypto");
|
|
3270
|
+
var { createHash: createHash2 } = __require("crypto");
|
|
3271
3271
|
var extension = require_extension();
|
|
3272
3272
|
var PerMessageDeflate = require_permessage_deflate();
|
|
3273
3273
|
var subprotocol = require_subprotocol();
|
|
@@ -3568,7 +3568,7 @@ var require_websocket_server = __commonJS({
|
|
|
3568
3568
|
);
|
|
3569
3569
|
}
|
|
3570
3570
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
3571
|
-
const digest =
|
|
3571
|
+
const digest = createHash2("sha1").update(key + GUID).digest("base64");
|
|
3572
3572
|
const headers = [
|
|
3573
3573
|
"HTTP/1.1 101 Switching Protocols",
|
|
3574
3574
|
"Upgrade: websocket",
|
|
@@ -4065,8 +4065,8 @@ var init_parseUtil = __esm({
|
|
|
4065
4065
|
init_errors();
|
|
4066
4066
|
init_en();
|
|
4067
4067
|
makeIssue = (params) => {
|
|
4068
|
-
const { data, path:
|
|
4069
|
-
const fullPath = [...
|
|
4068
|
+
const { data, path: path41, errorMaps, issueData } = params;
|
|
4069
|
+
const fullPath = [...path41, ...issueData.path || []];
|
|
4070
4070
|
const fullIssue = {
|
|
4071
4071
|
...issueData,
|
|
4072
4072
|
path: fullPath
|
|
@@ -4374,11 +4374,11 @@ var init_types = __esm({
|
|
|
4374
4374
|
init_parseUtil();
|
|
4375
4375
|
init_util();
|
|
4376
4376
|
ParseInputLazyPath = class {
|
|
4377
|
-
constructor(parent, value,
|
|
4377
|
+
constructor(parent, value, path41, key) {
|
|
4378
4378
|
this._cachedPath = [];
|
|
4379
4379
|
this.parent = parent;
|
|
4380
4380
|
this.data = value;
|
|
4381
|
-
this._path =
|
|
4381
|
+
this._path = path41;
|
|
4382
4382
|
this._key = key;
|
|
4383
4383
|
}
|
|
4384
4384
|
get path() {
|
|
@@ -7993,10 +7993,10 @@ function assignProp(target, prop, value) {
|
|
|
7993
7993
|
configurable: true
|
|
7994
7994
|
});
|
|
7995
7995
|
}
|
|
7996
|
-
function getElementAtPath(obj,
|
|
7997
|
-
if (!
|
|
7996
|
+
function getElementAtPath(obj, path41) {
|
|
7997
|
+
if (!path41)
|
|
7998
7998
|
return obj;
|
|
7999
|
-
return
|
|
7999
|
+
return path41.reduce((acc, key) => acc?.[key], obj);
|
|
8000
8000
|
}
|
|
8001
8001
|
function promiseAllObject(promisesObj) {
|
|
8002
8002
|
const keys = Object.keys(promisesObj);
|
|
@@ -8245,11 +8245,11 @@ function aborted(x, startIndex = 0) {
|
|
|
8245
8245
|
}
|
|
8246
8246
|
return false;
|
|
8247
8247
|
}
|
|
8248
|
-
function prefixIssues(
|
|
8248
|
+
function prefixIssues(path41, issues) {
|
|
8249
8249
|
return issues.map((iss) => {
|
|
8250
8250
|
var _a2;
|
|
8251
8251
|
(_a2 = iss).path ?? (_a2.path = []);
|
|
8252
|
-
iss.path.unshift(
|
|
8252
|
+
iss.path.unshift(path41);
|
|
8253
8253
|
return iss;
|
|
8254
8254
|
});
|
|
8255
8255
|
}
|
|
@@ -8438,7 +8438,7 @@ function treeifyError(error40, _mapper) {
|
|
|
8438
8438
|
return issue2.message;
|
|
8439
8439
|
};
|
|
8440
8440
|
const result = { errors: [] };
|
|
8441
|
-
const processError = (error41,
|
|
8441
|
+
const processError = (error41, path41 = []) => {
|
|
8442
8442
|
var _a2, _b;
|
|
8443
8443
|
for (const issue2 of error41.issues) {
|
|
8444
8444
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -8448,7 +8448,7 @@ function treeifyError(error40, _mapper) {
|
|
|
8448
8448
|
} else if (issue2.code === "invalid_element") {
|
|
8449
8449
|
processError({ issues: issue2.issues }, issue2.path);
|
|
8450
8450
|
} else {
|
|
8451
|
-
const fullpath = [...
|
|
8451
|
+
const fullpath = [...path41, ...issue2.path];
|
|
8452
8452
|
if (fullpath.length === 0) {
|
|
8453
8453
|
result.errors.push(mapper(issue2));
|
|
8454
8454
|
continue;
|
|
@@ -8478,9 +8478,9 @@ function treeifyError(error40, _mapper) {
|
|
|
8478
8478
|
processError(error40);
|
|
8479
8479
|
return result;
|
|
8480
8480
|
}
|
|
8481
|
-
function toDotPath(
|
|
8481
|
+
function toDotPath(path41) {
|
|
8482
8482
|
const segs = [];
|
|
8483
|
-
for (const seg of
|
|
8483
|
+
for (const seg of path41) {
|
|
8484
8484
|
if (typeof seg === "number")
|
|
8485
8485
|
segs.push(`[${seg}]`);
|
|
8486
8486
|
else if (typeof seg === "symbol")
|
|
@@ -20943,8 +20943,8 @@ var init_acp = __esm({
|
|
|
20943
20943
|
this.#requestHandler = requestHandler;
|
|
20944
20944
|
this.#notificationHandler = notificationHandler;
|
|
20945
20945
|
this.#stream = stream;
|
|
20946
|
-
this.#closedPromise = new Promise((
|
|
20947
|
-
this.#abortController.signal.addEventListener("abort", () =>
|
|
20946
|
+
this.#closedPromise = new Promise((resolve18) => {
|
|
20947
|
+
this.#abortController.signal.addEventListener("abort", () => resolve18());
|
|
20948
20948
|
});
|
|
20949
20949
|
this.#receive();
|
|
20950
20950
|
}
|
|
@@ -21093,8 +21093,8 @@ var init_acp = __esm({
|
|
|
21093
21093
|
}
|
|
21094
21094
|
async sendRequest(method, params) {
|
|
21095
21095
|
const id = this.#nextRequestId++;
|
|
21096
|
-
const responsePromise = new Promise((
|
|
21097
|
-
this.#pendingResponses.set(id, { resolve:
|
|
21096
|
+
const responsePromise = new Promise((resolve18, reject) => {
|
|
21097
|
+
this.#pendingResponses.set(id, { resolve: resolve18, reject });
|
|
21098
21098
|
});
|
|
21099
21099
|
await this.#sendMessage({ jsonrpc: "2.0", id, method, params });
|
|
21100
21100
|
return responsePromise;
|
|
@@ -21963,10 +21963,10 @@ var require_src2 = __commonJS({
|
|
|
21963
21963
|
var fs_1 = __require("fs");
|
|
21964
21964
|
var debug_1 = __importDefault(require_src());
|
|
21965
21965
|
var log2 = debug_1.default("@kwsites/file-exists");
|
|
21966
|
-
function check2(
|
|
21967
|
-
log2(`checking %s`,
|
|
21966
|
+
function check2(path41, isFile, isDirectory) {
|
|
21967
|
+
log2(`checking %s`, path41);
|
|
21968
21968
|
try {
|
|
21969
|
-
const stat2 = fs_1.statSync(
|
|
21969
|
+
const stat2 = fs_1.statSync(path41);
|
|
21970
21970
|
if (stat2.isFile() && isFile) {
|
|
21971
21971
|
log2(`[OK] path represents a file`);
|
|
21972
21972
|
return true;
|
|
@@ -21986,8 +21986,8 @@ var require_src2 = __commonJS({
|
|
|
21986
21986
|
throw e;
|
|
21987
21987
|
}
|
|
21988
21988
|
}
|
|
21989
|
-
function exists2(
|
|
21990
|
-
return check2(
|
|
21989
|
+
function exists2(path41, type = exports.READABLE) {
|
|
21990
|
+
return check2(path41, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
|
|
21991
21991
|
}
|
|
21992
21992
|
exports.exists = exists2;
|
|
21993
21993
|
exports.FILE = 1;
|
|
@@ -22792,9 +22792,9 @@ function parseChangeSummaryJson(raw, allowedPaths, options) {
|
|
|
22792
22792
|
const rawPath = typeof o.path === "string" ? o.path.trim() : "";
|
|
22793
22793
|
const summary = typeof o.summary === "string" ? o.summary.trim() : "";
|
|
22794
22794
|
if (!rawPath || !summary) continue;
|
|
22795
|
-
const
|
|
22796
|
-
if (!
|
|
22797
|
-
rows.push({ path:
|
|
22795
|
+
const path41 = skip ? normalizeRepoRelativePath(rawPath) || rawPath : resolveChangeSummaryPathAgainstAllowed(rawPath, allowedPaths);
|
|
22796
|
+
if (!path41) continue;
|
|
22797
|
+
rows.push({ path: path41, summary: clampSummaryToAtMostTwoLines(summary) });
|
|
22798
22798
|
}
|
|
22799
22799
|
return rows;
|
|
22800
22800
|
}
|
|
@@ -23004,6 +23004,7 @@ function buildCliAutoApprovedPermissionRpcResult(requestParams) {
|
|
|
23004
23004
|
// ../types/src/agent-config.ts
|
|
23005
23005
|
var AGENT_CONFIG_CLAUDE_PERMISSION_MODE_KEY = "claude_permission_mode";
|
|
23006
23006
|
var AGENT_CONFIG_CLI_PERMISSION_MODE_KEY = "cli_permission_mode";
|
|
23007
|
+
var AGENT_CONFIG_AGENT_MODEL_KEY = "agent_model";
|
|
23007
23008
|
function getClaudePermissionModeFromAgentConfig(config2) {
|
|
23008
23009
|
if (!config2) return null;
|
|
23009
23010
|
const raw = config2[AGENT_CONFIG_CLAUDE_PERMISSION_MODE_KEY];
|
|
@@ -23015,6 +23016,13 @@ function getCliPermissionModeFromAgentConfig(config2) {
|
|
|
23015
23016
|
if (!config2) return CLI_PERMISSION_MODE_DEFAULT;
|
|
23016
23017
|
return normalizeCliPermissionModeInput(config2[AGENT_CONFIG_CLI_PERMISSION_MODE_KEY]);
|
|
23017
23018
|
}
|
|
23019
|
+
function getAgentModelFromAgentConfig(config2) {
|
|
23020
|
+
if (!config2) return null;
|
|
23021
|
+
const cur = config2[AGENT_CONFIG_AGENT_MODEL_KEY];
|
|
23022
|
+
if (typeof cur !== "string") return null;
|
|
23023
|
+
const t = cur.trim();
|
|
23024
|
+
return t !== "" ? t : null;
|
|
23025
|
+
}
|
|
23018
23026
|
|
|
23019
23027
|
// src/agents/acp/claude-acp-permission-from-session.ts
|
|
23020
23028
|
function flattenSelectOptions(options) {
|
|
@@ -23070,6 +23078,48 @@ async function applyClaudePermissionFromAcpSession(params) {
|
|
|
23070
23078
|
}
|
|
23071
23079
|
}
|
|
23072
23080
|
|
|
23081
|
+
// src/agents/acp/apply-acp-model-from-agent-session.ts
|
|
23082
|
+
function flattenSelectOptions2(options) {
|
|
23083
|
+
if (options == null || options.length === 0) return [];
|
|
23084
|
+
const first2 = options[0];
|
|
23085
|
+
if (first2 != null && typeof first2 === "object" && "group" in first2 && first2.group != null) {
|
|
23086
|
+
return options.flatMap((g) => Array.isArray(g.options) ? g.options : []);
|
|
23087
|
+
}
|
|
23088
|
+
return options;
|
|
23089
|
+
}
|
|
23090
|
+
function looksLikeModelOption(o) {
|
|
23091
|
+
if (o.category === "model" || o.category === "models") return true;
|
|
23092
|
+
const id = typeof o.id === "string" ? o.id.toLowerCase() : "";
|
|
23093
|
+
if (id === "model" || id.endsWith("_model") || id.includes("model")) return true;
|
|
23094
|
+
const name = typeof o.name === "string" ? o.name.toLowerCase() : "";
|
|
23095
|
+
return name.includes("model") && !name.includes("mode");
|
|
23096
|
+
}
|
|
23097
|
+
function pickModelConfigOption(configOptions) {
|
|
23098
|
+
if (configOptions == null || configOptions.length === 0) return null;
|
|
23099
|
+
return configOptions.find(looksLikeModelOption) ?? null;
|
|
23100
|
+
}
|
|
23101
|
+
async function applyAcpModelFromAcpSession(params) {
|
|
23102
|
+
const { sessionId, agentConfig, configOptions, setSessionConfigOption, logDebug: logDebug2 } = params;
|
|
23103
|
+
const desired = getAgentModelFromAgentConfig(agentConfig);
|
|
23104
|
+
if (desired == null) return;
|
|
23105
|
+
const modelOpt = pickModelConfigOption(configOptions ?? null);
|
|
23106
|
+
if (modelOpt == null) return;
|
|
23107
|
+
const flat = flattenSelectOptions2(modelOpt.options);
|
|
23108
|
+
const allowed = flat.some((o) => o.value === desired);
|
|
23109
|
+
if (!allowed) return;
|
|
23110
|
+
if (modelOpt.currentValue === desired) return;
|
|
23111
|
+
try {
|
|
23112
|
+
logDebug2(
|
|
23113
|
+
`[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`
|
|
23114
|
+
);
|
|
23115
|
+
await setSessionConfigOption({ sessionId, configId: modelOpt.id, value: desired });
|
|
23116
|
+
} catch (e) {
|
|
23117
|
+
logDebug2(
|
|
23118
|
+
`[Agent] ACP session/set_config_option (model) failed: ${e instanceof Error ? e.message : String(e)}`
|
|
23119
|
+
);
|
|
23120
|
+
}
|
|
23121
|
+
}
|
|
23122
|
+
|
|
23073
23123
|
// src/agents/acp/clients/shared/config-options-for-permission.ts
|
|
23074
23124
|
function configOptionsForPermission(getActive, established) {
|
|
23075
23125
|
const mem = getActive?.();
|
|
@@ -23162,6 +23212,17 @@ async function bootstrapAcpWireSession(transport, ctx, initializeRequest) {
|
|
|
23162
23212
|
logDebug: ctx.logDebug
|
|
23163
23213
|
});
|
|
23164
23214
|
}
|
|
23215
|
+
const cfgAll = ctx.agentConfig != null && typeof ctx.agentConfig === "object" && !Array.isArray(ctx.agentConfig) ? ctx.agentConfig : null;
|
|
23216
|
+
const configOptionsForModel = established.configOptions;
|
|
23217
|
+
if (transport.setSessionConfigOption) {
|
|
23218
|
+
await applyAcpModelFromAcpSession({
|
|
23219
|
+
sessionId,
|
|
23220
|
+
agentConfig: cfgAll,
|
|
23221
|
+
configOptions: configOptionsForPermission(ctx.getActiveConfigOptions, configOptionsForModel),
|
|
23222
|
+
setSessionConfigOption: (p) => transport.setSessionConfigOption(p),
|
|
23223
|
+
logDebug: ctx.logDebug
|
|
23224
|
+
});
|
|
23225
|
+
}
|
|
23165
23226
|
return established;
|
|
23166
23227
|
}
|
|
23167
23228
|
|
|
@@ -23267,10 +23328,15 @@ async function sendAcpPromptViaTransport(transport, ctx, sessionId, promptText,
|
|
|
23267
23328
|
// src/agents/acp/clients/sdk/sdk-stdio-permission-request-handshake.ts
|
|
23268
23329
|
function awaitSdkStdioPermissionRequestHandshake(params) {
|
|
23269
23330
|
const { requestId, paramsRecord, pending, onRequest } = params;
|
|
23270
|
-
return new Promise((
|
|
23271
|
-
pending.set(requestId, { resolve:
|
|
23331
|
+
return new Promise((resolve18) => {
|
|
23332
|
+
pending.set(requestId, { resolve: resolve18, params: paramsRecord });
|
|
23333
|
+
if (onRequest == null) {
|
|
23334
|
+
pending.delete(requestId);
|
|
23335
|
+
resolve18({ outcome: { outcome: "denied" } });
|
|
23336
|
+
return;
|
|
23337
|
+
}
|
|
23272
23338
|
try {
|
|
23273
|
-
onRequest
|
|
23339
|
+
onRequest({
|
|
23274
23340
|
requestId,
|
|
23275
23341
|
method: "session/request_permission",
|
|
23276
23342
|
params: paramsRecord
|
|
@@ -23332,7 +23398,7 @@ async function createSdkStdioAcpClient(options) {
|
|
|
23332
23398
|
child.once("close", (code, signal) => {
|
|
23333
23399
|
onAgentSubprocessExit?.({ code, signal });
|
|
23334
23400
|
});
|
|
23335
|
-
return new Promise((
|
|
23401
|
+
return new Promise((resolve18, reject) => {
|
|
23336
23402
|
let initSettled = false;
|
|
23337
23403
|
const settleReject = (err) => {
|
|
23338
23404
|
if (initSettled) return;
|
|
@@ -23346,7 +23412,7 @@ async function createSdkStdioAcpClient(options) {
|
|
|
23346
23412
|
const settleResolve = (handle) => {
|
|
23347
23413
|
if (initSettled) return;
|
|
23348
23414
|
initSettled = true;
|
|
23349
|
-
|
|
23415
|
+
resolve18(handle);
|
|
23350
23416
|
};
|
|
23351
23417
|
child.on("error", (err) => {
|
|
23352
23418
|
settleReject(new Error(formatSpawnError(err, command[0])));
|
|
@@ -23566,7 +23632,7 @@ async function proxyToLocal(request) {
|
|
|
23566
23632
|
};
|
|
23567
23633
|
const maxAttempts = isIdempotentProxyMethod(request.method) ? LOCAL_PREVIEW_FETCH_RETRY_DELAYS_MS.length + 1 : 1;
|
|
23568
23634
|
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
|
|
23569
|
-
const once = await new Promise((
|
|
23635
|
+
const once = await new Promise((resolve18) => {
|
|
23570
23636
|
const req = mod.request(opts, (res) => {
|
|
23571
23637
|
const chunks = [];
|
|
23572
23638
|
res.on("data", (c) => chunks.push(c));
|
|
@@ -23577,7 +23643,7 @@ async function proxyToLocal(request) {
|
|
|
23577
23643
|
if (typeof v === "string") headers[k] = v;
|
|
23578
23644
|
else if (Array.isArray(v) && v[0]) headers[k] = v[0];
|
|
23579
23645
|
}
|
|
23580
|
-
|
|
23646
|
+
resolve18({
|
|
23581
23647
|
id: request.id,
|
|
23582
23648
|
statusCode: res.statusCode ?? 0,
|
|
23583
23649
|
headers,
|
|
@@ -23586,7 +23652,7 @@ async function proxyToLocal(request) {
|
|
|
23586
23652
|
});
|
|
23587
23653
|
});
|
|
23588
23654
|
req.on("error", (err) => {
|
|
23589
|
-
|
|
23655
|
+
resolve18({
|
|
23590
23656
|
id: request.id,
|
|
23591
23657
|
statusCode: 0,
|
|
23592
23658
|
headers: {},
|
|
@@ -23668,8 +23734,8 @@ function randomSecret() {
|
|
|
23668
23734
|
}
|
|
23669
23735
|
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
23670
23736
|
}
|
|
23671
|
-
async function requestPreviewApi(port, secret, method,
|
|
23672
|
-
const url2 = `http://127.0.0.1:${port}${
|
|
23737
|
+
async function requestPreviewApi(port, secret, method, path41, body) {
|
|
23738
|
+
const url2 = `http://127.0.0.1:${port}${path41}`;
|
|
23673
23739
|
const headers = {
|
|
23674
23740
|
[PREVIEW_SECRET_HEADER]: secret,
|
|
23675
23741
|
"Content-Type": "application/json"
|
|
@@ -23681,7 +23747,7 @@ async function requestPreviewApi(port, secret, method, path39, body) {
|
|
|
23681
23747
|
});
|
|
23682
23748
|
const data = await res.json().catch(() => ({}));
|
|
23683
23749
|
if (!res.ok) {
|
|
23684
|
-
throw new Error(data?.error ?? `Preview API ${method} ${
|
|
23750
|
+
throw new Error(data?.error ?? `Preview API ${method} ${path41}: ${res.status}`);
|
|
23685
23751
|
}
|
|
23686
23752
|
return data;
|
|
23687
23753
|
}
|
|
@@ -23896,7 +23962,7 @@ function installBridgeProcessResilience() {
|
|
|
23896
23962
|
}
|
|
23897
23963
|
|
|
23898
23964
|
// src/cli-version.ts
|
|
23899
|
-
var CLI_VERSION = "0.1.
|
|
23965
|
+
var CLI_VERSION = "0.1.30".length > 0 ? "0.1.30" : "0.0.0-dev";
|
|
23900
23966
|
|
|
23901
23967
|
// src/connection/heartbeat/constants.ts
|
|
23902
23968
|
var BRIDGE_APP_HEARTBEAT_INTERVAL_MS = 1e4;
|
|
@@ -24337,14 +24403,14 @@ var baseOpen = async (options) => {
|
|
|
24337
24403
|
}
|
|
24338
24404
|
const subprocess = childProcess.spawn(command, cliArguments, childProcessOptions);
|
|
24339
24405
|
if (options.wait) {
|
|
24340
|
-
return new Promise((
|
|
24406
|
+
return new Promise((resolve18, reject) => {
|
|
24341
24407
|
subprocess.once("error", reject);
|
|
24342
24408
|
subprocess.once("close", (exitCode) => {
|
|
24343
24409
|
if (!options.allowNonzeroExitCode && exitCode > 0) {
|
|
24344
24410
|
reject(new Error(`Exited with code ${exitCode}`));
|
|
24345
24411
|
return;
|
|
24346
24412
|
}
|
|
24347
|
-
|
|
24413
|
+
resolve18(subprocess);
|
|
24348
24414
|
});
|
|
24349
24415
|
});
|
|
24350
24416
|
}
|
|
@@ -24833,8 +24899,8 @@ function runPendingAuth(options) {
|
|
|
24833
24899
|
let hasOpenedBrowser = false;
|
|
24834
24900
|
let resolved = false;
|
|
24835
24901
|
let resolveAuth;
|
|
24836
|
-
const authPromise = new Promise((
|
|
24837
|
-
resolveAuth =
|
|
24902
|
+
const authPromise = new Promise((resolve18) => {
|
|
24903
|
+
resolveAuth = resolve18;
|
|
24838
24904
|
});
|
|
24839
24905
|
let reconnectAttempt = 0;
|
|
24840
24906
|
const signInQuiet = createEmptyReconnectQuietSlot();
|
|
@@ -25189,6 +25255,16 @@ function recordMigrationAndPruneCheckpointLegacy(db, migration, applied2) {
|
|
|
25189
25255
|
}
|
|
25190
25256
|
var CHECKPOINT_V1 = "001_cli_sqlite_checkpoint_v1";
|
|
25191
25257
|
var CHECKPOINT_V1_SQL = readCliSqliteMigrationSql("001_cli_sqlite_checkpoint_v1.sql");
|
|
25258
|
+
var AGENT_CAPABILITIES_SQL = readCliSqliteMigrationSql("002_agent_capabilities.sql");
|
|
25259
|
+
function agentCapabilitiesTableState(db) {
|
|
25260
|
+
const rows = db.all(
|
|
25261
|
+
`SELECT name FROM sqlite_master WHERE type='table' AND name IN ('agent_capabilities', 'agent_capability_cache')`
|
|
25262
|
+
);
|
|
25263
|
+
const names = new Set(rows.map((r) => r.name));
|
|
25264
|
+
if (names.has("agent_capabilities")) return "current";
|
|
25265
|
+
if (names.has("agent_capability_cache")) return "legacy";
|
|
25266
|
+
return "new";
|
|
25267
|
+
}
|
|
25192
25268
|
var CLI_SQLITE_MIGRATIONS = [
|
|
25193
25269
|
{
|
|
25194
25270
|
name: CHECKPOINT_V1,
|
|
@@ -25196,6 +25272,23 @@ var CLI_SQLITE_MIGRATIONS = [
|
|
|
25196
25272
|
migrate: (db) => {
|
|
25197
25273
|
db.exec(CHECKPOINT_V1_SQL);
|
|
25198
25274
|
}
|
|
25275
|
+
},
|
|
25276
|
+
{
|
|
25277
|
+
name: "002_agent_capabilities",
|
|
25278
|
+
migrate: (db) => {
|
|
25279
|
+
const state = agentCapabilitiesTableState(db);
|
|
25280
|
+
if (state === "current") return;
|
|
25281
|
+
if (state === "legacy") {
|
|
25282
|
+
db.exec(`
|
|
25283
|
+
ALTER TABLE agent_capability_cache RENAME TO agent_capabilities;
|
|
25284
|
+
DROP INDEX IF EXISTS idx_agent_capability_cache_workspace;
|
|
25285
|
+
CREATE INDEX IF NOT EXISTS idx_agent_capabilities_workspace ON agent_capabilities(workspace_id);
|
|
25286
|
+
`);
|
|
25287
|
+
return;
|
|
25288
|
+
}
|
|
25289
|
+
db.exec(AGENT_CAPABILITIES_SQL);
|
|
25290
|
+
},
|
|
25291
|
+
alreadyApplied: (db) => agentCapabilitiesTableState(db) === "current"
|
|
25199
25292
|
}
|
|
25200
25293
|
];
|
|
25201
25294
|
function migrateCliSqlite(db) {
|
|
@@ -25275,7 +25368,7 @@ function getCliDatabase(options) {
|
|
|
25275
25368
|
async function closeBridgeConnection(state, acpManager, devServerManager, log2) {
|
|
25276
25369
|
const say = log2 ?? logImmediate;
|
|
25277
25370
|
say("Cleaning up connections\u2026");
|
|
25278
|
-
await new Promise((
|
|
25371
|
+
await new Promise((resolve18) => setImmediate(resolve18));
|
|
25279
25372
|
state.closedByUser = true;
|
|
25280
25373
|
clearReconnectQuietTimer(state.mainQuiet);
|
|
25281
25374
|
clearReconnectQuietTimer(state.firehoseQuiet);
|
|
@@ -25389,8 +25482,8 @@ function pathspec(...paths) {
|
|
|
25389
25482
|
cache.set(key, paths);
|
|
25390
25483
|
return key;
|
|
25391
25484
|
}
|
|
25392
|
-
function isPathSpec(
|
|
25393
|
-
return
|
|
25485
|
+
function isPathSpec(path41) {
|
|
25486
|
+
return path41 instanceof String && cache.has(path41);
|
|
25394
25487
|
}
|
|
25395
25488
|
function toPaths(pathSpec) {
|
|
25396
25489
|
return cache.get(pathSpec) || [];
|
|
@@ -25479,8 +25572,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
|
|
|
25479
25572
|
function forEachLineWithContent(input, callback) {
|
|
25480
25573
|
return toLinesWithContent(input, true).map((line) => callback(line));
|
|
25481
25574
|
}
|
|
25482
|
-
function folderExists(
|
|
25483
|
-
return (0, import_file_exists.exists)(
|
|
25575
|
+
function folderExists(path41) {
|
|
25576
|
+
return (0, import_file_exists.exists)(path41, import_file_exists.FOLDER);
|
|
25484
25577
|
}
|
|
25485
25578
|
function append(target, item) {
|
|
25486
25579
|
if (Array.isArray(target)) {
|
|
@@ -25884,8 +25977,8 @@ function checkIsRepoRootTask() {
|
|
|
25884
25977
|
commands,
|
|
25885
25978
|
format: "utf-8",
|
|
25886
25979
|
onError,
|
|
25887
|
-
parser(
|
|
25888
|
-
return /^\.(git)?$/.test(
|
|
25980
|
+
parser(path41) {
|
|
25981
|
+
return /^\.(git)?$/.test(path41.trim());
|
|
25889
25982
|
}
|
|
25890
25983
|
};
|
|
25891
25984
|
}
|
|
@@ -26319,11 +26412,11 @@ function parseGrep(grep) {
|
|
|
26319
26412
|
const paths = /* @__PURE__ */ new Set();
|
|
26320
26413
|
const results = {};
|
|
26321
26414
|
forEachLineWithContent(grep, (input) => {
|
|
26322
|
-
const [
|
|
26323
|
-
paths.add(
|
|
26324
|
-
(results[
|
|
26415
|
+
const [path41, line, preview] = input.split(NULL);
|
|
26416
|
+
paths.add(path41);
|
|
26417
|
+
(results[path41] = results[path41] || []).push({
|
|
26325
26418
|
line: asNumber(line),
|
|
26326
|
-
path:
|
|
26419
|
+
path: path41,
|
|
26327
26420
|
preview
|
|
26328
26421
|
});
|
|
26329
26422
|
});
|
|
@@ -27088,14 +27181,14 @@ var init_hash_object = __esm2({
|
|
|
27088
27181
|
init_task();
|
|
27089
27182
|
}
|
|
27090
27183
|
});
|
|
27091
|
-
function parseInit(bare,
|
|
27184
|
+
function parseInit(bare, path41, text) {
|
|
27092
27185
|
const response = String(text).trim();
|
|
27093
27186
|
let result;
|
|
27094
27187
|
if (result = initResponseRegex.exec(response)) {
|
|
27095
|
-
return new InitSummary(bare,
|
|
27188
|
+
return new InitSummary(bare, path41, false, result[1]);
|
|
27096
27189
|
}
|
|
27097
27190
|
if (result = reInitResponseRegex.exec(response)) {
|
|
27098
|
-
return new InitSummary(bare,
|
|
27191
|
+
return new InitSummary(bare, path41, true, result[1]);
|
|
27099
27192
|
}
|
|
27100
27193
|
let gitDir = "";
|
|
27101
27194
|
const tokens = response.split(" ");
|
|
@@ -27106,7 +27199,7 @@ function parseInit(bare, path39, text) {
|
|
|
27106
27199
|
break;
|
|
27107
27200
|
}
|
|
27108
27201
|
}
|
|
27109
|
-
return new InitSummary(bare,
|
|
27202
|
+
return new InitSummary(bare, path41, /^re/i.test(response), gitDir);
|
|
27110
27203
|
}
|
|
27111
27204
|
var InitSummary;
|
|
27112
27205
|
var initResponseRegex;
|
|
@@ -27115,9 +27208,9 @@ var init_InitSummary = __esm2({
|
|
|
27115
27208
|
"src/lib/responses/InitSummary.ts"() {
|
|
27116
27209
|
"use strict";
|
|
27117
27210
|
InitSummary = class {
|
|
27118
|
-
constructor(bare,
|
|
27211
|
+
constructor(bare, path41, existing, gitDir) {
|
|
27119
27212
|
this.bare = bare;
|
|
27120
|
-
this.path =
|
|
27213
|
+
this.path = path41;
|
|
27121
27214
|
this.existing = existing;
|
|
27122
27215
|
this.gitDir = gitDir;
|
|
27123
27216
|
}
|
|
@@ -27129,7 +27222,7 @@ var init_InitSummary = __esm2({
|
|
|
27129
27222
|
function hasBareCommand(command) {
|
|
27130
27223
|
return command.includes(bareCommand);
|
|
27131
27224
|
}
|
|
27132
|
-
function initTask(bare = false,
|
|
27225
|
+
function initTask(bare = false, path41, customArgs) {
|
|
27133
27226
|
const commands = ["init", ...customArgs];
|
|
27134
27227
|
if (bare && !hasBareCommand(commands)) {
|
|
27135
27228
|
commands.splice(1, 0, bareCommand);
|
|
@@ -27138,7 +27231,7 @@ function initTask(bare = false, path39, customArgs) {
|
|
|
27138
27231
|
commands,
|
|
27139
27232
|
format: "utf-8",
|
|
27140
27233
|
parser(text) {
|
|
27141
|
-
return parseInit(commands.includes("--bare"),
|
|
27234
|
+
return parseInit(commands.includes("--bare"), path41, text);
|
|
27142
27235
|
}
|
|
27143
27236
|
};
|
|
27144
27237
|
}
|
|
@@ -27954,12 +28047,12 @@ var init_FileStatusSummary = __esm2({
|
|
|
27954
28047
|
"use strict";
|
|
27955
28048
|
fromPathRegex = /^(.+)\0(.+)$/;
|
|
27956
28049
|
FileStatusSummary = class {
|
|
27957
|
-
constructor(
|
|
27958
|
-
this.path =
|
|
28050
|
+
constructor(path41, index, working_dir) {
|
|
28051
|
+
this.path = path41;
|
|
27959
28052
|
this.index = index;
|
|
27960
28053
|
this.working_dir = working_dir;
|
|
27961
28054
|
if (index === "R" || working_dir === "R") {
|
|
27962
|
-
const detail = fromPathRegex.exec(
|
|
28055
|
+
const detail = fromPathRegex.exec(path41) || [null, path41, path41];
|
|
27963
28056
|
this.from = detail[2] || "";
|
|
27964
28057
|
this.path = detail[1] || "";
|
|
27965
28058
|
}
|
|
@@ -27990,14 +28083,14 @@ function splitLine(result, lineStr) {
|
|
|
27990
28083
|
default:
|
|
27991
28084
|
return;
|
|
27992
28085
|
}
|
|
27993
|
-
function data(index, workingDir,
|
|
28086
|
+
function data(index, workingDir, path41) {
|
|
27994
28087
|
const raw = `${index}${workingDir}`;
|
|
27995
28088
|
const handler = parsers6.get(raw);
|
|
27996
28089
|
if (handler) {
|
|
27997
|
-
handler(result,
|
|
28090
|
+
handler(result, path41);
|
|
27998
28091
|
}
|
|
27999
28092
|
if (raw !== "##" && raw !== "!!") {
|
|
28000
|
-
result.files.push(new FileStatusSummary(
|
|
28093
|
+
result.files.push(new FileStatusSummary(path41, index, workingDir));
|
|
28001
28094
|
}
|
|
28002
28095
|
}
|
|
28003
28096
|
}
|
|
@@ -28306,9 +28399,9 @@ var init_simple_git_api = __esm2({
|
|
|
28306
28399
|
next
|
|
28307
28400
|
);
|
|
28308
28401
|
}
|
|
28309
|
-
hashObject(
|
|
28402
|
+
hashObject(path41, write) {
|
|
28310
28403
|
return this._runTask(
|
|
28311
|
-
hashObjectTask(
|
|
28404
|
+
hashObjectTask(path41, write === true),
|
|
28312
28405
|
trailingFunctionArgument(arguments)
|
|
28313
28406
|
);
|
|
28314
28407
|
}
|
|
@@ -28661,8 +28754,8 @@ var init_branch = __esm2({
|
|
|
28661
28754
|
}
|
|
28662
28755
|
});
|
|
28663
28756
|
function toPath(input) {
|
|
28664
|
-
const
|
|
28665
|
-
return
|
|
28757
|
+
const path41 = input.trim().replace(/^["']|["']$/g, "");
|
|
28758
|
+
return path41 && normalize2(path41);
|
|
28666
28759
|
}
|
|
28667
28760
|
var parseCheckIgnore;
|
|
28668
28761
|
var init_CheckIgnore = __esm2({
|
|
@@ -28976,8 +29069,8 @@ __export2(sub_module_exports, {
|
|
|
28976
29069
|
subModuleTask: () => subModuleTask,
|
|
28977
29070
|
updateSubModuleTask: () => updateSubModuleTask
|
|
28978
29071
|
});
|
|
28979
|
-
function addSubModuleTask(repo,
|
|
28980
|
-
return subModuleTask(["add", repo,
|
|
29072
|
+
function addSubModuleTask(repo, path41) {
|
|
29073
|
+
return subModuleTask(["add", repo, path41]);
|
|
28981
29074
|
}
|
|
28982
29075
|
function initSubModuleTask(customArgs) {
|
|
28983
29076
|
return subModuleTask(["init", ...customArgs]);
|
|
@@ -29310,8 +29403,8 @@ var require_git = __commonJS2({
|
|
|
29310
29403
|
}
|
|
29311
29404
|
return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
|
|
29312
29405
|
};
|
|
29313
|
-
Git2.prototype.submoduleAdd = function(repo,
|
|
29314
|
-
return this._runTask(addSubModuleTask2(repo,
|
|
29406
|
+
Git2.prototype.submoduleAdd = function(repo, path41, then) {
|
|
29407
|
+
return this._runTask(addSubModuleTask2(repo, path41), trailingFunctionArgument2(arguments));
|
|
29315
29408
|
};
|
|
29316
29409
|
Git2.prototype.submoduleUpdate = function(args, then) {
|
|
29317
29410
|
return this._runTask(
|
|
@@ -30198,9 +30291,9 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
|
|
|
30198
30291
|
// src/agents/acp/put-summarize-change-summaries.ts
|
|
30199
30292
|
async function putEncryptedChangeSummaryRows(params) {
|
|
30200
30293
|
const base = params.apiBaseUrl.replace(/\/+$/, "");
|
|
30201
|
-
const entries = params.rows.map(({ path:
|
|
30294
|
+
const entries = params.rows.map(({ path: path41, summary }) => {
|
|
30202
30295
|
const enc = params.e2ee.encryptFields({ summary }, ["summary"]);
|
|
30203
|
-
return { path:
|
|
30296
|
+
return { path: path41, summary: JSON.stringify(enc) };
|
|
30204
30297
|
});
|
|
30205
30298
|
const res = await fetch(
|
|
30206
30299
|
`${base}/api/sessions/${encodeURIComponent(params.sessionId)}/follow-ups/summarize-changes`,
|
|
@@ -30733,7 +30826,7 @@ async function createCursorAcpClient(options) {
|
|
|
30733
30826
|
logDebug,
|
|
30734
30827
|
getStderrText: () => stderrCapture.getText()
|
|
30735
30828
|
};
|
|
30736
|
-
return new Promise((
|
|
30829
|
+
return new Promise((resolve18, reject) => {
|
|
30737
30830
|
child.on("error", (err) => {
|
|
30738
30831
|
child.kill();
|
|
30739
30832
|
reject(new Error(formatSpawnError2(err, command[0])));
|
|
@@ -30812,12 +30905,16 @@ async function createCursorAcpClient(options) {
|
|
|
30812
30905
|
}
|
|
30813
30906
|
if (method === "session/request_permission" && typeof id === "number") {
|
|
30814
30907
|
const params = msg.params ?? {};
|
|
30815
|
-
|
|
30816
|
-
|
|
30817
|
-
|
|
30818
|
-
|
|
30819
|
-
|
|
30820
|
-
|
|
30908
|
+
if (onRequest) {
|
|
30909
|
+
pendingRequests.set(id, { method, params });
|
|
30910
|
+
onRequest({
|
|
30911
|
+
requestId: String(id),
|
|
30912
|
+
method,
|
|
30913
|
+
params
|
|
30914
|
+
});
|
|
30915
|
+
} else {
|
|
30916
|
+
respond(id, { outcome: { outcome: "denied" } });
|
|
30917
|
+
}
|
|
30821
30918
|
return;
|
|
30822
30919
|
}
|
|
30823
30920
|
if (typeof id === "number" && method) {
|
|
@@ -30905,7 +31002,7 @@ async function createCursorAcpClient(options) {
|
|
|
30905
31002
|
clientInfo: { name: "buildautomaton-cli", version: "0.1.0" }
|
|
30906
31003
|
});
|
|
30907
31004
|
const sessionId = established.sessionId;
|
|
30908
|
-
|
|
31005
|
+
resolve18({
|
|
30909
31006
|
sessionId,
|
|
30910
31007
|
async sendPrompt(prompt, options2) {
|
|
30911
31008
|
const imgs = options2?.images?.map((im) => ({ type: "image", mimeType: im.mimeType, data: im.dataBase64 }));
|
|
@@ -31785,6 +31882,7 @@ async function ensureAcpClient(options) {
|
|
|
31785
31882
|
sessionParentPath,
|
|
31786
31883
|
routing,
|
|
31787
31884
|
cloudSessionId,
|
|
31885
|
+
reportAgentCapabilities,
|
|
31788
31886
|
sendSessionUpdate,
|
|
31789
31887
|
sendRequest,
|
|
31790
31888
|
log: log2
|
|
@@ -31872,6 +31970,12 @@ async function ensureAcpClient(options) {
|
|
|
31872
31970
|
backendAgentType: preferredAgentType
|
|
31873
31971
|
});
|
|
31874
31972
|
}
|
|
31973
|
+
if (reportAgentCapabilities && preferredAgentType && Array.isArray(info.configOptions) && info.configOptions.length > 0) {
|
|
31974
|
+
reportAgentCapabilities({
|
|
31975
|
+
agentType: preferredAgentType,
|
|
31976
|
+
configOptions: info.configOptions
|
|
31977
|
+
});
|
|
31978
|
+
}
|
|
31875
31979
|
},
|
|
31876
31980
|
onAcpConfigOptionsUpdated: (configOptions) => {
|
|
31877
31981
|
state.activeSessionConfigOptions = configOptions;
|
|
@@ -31881,6 +31985,12 @@ async function ensureAcpClient(options) {
|
|
|
31881
31985
|
backendAgentType: preferredAgentType
|
|
31882
31986
|
});
|
|
31883
31987
|
}
|
|
31988
|
+
if (reportAgentCapabilities && preferredAgentType && Array.isArray(configOptions) && configOptions.length > 0) {
|
|
31989
|
+
reportAgentCapabilities({
|
|
31990
|
+
agentType: preferredAgentType,
|
|
31991
|
+
configOptions
|
|
31992
|
+
});
|
|
31993
|
+
}
|
|
31884
31994
|
},
|
|
31885
31995
|
onAgentSubprocessExit: () => {
|
|
31886
31996
|
state.acpHandle = null;
|
|
@@ -31911,7 +32021,7 @@ async function ensureAcpClient(options) {
|
|
|
31911
32021
|
|
|
31912
32022
|
// src/agents/acp/create-acp-manager.ts
|
|
31913
32023
|
async function createAcpManager(options) {
|
|
31914
|
-
const { log: log2 } = options;
|
|
32024
|
+
const { log: log2, reportAgentCapabilities } = options;
|
|
31915
32025
|
const state = {
|
|
31916
32026
|
acpHandle: null,
|
|
31917
32027
|
acpStartPromise: null,
|
|
@@ -31955,7 +32065,8 @@ async function createAcpManager(options) {
|
|
|
31955
32065
|
cloudApiBaseUrl,
|
|
31956
32066
|
getCloudAccessToken,
|
|
31957
32067
|
e2ee,
|
|
31958
|
-
attachments
|
|
32068
|
+
attachments,
|
|
32069
|
+
agentId
|
|
31959
32070
|
} = opts;
|
|
31960
32071
|
const preferredForPrompt = agentType ?? backendFallbackAgentType ?? null;
|
|
31961
32072
|
pendingCancelRunId = void 0;
|
|
@@ -31973,7 +32084,8 @@ async function createAcpManager(options) {
|
|
|
31973
32084
|
cloudSessionId: sessionId,
|
|
31974
32085
|
sendSessionUpdate,
|
|
31975
32086
|
sendRequest: sendSessionUpdate,
|
|
31976
|
-
log: log2
|
|
32087
|
+
log: log2,
|
|
32088
|
+
reportAgentCapabilities
|
|
31977
32089
|
});
|
|
31978
32090
|
if (!handle) {
|
|
31979
32091
|
const errMsg = state.lastAcpStartError || "No agent configured. Register local agents on this bridge in the app.";
|
|
@@ -33340,7 +33452,7 @@ import path28 from "node:path";
|
|
|
33340
33452
|
|
|
33341
33453
|
// src/runtime/yield-to-event-loop.ts
|
|
33342
33454
|
function yieldToEventLoop() {
|
|
33343
|
-
return new Promise((
|
|
33455
|
+
return new Promise((resolve18) => setImmediate(resolve18));
|
|
33344
33456
|
}
|
|
33345
33457
|
|
|
33346
33458
|
// src/files/index/walk-workspace-tree.ts
|
|
@@ -33564,7 +33676,7 @@ function startFileIndexWatcher(cwd = getBridgeRoot()) {
|
|
|
33564
33676
|
}
|
|
33565
33677
|
|
|
33566
33678
|
// src/connection/create-bridge-connection.ts
|
|
33567
|
-
import * as
|
|
33679
|
+
import * as path40 from "node:path";
|
|
33568
33680
|
|
|
33569
33681
|
// src/dev-servers/manager/dev-server-manager.ts
|
|
33570
33682
|
import { rm as rm2 } from "node:fs/promises";
|
|
@@ -33586,15 +33698,15 @@ function sendDevServerStatus(getWs, serverId, status, options) {
|
|
|
33586
33698
|
|
|
33587
33699
|
// src/dev-servers/process/terminate-child-process.ts
|
|
33588
33700
|
async function sigtermAndWaitForExit(proc, graceMs, log2, shortId) {
|
|
33589
|
-
const exited = new Promise((
|
|
33590
|
-
proc.once("exit", () =>
|
|
33701
|
+
const exited = new Promise((resolve18) => {
|
|
33702
|
+
proc.once("exit", () => resolve18());
|
|
33591
33703
|
});
|
|
33592
33704
|
log2(`[dev-server] Sending SIGTERM to ${shortId} (pid=${proc.pid ?? "?"}).`);
|
|
33593
33705
|
try {
|
|
33594
33706
|
proc.kill("SIGTERM");
|
|
33595
33707
|
} catch {
|
|
33596
33708
|
}
|
|
33597
|
-
await Promise.race([exited, new Promise((
|
|
33709
|
+
await Promise.race([exited, new Promise((resolve18) => setTimeout(resolve18, graceMs))]);
|
|
33598
33710
|
}
|
|
33599
33711
|
function forceKillChild(proc, log2, shortId, graceMs) {
|
|
33600
33712
|
log2(
|
|
@@ -34948,6 +35060,13 @@ var handleBridgeIdentified = (msg, deps) => {
|
|
|
34948
35060
|
`[Bridge service] Auto-detect agents failed: ${e instanceof Error ? e.message : String(e)}`
|
|
34949
35061
|
);
|
|
34950
35062
|
}
|
|
35063
|
+
try {
|
|
35064
|
+
await deps.warmupAgentCapabilitiesOnConnect?.();
|
|
35065
|
+
} catch (e) {
|
|
35066
|
+
deps.log(
|
|
35067
|
+
`[Bridge service] Agent capability warmup failed: ${e instanceof Error ? e.message : String(e)}`
|
|
35068
|
+
);
|
|
35069
|
+
}
|
|
34951
35070
|
})();
|
|
34952
35071
|
});
|
|
34953
35072
|
setImmediate(() => {
|
|
@@ -35300,9 +35419,9 @@ function parseChangeSummarySnapshots(raw) {
|
|
|
35300
35419
|
for (const item of raw) {
|
|
35301
35420
|
if (!item || typeof item !== "object") continue;
|
|
35302
35421
|
const o = item;
|
|
35303
|
-
const
|
|
35304
|
-
if (!
|
|
35305
|
-
const row = { path:
|
|
35422
|
+
const path41 = typeof o.path === "string" && o.path.trim() !== "" ? o.path.trim() : "";
|
|
35423
|
+
if (!path41) continue;
|
|
35424
|
+
const row = { path: path41 };
|
|
35306
35425
|
if (typeof o.patchContent === "string") row.patchContent = o.patchContent;
|
|
35307
35426
|
if (typeof o.oldText === "string") row.oldText = o.oldText;
|
|
35308
35427
|
if (typeof o.newText === "string") row.newText = o.newText;
|
|
@@ -35420,6 +35539,8 @@ function handleBridgePrompt(msg, deps) {
|
|
|
35420
35539
|
const sessionParent = rawParent === "bridge_root" || rawParent === "worktrees_root" ? rawParent : rawParent === "session_worktrees_root" ? "worktrees_root" : null;
|
|
35421
35540
|
const sessionParentPath = typeof msg.sessionParentPath === "string" && msg.sessionParentPath.trim() ? msg.sessionParentPath.trim() : null;
|
|
35422
35541
|
const agentType = typeof msg.agentType === "string" && msg.agentType.trim() ? msg.agentType.trim() : void 0;
|
|
35542
|
+
const rawAgentId = msg.agentId;
|
|
35543
|
+
const agentId = typeof rawAgentId === "string" && rawAgentId.trim() !== "" ? rawAgentId.trim() : null;
|
|
35423
35544
|
const mode = typeof msg.mode === "string" && msg.mode.trim() ? msg.mode.trim() : void 0;
|
|
35424
35545
|
const agentConfig = msg.agentConfig != null && typeof msg.agentConfig === "object" && !Array.isArray(msg.agentConfig) ? msg.agentConfig : void 0;
|
|
35425
35546
|
acpManager.logPromptReceivedFromBridge({ agentType, mode });
|
|
@@ -35457,6 +35578,7 @@ function handleBridgePrompt(msg, deps) {
|
|
|
35457
35578
|
runId,
|
|
35458
35579
|
mode,
|
|
35459
35580
|
agentType,
|
|
35581
|
+
agentId,
|
|
35460
35582
|
agentConfig,
|
|
35461
35583
|
sessionParentPath: effectiveCwd,
|
|
35462
35584
|
sendResult: sendResult2,
|
|
@@ -36551,6 +36673,242 @@ function createBridgeHeartbeatController(params) {
|
|
|
36551
36673
|
};
|
|
36552
36674
|
}
|
|
36553
36675
|
|
|
36676
|
+
// src/sqlite/hash-json-sha256.ts
|
|
36677
|
+
import { createHash } from "node:crypto";
|
|
36678
|
+
function hashJsonUtf8Sha256(value) {
|
|
36679
|
+
return createHash("sha256").update(JSON.stringify(value), "utf8").digest("hex");
|
|
36680
|
+
}
|
|
36681
|
+
|
|
36682
|
+
// src/sqlite/agent-capability-cache.ts
|
|
36683
|
+
function hasNonEmptyAgentCapabilityCache(db, workspaceId, agentType) {
|
|
36684
|
+
const t = agentType.trim();
|
|
36685
|
+
if (!t) return false;
|
|
36686
|
+
try {
|
|
36687
|
+
const row = db.get(
|
|
36688
|
+
`SELECT config_options_json FROM agent_capabilities WHERE workspace_id = ? AND agent_type = ?`,
|
|
36689
|
+
[workspaceId, t]
|
|
36690
|
+
);
|
|
36691
|
+
if (row?.config_options_json == null || row.config_options_json === "") return false;
|
|
36692
|
+
const parsed = JSON.parse(row.config_options_json);
|
|
36693
|
+
return Array.isArray(parsed) && parsed.length > 0;
|
|
36694
|
+
} catch {
|
|
36695
|
+
return false;
|
|
36696
|
+
}
|
|
36697
|
+
}
|
|
36698
|
+
function upsertCliAgentCapabilityCache(db, row) {
|
|
36699
|
+
const t = row.agentType.trim();
|
|
36700
|
+
if (!t) return false;
|
|
36701
|
+
const hash = hashJsonUtf8Sha256(row.configOptions);
|
|
36702
|
+
try {
|
|
36703
|
+
const prev = db.get(
|
|
36704
|
+
`SELECT content_hash FROM agent_capabilities WHERE workspace_id = ? AND agent_type = ?`,
|
|
36705
|
+
[row.workspaceId, t]
|
|
36706
|
+
);
|
|
36707
|
+
if (prev?.content_hash === hash) return false;
|
|
36708
|
+
} catch {
|
|
36709
|
+
}
|
|
36710
|
+
const json2 = JSON.stringify(row.configOptions);
|
|
36711
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
36712
|
+
db.run(
|
|
36713
|
+
`INSERT INTO agent_capabilities (workspace_id, agent_type, config_options_json, content_hash, updated_at)
|
|
36714
|
+
VALUES (?, ?, ?, ?, ?)
|
|
36715
|
+
ON CONFLICT(workspace_id, agent_type) DO UPDATE SET
|
|
36716
|
+
config_options_json = excluded.config_options_json,
|
|
36717
|
+
content_hash = excluded.content_hash,
|
|
36718
|
+
updated_at = excluded.updated_at`,
|
|
36719
|
+
[row.workspaceId, t, json2, hash, now]
|
|
36720
|
+
);
|
|
36721
|
+
return true;
|
|
36722
|
+
}
|
|
36723
|
+
function listCliAgentCapabilityCacheForWorkspace(db, workspaceId) {
|
|
36724
|
+
const rows = db.all(
|
|
36725
|
+
`SELECT agent_type, config_options_json FROM agent_capabilities WHERE workspace_id = ?`,
|
|
36726
|
+
[workspaceId]
|
|
36727
|
+
);
|
|
36728
|
+
const out = [];
|
|
36729
|
+
for (const r of rows) {
|
|
36730
|
+
try {
|
|
36731
|
+
const parsed = JSON.parse(r.config_options_json);
|
|
36732
|
+
if (!Array.isArray(parsed) || parsed.length === 0) continue;
|
|
36733
|
+
out.push({ agentType: r.agent_type, configOptions: parsed });
|
|
36734
|
+
} catch {
|
|
36735
|
+
}
|
|
36736
|
+
}
|
|
36737
|
+
return out;
|
|
36738
|
+
}
|
|
36739
|
+
|
|
36740
|
+
// src/agents/capabilities/warmup-agent-capabilities-on-connect.ts
|
|
36741
|
+
import * as path39 from "node:path";
|
|
36742
|
+
|
|
36743
|
+
// src/agents/capabilities/probe-one-agent-type-for-capabilities.ts
|
|
36744
|
+
import * as path38 from "node:path";
|
|
36745
|
+
async function probeOneAgentTypeForCapabilities(params) {
|
|
36746
|
+
const { agentType, cwd, workspaceId, log: log2, getDb, reportAgentCapabilities, bridgeReport = true } = params;
|
|
36747
|
+
const resolved = resolveAgentCommand(agentType);
|
|
36748
|
+
if (!resolved) return false;
|
|
36749
|
+
let sqliteChanged = false;
|
|
36750
|
+
const reportedRef = { done: false };
|
|
36751
|
+
const tryReport = (co) => {
|
|
36752
|
+
if (reportedRef.done) return;
|
|
36753
|
+
if (!Array.isArray(co) || co.length === 0) return;
|
|
36754
|
+
reportedRef.done = true;
|
|
36755
|
+
let changed = false;
|
|
36756
|
+
try {
|
|
36757
|
+
changed = upsertCliAgentCapabilityCache(getDb(), {
|
|
36758
|
+
workspaceId,
|
|
36759
|
+
agentType,
|
|
36760
|
+
configOptions: co
|
|
36761
|
+
});
|
|
36762
|
+
} catch {
|
|
36763
|
+
}
|
|
36764
|
+
sqliteChanged ||= changed;
|
|
36765
|
+
if (bridgeReport && changed) {
|
|
36766
|
+
reportAgentCapabilities?.({ agentType, configOptions: co });
|
|
36767
|
+
}
|
|
36768
|
+
};
|
|
36769
|
+
let handle = null;
|
|
36770
|
+
const killTimer = setTimeout(() => {
|
|
36771
|
+
try {
|
|
36772
|
+
handle?.disconnect();
|
|
36773
|
+
} catch {
|
|
36774
|
+
}
|
|
36775
|
+
}, 28e3);
|
|
36776
|
+
killTimer.unref?.();
|
|
36777
|
+
try {
|
|
36778
|
+
handle = await resolved.createClient({
|
|
36779
|
+
command: resolved.command,
|
|
36780
|
+
cwd: path38.resolve(cwd),
|
|
36781
|
+
backendAgentType: agentType,
|
|
36782
|
+
sessionMode: "agent",
|
|
36783
|
+
persistedAcpSessionId: null,
|
|
36784
|
+
agentConfig: null,
|
|
36785
|
+
getActiveConfigOptions: () => null,
|
|
36786
|
+
onAcpSessionEstablished: (info) => {
|
|
36787
|
+
tryReport(info.configOptions ?? null);
|
|
36788
|
+
},
|
|
36789
|
+
onAcpConfigOptionsUpdated: (co) => {
|
|
36790
|
+
tryReport(co);
|
|
36791
|
+
},
|
|
36792
|
+
onAgentSubprocessExit: () => {
|
|
36793
|
+
},
|
|
36794
|
+
onSessionUpdate: () => {
|
|
36795
|
+
}
|
|
36796
|
+
});
|
|
36797
|
+
await new Promise((r) => setTimeout(r, 1200));
|
|
36798
|
+
} catch (e) {
|
|
36799
|
+
log2(
|
|
36800
|
+
`[Bridge service] Agent capability probe (${agentType}): ${e instanceof Error ? e.message : String(e)}`
|
|
36801
|
+
);
|
|
36802
|
+
} finally {
|
|
36803
|
+
clearTimeout(killTimer);
|
|
36804
|
+
try {
|
|
36805
|
+
handle?.disconnect();
|
|
36806
|
+
} catch {
|
|
36807
|
+
}
|
|
36808
|
+
}
|
|
36809
|
+
return sqliteChanged;
|
|
36810
|
+
}
|
|
36811
|
+
|
|
36812
|
+
// src/agents/capabilities/probe-agent-capabilities-for-types.ts
|
|
36813
|
+
async function probeAgentCapabilitiesForDetectedTypes(params) {
|
|
36814
|
+
const {
|
|
36815
|
+
agentTypes,
|
|
36816
|
+
cwd,
|
|
36817
|
+
workspaceId,
|
|
36818
|
+
log: log2,
|
|
36819
|
+
getDb,
|
|
36820
|
+
reportAgentCapabilities,
|
|
36821
|
+
bridgeReport = true,
|
|
36822
|
+
forceAllTypes = false
|
|
36823
|
+
} = params;
|
|
36824
|
+
let changedCount = 0;
|
|
36825
|
+
for (let i = 0; i < agentTypes.length; i++) {
|
|
36826
|
+
if (i > 0) await yieldToEventLoop();
|
|
36827
|
+
const agentType = agentTypes[i];
|
|
36828
|
+
if (!agentType.trim()) continue;
|
|
36829
|
+
if (!forceAllTypes) {
|
|
36830
|
+
try {
|
|
36831
|
+
if (process.env.BUILDAUTOMATON_FORCE_PROBE_ACP_CAPABILITIES !== "1" && hasNonEmptyAgentCapabilityCache(getDb(), workspaceId, agentType)) {
|
|
36832
|
+
continue;
|
|
36833
|
+
}
|
|
36834
|
+
} catch {
|
|
36835
|
+
}
|
|
36836
|
+
}
|
|
36837
|
+
const changed = await probeOneAgentTypeForCapabilities({
|
|
36838
|
+
agentType,
|
|
36839
|
+
cwd,
|
|
36840
|
+
workspaceId,
|
|
36841
|
+
log: log2,
|
|
36842
|
+
getDb,
|
|
36843
|
+
reportAgentCapabilities,
|
|
36844
|
+
bridgeReport
|
|
36845
|
+
});
|
|
36846
|
+
if (changed) changedCount += 1;
|
|
36847
|
+
}
|
|
36848
|
+
return changedCount;
|
|
36849
|
+
}
|
|
36850
|
+
|
|
36851
|
+
// src/agents/capabilities/warmup-agent-capabilities-on-connect.ts
|
|
36852
|
+
async function warmupAgentCapabilitiesOnConnect(params) {
|
|
36853
|
+
const { workspaceId, log: log2, getDb, getWs } = params;
|
|
36854
|
+
const cwd = path39.resolve(getBridgeRoot());
|
|
36855
|
+
const db = getDb();
|
|
36856
|
+
function sendBatchFromCache() {
|
|
36857
|
+
const socket = getWs();
|
|
36858
|
+
if (!socket || socket.readyState !== wrapper_default.OPEN) return;
|
|
36859
|
+
try {
|
|
36860
|
+
const rows = listCliAgentCapabilityCacheForWorkspace(db, workspaceId);
|
|
36861
|
+
if (rows.length === 0) return;
|
|
36862
|
+
sendWsMessage(socket, {
|
|
36863
|
+
type: "agent_capabilities_batch",
|
|
36864
|
+
items: rows.map((r) => ({ agentType: r.agentType, configOptions: r.configOptions }))
|
|
36865
|
+
});
|
|
36866
|
+
} catch (e) {
|
|
36867
|
+
log2(
|
|
36868
|
+
`[Bridge service] Agent capability batch to bridge failed: ${e instanceof Error ? e.message : String(e)}`
|
|
36869
|
+
);
|
|
36870
|
+
}
|
|
36871
|
+
}
|
|
36872
|
+
sendBatchFromCache();
|
|
36873
|
+
let types = [];
|
|
36874
|
+
try {
|
|
36875
|
+
types = [...await detectLocalAgentTypes()];
|
|
36876
|
+
} catch (e) {
|
|
36877
|
+
log2(`[Bridge service] detectLocalAgentTypes failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
36878
|
+
}
|
|
36879
|
+
try {
|
|
36880
|
+
const n = await probeAgentCapabilitiesForDetectedTypes({
|
|
36881
|
+
agentTypes: types,
|
|
36882
|
+
cwd,
|
|
36883
|
+
workspaceId,
|
|
36884
|
+
log: log2,
|
|
36885
|
+
getDb,
|
|
36886
|
+
bridgeReport: false,
|
|
36887
|
+
forceAllTypes: false
|
|
36888
|
+
});
|
|
36889
|
+
if (n > 0) sendBatchFromCache();
|
|
36890
|
+
} catch (e) {
|
|
36891
|
+
log2(`[Bridge service] Agent capability probe (missing cache) failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
36892
|
+
}
|
|
36893
|
+
void (async () => {
|
|
36894
|
+
try {
|
|
36895
|
+
await yieldToEventLoop();
|
|
36896
|
+
const n = await probeAgentCapabilitiesForDetectedTypes({
|
|
36897
|
+
agentTypes: types,
|
|
36898
|
+
cwd,
|
|
36899
|
+
workspaceId,
|
|
36900
|
+
log: log2,
|
|
36901
|
+
getDb,
|
|
36902
|
+
bridgeReport: false,
|
|
36903
|
+
forceAllTypes: true
|
|
36904
|
+
});
|
|
36905
|
+
if (n > 0) sendBatchFromCache();
|
|
36906
|
+
} catch (e) {
|
|
36907
|
+
log2(`[Bridge service] Agent capability lazy refresh failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
36908
|
+
}
|
|
36909
|
+
})();
|
|
36910
|
+
}
|
|
36911
|
+
|
|
36554
36912
|
// src/connection/create-bridge-connection.ts
|
|
36555
36913
|
async function createBridgeConnection(options) {
|
|
36556
36914
|
const { apiUrl, workspaceId, justAuthenticated, onAuthInvalid, persistTokens } = options;
|
|
@@ -36579,16 +36937,39 @@ async function createBridgeConnection(options) {
|
|
|
36579
36937
|
firehoseOutage: createEmptyReconnectOutageTracker(),
|
|
36580
36938
|
lastFirehoseReconnectCloseMeta: null
|
|
36581
36939
|
};
|
|
36940
|
+
function getWs() {
|
|
36941
|
+
return state.currentWs;
|
|
36942
|
+
}
|
|
36943
|
+
function sendAgentCapabilitiesToBridge(info) {
|
|
36944
|
+
if (!Array.isArray(info.configOptions) || info.configOptions.length === 0) return;
|
|
36945
|
+
let changed = false;
|
|
36946
|
+
try {
|
|
36947
|
+
changed = upsertCliAgentCapabilityCache(getCliDatabase(), {
|
|
36948
|
+
workspaceId,
|
|
36949
|
+
agentType: info.agentType,
|
|
36950
|
+
configOptions: info.configOptions
|
|
36951
|
+
});
|
|
36952
|
+
} catch {
|
|
36953
|
+
}
|
|
36954
|
+
if (!changed) return;
|
|
36955
|
+
const socket = getWs();
|
|
36956
|
+
if (!socket || socket.readyState !== wrapper_default.OPEN) return;
|
|
36957
|
+
sendWsMessage(socket, {
|
|
36958
|
+
type: "agent_capabilities",
|
|
36959
|
+
agentType: info.agentType,
|
|
36960
|
+
configOptions: info.configOptions
|
|
36961
|
+
});
|
|
36962
|
+
}
|
|
36582
36963
|
const worktreesRootPath = options.worktreesRootPath ?? defaultWorktreesRootPath();
|
|
36583
36964
|
const sessionWorktreeManager = new SessionWorktreeManager({
|
|
36584
36965
|
worktreesRootPath,
|
|
36585
36966
|
log: logFn
|
|
36586
36967
|
});
|
|
36587
|
-
const acpManager = await createAcpManager({
|
|
36968
|
+
const acpManager = await createAcpManager({
|
|
36969
|
+
log: logFn,
|
|
36970
|
+
reportAgentCapabilities: sendAgentCapabilitiesToBridge
|
|
36971
|
+
});
|
|
36588
36972
|
logFn("CLI running. Press Ctrl+C to exit.");
|
|
36589
|
-
function getWs() {
|
|
36590
|
-
return state.currentWs;
|
|
36591
|
-
}
|
|
36592
36973
|
const e2ee = options.e2eCertificate ? createCliE2eeRuntime(options.e2eCertificate) : void 0;
|
|
36593
36974
|
const devServerManager = new DevServerManager({ getWs, log: logFn, getBridgeRoot, e2ee });
|
|
36594
36975
|
const bridgeHeartbeat = createBridgeHeartbeatController({ getWs, log: logFn });
|
|
@@ -36616,14 +36997,22 @@ async function createBridgeConnection(options) {
|
|
|
36616
36997
|
},
|
|
36617
36998
|
sendLocalSkillsReport,
|
|
36618
36999
|
reportAutoDetectedAgents,
|
|
37000
|
+
warmupAgentCapabilitiesOnConnect: async () => {
|
|
37001
|
+
await warmupAgentCapabilitiesOnConnect({
|
|
37002
|
+
workspaceId,
|
|
37003
|
+
log: logFn,
|
|
37004
|
+
getDb: getCliDatabase,
|
|
37005
|
+
getWs
|
|
37006
|
+
});
|
|
37007
|
+
},
|
|
36619
37008
|
devServerManager,
|
|
36620
37009
|
e2ee,
|
|
36621
37010
|
cloudApiBaseUrl: apiUrl,
|
|
36622
37011
|
getCloudAccessToken: () => tokens.accessToken
|
|
36623
37012
|
};
|
|
36624
37013
|
const identifyReportedPaths = {
|
|
36625
|
-
bridgeRootPath:
|
|
36626
|
-
worktreesRootPath:
|
|
37014
|
+
bridgeRootPath: path40.resolve(getBridgeRoot()),
|
|
37015
|
+
worktreesRootPath: path40.resolve(worktreesRootPath)
|
|
36627
37016
|
};
|
|
36628
37017
|
const { connect } = createMainBridgeWebSocketLifecycle({
|
|
36629
37018
|
state,
|