@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 CHANGED
@@ -973,7 +973,7 @@ var require_command = __commonJS({
973
973
  "../../node_modules/.pnpm/commander@12.1.0/node_modules/commander/lib/command.js"(exports) {
974
974
  var EventEmitter2 = __require("node:events").EventEmitter;
975
975
  var childProcess2 = __require("node:child_process");
976
- var path41 = __require("node:path");
976
+ var path43 = __require("node:path");
977
977
  var fs38 = __require("node:fs");
978
978
  var process8 = __require("node:process");
979
979
  var { Argument: Argument2, humanReadableArgName } = require_argument();
@@ -1906,9 +1906,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
1906
1906
  let launchWithNode = false;
1907
1907
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
1908
1908
  function findFile(baseDir, baseName) {
1909
- const localBin = path41.resolve(baseDir, baseName);
1909
+ const localBin = path43.resolve(baseDir, baseName);
1910
1910
  if (fs38.existsSync(localBin)) return localBin;
1911
- if (sourceExt.includes(path41.extname(baseName))) return void 0;
1911
+ if (sourceExt.includes(path43.extname(baseName))) return void 0;
1912
1912
  const foundExt = sourceExt.find(
1913
1913
  (ext) => fs38.existsSync(`${localBin}${ext}`)
1914
1914
  );
@@ -1926,17 +1926,17 @@ Expecting one of '${allowedValues.join("', '")}'`);
1926
1926
  } catch (err) {
1927
1927
  resolvedScriptPath = this._scriptPath;
1928
1928
  }
1929
- executableDir = path41.resolve(
1930
- path41.dirname(resolvedScriptPath),
1929
+ executableDir = path43.resolve(
1930
+ path43.dirname(resolvedScriptPath),
1931
1931
  executableDir
1932
1932
  );
1933
1933
  }
1934
1934
  if (executableDir) {
1935
1935
  let localFile = findFile(executableDir, executableFile);
1936
1936
  if (!localFile && !subcommand._executableFile && this._scriptPath) {
1937
- const legacyName = path41.basename(
1937
+ const legacyName = path43.basename(
1938
1938
  this._scriptPath,
1939
- path41.extname(this._scriptPath)
1939
+ path43.extname(this._scriptPath)
1940
1940
  );
1941
1941
  if (legacyName !== this._name) {
1942
1942
  localFile = findFile(
@@ -1947,7 +1947,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1947
1947
  }
1948
1948
  executableFile = localFile || executableFile;
1949
1949
  }
1950
- launchWithNode = sourceExt.includes(path41.extname(executableFile));
1950
+ launchWithNode = sourceExt.includes(path43.extname(executableFile));
1951
1951
  let proc;
1952
1952
  if (process8.platform !== "win32") {
1953
1953
  if (launchWithNode) {
@@ -2787,7 +2787,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2787
2787
  * @return {Command}
2788
2788
  */
2789
2789
  nameFromFilename(filename) {
2790
- this._name = path41.basename(filename, path41.extname(filename));
2790
+ this._name = path43.basename(filename, path43.extname(filename));
2791
2791
  return this;
2792
2792
  }
2793
2793
  /**
@@ -2801,9 +2801,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
2801
2801
  * @param {string} [path]
2802
2802
  * @return {(string|null|Command)}
2803
2803
  */
2804
- executableDir(path42) {
2805
- if (path42 === void 0) return this._executableDir;
2806
- this._executableDir = path42;
2804
+ executableDir(path44) {
2805
+ if (path44 === void 0) return this._executableDir;
2806
+ this._executableDir = path44;
2807
2807
  return this;
2808
2808
  }
2809
2809
  /**
@@ -5236,7 +5236,7 @@ var require_websocket = __commonJS({
5236
5236
  var http = __require("http");
5237
5237
  var net = __require("net");
5238
5238
  var tls = __require("tls");
5239
- var { randomBytes: randomBytes3, createHash: createHash2 } = __require("crypto");
5239
+ var { randomBytes: randomBytes3, createHash: createHash3 } = __require("crypto");
5240
5240
  var { Duplex, Readable: Readable2 } = __require("stream");
5241
5241
  var { URL: URL2 } = __require("url");
5242
5242
  var PerMessageDeflate = require_permessage_deflate();
@@ -5896,7 +5896,7 @@ var require_websocket = __commonJS({
5896
5896
  abortHandshake(websocket, socket, "Invalid Upgrade header");
5897
5897
  return;
5898
5898
  }
5899
- const digest = createHash2("sha1").update(key + GUID).digest("base64");
5899
+ const digest = createHash3("sha1").update(key + GUID).digest("base64");
5900
5900
  if (res.headers["sec-websocket-accept"] !== digest) {
5901
5901
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
5902
5902
  return;
@@ -6263,7 +6263,7 @@ var require_websocket_server = __commonJS({
6263
6263
  var EventEmitter2 = __require("events");
6264
6264
  var http = __require("http");
6265
6265
  var { Duplex } = __require("stream");
6266
- var { createHash: createHash2 } = __require("crypto");
6266
+ var { createHash: createHash3 } = __require("crypto");
6267
6267
  var extension = require_extension();
6268
6268
  var PerMessageDeflate = require_permessage_deflate();
6269
6269
  var subprotocol = require_subprotocol();
@@ -6564,7 +6564,7 @@ var require_websocket_server = __commonJS({
6564
6564
  );
6565
6565
  }
6566
6566
  if (this._state > RUNNING) return abortHandshake(socket, 503);
6567
- const digest = createHash2("sha1").update(key + GUID).digest("base64");
6567
+ const digest = createHash3("sha1").update(key + GUID).digest("base64");
6568
6568
  const headers = [
6569
6569
  "HTTP/1.1 101 Switching Protocols",
6570
6570
  "Upgrade: websocket",
@@ -7061,8 +7061,8 @@ var init_parseUtil = __esm({
7061
7061
  init_errors();
7062
7062
  init_en();
7063
7063
  makeIssue = (params) => {
7064
- const { data, path: path41, errorMaps, issueData } = params;
7065
- const fullPath = [...path41, ...issueData.path || []];
7064
+ const { data, path: path43, errorMaps, issueData } = params;
7065
+ const fullPath = [...path43, ...issueData.path || []];
7066
7066
  const fullIssue = {
7067
7067
  ...issueData,
7068
7068
  path: fullPath
@@ -7370,11 +7370,11 @@ var init_types = __esm({
7370
7370
  init_parseUtil();
7371
7371
  init_util();
7372
7372
  ParseInputLazyPath = class {
7373
- constructor(parent, value, path41, key) {
7373
+ constructor(parent, value, path43, key) {
7374
7374
  this._cachedPath = [];
7375
7375
  this.parent = parent;
7376
7376
  this.data = value;
7377
- this._path = path41;
7377
+ this._path = path43;
7378
7378
  this._key = key;
7379
7379
  }
7380
7380
  get path() {
@@ -11529,10 +11529,10 @@ var require_src2 = __commonJS({
11529
11529
  var fs_1 = __require("fs");
11530
11530
  var debug_1 = __importDefault(require_src());
11531
11531
  var log2 = debug_1.default("@kwsites/file-exists");
11532
- function check2(path41, isFile, isDirectory) {
11533
- log2(`checking %s`, path41);
11532
+ function check2(path43, isFile, isDirectory) {
11533
+ log2(`checking %s`, path43);
11534
11534
  try {
11535
- const stat3 = fs_1.statSync(path41);
11535
+ const stat3 = fs_1.statSync(path43);
11536
11536
  if (stat3.isFile() && isFile) {
11537
11537
  log2(`[OK] path represents a file`);
11538
11538
  return true;
@@ -11552,8 +11552,8 @@ var require_src2 = __commonJS({
11552
11552
  throw e;
11553
11553
  }
11554
11554
  }
11555
- function exists2(path41, type = exports.READABLE) {
11556
- return check2(path41, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
11555
+ function exists2(path43, type = exports.READABLE) {
11556
+ return check2(path43, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
11557
11557
  }
11558
11558
  exports.exists = exists2;
11559
11559
  exports.FILE = 1;
@@ -11850,10 +11850,10 @@ function assignProp(target, prop, value) {
11850
11850
  configurable: true
11851
11851
  });
11852
11852
  }
11853
- function getElementAtPath(obj, path41) {
11854
- if (!path41)
11853
+ function getElementAtPath(obj, path43) {
11854
+ if (!path43)
11855
11855
  return obj;
11856
- return path41.reduce((acc, key) => acc?.[key], obj);
11856
+ return path43.reduce((acc, key) => acc?.[key], obj);
11857
11857
  }
11858
11858
  function promiseAllObject(promisesObj) {
11859
11859
  const keys = Object.keys(promisesObj);
@@ -12102,11 +12102,11 @@ function aborted(x, startIndex = 0) {
12102
12102
  }
12103
12103
  return false;
12104
12104
  }
12105
- function prefixIssues(path41, issues) {
12105
+ function prefixIssues(path43, issues) {
12106
12106
  return issues.map((iss) => {
12107
12107
  var _a2;
12108
12108
  (_a2 = iss).path ?? (_a2.path = []);
12109
- iss.path.unshift(path41);
12109
+ iss.path.unshift(path43);
12110
12110
  return iss;
12111
12111
  });
12112
12112
  }
@@ -12295,7 +12295,7 @@ function treeifyError(error40, _mapper) {
12295
12295
  return issue2.message;
12296
12296
  };
12297
12297
  const result = { errors: [] };
12298
- const processError = (error41, path41 = []) => {
12298
+ const processError = (error41, path43 = []) => {
12299
12299
  var _a2, _b;
12300
12300
  for (const issue2 of error41.issues) {
12301
12301
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -12305,7 +12305,7 @@ function treeifyError(error40, _mapper) {
12305
12305
  } else if (issue2.code === "invalid_element") {
12306
12306
  processError({ issues: issue2.issues }, issue2.path);
12307
12307
  } else {
12308
- const fullpath = [...path41, ...issue2.path];
12308
+ const fullpath = [...path43, ...issue2.path];
12309
12309
  if (fullpath.length === 0) {
12310
12310
  result.errors.push(mapper(issue2));
12311
12311
  continue;
@@ -12335,9 +12335,9 @@ function treeifyError(error40, _mapper) {
12335
12335
  processError(error40);
12336
12336
  return result;
12337
12337
  }
12338
- function toDotPath(path41) {
12338
+ function toDotPath(path43) {
12339
12339
  const segs = [];
12340
- for (const seg of path41) {
12340
+ for (const seg of path43) {
12341
12341
  if (typeof seg === "number")
12342
12342
  segs.push(`[${seg}]`);
12343
12343
  else if (typeof seg === "symbol")
@@ -24800,8 +24800,8 @@ var init_acp = __esm({
24800
24800
  this.#requestHandler = requestHandler;
24801
24801
  this.#notificationHandler = notificationHandler;
24802
24802
  this.#stream = stream;
24803
- this.#closedPromise = new Promise((resolve18) => {
24804
- this.#abortController.signal.addEventListener("abort", () => resolve18());
24803
+ this.#closedPromise = new Promise((resolve20) => {
24804
+ this.#abortController.signal.addEventListener("abort", () => resolve20());
24805
24805
  });
24806
24806
  this.#receive();
24807
24807
  }
@@ -24950,8 +24950,8 @@ var init_acp = __esm({
24950
24950
  }
24951
24951
  async sendRequest(method, params) {
24952
24952
  const id = this.#nextRequestId++;
24953
- const responsePromise = new Promise((resolve18, reject) => {
24954
- this.#pendingResponses.set(id, { resolve: resolve18, reject });
24953
+ const responsePromise = new Promise((resolve20, reject) => {
24954
+ this.#pendingResponses.set(id, { resolve: resolve20, reject });
24955
24955
  });
24956
24956
  await this.#sendMessage({ jsonrpc: "2.0", id, method, params });
24957
24957
  return responsePromise;
@@ -25064,7 +25064,7 @@ var {
25064
25064
  } = import_index.default;
25065
25065
 
25066
25066
  // src/cli-version.ts
25067
- var CLI_VERSION = "0.1.29".length > 0 ? "0.1.29" : "0.0.0-dev";
25067
+ var CLI_VERSION = "0.1.30".length > 0 ? "0.1.30" : "0.0.0-dev";
25068
25068
 
25069
25069
  // src/cli/defaults.ts
25070
25070
  var DEFAULT_API_URL = process.env.BUILDAUTOMATON_API_URL ?? "https://api.buildautomaton.com";
@@ -25072,7 +25072,7 @@ var DEFAULT_FIREHOSE_URL = "https://buildautomaton-firehose.fly.dev";
25072
25072
 
25073
25073
  // src/cli/run-cli-action.ts
25074
25074
  import * as fs37 from "node:fs";
25075
- import * as path40 from "node:path";
25075
+ import * as path42 from "node:path";
25076
25076
 
25077
25077
  // src/cli-log-level.ts
25078
25078
  var verbosity = "info";
@@ -26077,14 +26077,14 @@ var baseOpen = async (options) => {
26077
26077
  }
26078
26078
  const subprocess = childProcess.spawn(command, cliArguments, childProcessOptions);
26079
26079
  if (options.wait) {
26080
- return new Promise((resolve18, reject) => {
26080
+ return new Promise((resolve20, reject) => {
26081
26081
  subprocess.once("error", reject);
26082
26082
  subprocess.once("close", (exitCode) => {
26083
26083
  if (!options.allowNonzeroExitCode && exitCode > 0) {
26084
26084
  reject(new Error(`Exited with code ${exitCode}`));
26085
26085
  return;
26086
26086
  }
26087
- resolve18(subprocess);
26087
+ resolve20(subprocess);
26088
26088
  });
26089
26089
  });
26090
26090
  }
@@ -26573,8 +26573,8 @@ function runPendingAuth(options) {
26573
26573
  let hasOpenedBrowser = false;
26574
26574
  let resolved = false;
26575
26575
  let resolveAuth;
26576
- const authPromise = new Promise((resolve18) => {
26577
- resolveAuth = resolve18;
26576
+ const authPromise = new Promise((resolve20) => {
26577
+ resolveAuth = resolve20;
26578
26578
  });
26579
26579
  let reconnectAttempt = 0;
26580
26580
  const signInQuiet = createEmptyReconnectQuietSlot();
@@ -26929,6 +26929,16 @@ function recordMigrationAndPruneCheckpointLegacy(db, migration, applied2) {
26929
26929
  }
26930
26930
  var CHECKPOINT_V1 = "001_cli_sqlite_checkpoint_v1";
26931
26931
  var CHECKPOINT_V1_SQL = readCliSqliteMigrationSql("001_cli_sqlite_checkpoint_v1.sql");
26932
+ var AGENT_CAPABILITIES_SQL = readCliSqliteMigrationSql("002_agent_capabilities.sql");
26933
+ function agentCapabilitiesTableState(db) {
26934
+ const rows = db.all(
26935
+ `SELECT name FROM sqlite_master WHERE type='table' AND name IN ('agent_capabilities', 'agent_capability_cache')`
26936
+ );
26937
+ const names = new Set(rows.map((r) => r.name));
26938
+ if (names.has("agent_capabilities")) return "current";
26939
+ if (names.has("agent_capability_cache")) return "legacy";
26940
+ return "new";
26941
+ }
26932
26942
  var CLI_SQLITE_MIGRATIONS = [
26933
26943
  {
26934
26944
  name: CHECKPOINT_V1,
@@ -26936,6 +26946,23 @@ var CLI_SQLITE_MIGRATIONS = [
26936
26946
  migrate: (db) => {
26937
26947
  db.exec(CHECKPOINT_V1_SQL);
26938
26948
  }
26949
+ },
26950
+ {
26951
+ name: "002_agent_capabilities",
26952
+ migrate: (db) => {
26953
+ const state = agentCapabilitiesTableState(db);
26954
+ if (state === "current") return;
26955
+ if (state === "legacy") {
26956
+ db.exec(`
26957
+ ALTER TABLE agent_capability_cache RENAME TO agent_capabilities;
26958
+ DROP INDEX IF EXISTS idx_agent_capability_cache_workspace;
26959
+ CREATE INDEX IF NOT EXISTS idx_agent_capabilities_workspace ON agent_capabilities(workspace_id);
26960
+ `);
26961
+ return;
26962
+ }
26963
+ db.exec(AGENT_CAPABILITIES_SQL);
26964
+ },
26965
+ alreadyApplied: (db) => agentCapabilitiesTableState(db) === "current"
26939
26966
  }
26940
26967
  ];
26941
26968
  function migrateCliSqlite(db) {
@@ -27015,7 +27042,7 @@ function getCliDatabase(options) {
27015
27042
  async function closeBridgeConnection(state, acpManager, devServerManager, log2) {
27016
27043
  const say = log2 ?? logImmediate;
27017
27044
  say("Cleaning up connections\u2026");
27018
- await new Promise((resolve18) => setImmediate(resolve18));
27045
+ await new Promise((resolve20) => setImmediate(resolve20));
27019
27046
  state.closedByUser = true;
27020
27047
  clearReconnectQuietTimer(state.mainQuiet);
27021
27048
  clearReconnectQuietTimer(state.firehoseQuiet);
@@ -27403,9 +27430,9 @@ function parseChangeSummaryJson(raw, allowedPaths, options) {
27403
27430
  const rawPath = typeof o.path === "string" ? o.path.trim() : "";
27404
27431
  const summary = typeof o.summary === "string" ? o.summary.trim() : "";
27405
27432
  if (!rawPath || !summary) continue;
27406
- const path41 = skip ? normalizeRepoRelativePath(rawPath) || rawPath : resolveChangeSummaryPathAgainstAllowed(rawPath, allowedPaths);
27407
- if (!path41) continue;
27408
- rows.push({ path: path41, summary: clampSummaryToAtMostTwoLines(summary) });
27433
+ const path43 = skip ? normalizeRepoRelativePath(rawPath) || rawPath : resolveChangeSummaryPathAgainstAllowed(rawPath, allowedPaths);
27434
+ if (!path43) continue;
27435
+ rows.push({ path: path43, summary: clampSummaryToAtMostTwoLines(summary) });
27409
27436
  }
27410
27437
  return rows;
27411
27438
  }
@@ -27615,6 +27642,7 @@ function buildCliAutoApprovedPermissionRpcResult(requestParams) {
27615
27642
  // ../types/src/agent-config.ts
27616
27643
  var AGENT_CONFIG_CLAUDE_PERMISSION_MODE_KEY = "claude_permission_mode";
27617
27644
  var AGENT_CONFIG_CLI_PERMISSION_MODE_KEY = "cli_permission_mode";
27645
+ var AGENT_CONFIG_AGENT_MODEL_KEY = "agent_model";
27618
27646
  function getClaudePermissionModeFromAgentConfig(config2) {
27619
27647
  if (!config2) return null;
27620
27648
  const raw = config2[AGENT_CONFIG_CLAUDE_PERMISSION_MODE_KEY];
@@ -27626,6 +27654,13 @@ function getCliPermissionModeFromAgentConfig(config2) {
27626
27654
  if (!config2) return CLI_PERMISSION_MODE_DEFAULT;
27627
27655
  return normalizeCliPermissionModeInput(config2[AGENT_CONFIG_CLI_PERMISSION_MODE_KEY]);
27628
27656
  }
27657
+ function getAgentModelFromAgentConfig(config2) {
27658
+ if (!config2) return null;
27659
+ const cur = config2[AGENT_CONFIG_AGENT_MODEL_KEY];
27660
+ if (typeof cur !== "string") return null;
27661
+ const t = cur.trim();
27662
+ return t !== "" ? t : null;
27663
+ }
27629
27664
 
27630
27665
  // src/git/session-git-queue.ts
27631
27666
  import { execFile as execFile7 } from "node:child_process";
@@ -27680,8 +27715,8 @@ function pathspec(...paths) {
27680
27715
  cache.set(key, paths);
27681
27716
  return key;
27682
27717
  }
27683
- function isPathSpec(path41) {
27684
- return path41 instanceof String && cache.has(path41);
27718
+ function isPathSpec(path43) {
27719
+ return path43 instanceof String && cache.has(path43);
27685
27720
  }
27686
27721
  function toPaths(pathSpec) {
27687
27722
  return cache.get(pathSpec) || [];
@@ -27770,8 +27805,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
27770
27805
  function forEachLineWithContent(input, callback) {
27771
27806
  return toLinesWithContent(input, true).map((line) => callback(line));
27772
27807
  }
27773
- function folderExists(path41) {
27774
- return (0, import_file_exists.exists)(path41, import_file_exists.FOLDER);
27808
+ function folderExists(path43) {
27809
+ return (0, import_file_exists.exists)(path43, import_file_exists.FOLDER);
27775
27810
  }
27776
27811
  function append(target, item) {
27777
27812
  if (Array.isArray(target)) {
@@ -28175,8 +28210,8 @@ function checkIsRepoRootTask() {
28175
28210
  commands,
28176
28211
  format: "utf-8",
28177
28212
  onError,
28178
- parser(path41) {
28179
- return /^\.(git)?$/.test(path41.trim());
28213
+ parser(path43) {
28214
+ return /^\.(git)?$/.test(path43.trim());
28180
28215
  }
28181
28216
  };
28182
28217
  }
@@ -28610,11 +28645,11 @@ function parseGrep(grep) {
28610
28645
  const paths = /* @__PURE__ */ new Set();
28611
28646
  const results = {};
28612
28647
  forEachLineWithContent(grep, (input) => {
28613
- const [path41, line, preview] = input.split(NULL);
28614
- paths.add(path41);
28615
- (results[path41] = results[path41] || []).push({
28648
+ const [path43, line, preview] = input.split(NULL);
28649
+ paths.add(path43);
28650
+ (results[path43] = results[path43] || []).push({
28616
28651
  line: asNumber(line),
28617
- path: path41,
28652
+ path: path43,
28618
28653
  preview
28619
28654
  });
28620
28655
  });
@@ -29379,14 +29414,14 @@ var init_hash_object = __esm2({
29379
29414
  init_task();
29380
29415
  }
29381
29416
  });
29382
- function parseInit(bare, path41, text) {
29417
+ function parseInit(bare, path43, text) {
29383
29418
  const response = String(text).trim();
29384
29419
  let result;
29385
29420
  if (result = initResponseRegex.exec(response)) {
29386
- return new InitSummary(bare, path41, false, result[1]);
29421
+ return new InitSummary(bare, path43, false, result[1]);
29387
29422
  }
29388
29423
  if (result = reInitResponseRegex.exec(response)) {
29389
- return new InitSummary(bare, path41, true, result[1]);
29424
+ return new InitSummary(bare, path43, true, result[1]);
29390
29425
  }
29391
29426
  let gitDir = "";
29392
29427
  const tokens = response.split(" ");
@@ -29397,7 +29432,7 @@ function parseInit(bare, path41, text) {
29397
29432
  break;
29398
29433
  }
29399
29434
  }
29400
- return new InitSummary(bare, path41, /^re/i.test(response), gitDir);
29435
+ return new InitSummary(bare, path43, /^re/i.test(response), gitDir);
29401
29436
  }
29402
29437
  var InitSummary;
29403
29438
  var initResponseRegex;
@@ -29406,9 +29441,9 @@ var init_InitSummary = __esm2({
29406
29441
  "src/lib/responses/InitSummary.ts"() {
29407
29442
  "use strict";
29408
29443
  InitSummary = class {
29409
- constructor(bare, path41, existing, gitDir) {
29444
+ constructor(bare, path43, existing, gitDir) {
29410
29445
  this.bare = bare;
29411
- this.path = path41;
29446
+ this.path = path43;
29412
29447
  this.existing = existing;
29413
29448
  this.gitDir = gitDir;
29414
29449
  }
@@ -29420,7 +29455,7 @@ var init_InitSummary = __esm2({
29420
29455
  function hasBareCommand(command) {
29421
29456
  return command.includes(bareCommand);
29422
29457
  }
29423
- function initTask(bare = false, path41, customArgs) {
29458
+ function initTask(bare = false, path43, customArgs) {
29424
29459
  const commands = ["init", ...customArgs];
29425
29460
  if (bare && !hasBareCommand(commands)) {
29426
29461
  commands.splice(1, 0, bareCommand);
@@ -29429,7 +29464,7 @@ function initTask(bare = false, path41, customArgs) {
29429
29464
  commands,
29430
29465
  format: "utf-8",
29431
29466
  parser(text) {
29432
- return parseInit(commands.includes("--bare"), path41, text);
29467
+ return parseInit(commands.includes("--bare"), path43, text);
29433
29468
  }
29434
29469
  };
29435
29470
  }
@@ -30245,12 +30280,12 @@ var init_FileStatusSummary = __esm2({
30245
30280
  "use strict";
30246
30281
  fromPathRegex = /^(.+)\0(.+)$/;
30247
30282
  FileStatusSummary = class {
30248
- constructor(path41, index, working_dir) {
30249
- this.path = path41;
30283
+ constructor(path43, index, working_dir) {
30284
+ this.path = path43;
30250
30285
  this.index = index;
30251
30286
  this.working_dir = working_dir;
30252
30287
  if (index === "R" || working_dir === "R") {
30253
- const detail = fromPathRegex.exec(path41) || [null, path41, path41];
30288
+ const detail = fromPathRegex.exec(path43) || [null, path43, path43];
30254
30289
  this.from = detail[2] || "";
30255
30290
  this.path = detail[1] || "";
30256
30291
  }
@@ -30281,14 +30316,14 @@ function splitLine(result, lineStr) {
30281
30316
  default:
30282
30317
  return;
30283
30318
  }
30284
- function data(index, workingDir, path41) {
30319
+ function data(index, workingDir, path43) {
30285
30320
  const raw = `${index}${workingDir}`;
30286
30321
  const handler = parsers6.get(raw);
30287
30322
  if (handler) {
30288
- handler(result, path41);
30323
+ handler(result, path43);
30289
30324
  }
30290
30325
  if (raw !== "##" && raw !== "!!") {
30291
- result.files.push(new FileStatusSummary(path41, index, workingDir));
30326
+ result.files.push(new FileStatusSummary(path43, index, workingDir));
30292
30327
  }
30293
30328
  }
30294
30329
  }
@@ -30597,9 +30632,9 @@ var init_simple_git_api = __esm2({
30597
30632
  next
30598
30633
  );
30599
30634
  }
30600
- hashObject(path41, write) {
30635
+ hashObject(path43, write) {
30601
30636
  return this._runTask(
30602
- hashObjectTask(path41, write === true),
30637
+ hashObjectTask(path43, write === true),
30603
30638
  trailingFunctionArgument(arguments)
30604
30639
  );
30605
30640
  }
@@ -30952,8 +30987,8 @@ var init_branch = __esm2({
30952
30987
  }
30953
30988
  });
30954
30989
  function toPath(input) {
30955
- const path41 = input.trim().replace(/^["']|["']$/g, "");
30956
- return path41 && normalize(path41);
30990
+ const path43 = input.trim().replace(/^["']|["']$/g, "");
30991
+ return path43 && normalize(path43);
30957
30992
  }
30958
30993
  var parseCheckIgnore;
30959
30994
  var init_CheckIgnore = __esm2({
@@ -31267,8 +31302,8 @@ __export2(sub_module_exports, {
31267
31302
  subModuleTask: () => subModuleTask,
31268
31303
  updateSubModuleTask: () => updateSubModuleTask
31269
31304
  });
31270
- function addSubModuleTask(repo, path41) {
31271
- return subModuleTask(["add", repo, path41]);
31305
+ function addSubModuleTask(repo, path43) {
31306
+ return subModuleTask(["add", repo, path43]);
31272
31307
  }
31273
31308
  function initSubModuleTask(customArgs) {
31274
31309
  return subModuleTask(["init", ...customArgs]);
@@ -31601,8 +31636,8 @@ var require_git = __commonJS2({
31601
31636
  }
31602
31637
  return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
31603
31638
  };
31604
- Git2.prototype.submoduleAdd = function(repo, path41, then) {
31605
- return this._runTask(addSubModuleTask2(repo, path41), trailingFunctionArgument2(arguments));
31639
+ Git2.prototype.submoduleAdd = function(repo, path43, then) {
31640
+ return this._runTask(addSubModuleTask2(repo, path43), trailingFunctionArgument2(arguments));
31606
31641
  };
31607
31642
  Git2.prototype.submoduleUpdate = function(args, then) {
31608
31643
  return this._runTask(
@@ -32489,9 +32524,9 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
32489
32524
  // src/agents/acp/put-summarize-change-summaries.ts
32490
32525
  async function putEncryptedChangeSummaryRows(params) {
32491
32526
  const base = params.apiBaseUrl.replace(/\/+$/, "");
32492
- const entries = params.rows.map(({ path: path41, summary }) => {
32527
+ const entries = params.rows.map(({ path: path43, summary }) => {
32493
32528
  const enc = params.e2ee.encryptFields({ summary }, ["summary"]);
32494
- return { path: path41, summary: JSON.stringify(enc) };
32529
+ return { path: path43, summary: JSON.stringify(enc) };
32495
32530
  });
32496
32531
  const res = await fetch(
32497
32532
  `${base}/api/sessions/${encodeURIComponent(params.sessionId)}/follow-ups/summarize-changes`,
@@ -33125,6 +33160,48 @@ async function applyClaudePermissionFromAcpSession(params) {
33125
33160
  }
33126
33161
  }
33127
33162
 
33163
+ // src/agents/acp/apply-acp-model-from-agent-session.ts
33164
+ function flattenSelectOptions2(options) {
33165
+ if (options == null || options.length === 0) return [];
33166
+ const first2 = options[0];
33167
+ if (first2 != null && typeof first2 === "object" && "group" in first2 && first2.group != null) {
33168
+ return options.flatMap((g) => Array.isArray(g.options) ? g.options : []);
33169
+ }
33170
+ return options;
33171
+ }
33172
+ function looksLikeModelOption(o) {
33173
+ if (o.category === "model" || o.category === "models") return true;
33174
+ const id = typeof o.id === "string" ? o.id.toLowerCase() : "";
33175
+ if (id === "model" || id.endsWith("_model") || id.includes("model")) return true;
33176
+ const name = typeof o.name === "string" ? o.name.toLowerCase() : "";
33177
+ return name.includes("model") && !name.includes("mode");
33178
+ }
33179
+ function pickModelConfigOption(configOptions) {
33180
+ if (configOptions == null || configOptions.length === 0) return null;
33181
+ return configOptions.find(looksLikeModelOption) ?? null;
33182
+ }
33183
+ async function applyAcpModelFromAcpSession(params) {
33184
+ const { sessionId, agentConfig, configOptions, setSessionConfigOption, logDebug: logDebug2 } = params;
33185
+ const desired = getAgentModelFromAgentConfig(agentConfig);
33186
+ if (desired == null) return;
33187
+ const modelOpt = pickModelConfigOption(configOptions ?? null);
33188
+ if (modelOpt == null) return;
33189
+ const flat = flattenSelectOptions2(modelOpt.options);
33190
+ const allowed = flat.some((o) => o.value === desired);
33191
+ if (!allowed) return;
33192
+ if (modelOpt.currentValue === desired) return;
33193
+ try {
33194
+ logDebug2(
33195
+ `[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`
33196
+ );
33197
+ await setSessionConfigOption({ sessionId, configId: modelOpt.id, value: desired });
33198
+ } catch (e) {
33199
+ logDebug2(
33200
+ `[Agent] ACP session/set_config_option (model) failed: ${e instanceof Error ? e.message : String(e)}`
33201
+ );
33202
+ }
33203
+ }
33204
+
33128
33205
  // src/agents/acp/clients/shared/config-options-for-permission.ts
33129
33206
  function configOptionsForPermission(getActive, established) {
33130
33207
  const mem = getActive?.();
@@ -33217,6 +33294,17 @@ async function bootstrapAcpWireSession(transport, ctx, initializeRequest) {
33217
33294
  logDebug: ctx.logDebug
33218
33295
  });
33219
33296
  }
33297
+ const cfgAll = ctx.agentConfig != null && typeof ctx.agentConfig === "object" && !Array.isArray(ctx.agentConfig) ? ctx.agentConfig : null;
33298
+ const configOptionsForModel = established.configOptions;
33299
+ if (transport.setSessionConfigOption) {
33300
+ await applyAcpModelFromAcpSession({
33301
+ sessionId,
33302
+ agentConfig: cfgAll,
33303
+ configOptions: configOptionsForPermission(ctx.getActiveConfigOptions, configOptionsForModel),
33304
+ setSessionConfigOption: (p) => transport.setSessionConfigOption(p),
33305
+ logDebug: ctx.logDebug
33306
+ });
33307
+ }
33220
33308
  return established;
33221
33309
  }
33222
33310
 
@@ -33322,10 +33410,15 @@ async function sendAcpPromptViaTransport(transport, ctx, sessionId, promptText,
33322
33410
  // src/agents/acp/clients/sdk/sdk-stdio-permission-request-handshake.ts
33323
33411
  function awaitSdkStdioPermissionRequestHandshake(params) {
33324
33412
  const { requestId, paramsRecord, pending, onRequest } = params;
33325
- return new Promise((resolve18) => {
33326
- pending.set(requestId, { resolve: resolve18, params: paramsRecord });
33413
+ return new Promise((resolve20) => {
33414
+ pending.set(requestId, { resolve: resolve20, params: paramsRecord });
33415
+ if (onRequest == null) {
33416
+ pending.delete(requestId);
33417
+ resolve20({ outcome: { outcome: "denied" } });
33418
+ return;
33419
+ }
33327
33420
  try {
33328
- onRequest?.({
33421
+ onRequest({
33329
33422
  requestId,
33330
33423
  method: "session/request_permission",
33331
33424
  params: paramsRecord
@@ -33387,7 +33480,7 @@ async function createSdkStdioAcpClient(options) {
33387
33480
  child.once("close", (code, signal) => {
33388
33481
  onAgentSubprocessExit?.({ code, signal });
33389
33482
  });
33390
- return new Promise((resolve18, reject) => {
33483
+ return new Promise((resolve20, reject) => {
33391
33484
  let initSettled = false;
33392
33485
  const settleReject = (err) => {
33393
33486
  if (initSettled) return;
@@ -33401,7 +33494,7 @@ async function createSdkStdioAcpClient(options) {
33401
33494
  const settleResolve = (handle) => {
33402
33495
  if (initSettled) return;
33403
33496
  initSettled = true;
33404
- resolve18(handle);
33497
+ resolve20(handle);
33405
33498
  };
33406
33499
  child.on("error", (err) => {
33407
33500
  settleReject(new Error(formatSpawnError(err, command[0])));
@@ -33693,7 +33786,7 @@ async function createCursorAcpClient(options) {
33693
33786
  logDebug,
33694
33787
  getStderrText: () => stderrCapture.getText()
33695
33788
  };
33696
- return new Promise((resolve18, reject) => {
33789
+ return new Promise((resolve20, reject) => {
33697
33790
  child.on("error", (err) => {
33698
33791
  child.kill();
33699
33792
  reject(new Error(formatSpawnError2(err, command[0])));
@@ -33772,12 +33865,16 @@ async function createCursorAcpClient(options) {
33772
33865
  }
33773
33866
  if (method === "session/request_permission" && typeof id === "number") {
33774
33867
  const params = msg.params ?? {};
33775
- pendingRequests.set(id, { method, params });
33776
- onRequest?.({
33777
- requestId: String(id),
33778
- method,
33779
- params
33780
- });
33868
+ if (onRequest) {
33869
+ pendingRequests.set(id, { method, params });
33870
+ onRequest({
33871
+ requestId: String(id),
33872
+ method,
33873
+ params
33874
+ });
33875
+ } else {
33876
+ respond(id, { outcome: { outcome: "denied" } });
33877
+ }
33781
33878
  return;
33782
33879
  }
33783
33880
  if (typeof id === "number" && method) {
@@ -33865,7 +33962,7 @@ async function createCursorAcpClient(options) {
33865
33962
  clientInfo: { name: "buildautomaton-cli", version: "0.1.0" }
33866
33963
  });
33867
33964
  const sessionId = established.sessionId;
33868
- resolve18({
33965
+ resolve20({
33869
33966
  sessionId,
33870
33967
  async sendPrompt(prompt, options2) {
33871
33968
  const imgs = options2?.images?.map((im) => ({ type: "image", mimeType: im.mimeType, data: im.dataBase64 }));
@@ -34745,6 +34842,7 @@ async function ensureAcpClient(options) {
34745
34842
  sessionParentPath,
34746
34843
  routing,
34747
34844
  cloudSessionId,
34845
+ reportAgentCapabilities,
34748
34846
  sendSessionUpdate,
34749
34847
  sendRequest,
34750
34848
  log: log2
@@ -34832,6 +34930,12 @@ async function ensureAcpClient(options) {
34832
34930
  backendAgentType: preferredAgentType
34833
34931
  });
34834
34932
  }
34933
+ if (reportAgentCapabilities && preferredAgentType && Array.isArray(info.configOptions) && info.configOptions.length > 0) {
34934
+ reportAgentCapabilities({
34935
+ agentType: preferredAgentType,
34936
+ configOptions: info.configOptions
34937
+ });
34938
+ }
34835
34939
  },
34836
34940
  onAcpConfigOptionsUpdated: (configOptions) => {
34837
34941
  state.activeSessionConfigOptions = configOptions;
@@ -34841,6 +34945,12 @@ async function ensureAcpClient(options) {
34841
34945
  backendAgentType: preferredAgentType
34842
34946
  });
34843
34947
  }
34948
+ if (reportAgentCapabilities && preferredAgentType && Array.isArray(configOptions) && configOptions.length > 0) {
34949
+ reportAgentCapabilities({
34950
+ agentType: preferredAgentType,
34951
+ configOptions
34952
+ });
34953
+ }
34844
34954
  },
34845
34955
  onAgentSubprocessExit: () => {
34846
34956
  state.acpHandle = null;
@@ -34871,7 +34981,7 @@ async function ensureAcpClient(options) {
34871
34981
 
34872
34982
  // src/agents/acp/create-acp-manager.ts
34873
34983
  async function createAcpManager(options) {
34874
- const { log: log2 } = options;
34984
+ const { log: log2, reportAgentCapabilities } = options;
34875
34985
  const state = {
34876
34986
  acpHandle: null,
34877
34987
  acpStartPromise: null,
@@ -34915,7 +35025,8 @@ async function createAcpManager(options) {
34915
35025
  cloudApiBaseUrl,
34916
35026
  getCloudAccessToken,
34917
35027
  e2ee,
34918
- attachments
35028
+ attachments,
35029
+ agentId
34919
35030
  } = opts;
34920
35031
  const preferredForPrompt = agentType ?? backendFallbackAgentType ?? null;
34921
35032
  pendingCancelRunId = void 0;
@@ -34933,7 +35044,8 @@ async function createAcpManager(options) {
34933
35044
  cloudSessionId: sessionId,
34934
35045
  sendSessionUpdate,
34935
35046
  sendRequest: sendSessionUpdate,
34936
- log: log2
35047
+ log: log2,
35048
+ reportAgentCapabilities
34937
35049
  });
34938
35050
  if (!handle) {
34939
35051
  const errMsg = state.lastAcpStartError || "No agent configured. Register local agents on this bridge in the app.";
@@ -36300,7 +36412,7 @@ import path29 from "node:path";
36300
36412
 
36301
36413
  // src/runtime/yield-to-event-loop.ts
36302
36414
  function yieldToEventLoop() {
36303
- return new Promise((resolve18) => setImmediate(resolve18));
36415
+ return new Promise((resolve20) => setImmediate(resolve20));
36304
36416
  }
36305
36417
 
36306
36418
  // src/files/index/walk-workspace-tree.ts
@@ -36524,7 +36636,7 @@ function startFileIndexWatcher(cwd = getBridgeRoot()) {
36524
36636
  }
36525
36637
 
36526
36638
  // src/connection/create-bridge-connection.ts
36527
- import * as path39 from "node:path";
36639
+ import * as path41 from "node:path";
36528
36640
 
36529
36641
  // src/dev-servers/manager/dev-server-manager.ts
36530
36642
  import { rm as rm2 } from "node:fs/promises";
@@ -36546,15 +36658,15 @@ function sendDevServerStatus(getWs, serverId, status, options) {
36546
36658
 
36547
36659
  // src/dev-servers/process/terminate-child-process.ts
36548
36660
  async function sigtermAndWaitForExit(proc, graceMs, log2, shortId) {
36549
- const exited = new Promise((resolve18) => {
36550
- proc.once("exit", () => resolve18());
36661
+ const exited = new Promise((resolve20) => {
36662
+ proc.once("exit", () => resolve20());
36551
36663
  });
36552
36664
  log2(`[dev-server] Sending SIGTERM to ${shortId} (pid=${proc.pid ?? "?"}).`);
36553
36665
  try {
36554
36666
  proc.kill("SIGTERM");
36555
36667
  } catch {
36556
36668
  }
36557
- await Promise.race([exited, new Promise((resolve18) => setTimeout(resolve18, graceMs))]);
36669
+ await Promise.race([exited, new Promise((resolve20) => setTimeout(resolve20, graceMs))]);
36558
36670
  }
36559
36671
  function forceKillChild(proc, log2, shortId, graceMs) {
36560
36672
  log2(
@@ -37437,7 +37549,7 @@ async function proxyToLocal(request) {
37437
37549
  };
37438
37550
  const maxAttempts = isIdempotentProxyMethod(request.method) ? LOCAL_PREVIEW_FETCH_RETRY_DELAYS_MS.length + 1 : 1;
37439
37551
  for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
37440
- const once = await new Promise((resolve18) => {
37552
+ const once = await new Promise((resolve20) => {
37441
37553
  const req = mod.request(opts, (res) => {
37442
37554
  const chunks = [];
37443
37555
  res.on("data", (c) => chunks.push(c));
@@ -37448,7 +37560,7 @@ async function proxyToLocal(request) {
37448
37560
  if (typeof v === "string") headers[k] = v;
37449
37561
  else if (Array.isArray(v) && v[0]) headers[k] = v[0];
37450
37562
  }
37451
- resolve18({
37563
+ resolve20({
37452
37564
  id: request.id,
37453
37565
  statusCode: res.statusCode ?? 0,
37454
37566
  headers,
@@ -37457,7 +37569,7 @@ async function proxyToLocal(request) {
37457
37569
  });
37458
37570
  });
37459
37571
  req.on("error", (err) => {
37460
- resolve18({
37572
+ resolve20({
37461
37573
  id: request.id,
37462
37574
  statusCode: 0,
37463
37575
  headers: {},
@@ -38076,6 +38188,13 @@ var handleBridgeIdentified = (msg, deps) => {
38076
38188
  `[Bridge service] Auto-detect agents failed: ${e instanceof Error ? e.message : String(e)}`
38077
38189
  );
38078
38190
  }
38191
+ try {
38192
+ await deps.warmupAgentCapabilitiesOnConnect?.();
38193
+ } catch (e) {
38194
+ deps.log(
38195
+ `[Bridge service] Agent capability warmup failed: ${e instanceof Error ? e.message : String(e)}`
38196
+ );
38197
+ }
38079
38198
  })();
38080
38199
  });
38081
38200
  setImmediate(() => {
@@ -38428,9 +38547,9 @@ function parseChangeSummarySnapshots(raw) {
38428
38547
  for (const item of raw) {
38429
38548
  if (!item || typeof item !== "object") continue;
38430
38549
  const o = item;
38431
- const path41 = typeof o.path === "string" && o.path.trim() !== "" ? o.path.trim() : "";
38432
- if (!path41) continue;
38433
- const row = { path: path41 };
38550
+ const path43 = typeof o.path === "string" && o.path.trim() !== "" ? o.path.trim() : "";
38551
+ if (!path43) continue;
38552
+ const row = { path: path43 };
38434
38553
  if (typeof o.patchContent === "string") row.patchContent = o.patchContent;
38435
38554
  if (typeof o.oldText === "string") row.oldText = o.oldText;
38436
38555
  if (typeof o.newText === "string") row.newText = o.newText;
@@ -38548,6 +38667,8 @@ function handleBridgePrompt(msg, deps) {
38548
38667
  const sessionParent = rawParent === "bridge_root" || rawParent === "worktrees_root" ? rawParent : rawParent === "session_worktrees_root" ? "worktrees_root" : null;
38549
38668
  const sessionParentPath = typeof msg.sessionParentPath === "string" && msg.sessionParentPath.trim() ? msg.sessionParentPath.trim() : null;
38550
38669
  const agentType = typeof msg.agentType === "string" && msg.agentType.trim() ? msg.agentType.trim() : void 0;
38670
+ const rawAgentId = msg.agentId;
38671
+ const agentId = typeof rawAgentId === "string" && rawAgentId.trim() !== "" ? rawAgentId.trim() : null;
38551
38672
  const mode = typeof msg.mode === "string" && msg.mode.trim() ? msg.mode.trim() : void 0;
38552
38673
  const agentConfig = msg.agentConfig != null && typeof msg.agentConfig === "object" && !Array.isArray(msg.agentConfig) ? msg.agentConfig : void 0;
38553
38674
  acpManager.logPromptReceivedFromBridge({ agentType, mode });
@@ -38585,6 +38706,7 @@ function handleBridgePrompt(msg, deps) {
38585
38706
  runId,
38586
38707
  mode,
38587
38708
  agentType,
38709
+ agentId,
38588
38710
  agentConfig,
38589
38711
  sessionParentPath: effectiveCwd,
38590
38712
  sendResult: sendResult2,
@@ -38647,8 +38769,8 @@ function randomSecret() {
38647
38769
  }
38648
38770
  return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
38649
38771
  }
38650
- async function requestPreviewApi(port, secret, method, path41, body) {
38651
- const url2 = `http://127.0.0.1:${port}${path41}`;
38772
+ async function requestPreviewApi(port, secret, method, path43, body) {
38773
+ const url2 = `http://127.0.0.1:${port}${path43}`;
38652
38774
  const headers = {
38653
38775
  [PREVIEW_SECRET_HEADER]: secret,
38654
38776
  "Content-Type": "application/json"
@@ -38660,7 +38782,7 @@ async function requestPreviewApi(port, secret, method, path41, body) {
38660
38782
  });
38661
38783
  const data = await res.json().catch(() => ({}));
38662
38784
  if (!res.ok) {
38663
- throw new Error(data?.error ?? `Preview API ${method} ${path41}: ${res.status}`);
38785
+ throw new Error(data?.error ?? `Preview API ${method} ${path43}: ${res.status}`);
38664
38786
  }
38665
38787
  return data;
38666
38788
  }
@@ -39774,6 +39896,242 @@ function createBridgeHeartbeatController(params) {
39774
39896
  };
39775
39897
  }
39776
39898
 
39899
+ // src/sqlite/hash-json-sha256.ts
39900
+ import { createHash as createHash2 } from "node:crypto";
39901
+ function hashJsonUtf8Sha256(value) {
39902
+ return createHash2("sha256").update(JSON.stringify(value), "utf8").digest("hex");
39903
+ }
39904
+
39905
+ // src/sqlite/agent-capability-cache.ts
39906
+ function hasNonEmptyAgentCapabilityCache(db, workspaceId, agentType) {
39907
+ const t = agentType.trim();
39908
+ if (!t) return false;
39909
+ try {
39910
+ const row = db.get(
39911
+ `SELECT config_options_json FROM agent_capabilities WHERE workspace_id = ? AND agent_type = ?`,
39912
+ [workspaceId, t]
39913
+ );
39914
+ if (row?.config_options_json == null || row.config_options_json === "") return false;
39915
+ const parsed = JSON.parse(row.config_options_json);
39916
+ return Array.isArray(parsed) && parsed.length > 0;
39917
+ } catch {
39918
+ return false;
39919
+ }
39920
+ }
39921
+ function upsertCliAgentCapabilityCache(db, row) {
39922
+ const t = row.agentType.trim();
39923
+ if (!t) return false;
39924
+ const hash = hashJsonUtf8Sha256(row.configOptions);
39925
+ try {
39926
+ const prev = db.get(
39927
+ `SELECT content_hash FROM agent_capabilities WHERE workspace_id = ? AND agent_type = ?`,
39928
+ [row.workspaceId, t]
39929
+ );
39930
+ if (prev?.content_hash === hash) return false;
39931
+ } catch {
39932
+ }
39933
+ const json2 = JSON.stringify(row.configOptions);
39934
+ const now = (/* @__PURE__ */ new Date()).toISOString();
39935
+ db.run(
39936
+ `INSERT INTO agent_capabilities (workspace_id, agent_type, config_options_json, content_hash, updated_at)
39937
+ VALUES (?, ?, ?, ?, ?)
39938
+ ON CONFLICT(workspace_id, agent_type) DO UPDATE SET
39939
+ config_options_json = excluded.config_options_json,
39940
+ content_hash = excluded.content_hash,
39941
+ updated_at = excluded.updated_at`,
39942
+ [row.workspaceId, t, json2, hash, now]
39943
+ );
39944
+ return true;
39945
+ }
39946
+ function listCliAgentCapabilityCacheForWorkspace(db, workspaceId) {
39947
+ const rows = db.all(
39948
+ `SELECT agent_type, config_options_json FROM agent_capabilities WHERE workspace_id = ?`,
39949
+ [workspaceId]
39950
+ );
39951
+ const out = [];
39952
+ for (const r of rows) {
39953
+ try {
39954
+ const parsed = JSON.parse(r.config_options_json);
39955
+ if (!Array.isArray(parsed) || parsed.length === 0) continue;
39956
+ out.push({ agentType: r.agent_type, configOptions: parsed });
39957
+ } catch {
39958
+ }
39959
+ }
39960
+ return out;
39961
+ }
39962
+
39963
+ // src/agents/capabilities/warmup-agent-capabilities-on-connect.ts
39964
+ import * as path40 from "node:path";
39965
+
39966
+ // src/agents/capabilities/probe-one-agent-type-for-capabilities.ts
39967
+ import * as path39 from "node:path";
39968
+ async function probeOneAgentTypeForCapabilities(params) {
39969
+ const { agentType, cwd, workspaceId, log: log2, getDb, reportAgentCapabilities, bridgeReport = true } = params;
39970
+ const resolved = resolveAgentCommand(agentType);
39971
+ if (!resolved) return false;
39972
+ let sqliteChanged = false;
39973
+ const reportedRef = { done: false };
39974
+ const tryReport = (co) => {
39975
+ if (reportedRef.done) return;
39976
+ if (!Array.isArray(co) || co.length === 0) return;
39977
+ reportedRef.done = true;
39978
+ let changed = false;
39979
+ try {
39980
+ changed = upsertCliAgentCapabilityCache(getDb(), {
39981
+ workspaceId,
39982
+ agentType,
39983
+ configOptions: co
39984
+ });
39985
+ } catch {
39986
+ }
39987
+ sqliteChanged ||= changed;
39988
+ if (bridgeReport && changed) {
39989
+ reportAgentCapabilities?.({ agentType, configOptions: co });
39990
+ }
39991
+ };
39992
+ let handle = null;
39993
+ const killTimer = setTimeout(() => {
39994
+ try {
39995
+ handle?.disconnect();
39996
+ } catch {
39997
+ }
39998
+ }, 28e3);
39999
+ killTimer.unref?.();
40000
+ try {
40001
+ handle = await resolved.createClient({
40002
+ command: resolved.command,
40003
+ cwd: path39.resolve(cwd),
40004
+ backendAgentType: agentType,
40005
+ sessionMode: "agent",
40006
+ persistedAcpSessionId: null,
40007
+ agentConfig: null,
40008
+ getActiveConfigOptions: () => null,
40009
+ onAcpSessionEstablished: (info) => {
40010
+ tryReport(info.configOptions ?? null);
40011
+ },
40012
+ onAcpConfigOptionsUpdated: (co) => {
40013
+ tryReport(co);
40014
+ },
40015
+ onAgentSubprocessExit: () => {
40016
+ },
40017
+ onSessionUpdate: () => {
40018
+ }
40019
+ });
40020
+ await new Promise((r) => setTimeout(r, 1200));
40021
+ } catch (e) {
40022
+ log2(
40023
+ `[Bridge service] Agent capability probe (${agentType}): ${e instanceof Error ? e.message : String(e)}`
40024
+ );
40025
+ } finally {
40026
+ clearTimeout(killTimer);
40027
+ try {
40028
+ handle?.disconnect();
40029
+ } catch {
40030
+ }
40031
+ }
40032
+ return sqliteChanged;
40033
+ }
40034
+
40035
+ // src/agents/capabilities/probe-agent-capabilities-for-types.ts
40036
+ async function probeAgentCapabilitiesForDetectedTypes(params) {
40037
+ const {
40038
+ agentTypes,
40039
+ cwd,
40040
+ workspaceId,
40041
+ log: log2,
40042
+ getDb,
40043
+ reportAgentCapabilities,
40044
+ bridgeReport = true,
40045
+ forceAllTypes = false
40046
+ } = params;
40047
+ let changedCount = 0;
40048
+ for (let i = 0; i < agentTypes.length; i++) {
40049
+ if (i > 0) await yieldToEventLoop();
40050
+ const agentType = agentTypes[i];
40051
+ if (!agentType.trim()) continue;
40052
+ if (!forceAllTypes) {
40053
+ try {
40054
+ if (process.env.BUILDAUTOMATON_FORCE_PROBE_ACP_CAPABILITIES !== "1" && hasNonEmptyAgentCapabilityCache(getDb(), workspaceId, agentType)) {
40055
+ continue;
40056
+ }
40057
+ } catch {
40058
+ }
40059
+ }
40060
+ const changed = await probeOneAgentTypeForCapabilities({
40061
+ agentType,
40062
+ cwd,
40063
+ workspaceId,
40064
+ log: log2,
40065
+ getDb,
40066
+ reportAgentCapabilities,
40067
+ bridgeReport
40068
+ });
40069
+ if (changed) changedCount += 1;
40070
+ }
40071
+ return changedCount;
40072
+ }
40073
+
40074
+ // src/agents/capabilities/warmup-agent-capabilities-on-connect.ts
40075
+ async function warmupAgentCapabilitiesOnConnect(params) {
40076
+ const { workspaceId, log: log2, getDb, getWs } = params;
40077
+ const cwd = path40.resolve(getBridgeRoot());
40078
+ const db = getDb();
40079
+ function sendBatchFromCache() {
40080
+ const socket = getWs();
40081
+ if (!socket || socket.readyState !== wrapper_default.OPEN) return;
40082
+ try {
40083
+ const rows = listCliAgentCapabilityCacheForWorkspace(db, workspaceId);
40084
+ if (rows.length === 0) return;
40085
+ sendWsMessage(socket, {
40086
+ type: "agent_capabilities_batch",
40087
+ items: rows.map((r) => ({ agentType: r.agentType, configOptions: r.configOptions }))
40088
+ });
40089
+ } catch (e) {
40090
+ log2(
40091
+ `[Bridge service] Agent capability batch to bridge failed: ${e instanceof Error ? e.message : String(e)}`
40092
+ );
40093
+ }
40094
+ }
40095
+ sendBatchFromCache();
40096
+ let types = [];
40097
+ try {
40098
+ types = [...await detectLocalAgentTypes()];
40099
+ } catch (e) {
40100
+ log2(`[Bridge service] detectLocalAgentTypes failed: ${e instanceof Error ? e.message : String(e)}`);
40101
+ }
40102
+ try {
40103
+ const n = await probeAgentCapabilitiesForDetectedTypes({
40104
+ agentTypes: types,
40105
+ cwd,
40106
+ workspaceId,
40107
+ log: log2,
40108
+ getDb,
40109
+ bridgeReport: false,
40110
+ forceAllTypes: false
40111
+ });
40112
+ if (n > 0) sendBatchFromCache();
40113
+ } catch (e) {
40114
+ log2(`[Bridge service] Agent capability probe (missing cache) failed: ${e instanceof Error ? e.message : String(e)}`);
40115
+ }
40116
+ void (async () => {
40117
+ try {
40118
+ await yieldToEventLoop();
40119
+ const n = await probeAgentCapabilitiesForDetectedTypes({
40120
+ agentTypes: types,
40121
+ cwd,
40122
+ workspaceId,
40123
+ log: log2,
40124
+ getDb,
40125
+ bridgeReport: false,
40126
+ forceAllTypes: true
40127
+ });
40128
+ if (n > 0) sendBatchFromCache();
40129
+ } catch (e) {
40130
+ log2(`[Bridge service] Agent capability lazy refresh failed: ${e instanceof Error ? e.message : String(e)}`);
40131
+ }
40132
+ })();
40133
+ }
40134
+
39777
40135
  // src/connection/create-bridge-connection.ts
39778
40136
  async function createBridgeConnection(options) {
39779
40137
  const { apiUrl, workspaceId, justAuthenticated, onAuthInvalid, persistTokens } = options;
@@ -39802,16 +40160,39 @@ async function createBridgeConnection(options) {
39802
40160
  firehoseOutage: createEmptyReconnectOutageTracker(),
39803
40161
  lastFirehoseReconnectCloseMeta: null
39804
40162
  };
40163
+ function getWs() {
40164
+ return state.currentWs;
40165
+ }
40166
+ function sendAgentCapabilitiesToBridge(info) {
40167
+ if (!Array.isArray(info.configOptions) || info.configOptions.length === 0) return;
40168
+ let changed = false;
40169
+ try {
40170
+ changed = upsertCliAgentCapabilityCache(getCliDatabase(), {
40171
+ workspaceId,
40172
+ agentType: info.agentType,
40173
+ configOptions: info.configOptions
40174
+ });
40175
+ } catch {
40176
+ }
40177
+ if (!changed) return;
40178
+ const socket = getWs();
40179
+ if (!socket || socket.readyState !== wrapper_default.OPEN) return;
40180
+ sendWsMessage(socket, {
40181
+ type: "agent_capabilities",
40182
+ agentType: info.agentType,
40183
+ configOptions: info.configOptions
40184
+ });
40185
+ }
39805
40186
  const worktreesRootPath = options.worktreesRootPath ?? defaultWorktreesRootPath();
39806
40187
  const sessionWorktreeManager = new SessionWorktreeManager({
39807
40188
  worktreesRootPath,
39808
40189
  log: logFn
39809
40190
  });
39810
- const acpManager = await createAcpManager({ log: logFn });
40191
+ const acpManager = await createAcpManager({
40192
+ log: logFn,
40193
+ reportAgentCapabilities: sendAgentCapabilitiesToBridge
40194
+ });
39811
40195
  logFn("CLI running. Press Ctrl+C to exit.");
39812
- function getWs() {
39813
- return state.currentWs;
39814
- }
39815
40196
  const e2ee = options.e2eCertificate ? createCliE2eeRuntime(options.e2eCertificate) : void 0;
39816
40197
  const devServerManager = new DevServerManager({ getWs, log: logFn, getBridgeRoot, e2ee });
39817
40198
  const bridgeHeartbeat = createBridgeHeartbeatController({ getWs, log: logFn });
@@ -39839,14 +40220,22 @@ async function createBridgeConnection(options) {
39839
40220
  },
39840
40221
  sendLocalSkillsReport,
39841
40222
  reportAutoDetectedAgents,
40223
+ warmupAgentCapabilitiesOnConnect: async () => {
40224
+ await warmupAgentCapabilitiesOnConnect({
40225
+ workspaceId,
40226
+ log: logFn,
40227
+ getDb: getCliDatabase,
40228
+ getWs
40229
+ });
40230
+ },
39842
40231
  devServerManager,
39843
40232
  e2ee,
39844
40233
  cloudApiBaseUrl: apiUrl,
39845
40234
  getCloudAccessToken: () => tokens.accessToken
39846
40235
  };
39847
40236
  const identifyReportedPaths = {
39848
- bridgeRootPath: path39.resolve(getBridgeRoot()),
39849
- worktreesRootPath: path39.resolve(worktreesRootPath)
40237
+ bridgeRootPath: path41.resolve(getBridgeRoot()),
40238
+ worktreesRootPath: path41.resolve(worktreesRootPath)
39850
40239
  };
39851
40240
  const { connect } = createMainBridgeWebSocketLifecycle({
39852
40241
  state,
@@ -40084,7 +40473,7 @@ async function runCliAction(program2, opts) {
40084
40473
  const firehoseServerUrl = opts.firehoseUrl ?? opts.proxyUrl ?? process.env.BUILDAUTOMATON_FIREHOSE_URL ?? process.env.BUILDAUTOMATON_PROXY_URL ?? DEFAULT_FIREHOSE_URL;
40085
40474
  const bridgeRootOpt = (opts.bridgeRoot && typeof opts.bridgeRoot === "string" && opts.bridgeRoot.trim() ? opts.bridgeRoot.trim() : null) ?? (opts.cwd && typeof opts.cwd === "string" && opts.cwd.trim() ? opts.cwd.trim() : null);
40086
40475
  if (bridgeRootOpt) {
40087
- const resolvedBridgeRoot = path40.resolve(process.cwd(), bridgeRootOpt);
40476
+ const resolvedBridgeRoot = path42.resolve(process.cwd(), bridgeRootOpt);
40088
40477
  try {
40089
40478
  const st = fs37.statSync(resolvedBridgeRoot);
40090
40479
  if (!st.isDirectory()) {
@@ -40106,7 +40495,7 @@ async function runCliAction(program2, opts) {
40106
40495
  );
40107
40496
  let worktreesRootPath;
40108
40497
  if (opts.worktreesRoot && opts.worktreesRoot.trim()) {
40109
- worktreesRootPath = path40.resolve(opts.worktreesRoot.trim());
40498
+ worktreesRootPath = path42.resolve(opts.worktreesRoot.trim());
40110
40499
  }
40111
40500
  const e2eCertificates = opts.e2eeCertificatesDir?.trim() ? await loadOrCreateE2eCertificates(opts.e2eeCertificatesDir.trim()) : void 0;
40112
40501
  if (e2eCertificates) {