@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/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.31".length > 0 ? "0.1.31" : "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) {
|
|
@@ -25224,6 +25317,13 @@ function migrateCliSqlite(db) {
|
|
|
25224
25317
|
|
|
25225
25318
|
// src/sqlite/cli-database.ts
|
|
25226
25319
|
var { Database: SqliteDatabase } = sqliteWasm;
|
|
25320
|
+
function applyCliSqliteMemoryPragmas(db) {
|
|
25321
|
+
try {
|
|
25322
|
+
db.run("PRAGMA cache_size = -8192");
|
|
25323
|
+
db.run("PRAGMA temp_store = FILE");
|
|
25324
|
+
} catch {
|
|
25325
|
+
}
|
|
25326
|
+
}
|
|
25227
25327
|
var openDatabases = /* @__PURE__ */ new Map();
|
|
25228
25328
|
var processExitCloseRegistered = false;
|
|
25229
25329
|
function registerProcessExitSqliteClose() {
|
|
@@ -25260,6 +25360,7 @@ function getCliDatabase(options) {
|
|
|
25260
25360
|
ensureCliSqliteParentDir(sqlitePath);
|
|
25261
25361
|
const db = new SqliteDatabase(sqlitePath);
|
|
25262
25362
|
try {
|
|
25363
|
+
applyCliSqliteMemoryPragmas(db);
|
|
25263
25364
|
migrateCliSqlite(db);
|
|
25264
25365
|
importCliSqliteLegacyDiskData(db, options?.logLegacyMigration);
|
|
25265
25366
|
} catch (e) {
|
|
@@ -25275,7 +25376,7 @@ function getCliDatabase(options) {
|
|
|
25275
25376
|
async function closeBridgeConnection(state, acpManager, devServerManager, log2) {
|
|
25276
25377
|
const say = log2 ?? logImmediate;
|
|
25277
25378
|
say("Cleaning up connections\u2026");
|
|
25278
|
-
await new Promise((
|
|
25379
|
+
await new Promise((resolve18) => setImmediate(resolve18));
|
|
25279
25380
|
state.closedByUser = true;
|
|
25280
25381
|
clearReconnectQuietTimer(state.mainQuiet);
|
|
25281
25382
|
clearReconnectQuietTimer(state.firehoseQuiet);
|
|
@@ -25389,8 +25490,8 @@ function pathspec(...paths) {
|
|
|
25389
25490
|
cache.set(key, paths);
|
|
25390
25491
|
return key;
|
|
25391
25492
|
}
|
|
25392
|
-
function isPathSpec(
|
|
25393
|
-
return
|
|
25493
|
+
function isPathSpec(path41) {
|
|
25494
|
+
return path41 instanceof String && cache.has(path41);
|
|
25394
25495
|
}
|
|
25395
25496
|
function toPaths(pathSpec) {
|
|
25396
25497
|
return cache.get(pathSpec) || [];
|
|
@@ -25479,8 +25580,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
|
|
|
25479
25580
|
function forEachLineWithContent(input, callback) {
|
|
25480
25581
|
return toLinesWithContent(input, true).map((line) => callback(line));
|
|
25481
25582
|
}
|
|
25482
|
-
function folderExists(
|
|
25483
|
-
return (0, import_file_exists.exists)(
|
|
25583
|
+
function folderExists(path41) {
|
|
25584
|
+
return (0, import_file_exists.exists)(path41, import_file_exists.FOLDER);
|
|
25484
25585
|
}
|
|
25485
25586
|
function append(target, item) {
|
|
25486
25587
|
if (Array.isArray(target)) {
|
|
@@ -25884,8 +25985,8 @@ function checkIsRepoRootTask() {
|
|
|
25884
25985
|
commands,
|
|
25885
25986
|
format: "utf-8",
|
|
25886
25987
|
onError,
|
|
25887
|
-
parser(
|
|
25888
|
-
return /^\.(git)?$/.test(
|
|
25988
|
+
parser(path41) {
|
|
25989
|
+
return /^\.(git)?$/.test(path41.trim());
|
|
25889
25990
|
}
|
|
25890
25991
|
};
|
|
25891
25992
|
}
|
|
@@ -26319,11 +26420,11 @@ function parseGrep(grep) {
|
|
|
26319
26420
|
const paths = /* @__PURE__ */ new Set();
|
|
26320
26421
|
const results = {};
|
|
26321
26422
|
forEachLineWithContent(grep, (input) => {
|
|
26322
|
-
const [
|
|
26323
|
-
paths.add(
|
|
26324
|
-
(results[
|
|
26423
|
+
const [path41, line, preview] = input.split(NULL);
|
|
26424
|
+
paths.add(path41);
|
|
26425
|
+
(results[path41] = results[path41] || []).push({
|
|
26325
26426
|
line: asNumber(line),
|
|
26326
|
-
path:
|
|
26427
|
+
path: path41,
|
|
26327
26428
|
preview
|
|
26328
26429
|
});
|
|
26329
26430
|
});
|
|
@@ -27088,14 +27189,14 @@ var init_hash_object = __esm2({
|
|
|
27088
27189
|
init_task();
|
|
27089
27190
|
}
|
|
27090
27191
|
});
|
|
27091
|
-
function parseInit(bare,
|
|
27192
|
+
function parseInit(bare, path41, text) {
|
|
27092
27193
|
const response = String(text).trim();
|
|
27093
27194
|
let result;
|
|
27094
27195
|
if (result = initResponseRegex.exec(response)) {
|
|
27095
|
-
return new InitSummary(bare,
|
|
27196
|
+
return new InitSummary(bare, path41, false, result[1]);
|
|
27096
27197
|
}
|
|
27097
27198
|
if (result = reInitResponseRegex.exec(response)) {
|
|
27098
|
-
return new InitSummary(bare,
|
|
27199
|
+
return new InitSummary(bare, path41, true, result[1]);
|
|
27099
27200
|
}
|
|
27100
27201
|
let gitDir = "";
|
|
27101
27202
|
const tokens = response.split(" ");
|
|
@@ -27106,7 +27207,7 @@ function parseInit(bare, path39, text) {
|
|
|
27106
27207
|
break;
|
|
27107
27208
|
}
|
|
27108
27209
|
}
|
|
27109
|
-
return new InitSummary(bare,
|
|
27210
|
+
return new InitSummary(bare, path41, /^re/i.test(response), gitDir);
|
|
27110
27211
|
}
|
|
27111
27212
|
var InitSummary;
|
|
27112
27213
|
var initResponseRegex;
|
|
@@ -27115,9 +27216,9 @@ var init_InitSummary = __esm2({
|
|
|
27115
27216
|
"src/lib/responses/InitSummary.ts"() {
|
|
27116
27217
|
"use strict";
|
|
27117
27218
|
InitSummary = class {
|
|
27118
|
-
constructor(bare,
|
|
27219
|
+
constructor(bare, path41, existing, gitDir) {
|
|
27119
27220
|
this.bare = bare;
|
|
27120
|
-
this.path =
|
|
27221
|
+
this.path = path41;
|
|
27121
27222
|
this.existing = existing;
|
|
27122
27223
|
this.gitDir = gitDir;
|
|
27123
27224
|
}
|
|
@@ -27129,7 +27230,7 @@ var init_InitSummary = __esm2({
|
|
|
27129
27230
|
function hasBareCommand(command) {
|
|
27130
27231
|
return command.includes(bareCommand);
|
|
27131
27232
|
}
|
|
27132
|
-
function initTask(bare = false,
|
|
27233
|
+
function initTask(bare = false, path41, customArgs) {
|
|
27133
27234
|
const commands = ["init", ...customArgs];
|
|
27134
27235
|
if (bare && !hasBareCommand(commands)) {
|
|
27135
27236
|
commands.splice(1, 0, bareCommand);
|
|
@@ -27138,7 +27239,7 @@ function initTask(bare = false, path39, customArgs) {
|
|
|
27138
27239
|
commands,
|
|
27139
27240
|
format: "utf-8",
|
|
27140
27241
|
parser(text) {
|
|
27141
|
-
return parseInit(commands.includes("--bare"),
|
|
27242
|
+
return parseInit(commands.includes("--bare"), path41, text);
|
|
27142
27243
|
}
|
|
27143
27244
|
};
|
|
27144
27245
|
}
|
|
@@ -27954,12 +28055,12 @@ var init_FileStatusSummary = __esm2({
|
|
|
27954
28055
|
"use strict";
|
|
27955
28056
|
fromPathRegex = /^(.+)\0(.+)$/;
|
|
27956
28057
|
FileStatusSummary = class {
|
|
27957
|
-
constructor(
|
|
27958
|
-
this.path =
|
|
28058
|
+
constructor(path41, index, working_dir) {
|
|
28059
|
+
this.path = path41;
|
|
27959
28060
|
this.index = index;
|
|
27960
28061
|
this.working_dir = working_dir;
|
|
27961
28062
|
if (index === "R" || working_dir === "R") {
|
|
27962
|
-
const detail = fromPathRegex.exec(
|
|
28063
|
+
const detail = fromPathRegex.exec(path41) || [null, path41, path41];
|
|
27963
28064
|
this.from = detail[2] || "";
|
|
27964
28065
|
this.path = detail[1] || "";
|
|
27965
28066
|
}
|
|
@@ -27990,14 +28091,14 @@ function splitLine(result, lineStr) {
|
|
|
27990
28091
|
default:
|
|
27991
28092
|
return;
|
|
27992
28093
|
}
|
|
27993
|
-
function data(index, workingDir,
|
|
28094
|
+
function data(index, workingDir, path41) {
|
|
27994
28095
|
const raw = `${index}${workingDir}`;
|
|
27995
28096
|
const handler = parsers6.get(raw);
|
|
27996
28097
|
if (handler) {
|
|
27997
|
-
handler(result,
|
|
28098
|
+
handler(result, path41);
|
|
27998
28099
|
}
|
|
27999
28100
|
if (raw !== "##" && raw !== "!!") {
|
|
28000
|
-
result.files.push(new FileStatusSummary(
|
|
28101
|
+
result.files.push(new FileStatusSummary(path41, index, workingDir));
|
|
28001
28102
|
}
|
|
28002
28103
|
}
|
|
28003
28104
|
}
|
|
@@ -28306,9 +28407,9 @@ var init_simple_git_api = __esm2({
|
|
|
28306
28407
|
next
|
|
28307
28408
|
);
|
|
28308
28409
|
}
|
|
28309
|
-
hashObject(
|
|
28410
|
+
hashObject(path41, write) {
|
|
28310
28411
|
return this._runTask(
|
|
28311
|
-
hashObjectTask(
|
|
28412
|
+
hashObjectTask(path41, write === true),
|
|
28312
28413
|
trailingFunctionArgument(arguments)
|
|
28313
28414
|
);
|
|
28314
28415
|
}
|
|
@@ -28661,8 +28762,8 @@ var init_branch = __esm2({
|
|
|
28661
28762
|
}
|
|
28662
28763
|
});
|
|
28663
28764
|
function toPath(input) {
|
|
28664
|
-
const
|
|
28665
|
-
return
|
|
28765
|
+
const path41 = input.trim().replace(/^["']|["']$/g, "");
|
|
28766
|
+
return path41 && normalize2(path41);
|
|
28666
28767
|
}
|
|
28667
28768
|
var parseCheckIgnore;
|
|
28668
28769
|
var init_CheckIgnore = __esm2({
|
|
@@ -28976,8 +29077,8 @@ __export2(sub_module_exports, {
|
|
|
28976
29077
|
subModuleTask: () => subModuleTask,
|
|
28977
29078
|
updateSubModuleTask: () => updateSubModuleTask
|
|
28978
29079
|
});
|
|
28979
|
-
function addSubModuleTask(repo,
|
|
28980
|
-
return subModuleTask(["add", repo,
|
|
29080
|
+
function addSubModuleTask(repo, path41) {
|
|
29081
|
+
return subModuleTask(["add", repo, path41]);
|
|
28981
29082
|
}
|
|
28982
29083
|
function initSubModuleTask(customArgs) {
|
|
28983
29084
|
return subModuleTask(["init", ...customArgs]);
|
|
@@ -29310,8 +29411,8 @@ var require_git = __commonJS2({
|
|
|
29310
29411
|
}
|
|
29311
29412
|
return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
|
|
29312
29413
|
};
|
|
29313
|
-
Git2.prototype.submoduleAdd = function(repo,
|
|
29314
|
-
return this._runTask(addSubModuleTask2(repo,
|
|
29414
|
+
Git2.prototype.submoduleAdd = function(repo, path41, then) {
|
|
29415
|
+
return this._runTask(addSubModuleTask2(repo, path41), trailingFunctionArgument2(arguments));
|
|
29315
29416
|
};
|
|
29316
29417
|
Git2.prototype.submoduleUpdate = function(args, then) {
|
|
29317
29418
|
return this._runTask(
|
|
@@ -30198,9 +30299,9 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
|
|
|
30198
30299
|
// src/agents/acp/put-summarize-change-summaries.ts
|
|
30199
30300
|
async function putEncryptedChangeSummaryRows(params) {
|
|
30200
30301
|
const base = params.apiBaseUrl.replace(/\/+$/, "");
|
|
30201
|
-
const entries = params.rows.map(({ path:
|
|
30302
|
+
const entries = params.rows.map(({ path: path41, summary }) => {
|
|
30202
30303
|
const enc = params.e2ee.encryptFields({ summary }, ["summary"]);
|
|
30203
|
-
return { path:
|
|
30304
|
+
return { path: path41, summary: JSON.stringify(enc) };
|
|
30204
30305
|
});
|
|
30205
30306
|
const res = await fetch(
|
|
30206
30307
|
`${base}/api/sessions/${encodeURIComponent(params.sessionId)}/follow-ups/summarize-changes`,
|
|
@@ -30733,7 +30834,7 @@ async function createCursorAcpClient(options) {
|
|
|
30733
30834
|
logDebug,
|
|
30734
30835
|
getStderrText: () => stderrCapture.getText()
|
|
30735
30836
|
};
|
|
30736
|
-
return new Promise((
|
|
30837
|
+
return new Promise((resolve18, reject) => {
|
|
30737
30838
|
child.on("error", (err) => {
|
|
30738
30839
|
child.kill();
|
|
30739
30840
|
reject(new Error(formatSpawnError2(err, command[0])));
|
|
@@ -30812,12 +30913,16 @@ async function createCursorAcpClient(options) {
|
|
|
30812
30913
|
}
|
|
30813
30914
|
if (method === "session/request_permission" && typeof id === "number") {
|
|
30814
30915
|
const params = msg.params ?? {};
|
|
30815
|
-
|
|
30816
|
-
|
|
30817
|
-
|
|
30818
|
-
|
|
30819
|
-
|
|
30820
|
-
|
|
30916
|
+
if (onRequest) {
|
|
30917
|
+
pendingRequests.set(id, { method, params });
|
|
30918
|
+
onRequest({
|
|
30919
|
+
requestId: String(id),
|
|
30920
|
+
method,
|
|
30921
|
+
params
|
|
30922
|
+
});
|
|
30923
|
+
} else {
|
|
30924
|
+
respond(id, { outcome: { outcome: "denied" } });
|
|
30925
|
+
}
|
|
30821
30926
|
return;
|
|
30822
30927
|
}
|
|
30823
30928
|
if (typeof id === "number" && method) {
|
|
@@ -30905,7 +31010,7 @@ async function createCursorAcpClient(options) {
|
|
|
30905
31010
|
clientInfo: { name: "buildautomaton-cli", version: "0.1.0" }
|
|
30906
31011
|
});
|
|
30907
31012
|
const sessionId = established.sessionId;
|
|
30908
|
-
|
|
31013
|
+
resolve18({
|
|
30909
31014
|
sessionId,
|
|
30910
31015
|
async sendPrompt(prompt, options2) {
|
|
30911
31016
|
const imgs = options2?.images?.map((im) => ({ type: "image", mimeType: im.mimeType, data: im.dataBase64 }));
|
|
@@ -31613,6 +31718,28 @@ function sendGitHeadVsWorkspaceForToolPaths(mergedPaths, sentPaths, send, sessio
|
|
|
31613
31718
|
}
|
|
31614
31719
|
}
|
|
31615
31720
|
|
|
31721
|
+
// src/agents/acp/hooks/bridge-on-session-update/send-session-info-title-update.ts
|
|
31722
|
+
function extractSessionInfoTitle(params) {
|
|
31723
|
+
if (!params || typeof params !== "object") return null;
|
|
31724
|
+
const p = params;
|
|
31725
|
+
const title = typeof p.title === "string" ? p.title.trim() : "";
|
|
31726
|
+
return title ? title : null;
|
|
31727
|
+
}
|
|
31728
|
+
function sendSessionInfoTitleUpdate(params) {
|
|
31729
|
+
const title = extractSessionInfoTitle(params.payload);
|
|
31730
|
+
if (!title || !params.runId || !params.send) return;
|
|
31731
|
+
try {
|
|
31732
|
+
params.send({
|
|
31733
|
+
type: "session_title_update",
|
|
31734
|
+
...params.sessionId ? { sessionId: params.sessionId } : {},
|
|
31735
|
+
runId: params.runId,
|
|
31736
|
+
title
|
|
31737
|
+
});
|
|
31738
|
+
} catch (err) {
|
|
31739
|
+
params.log(`[Bridge service] Session title update send failed: ${errorMessage(err)}`);
|
|
31740
|
+
}
|
|
31741
|
+
}
|
|
31742
|
+
|
|
31616
31743
|
// src/agents/acp/hooks/bridge-on-session-update/create-bridge-on-session-update.ts
|
|
31617
31744
|
function createBridgeOnSessionUpdate(opts) {
|
|
31618
31745
|
const { routing, getSendSessionUpdate, log: log2, sessionParentPath } = opts;
|
|
@@ -31628,6 +31755,10 @@ function createBridgeOnSessionUpdate(opts) {
|
|
|
31628
31755
|
if (updateKind === "config_option_update") {
|
|
31629
31756
|
return;
|
|
31630
31757
|
}
|
|
31758
|
+
if (updateKind === "session_info_update") {
|
|
31759
|
+
sendSessionInfoTitleUpdate({ payload: params, runId, sessionId, send, log: log2 });
|
|
31760
|
+
return;
|
|
31761
|
+
}
|
|
31631
31762
|
const isCompletedToolCallUpdate = updateKind === "tool_call_update" && isCompletedToolStatus(p.status);
|
|
31632
31763
|
const toolName = p.toolCall?.name ?? p.tool_call?.name ?? "";
|
|
31633
31764
|
const isToolUpdate = updateKind === "tool_call" || updateKind === "tool_call_update" || typeof toolName === "string" && toolName.length > 0;
|
|
@@ -31785,6 +31916,7 @@ async function ensureAcpClient(options) {
|
|
|
31785
31916
|
sessionParentPath,
|
|
31786
31917
|
routing,
|
|
31787
31918
|
cloudSessionId,
|
|
31919
|
+
reportAgentCapabilities,
|
|
31788
31920
|
sendSessionUpdate,
|
|
31789
31921
|
sendRequest,
|
|
31790
31922
|
log: log2
|
|
@@ -31872,6 +32004,12 @@ async function ensureAcpClient(options) {
|
|
|
31872
32004
|
backendAgentType: preferredAgentType
|
|
31873
32005
|
});
|
|
31874
32006
|
}
|
|
32007
|
+
if (reportAgentCapabilities && preferredAgentType && Array.isArray(info.configOptions) && info.configOptions.length > 0) {
|
|
32008
|
+
reportAgentCapabilities({
|
|
32009
|
+
agentType: preferredAgentType,
|
|
32010
|
+
configOptions: info.configOptions
|
|
32011
|
+
});
|
|
32012
|
+
}
|
|
31875
32013
|
},
|
|
31876
32014
|
onAcpConfigOptionsUpdated: (configOptions) => {
|
|
31877
32015
|
state.activeSessionConfigOptions = configOptions;
|
|
@@ -31881,6 +32019,12 @@ async function ensureAcpClient(options) {
|
|
|
31881
32019
|
backendAgentType: preferredAgentType
|
|
31882
32020
|
});
|
|
31883
32021
|
}
|
|
32022
|
+
if (reportAgentCapabilities && preferredAgentType && Array.isArray(configOptions) && configOptions.length > 0) {
|
|
32023
|
+
reportAgentCapabilities({
|
|
32024
|
+
agentType: preferredAgentType,
|
|
32025
|
+
configOptions
|
|
32026
|
+
});
|
|
32027
|
+
}
|
|
31884
32028
|
},
|
|
31885
32029
|
onAgentSubprocessExit: () => {
|
|
31886
32030
|
state.acpHandle = null;
|
|
@@ -31911,7 +32055,7 @@ async function ensureAcpClient(options) {
|
|
|
31911
32055
|
|
|
31912
32056
|
// src/agents/acp/create-acp-manager.ts
|
|
31913
32057
|
async function createAcpManager(options) {
|
|
31914
|
-
const { log: log2 } = options;
|
|
32058
|
+
const { log: log2, reportAgentCapabilities } = options;
|
|
31915
32059
|
const state = {
|
|
31916
32060
|
acpHandle: null,
|
|
31917
32061
|
acpStartPromise: null,
|
|
@@ -31955,7 +32099,8 @@ async function createAcpManager(options) {
|
|
|
31955
32099
|
cloudApiBaseUrl,
|
|
31956
32100
|
getCloudAccessToken,
|
|
31957
32101
|
e2ee,
|
|
31958
|
-
attachments
|
|
32102
|
+
attachments,
|
|
32103
|
+
agentId
|
|
31959
32104
|
} = opts;
|
|
31960
32105
|
const preferredForPrompt = agentType ?? backendFallbackAgentType ?? null;
|
|
31961
32106
|
pendingCancelRunId = void 0;
|
|
@@ -31973,7 +32118,8 @@ async function createAcpManager(options) {
|
|
|
31973
32118
|
cloudSessionId: sessionId,
|
|
31974
32119
|
sendSessionUpdate,
|
|
31975
32120
|
sendRequest: sendSessionUpdate,
|
|
31976
|
-
log: log2
|
|
32121
|
+
log: log2,
|
|
32122
|
+
reportAgentCapabilities
|
|
31977
32123
|
});
|
|
31978
32124
|
if (!handle) {
|
|
31979
32125
|
const errMsg = state.lastAcpStartError || "No agent configured. Register local agents on this bridge in the app.";
|
|
@@ -33340,43 +33486,39 @@ import path28 from "node:path";
|
|
|
33340
33486
|
|
|
33341
33487
|
// src/runtime/yield-to-event-loop.ts
|
|
33342
33488
|
function yieldToEventLoop() {
|
|
33343
|
-
return new Promise((
|
|
33489
|
+
return new Promise((resolve18) => setImmediate(resolve18));
|
|
33344
33490
|
}
|
|
33345
33491
|
|
|
33346
33492
|
// src/files/index/walk-workspace-tree.ts
|
|
33347
33493
|
import fs24 from "node:fs";
|
|
33348
33494
|
import path27 from "node:path";
|
|
33349
|
-
|
|
33495
|
+
function shouldSkipWorkspaceWalkEntry(name) {
|
|
33496
|
+
return name.startsWith(".");
|
|
33497
|
+
}
|
|
33498
|
+
function walkWorkspaceTreeSync(dir, baseDir, onFile) {
|
|
33350
33499
|
let names;
|
|
33351
33500
|
try {
|
|
33352
|
-
names =
|
|
33501
|
+
names = fs24.readdirSync(dir);
|
|
33353
33502
|
} catch {
|
|
33354
33503
|
return;
|
|
33355
33504
|
}
|
|
33356
33505
|
for (const name of names) {
|
|
33357
|
-
if (name
|
|
33358
|
-
if (state.n > 0 && state.n % INDEX_WORK_YIELD_EVERY === 0) {
|
|
33359
|
-
await yieldToEventLoop();
|
|
33360
|
-
}
|
|
33361
|
-
state.n++;
|
|
33506
|
+
if (shouldSkipWorkspaceWalkEntry(name)) continue;
|
|
33362
33507
|
const full = path27.join(dir, name);
|
|
33363
33508
|
let stat2;
|
|
33364
33509
|
try {
|
|
33365
|
-
stat2 =
|
|
33510
|
+
stat2 = fs24.statSync(full);
|
|
33366
33511
|
} catch {
|
|
33367
33512
|
continue;
|
|
33368
33513
|
}
|
|
33369
33514
|
const relative5 = path27.relative(baseDir, full).replace(/\\/g, "/");
|
|
33370
33515
|
if (stat2.isDirectory()) {
|
|
33371
|
-
|
|
33516
|
+
walkWorkspaceTreeSync(full, baseDir, onFile);
|
|
33372
33517
|
} else if (stat2.isFile()) {
|
|
33373
|
-
|
|
33518
|
+
onFile(relative5);
|
|
33374
33519
|
}
|
|
33375
33520
|
}
|
|
33376
33521
|
}
|
|
33377
|
-
function createWalkYieldState() {
|
|
33378
|
-
return { n: 0 };
|
|
33379
|
-
}
|
|
33380
33522
|
|
|
33381
33523
|
// src/files/index/file-index-sqlite-lock.ts
|
|
33382
33524
|
import fs25 from "node:fs";
|
|
@@ -33409,20 +33551,29 @@ function withFileIndexSqliteLock(fn) {
|
|
|
33409
33551
|
}
|
|
33410
33552
|
|
|
33411
33553
|
// src/files/index/build-file-index.ts
|
|
33412
|
-
|
|
33413
|
-
|
|
33414
|
-
}
|
|
33415
|
-
function persistPathsToSqlite(resolved, paths) {
|
|
33554
|
+
var FILE_INDEX_INSERT_BUFFER = 2048;
|
|
33555
|
+
function persistFileIndexForResolvedCwd(resolved) {
|
|
33416
33556
|
const db = getCliDatabase();
|
|
33417
33557
|
const h = getCwdHashForFileIndex(resolved);
|
|
33558
|
+
const buf = [];
|
|
33559
|
+
let pathCount = 0;
|
|
33418
33560
|
db.run("BEGIN IMMEDIATE");
|
|
33419
33561
|
try {
|
|
33420
33562
|
db.run("DELETE FROM file_index_path WHERE cwd_hash = ?", [h]);
|
|
33421
33563
|
const ins = db.prepare("INSERT INTO file_index_path (cwd_hash, path) VALUES (?, ?)");
|
|
33422
33564
|
try {
|
|
33423
|
-
|
|
33424
|
-
|
|
33425
|
-
|
|
33565
|
+
const flushBuf = () => {
|
|
33566
|
+
for (const rel of buf) {
|
|
33567
|
+
ins.run([h, rel]);
|
|
33568
|
+
}
|
|
33569
|
+
pathCount += buf.length;
|
|
33570
|
+
buf.length = 0;
|
|
33571
|
+
};
|
|
33572
|
+
walkWorkspaceTreeSync(resolved, resolved, (rel) => {
|
|
33573
|
+
buf.push(rel);
|
|
33574
|
+
if (buf.length >= FILE_INDEX_INSERT_BUFFER) flushBuf();
|
|
33575
|
+
});
|
|
33576
|
+
flushBuf();
|
|
33426
33577
|
} finally {
|
|
33427
33578
|
ins.finalize();
|
|
33428
33579
|
}
|
|
@@ -33434,22 +33585,26 @@ function persistPathsToSqlite(resolved, paths) {
|
|
|
33434
33585
|
}
|
|
33435
33586
|
throw e;
|
|
33436
33587
|
}
|
|
33588
|
+
return pathCount;
|
|
33437
33589
|
}
|
|
33438
33590
|
async function buildFileIndexAsync(cwd) {
|
|
33439
33591
|
return withFileIndexSqliteLock(async () => {
|
|
33440
33592
|
const resolved = path28.resolve(cwd);
|
|
33441
|
-
const paths = [];
|
|
33442
|
-
await walkWorkspaceTreeAsync(resolved, resolved, paths, createWalkYieldState());
|
|
33443
33593
|
await yieldToEventLoop();
|
|
33444
|
-
|
|
33445
|
-
|
|
33446
|
-
return { pathCount
|
|
33594
|
+
const pathCount = persistFileIndexForResolvedCwd(resolved);
|
|
33595
|
+
await yieldToEventLoop();
|
|
33596
|
+
return { pathCount };
|
|
33447
33597
|
});
|
|
33448
33598
|
}
|
|
33449
33599
|
|
|
33450
33600
|
// src/files/index/ensure-file-index.ts
|
|
33451
33601
|
import path29 from "node:path";
|
|
33452
33602
|
|
|
33603
|
+
// src/files/index/file-index-dependency-path.ts
|
|
33604
|
+
function sqliteExprBridgeFileIndexDependencyRank() {
|
|
33605
|
+
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`;
|
|
33606
|
+
}
|
|
33607
|
+
|
|
33453
33608
|
// src/files/index/search-file-index.ts
|
|
33454
33609
|
function escapeLikePattern(fragment) {
|
|
33455
33610
|
return fragment.replace(/\\/g, "\\\\").replace(/%/g, "\\%").replace(/_/g, "\\_");
|
|
@@ -33474,8 +33629,9 @@ function searchBridgeFilePaths(resolvedCwd, query, limit = 100) {
|
|
|
33474
33629
|
const h = getCwdHashForFileIndex(resolvedCwd);
|
|
33475
33630
|
const pattern = `%${escapeLikePattern(q)}%`;
|
|
33476
33631
|
const lim = Math.max(0, Math.min(1e4, Math.floor(limit)));
|
|
33632
|
+
const depRank = sqliteExprBridgeFileIndexDependencyRank();
|
|
33477
33633
|
const rows = db.all(
|
|
33478
|
-
`SELECT path FROM file_index_path WHERE cwd_hash = ? AND lower(path) LIKE ? ESCAPE '\\' LIMIT ?`,
|
|
33634
|
+
`SELECT path FROM file_index_path WHERE cwd_hash = ? AND lower(path) LIKE ? ESCAPE '\\' ORDER BY ${depRank}, path LIMIT ?`,
|
|
33479
33635
|
[h, pattern, lim]
|
|
33480
33636
|
);
|
|
33481
33637
|
return rows.map((r) => String(r.path));
|
|
@@ -33500,7 +33656,6 @@ async function ensureFileIndexAsync(cwd) {
|
|
|
33500
33656
|
var DEBOUNCE_MS = 900;
|
|
33501
33657
|
function shouldIgnoreRelative(rel) {
|
|
33502
33658
|
const n = rel.replace(/\\/g, "/");
|
|
33503
|
-
if (n.includes("/node_modules/") || n.startsWith("node_modules/")) return true;
|
|
33504
33659
|
if (n.includes("/.git/") || n === ".git" || n.startsWith(".git/")) return true;
|
|
33505
33660
|
if (n.includes("/.buildautomaton/") || n.startsWith(".buildautomaton/")) return true;
|
|
33506
33661
|
return false;
|
|
@@ -33564,7 +33719,7 @@ function startFileIndexWatcher(cwd = getBridgeRoot()) {
|
|
|
33564
33719
|
}
|
|
33565
33720
|
|
|
33566
33721
|
// src/connection/create-bridge-connection.ts
|
|
33567
|
-
import * as
|
|
33722
|
+
import * as path40 from "node:path";
|
|
33568
33723
|
|
|
33569
33724
|
// src/dev-servers/manager/dev-server-manager.ts
|
|
33570
33725
|
import { rm as rm2 } from "node:fs/promises";
|
|
@@ -33586,15 +33741,15 @@ function sendDevServerStatus(getWs, serverId, status, options) {
|
|
|
33586
33741
|
|
|
33587
33742
|
// src/dev-servers/process/terminate-child-process.ts
|
|
33588
33743
|
async function sigtermAndWaitForExit(proc, graceMs, log2, shortId) {
|
|
33589
|
-
const exited = new Promise((
|
|
33590
|
-
proc.once("exit", () =>
|
|
33744
|
+
const exited = new Promise((resolve18) => {
|
|
33745
|
+
proc.once("exit", () => resolve18());
|
|
33591
33746
|
});
|
|
33592
33747
|
log2(`[dev-server] Sending SIGTERM to ${shortId} (pid=${proc.pid ?? "?"}).`);
|
|
33593
33748
|
try {
|
|
33594
33749
|
proc.kill("SIGTERM");
|
|
33595
33750
|
} catch {
|
|
33596
33751
|
}
|
|
33597
|
-
await Promise.race([exited, new Promise((
|
|
33752
|
+
await Promise.race([exited, new Promise((resolve18) => setTimeout(resolve18, graceMs))]);
|
|
33598
33753
|
}
|
|
33599
33754
|
function forceKillChild(proc, log2, shortId, graceMs) {
|
|
33600
33755
|
log2(
|
|
@@ -34948,6 +35103,13 @@ var handleBridgeIdentified = (msg, deps) => {
|
|
|
34948
35103
|
`[Bridge service] Auto-detect agents failed: ${e instanceof Error ? e.message : String(e)}`
|
|
34949
35104
|
);
|
|
34950
35105
|
}
|
|
35106
|
+
try {
|
|
35107
|
+
await deps.warmupAgentCapabilitiesOnConnect?.();
|
|
35108
|
+
} catch (e) {
|
|
35109
|
+
deps.log(
|
|
35110
|
+
`[Bridge service] Agent capability warmup failed: ${e instanceof Error ? e.message : String(e)}`
|
|
35111
|
+
);
|
|
35112
|
+
}
|
|
34951
35113
|
})();
|
|
34952
35114
|
});
|
|
34953
35115
|
setImmediate(() => {
|
|
@@ -35300,9 +35462,9 @@ function parseChangeSummarySnapshots(raw) {
|
|
|
35300
35462
|
for (const item of raw) {
|
|
35301
35463
|
if (!item || typeof item !== "object") continue;
|
|
35302
35464
|
const o = item;
|
|
35303
|
-
const
|
|
35304
|
-
if (!
|
|
35305
|
-
const row = { path:
|
|
35465
|
+
const path41 = typeof o.path === "string" && o.path.trim() !== "" ? o.path.trim() : "";
|
|
35466
|
+
if (!path41) continue;
|
|
35467
|
+
const row = { path: path41 };
|
|
35306
35468
|
if (typeof o.patchContent === "string") row.patchContent = o.patchContent;
|
|
35307
35469
|
if (typeof o.oldText === "string") row.oldText = o.oldText;
|
|
35308
35470
|
if (typeof o.newText === "string") row.newText = o.newText;
|
|
@@ -35420,6 +35582,8 @@ function handleBridgePrompt(msg, deps) {
|
|
|
35420
35582
|
const sessionParent = rawParent === "bridge_root" || rawParent === "worktrees_root" ? rawParent : rawParent === "session_worktrees_root" ? "worktrees_root" : null;
|
|
35421
35583
|
const sessionParentPath = typeof msg.sessionParentPath === "string" && msg.sessionParentPath.trim() ? msg.sessionParentPath.trim() : null;
|
|
35422
35584
|
const agentType = typeof msg.agentType === "string" && msg.agentType.trim() ? msg.agentType.trim() : void 0;
|
|
35585
|
+
const rawAgentId = msg.agentId;
|
|
35586
|
+
const agentId = typeof rawAgentId === "string" && rawAgentId.trim() !== "" ? rawAgentId.trim() : null;
|
|
35423
35587
|
const mode = typeof msg.mode === "string" && msg.mode.trim() ? msg.mode.trim() : void 0;
|
|
35424
35588
|
const agentConfig = msg.agentConfig != null && typeof msg.agentConfig === "object" && !Array.isArray(msg.agentConfig) ? msg.agentConfig : void 0;
|
|
35425
35589
|
acpManager.logPromptReceivedFromBridge({ agentType, mode });
|
|
@@ -35457,6 +35621,7 @@ function handleBridgePrompt(msg, deps) {
|
|
|
35457
35621
|
runId,
|
|
35458
35622
|
mode,
|
|
35459
35623
|
agentType,
|
|
35624
|
+
agentId,
|
|
35460
35625
|
agentConfig,
|
|
35461
35626
|
sessionParentPath: effectiveCwd,
|
|
35462
35627
|
sendResult: sendResult2,
|
|
@@ -36551,6 +36716,242 @@ function createBridgeHeartbeatController(params) {
|
|
|
36551
36716
|
};
|
|
36552
36717
|
}
|
|
36553
36718
|
|
|
36719
|
+
// src/sqlite/hash-json-sha256.ts
|
|
36720
|
+
import { createHash } from "node:crypto";
|
|
36721
|
+
function hashJsonUtf8Sha256(value) {
|
|
36722
|
+
return createHash("sha256").update(JSON.stringify(value), "utf8").digest("hex");
|
|
36723
|
+
}
|
|
36724
|
+
|
|
36725
|
+
// src/sqlite/agent-capability-cache.ts
|
|
36726
|
+
function hasNonEmptyAgentCapabilityCache(db, workspaceId, agentType) {
|
|
36727
|
+
const t = agentType.trim();
|
|
36728
|
+
if (!t) return false;
|
|
36729
|
+
try {
|
|
36730
|
+
const row = db.get(
|
|
36731
|
+
`SELECT config_options_json FROM agent_capabilities WHERE workspace_id = ? AND agent_type = ?`,
|
|
36732
|
+
[workspaceId, t]
|
|
36733
|
+
);
|
|
36734
|
+
if (row?.config_options_json == null || row.config_options_json === "") return false;
|
|
36735
|
+
const parsed = JSON.parse(row.config_options_json);
|
|
36736
|
+
return Array.isArray(parsed) && parsed.length > 0;
|
|
36737
|
+
} catch {
|
|
36738
|
+
return false;
|
|
36739
|
+
}
|
|
36740
|
+
}
|
|
36741
|
+
function upsertCliAgentCapabilityCache(db, row) {
|
|
36742
|
+
const t = row.agentType.trim();
|
|
36743
|
+
if (!t) return false;
|
|
36744
|
+
const hash = hashJsonUtf8Sha256(row.configOptions);
|
|
36745
|
+
try {
|
|
36746
|
+
const prev = db.get(
|
|
36747
|
+
`SELECT content_hash FROM agent_capabilities WHERE workspace_id = ? AND agent_type = ?`,
|
|
36748
|
+
[row.workspaceId, t]
|
|
36749
|
+
);
|
|
36750
|
+
if (prev?.content_hash === hash) return false;
|
|
36751
|
+
} catch {
|
|
36752
|
+
}
|
|
36753
|
+
const json2 = JSON.stringify(row.configOptions);
|
|
36754
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
36755
|
+
db.run(
|
|
36756
|
+
`INSERT INTO agent_capabilities (workspace_id, agent_type, config_options_json, content_hash, updated_at)
|
|
36757
|
+
VALUES (?, ?, ?, ?, ?)
|
|
36758
|
+
ON CONFLICT(workspace_id, agent_type) DO UPDATE SET
|
|
36759
|
+
config_options_json = excluded.config_options_json,
|
|
36760
|
+
content_hash = excluded.content_hash,
|
|
36761
|
+
updated_at = excluded.updated_at`,
|
|
36762
|
+
[row.workspaceId, t, json2, hash, now]
|
|
36763
|
+
);
|
|
36764
|
+
return true;
|
|
36765
|
+
}
|
|
36766
|
+
function listCliAgentCapabilityCacheForWorkspace(db, workspaceId) {
|
|
36767
|
+
const rows = db.all(
|
|
36768
|
+
`SELECT agent_type, config_options_json FROM agent_capabilities WHERE workspace_id = ?`,
|
|
36769
|
+
[workspaceId]
|
|
36770
|
+
);
|
|
36771
|
+
const out = [];
|
|
36772
|
+
for (const r of rows) {
|
|
36773
|
+
try {
|
|
36774
|
+
const parsed = JSON.parse(r.config_options_json);
|
|
36775
|
+
if (!Array.isArray(parsed) || parsed.length === 0) continue;
|
|
36776
|
+
out.push({ agentType: r.agent_type, configOptions: parsed });
|
|
36777
|
+
} catch {
|
|
36778
|
+
}
|
|
36779
|
+
}
|
|
36780
|
+
return out;
|
|
36781
|
+
}
|
|
36782
|
+
|
|
36783
|
+
// src/agents/capabilities/warmup-agent-capabilities-on-connect.ts
|
|
36784
|
+
import * as path39 from "node:path";
|
|
36785
|
+
|
|
36786
|
+
// src/agents/capabilities/probe-one-agent-type-for-capabilities.ts
|
|
36787
|
+
import * as path38 from "node:path";
|
|
36788
|
+
async function probeOneAgentTypeForCapabilities(params) {
|
|
36789
|
+
const { agentType, cwd, workspaceId, log: log2, getDb, reportAgentCapabilities, bridgeReport = true } = params;
|
|
36790
|
+
const resolved = resolveAgentCommand(agentType);
|
|
36791
|
+
if (!resolved) return false;
|
|
36792
|
+
let sqliteChanged = false;
|
|
36793
|
+
const reportedRef = { done: false };
|
|
36794
|
+
const tryReport = (co) => {
|
|
36795
|
+
if (reportedRef.done) return;
|
|
36796
|
+
if (!Array.isArray(co) || co.length === 0) return;
|
|
36797
|
+
reportedRef.done = true;
|
|
36798
|
+
let changed = false;
|
|
36799
|
+
try {
|
|
36800
|
+
changed = upsertCliAgentCapabilityCache(getDb(), {
|
|
36801
|
+
workspaceId,
|
|
36802
|
+
agentType,
|
|
36803
|
+
configOptions: co
|
|
36804
|
+
});
|
|
36805
|
+
} catch {
|
|
36806
|
+
}
|
|
36807
|
+
sqliteChanged ||= changed;
|
|
36808
|
+
if (bridgeReport && changed) {
|
|
36809
|
+
reportAgentCapabilities?.({ agentType, configOptions: co });
|
|
36810
|
+
}
|
|
36811
|
+
};
|
|
36812
|
+
let handle = null;
|
|
36813
|
+
const killTimer = setTimeout(() => {
|
|
36814
|
+
try {
|
|
36815
|
+
handle?.disconnect();
|
|
36816
|
+
} catch {
|
|
36817
|
+
}
|
|
36818
|
+
}, 28e3);
|
|
36819
|
+
killTimer.unref?.();
|
|
36820
|
+
try {
|
|
36821
|
+
handle = await resolved.createClient({
|
|
36822
|
+
command: resolved.command,
|
|
36823
|
+
cwd: path38.resolve(cwd),
|
|
36824
|
+
backendAgentType: agentType,
|
|
36825
|
+
sessionMode: "agent",
|
|
36826
|
+
persistedAcpSessionId: null,
|
|
36827
|
+
agentConfig: null,
|
|
36828
|
+
getActiveConfigOptions: () => null,
|
|
36829
|
+
onAcpSessionEstablished: (info) => {
|
|
36830
|
+
tryReport(info.configOptions ?? null);
|
|
36831
|
+
},
|
|
36832
|
+
onAcpConfigOptionsUpdated: (co) => {
|
|
36833
|
+
tryReport(co);
|
|
36834
|
+
},
|
|
36835
|
+
onAgentSubprocessExit: () => {
|
|
36836
|
+
},
|
|
36837
|
+
onSessionUpdate: () => {
|
|
36838
|
+
}
|
|
36839
|
+
});
|
|
36840
|
+
await new Promise((r) => setTimeout(r, 1200));
|
|
36841
|
+
} catch (e) {
|
|
36842
|
+
log2(
|
|
36843
|
+
`[Bridge service] Agent capability probe (${agentType}): ${e instanceof Error ? e.message : String(e)}`
|
|
36844
|
+
);
|
|
36845
|
+
} finally {
|
|
36846
|
+
clearTimeout(killTimer);
|
|
36847
|
+
try {
|
|
36848
|
+
handle?.disconnect();
|
|
36849
|
+
} catch {
|
|
36850
|
+
}
|
|
36851
|
+
}
|
|
36852
|
+
return sqliteChanged;
|
|
36853
|
+
}
|
|
36854
|
+
|
|
36855
|
+
// src/agents/capabilities/probe-agent-capabilities-for-types.ts
|
|
36856
|
+
async function probeAgentCapabilitiesForDetectedTypes(params) {
|
|
36857
|
+
const {
|
|
36858
|
+
agentTypes,
|
|
36859
|
+
cwd,
|
|
36860
|
+
workspaceId,
|
|
36861
|
+
log: log2,
|
|
36862
|
+
getDb,
|
|
36863
|
+
reportAgentCapabilities,
|
|
36864
|
+
bridgeReport = true,
|
|
36865
|
+
forceAllTypes = false
|
|
36866
|
+
} = params;
|
|
36867
|
+
let changedCount = 0;
|
|
36868
|
+
for (let i = 0; i < agentTypes.length; i++) {
|
|
36869
|
+
if (i > 0) await yieldToEventLoop();
|
|
36870
|
+
const agentType = agentTypes[i];
|
|
36871
|
+
if (!agentType.trim()) continue;
|
|
36872
|
+
if (!forceAllTypes) {
|
|
36873
|
+
try {
|
|
36874
|
+
if (process.env.BUILDAUTOMATON_FORCE_PROBE_ACP_CAPABILITIES !== "1" && hasNonEmptyAgentCapabilityCache(getDb(), workspaceId, agentType)) {
|
|
36875
|
+
continue;
|
|
36876
|
+
}
|
|
36877
|
+
} catch {
|
|
36878
|
+
}
|
|
36879
|
+
}
|
|
36880
|
+
const changed = await probeOneAgentTypeForCapabilities({
|
|
36881
|
+
agentType,
|
|
36882
|
+
cwd,
|
|
36883
|
+
workspaceId,
|
|
36884
|
+
log: log2,
|
|
36885
|
+
getDb,
|
|
36886
|
+
reportAgentCapabilities,
|
|
36887
|
+
bridgeReport
|
|
36888
|
+
});
|
|
36889
|
+
if (changed) changedCount += 1;
|
|
36890
|
+
}
|
|
36891
|
+
return changedCount;
|
|
36892
|
+
}
|
|
36893
|
+
|
|
36894
|
+
// src/agents/capabilities/warmup-agent-capabilities-on-connect.ts
|
|
36895
|
+
async function warmupAgentCapabilitiesOnConnect(params) {
|
|
36896
|
+
const { workspaceId, log: log2, getDb, getWs } = params;
|
|
36897
|
+
const cwd = path39.resolve(getBridgeRoot());
|
|
36898
|
+
const db = getDb();
|
|
36899
|
+
function sendBatchFromCache() {
|
|
36900
|
+
const socket = getWs();
|
|
36901
|
+
if (!socket || socket.readyState !== wrapper_default.OPEN) return;
|
|
36902
|
+
try {
|
|
36903
|
+
const rows = listCliAgentCapabilityCacheForWorkspace(db, workspaceId);
|
|
36904
|
+
if (rows.length === 0) return;
|
|
36905
|
+
sendWsMessage(socket, {
|
|
36906
|
+
type: "agent_capabilities_batch",
|
|
36907
|
+
items: rows.map((r) => ({ agentType: r.agentType, configOptions: r.configOptions }))
|
|
36908
|
+
});
|
|
36909
|
+
} catch (e) {
|
|
36910
|
+
log2(
|
|
36911
|
+
`[Bridge service] Agent capability batch to bridge failed: ${e instanceof Error ? e.message : String(e)}`
|
|
36912
|
+
);
|
|
36913
|
+
}
|
|
36914
|
+
}
|
|
36915
|
+
sendBatchFromCache();
|
|
36916
|
+
let types = [];
|
|
36917
|
+
try {
|
|
36918
|
+
types = [...await detectLocalAgentTypes()];
|
|
36919
|
+
} catch (e) {
|
|
36920
|
+
log2(`[Bridge service] detectLocalAgentTypes failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
36921
|
+
}
|
|
36922
|
+
try {
|
|
36923
|
+
const n = await probeAgentCapabilitiesForDetectedTypes({
|
|
36924
|
+
agentTypes: types,
|
|
36925
|
+
cwd,
|
|
36926
|
+
workspaceId,
|
|
36927
|
+
log: log2,
|
|
36928
|
+
getDb,
|
|
36929
|
+
bridgeReport: false,
|
|
36930
|
+
forceAllTypes: false
|
|
36931
|
+
});
|
|
36932
|
+
if (n > 0) sendBatchFromCache();
|
|
36933
|
+
} catch (e) {
|
|
36934
|
+
log2(`[Bridge service] Agent capability probe (missing cache) failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
36935
|
+
}
|
|
36936
|
+
void (async () => {
|
|
36937
|
+
try {
|
|
36938
|
+
await yieldToEventLoop();
|
|
36939
|
+
const n = await probeAgentCapabilitiesForDetectedTypes({
|
|
36940
|
+
agentTypes: types,
|
|
36941
|
+
cwd,
|
|
36942
|
+
workspaceId,
|
|
36943
|
+
log: log2,
|
|
36944
|
+
getDb,
|
|
36945
|
+
bridgeReport: false,
|
|
36946
|
+
forceAllTypes: true
|
|
36947
|
+
});
|
|
36948
|
+
if (n > 0) sendBatchFromCache();
|
|
36949
|
+
} catch (e) {
|
|
36950
|
+
log2(`[Bridge service] Agent capability lazy refresh failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
36951
|
+
}
|
|
36952
|
+
})();
|
|
36953
|
+
}
|
|
36954
|
+
|
|
36554
36955
|
// src/connection/create-bridge-connection.ts
|
|
36555
36956
|
async function createBridgeConnection(options) {
|
|
36556
36957
|
const { apiUrl, workspaceId, justAuthenticated, onAuthInvalid, persistTokens } = options;
|
|
@@ -36579,16 +36980,39 @@ async function createBridgeConnection(options) {
|
|
|
36579
36980
|
firehoseOutage: createEmptyReconnectOutageTracker(),
|
|
36580
36981
|
lastFirehoseReconnectCloseMeta: null
|
|
36581
36982
|
};
|
|
36983
|
+
function getWs() {
|
|
36984
|
+
return state.currentWs;
|
|
36985
|
+
}
|
|
36986
|
+
function sendAgentCapabilitiesToBridge(info) {
|
|
36987
|
+
if (!Array.isArray(info.configOptions) || info.configOptions.length === 0) return;
|
|
36988
|
+
let changed = false;
|
|
36989
|
+
try {
|
|
36990
|
+
changed = upsertCliAgentCapabilityCache(getCliDatabase(), {
|
|
36991
|
+
workspaceId,
|
|
36992
|
+
agentType: info.agentType,
|
|
36993
|
+
configOptions: info.configOptions
|
|
36994
|
+
});
|
|
36995
|
+
} catch {
|
|
36996
|
+
}
|
|
36997
|
+
if (!changed) return;
|
|
36998
|
+
const socket = getWs();
|
|
36999
|
+
if (!socket || socket.readyState !== wrapper_default.OPEN) return;
|
|
37000
|
+
sendWsMessage(socket, {
|
|
37001
|
+
type: "agent_capabilities",
|
|
37002
|
+
agentType: info.agentType,
|
|
37003
|
+
configOptions: info.configOptions
|
|
37004
|
+
});
|
|
37005
|
+
}
|
|
36582
37006
|
const worktreesRootPath = options.worktreesRootPath ?? defaultWorktreesRootPath();
|
|
36583
37007
|
const sessionWorktreeManager = new SessionWorktreeManager({
|
|
36584
37008
|
worktreesRootPath,
|
|
36585
37009
|
log: logFn
|
|
36586
37010
|
});
|
|
36587
|
-
const acpManager = await createAcpManager({
|
|
37011
|
+
const acpManager = await createAcpManager({
|
|
37012
|
+
log: logFn,
|
|
37013
|
+
reportAgentCapabilities: sendAgentCapabilitiesToBridge
|
|
37014
|
+
});
|
|
36588
37015
|
logFn("CLI running. Press Ctrl+C to exit.");
|
|
36589
|
-
function getWs() {
|
|
36590
|
-
return state.currentWs;
|
|
36591
|
-
}
|
|
36592
37016
|
const e2ee = options.e2eCertificate ? createCliE2eeRuntime(options.e2eCertificate) : void 0;
|
|
36593
37017
|
const devServerManager = new DevServerManager({ getWs, log: logFn, getBridgeRoot, e2ee });
|
|
36594
37018
|
const bridgeHeartbeat = createBridgeHeartbeatController({ getWs, log: logFn });
|
|
@@ -36616,14 +37040,22 @@ async function createBridgeConnection(options) {
|
|
|
36616
37040
|
},
|
|
36617
37041
|
sendLocalSkillsReport,
|
|
36618
37042
|
reportAutoDetectedAgents,
|
|
37043
|
+
warmupAgentCapabilitiesOnConnect: async () => {
|
|
37044
|
+
await warmupAgentCapabilitiesOnConnect({
|
|
37045
|
+
workspaceId,
|
|
37046
|
+
log: logFn,
|
|
37047
|
+
getDb: getCliDatabase,
|
|
37048
|
+
getWs
|
|
37049
|
+
});
|
|
37050
|
+
},
|
|
36619
37051
|
devServerManager,
|
|
36620
37052
|
e2ee,
|
|
36621
37053
|
cloudApiBaseUrl: apiUrl,
|
|
36622
37054
|
getCloudAccessToken: () => tokens.accessToken
|
|
36623
37055
|
};
|
|
36624
37056
|
const identifyReportedPaths = {
|
|
36625
|
-
bridgeRootPath:
|
|
36626
|
-
worktreesRootPath:
|
|
37057
|
+
bridgeRootPath: path40.resolve(getBridgeRoot()),
|
|
37058
|
+
worktreesRootPath: path40.resolve(worktreesRootPath)
|
|
36627
37059
|
};
|
|
36628
37060
|
const { connect } = createMainBridgeWebSocketLifecycle({
|
|
36629
37061
|
state,
|