@buildautomaton/cli 0.1.98 → 0.1.99

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
@@ -7375,6 +7375,7 @@ var init_idle_yield = __esm({
7375
7375
  // ../bridge/src/files/browser/in-flight.ts
7376
7376
  var init_in_flight = __esm({
7377
7377
  "../bridge/src/files/browser/in-flight.ts"() {
7378
+ "use strict";
7378
7379
  init_activity_shared();
7379
7380
  init_activity_types();
7380
7381
  init_activity_tracker();
@@ -8366,7 +8367,7 @@ function migrateCliSqlite(db) {
8366
8367
  "cli-sqlite"
8367
8368
  );
8368
8369
  }
8369
- var CHECKPOINT_V12, CHECKPOINT_V1_SQL2, AGENT_CAPABILITIES_SQL, DROP_CACHE_TABLES_SQL, CLI_SQLITE_MIGRATIONS;
8370
+ var CHECKPOINT_V12, CHECKPOINT_V1_SQL2, AGENT_CAPABILITIES_SQL, AGENT_SESSION_AVAILABLE_COMMANDS_SQL, AGENT_CAPABILITIES_AVAILABLE_COMMANDS_SQL, DROP_CACHE_TABLES_SQL, CLI_SQLITE_MIGRATIONS;
8370
8371
  var init_migrate_cli_sqlite = __esm({
8371
8372
  "../bridge/src/sqlite/migrate-cli-sqlite.ts"() {
8372
8373
  "use strict";
@@ -8375,6 +8376,12 @@ var init_migrate_cli_sqlite = __esm({
8375
8376
  CHECKPOINT_V12 = "001_cli_sqlite_checkpoint_v1";
8376
8377
  CHECKPOINT_V1_SQL2 = readCliSqliteMigrationSql("001_cli_sqlite_checkpoint_v1.sql");
8377
8378
  AGENT_CAPABILITIES_SQL = readCliSqliteMigrationSql("002_agent_capabilities.sql");
8379
+ AGENT_SESSION_AVAILABLE_COMMANDS_SQL = readCliSqliteMigrationSql(
8380
+ "003_agent_session_available_commands.sql"
8381
+ );
8382
+ AGENT_CAPABILITIES_AVAILABLE_COMMANDS_SQL = readCliSqliteMigrationSql(
8383
+ "004_agent_capabilities_available_commands.sql"
8384
+ );
8378
8385
  DROP_CACHE_TABLES_SQL = readCliSqliteMigrationSql("006_drop_cache_tables.sql");
8379
8386
  CLI_SQLITE_MIGRATIONS = [
8380
8387
  {
@@ -8401,6 +8408,26 @@ var init_migrate_cli_sqlite = __esm({
8401
8408
  },
8402
8409
  alreadyApplied: (db) => agentCapabilitiesTableState(db) === "current"
8403
8410
  },
8411
+ {
8412
+ name: "003_agent_session_available_commands",
8413
+ migrate: (db) => {
8414
+ db.exec(AGENT_SESSION_AVAILABLE_COMMANDS_SQL);
8415
+ },
8416
+ alreadyApplied: (db) => {
8417
+ const rows = db.all(`PRAGMA table_info(agent_session)`);
8418
+ return rows.some((r) => r.name === "available_commands_json");
8419
+ }
8420
+ },
8421
+ {
8422
+ name: "004_agent_capabilities_available_commands",
8423
+ migrate: (db) => {
8424
+ db.exec(AGENT_CAPABILITIES_AVAILABLE_COMMANDS_SQL);
8425
+ },
8426
+ alreadyApplied: (db) => {
8427
+ const rows = db.all(`PRAGMA table_info(agent_capabilities)`);
8428
+ return rows.some((r) => r.name === "available_commands_json");
8429
+ }
8430
+ },
8404
8431
  {
8405
8432
  name: "006_drop_cache_tables",
8406
8433
  migrate: (db) => {
@@ -30370,7 +30397,7 @@ var {
30370
30397
  } = import_index.default;
30371
30398
 
30372
30399
  // src/cli-version.ts
30373
- var CLI_VERSION = "0.1.98".length > 0 ? "0.1.98" : "0.0.0-dev";
30400
+ var CLI_VERSION = "0.1.99".length > 0 ? "0.1.99" : "0.0.0-dev";
30374
30401
 
30375
30402
  // src/cli/defaults.ts
30376
30403
  var DEFAULT_API_URL = process.env.BUILDAUTOMATON_API_URL ?? "https://api.buildautomaton.com";
@@ -35851,6 +35878,12 @@ function liveEditSnippetToUnifiedDiff(filePath, oldText, newText) {
35851
35878
  // ../bridge/src/files/workspace/limits.ts
35852
35879
  var MAX_SYNC_WORKSPACE_FILE_BYTES = 512 * 1024;
35853
35880
 
35881
+ // ../bridge/src/files/workspace/path-has-dot-dot-segment.ts
35882
+ function pathHasDotDotSegment(path87) {
35883
+ if (!path87) return false;
35884
+ return path87.split(/[/\\]/).includes("..");
35885
+ }
35886
+
35854
35887
  // ../bridge/src/files/workspace/safe-path.ts
35855
35888
  import * as path2 from "node:path";
35856
35889
  function resolveSafePathUnderCwd(cwd, filePath) {
@@ -35859,7 +35892,7 @@ function resolveSafePathUnderCwd(cwd, filePath) {
35859
35892
  const normalizedCwd = path2.resolve(cwd);
35860
35893
  const resolved = path2.isAbsolute(trimmed2) ? path2.normalize(trimmed2) : path2.resolve(normalizedCwd, trimmed2);
35861
35894
  const rel = path2.relative(normalizedCwd, resolved);
35862
- if (rel.startsWith("..") || path2.isAbsolute(rel)) return null;
35895
+ if (rel === ".." || rel.startsWith(`..${path2.sep}`) || path2.isAbsolute(rel)) return null;
35863
35896
  return resolved;
35864
35897
  }
35865
35898
  function toDisplayPathRelativeToCwd(cwd, absolutePath) {
@@ -36021,6 +36054,9 @@ function resolveWorkspaceFilePath(sessionParentPath, rawPath) {
36021
36054
  import { readFileSync as readFileSync3, statSync } from "node:fs";
36022
36055
  import * as path19 from "node:path";
36023
36056
  var GIT_FILE_READ_TIMEOUT_MS = 2e3;
36057
+ function isRelUnderRoot(rel) {
36058
+ return rel !== ".." && !rel.startsWith(`..${path19.sep}`) && !path19.isAbsolute(rel);
36059
+ }
36024
36060
  function readUtf8FileCapped(resolvedPath) {
36025
36061
  try {
36026
36062
  const st = statSync(resolvedPath);
@@ -36031,12 +36067,12 @@ function readUtf8FileCapped(resolvedPath) {
36031
36067
  }
36032
36068
  }
36033
36069
  function readUtf8WorkspaceFile(sessionParentPath, displayPath) {
36034
- if (!displayPath || displayPath.includes("..")) return "";
36070
+ if (!displayPath || pathHasDotDotSegment(displayPath)) return "";
36035
36071
  const gitRoot = getGitRepoRootSync(sessionParentPath);
36036
36072
  if (gitRoot) {
36037
36073
  const resolvedPath2 = path19.resolve(gitRoot, displayPath);
36038
36074
  const rel = path19.relative(gitRoot, resolvedPath2);
36039
- if (!rel.startsWith("..") && !path19.isAbsolute(rel)) {
36075
+ if (isRelUnderRoot(rel)) {
36040
36076
  return readUtf8FileCapped(resolvedPath2);
36041
36077
  }
36042
36078
  }
@@ -36045,17 +36081,17 @@ function readUtf8WorkspaceFile(sessionParentPath, displayPath) {
36045
36081
  return readUtf8FileCapped(resolvedPath);
36046
36082
  }
36047
36083
  function tryWorkspaceDisplayToPath(sessionParentPath, displayPath) {
36048
- if (!displayPath || displayPath.includes("..")) return null;
36084
+ if (!displayPath || pathHasDotDotSegment(displayPath)) return null;
36049
36085
  const gitRoot = getGitRepoRootSync(sessionParentPath);
36050
36086
  if (gitRoot) {
36051
36087
  const resolvedPath = path19.resolve(gitRoot, displayPath);
36052
36088
  const rel = path19.relative(gitRoot, resolvedPath);
36053
- if (!rel.startsWith("..") && !path19.isAbsolute(rel)) return resolvedPath;
36089
+ if (isRelUnderRoot(rel)) return resolvedPath;
36054
36090
  }
36055
36091
  return resolveSafePathUnderCwd(sessionParentPath, displayPath);
36056
36092
  }
36057
36093
  function readGitHeadBlob(sessionParentPath, displayPath) {
36058
- if (!displayPath || displayPath.includes("..")) return "";
36094
+ if (!displayPath || pathHasDotDotSegment(displayPath)) return "";
36059
36095
  const gitRoot = getGitRepoRootSync(sessionParentPath);
36060
36096
  if (!gitRoot) return "";
36061
36097
  try {
@@ -36107,15 +36143,35 @@ function acpWriteTextFileInProcess(ctx, filePath, newText) {
36107
36143
  return {};
36108
36144
  }
36109
36145
 
36146
+ // ../bridge/src/agents/acp/clients/shared/parse-available-commands.ts
36147
+ function parseAvailableCommandsList(raw) {
36148
+ if (!Array.isArray(raw)) return null;
36149
+ return raw;
36150
+ }
36151
+ function availableCommandsFromSessionUpdatePayload(flatPayload) {
36152
+ return parseAvailableCommandsList(flatPayload.availableCommands ?? flatPayload.available_commands);
36153
+ }
36154
+
36110
36155
  // ../bridge/src/agents/acp/clients/shared/dispatch-session-update.ts
36111
36156
  function dispatchAcpSessionUpdate(opts) {
36112
- const { flatPayload, onAcpConfigOptionsUpdated, onSessionUpdate, suppressLoadReplay } = opts;
36157
+ const {
36158
+ flatPayload,
36159
+ onAcpConfigOptionsUpdated,
36160
+ onAcpAvailableCommandsUpdated,
36161
+ onSessionUpdate,
36162
+ suppressLoadReplay
36163
+ } = opts;
36113
36164
  const su = flatPayload.sessionUpdate ?? flatPayload.session_update;
36114
36165
  if (su === "config_option_update") {
36115
36166
  const co = flatPayload.configOptions;
36116
36167
  if (Array.isArray(co)) onAcpConfigOptionsUpdated?.(co);
36117
36168
  return;
36118
36169
  }
36170
+ if (su === "available_commands_update") {
36171
+ const cmds = availableCommandsFromSessionUpdatePayload(flatPayload);
36172
+ if (cmds) onAcpAvailableCommandsUpdated?.(cmds);
36173
+ return;
36174
+ }
36119
36175
  if (suppressLoadReplay()) return;
36120
36176
  onSessionUpdate?.(flatPayload);
36121
36177
  }
@@ -36188,6 +36244,7 @@ function createSdkStdioConnectionClient(deps) {
36188
36244
  dispatchAcpSessionUpdate({
36189
36245
  flatPayload: bridged,
36190
36246
  onAcpConfigOptionsUpdated: sessionCtx.onAcpConfigOptionsUpdated,
36247
+ onAcpAvailableCommandsUpdated: sessionCtx.onAcpAvailableCommandsUpdated,
36191
36248
  onSessionUpdate,
36192
36249
  suppressLoadReplay: () => sessionCtx.suppressLoadReplay.value
36193
36250
  });
@@ -36275,6 +36332,7 @@ function createSdkStdioSessionContext(options) {
36275
36332
  getActiveConfigOptions: options.getActiveConfigOptions,
36276
36333
  onAcpSessionEstablished: options.onAcpSessionEstablished,
36277
36334
  onAcpConfigOptionsUpdated: options.onAcpConfigOptionsUpdated,
36335
+ onAcpAvailableCommandsUpdated: options.onAcpAvailableCommandsUpdated,
36278
36336
  logDebug,
36279
36337
  getStderrText: () => options.stderrCapture.getText(),
36280
36338
  afterSessionEstablished: options.afterSessionEstablished
@@ -36633,6 +36691,7 @@ async function createSdkStdioAcpClient(options) {
36633
36691
  getActiveConfigOptions,
36634
36692
  onAcpSessionEstablished,
36635
36693
  onAcpConfigOptionsUpdated,
36694
+ onAcpAvailableCommandsUpdated: options.onAcpAvailableCommandsUpdated,
36636
36695
  onFileChange,
36637
36696
  afterSessionEstablished,
36638
36697
  stderrCapture
@@ -38769,6 +38828,7 @@ function createCursorAcpSessionContext(options) {
38769
38828
  getActiveConfigOptions: options.getActiveConfigOptions,
38770
38829
  onAcpSessionEstablished: options.onAcpSessionEstablished,
38771
38830
  onAcpConfigOptionsUpdated: options.onAcpConfigOptionsUpdated,
38831
+ onAcpAvailableCommandsUpdated: options.onAcpAvailableCommandsUpdated,
38772
38832
  logDebug,
38773
38833
  getStderrText: () => options.stderrCapture.getText(),
38774
38834
  pendingPlanExecute: { value: false },
@@ -39193,6 +39253,7 @@ function handleCursorIncomingSessionUpdate(msg, deps) {
39193
39253
  dispatchAcpSessionUpdate({
39194
39254
  flatPayload: update,
39195
39255
  onAcpConfigOptionsUpdated: deps.sessionCtx.onAcpConfigOptionsUpdated,
39256
+ onAcpAvailableCommandsUpdated: deps.sessionCtx.onAcpAvailableCommandsUpdated,
39196
39257
  onSessionUpdate: deps.onSessionUpdate,
39197
39258
  suppressLoadReplay: () => deps.sessionCtx.suppressLoadReplay.value
39198
39259
  });
@@ -39445,6 +39506,7 @@ async function createCursorAcpClient(options) {
39445
39506
  getActiveConfigOptions: options.getActiveConfigOptions,
39446
39507
  onAcpSessionEstablished,
39447
39508
  onAcpConfigOptionsUpdated,
39509
+ onAcpAvailableCommandsUpdated: options.onAcpAvailableCommandsUpdated,
39448
39510
  onFileChange,
39449
39511
  afterSessionEstablished,
39450
39512
  stderrCapture
@@ -39646,7 +39708,7 @@ function getAgentTypeDisplayName(agentType) {
39646
39708
  import { existsSync as existsSync4, statSync as statSync2 } from "node:fs";
39647
39709
  var GIT_PATH_KIND_TIMEOUT_MS = 2e3;
39648
39710
  function gitHeadPathObjectType(sessionParentPath, displayPath) {
39649
- if (!displayPath || displayPath.includes("..")) return null;
39711
+ if (!displayPath || pathHasDotDotSegment(displayPath)) return null;
39650
39712
  const gitRoot = getGitRepoRootSync(sessionParentPath);
39651
39713
  if (!gitRoot) return null;
39652
39714
  try {
@@ -40422,36 +40484,74 @@ function buildAcpSessionBridgeHooks(opts) {
40422
40484
 
40423
40485
  // ../bridge/src/agents/acp/local-agent-session-file.ts
40424
40486
  init_cli_database();
40487
+
40488
+ // ../bridge/src/agents/acp/local-agent-session-row.ts
40489
+ function parseJsonArray(raw) {
40490
+ if (raw == null || raw === "") return null;
40491
+ try {
40492
+ const parsed = JSON.parse(raw);
40493
+ return Array.isArray(parsed) ? parsed : null;
40494
+ } catch {
40495
+ return null;
40496
+ }
40497
+ }
40498
+ function rowToFile(row) {
40499
+ return {
40500
+ v: 1,
40501
+ acpSessionId: row.acp_session_id,
40502
+ backendAgentType: row.backend_agent_type,
40503
+ configOptions: parseJsonArray(row.config_options_json),
40504
+ availableCommands: parseJsonArray(row.available_commands_json),
40505
+ updatedAt: row.updated_at
40506
+ };
40507
+ }
40508
+ function readLocalAgentSessionRow(db, key) {
40509
+ const row = db.get(
40510
+ `SELECT acp_session_id, backend_agent_type, config_options_json, available_commands_json, updated_at
40511
+ FROM agent_session WHERE session_key = ?`,
40512
+ [key]
40513
+ );
40514
+ return row ? rowToFile(row) : null;
40515
+ }
40516
+ function writeLocalAgentSessionRow(db, key, patch) {
40517
+ const prev = readLocalAgentSessionRow(db, key);
40518
+ const next = {
40519
+ v: 1,
40520
+ acpSessionId: patch.acpSessionId !== void 0 ? patch.acpSessionId : prev?.acpSessionId ?? null,
40521
+ backendAgentType: patch.backendAgentType !== void 0 ? patch.backendAgentType : prev?.backendAgentType ?? null,
40522
+ configOptions: patch.configOptions !== void 0 ? patch.configOptions : prev?.configOptions ?? null,
40523
+ availableCommands: patch.availableCommands !== void 0 ? patch.availableCommands : prev?.availableCommands ?? null,
40524
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
40525
+ };
40526
+ db.run(
40527
+ `INSERT INTO agent_session (
40528
+ session_key, acp_session_id, backend_agent_type, config_options_json, available_commands_json, updated_at
40529
+ ) VALUES (?, ?, ?, ?, ?, ?)
40530
+ ON CONFLICT(session_key) DO UPDATE SET
40531
+ acp_session_id = excluded.acp_session_id,
40532
+ backend_agent_type = excluded.backend_agent_type,
40533
+ config_options_json = excluded.config_options_json,
40534
+ available_commands_json = excluded.available_commands_json,
40535
+ updated_at = excluded.updated_at`,
40536
+ [
40537
+ key,
40538
+ next.acpSessionId,
40539
+ next.backendAgentType,
40540
+ next.configOptions != null ? JSON.stringify(next.configOptions) : null,
40541
+ next.availableCommands != null ? JSON.stringify(next.availableCommands) : null,
40542
+ next.updatedAt
40543
+ ]
40544
+ );
40545
+ }
40546
+
40547
+ // ../bridge/src/agents/acp/local-agent-session-file.ts
40425
40548
  function sessionKeyForCloudSessionId(cloudSessionId) {
40426
40549
  const t = cloudSessionId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 220);
40427
40550
  return t.length > 0 ? t : "session";
40428
40551
  }
40429
40552
  function readLocalAgentSessionFile(cloudSessionId) {
40430
40553
  try {
40431
- return withCliSqliteSync((db) => {
40432
- const key = sessionKeyForCloudSessionId(cloudSessionId);
40433
- const row = db.get(
40434
- "SELECT acp_session_id, backend_agent_type, config_options_json, updated_at FROM agent_session WHERE session_key = ?",
40435
- [key]
40436
- );
40437
- if (!row) return null;
40438
- let configOptions = null;
40439
- if (row.config_options_json != null && row.config_options_json !== "") {
40440
- try {
40441
- const parsed = JSON.parse(row.config_options_json);
40442
- configOptions = Array.isArray(parsed) ? parsed : null;
40443
- } catch {
40444
- configOptions = null;
40445
- }
40446
- }
40447
- return {
40448
- v: 1,
40449
- acpSessionId: row.acp_session_id,
40450
- backendAgentType: row.backend_agent_type,
40451
- configOptions,
40452
- updatedAt: row.updated_at
40453
- };
40454
- });
40554
+ return withCliSqliteSync((db) => readLocalAgentSessionRow(db, sessionKeyForCloudSessionId(cloudSessionId)));
40455
40555
  } catch {
40456
40556
  return null;
40457
40557
  }
@@ -40459,53 +40559,28 @@ function readLocalAgentSessionFile(cloudSessionId) {
40459
40559
  function writeLocalAgentSessionFile(cloudSessionId, patch) {
40460
40560
  try {
40461
40561
  withCliSqliteSync((db) => {
40462
- const key = sessionKeyForCloudSessionId(cloudSessionId);
40463
- const prevRow = db.get(
40464
- "SELECT acp_session_id, backend_agent_type, config_options_json, updated_at FROM agent_session WHERE session_key = ?",
40465
- [key]
40466
- );
40467
- let prev = null;
40468
- if (prevRow) {
40469
- let configOptions = null;
40470
- if (prevRow.config_options_json != null && prevRow.config_options_json !== "") {
40471
- try {
40472
- const parsed = JSON.parse(prevRow.config_options_json);
40473
- configOptions = Array.isArray(parsed) ? parsed : null;
40474
- } catch {
40475
- configOptions = null;
40476
- }
40477
- }
40478
- prev = {
40479
- v: 1,
40480
- acpSessionId: prevRow.acp_session_id,
40481
- backendAgentType: prevRow.backend_agent_type,
40482
- configOptions,
40483
- updatedAt: prevRow.updated_at
40484
- };
40485
- }
40486
- const next = {
40487
- v: 1,
40488
- acpSessionId: patch.acpSessionId !== void 0 ? patch.acpSessionId : prev?.acpSessionId ?? null,
40489
- backendAgentType: patch.backendAgentType !== void 0 ? patch.backendAgentType : prev?.backendAgentType ?? null,
40490
- configOptions: patch.configOptions !== void 0 ? patch.configOptions : prev?.configOptions ?? null,
40491
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
40492
- };
40493
- const configJson = next.configOptions != null ? JSON.stringify(next.configOptions) : null;
40494
- db.run(
40495
- `INSERT INTO agent_session (session_key, acp_session_id, backend_agent_type, config_options_json, updated_at)
40496
- VALUES (?, ?, ?, ?, ?)
40497
- ON CONFLICT(session_key) DO UPDATE SET
40498
- acp_session_id = excluded.acp_session_id,
40499
- backend_agent_type = excluded.backend_agent_type,
40500
- config_options_json = excluded.config_options_json,
40501
- updated_at = excluded.updated_at`,
40502
- [key, next.acpSessionId, next.backendAgentType, configJson, next.updatedAt]
40503
- );
40562
+ writeLocalAgentSessionRow(db, sessionKeyForCloudSessionId(cloudSessionId), patch);
40504
40563
  });
40505
40564
  } catch {
40506
40565
  }
40507
40566
  }
40508
40567
 
40568
+ // ../bridge/src/agents/acp/persist-acp-available-commands.ts
40569
+ function persistAcpAvailableCommands(params) {
40570
+ const { availableCommands, setActive, cloudSessionId, preferredAgentType, reportAgentCapabilities } = params;
40571
+ if (!Array.isArray(availableCommands)) return;
40572
+ setActive(availableCommands);
40573
+ if (cloudSessionId != null && cloudSessionId !== "") {
40574
+ writeLocalAgentSessionFile(cloudSessionId, {
40575
+ availableCommands,
40576
+ ...preferredAgentType != null && preferredAgentType !== "" ? { backendAgentType: preferredAgentType } : {}
40577
+ });
40578
+ }
40579
+ if (reportAgentCapabilities && preferredAgentType != null && preferredAgentType !== "" && availableCommands.length > 0) {
40580
+ reportAgentCapabilities({ agentType: preferredAgentType, availableCommands });
40581
+ }
40582
+ }
40583
+
40509
40584
  // ../bridge/src/agents/acp/acp-agent.ts
40510
40585
  function computeAcpSessionAgentKey(cloudSessionId, acpAgentKey) {
40511
40586
  const sid = cloudSessionId?.trim();
@@ -40554,6 +40629,7 @@ function invalidateAcpClientState(state) {
40554
40629
  state.acpStartPromise = null;
40555
40630
  state.acpAgentKey = null;
40556
40631
  state.activeSessionConfigOptions = null;
40632
+ state.activeAvailableCommands = null;
40557
40633
  state.latestAgentConfigForBridgeHooks = null;
40558
40634
  }
40559
40635
  function createEmptyAcpClientState() {
@@ -40564,6 +40640,7 @@ function createEmptyAcpClientState() {
40564
40640
  lastAcpCwd: null,
40565
40641
  acpAgentKey: null,
40566
40642
  activeSessionConfigOptions: null,
40643
+ activeAvailableCommands: null,
40567
40644
  latestAgentConfigForBridgeHooks: null,
40568
40645
  clientEpoch: 0
40569
40646
  };
@@ -40649,6 +40726,7 @@ async function ensureAcpClient(options) {
40649
40726
  const persisted = cloudSessionId != null && cloudSessionId !== "" && preferredAgentType != null && preferredAgentType !== "" ? readLocalAgentSessionFile(cloudSessionId) : null;
40650
40727
  const persistedAcpSessionId = persisted && persisted.backendAgentType === preferredAgentType && typeof persisted.acpSessionId === "string" && persisted.acpSessionId.trim() !== "" ? persisted.acpSessionId.trim() : null;
40651
40728
  state.activeSessionConfigOptions = Array.isArray(persisted?.configOptions) ? persisted.configOptions : null;
40729
+ state.activeAvailableCommands = Array.isArray(persisted?.availableCommands) ? persisted.availableCommands : null;
40652
40730
  const spawnEpoch = state.clientEpoch;
40653
40731
  state.acpStartPromise = resolved.createClient({
40654
40732
  command: resolved.command,
@@ -40688,6 +40766,17 @@ async function ensureAcpClient(options) {
40688
40766
  });
40689
40767
  }
40690
40768
  },
40769
+ onAcpAvailableCommandsUpdated: (availableCommands) => {
40770
+ persistAcpAvailableCommands({
40771
+ availableCommands,
40772
+ setActive: (cmds) => {
40773
+ state.activeAvailableCommands = cmds;
40774
+ },
40775
+ cloudSessionId,
40776
+ preferredAgentType,
40777
+ reportAgentCapabilities
40778
+ });
40779
+ },
40691
40780
  onAgentSubprocessExit: () => {
40692
40781
  if (state.acpHandle != null) {
40693
40782
  state.clientEpoch += 1;
@@ -40696,6 +40785,7 @@ async function ensureAcpClient(options) {
40696
40785
  state.acpStartPromise = null;
40697
40786
  state.acpAgentKey = null;
40698
40787
  state.activeSessionConfigOptions = null;
40788
+ state.activeAvailableCommands = null;
40699
40789
  state.latestAgentConfigForBridgeHooks = null;
40700
40790
  state.lastAcpStartError = "Agent subprocess exited";
40701
40791
  },
@@ -40905,7 +40995,7 @@ function repoDisplayPath(repoPath, multiRepo) {
40905
40995
  return (rel) => multiRepo ? `${slug}/${rel}` : rel;
40906
40996
  }
40907
40997
  function safeRelPath(rel) {
40908
- return typeof rel === "string" && rel.length > 0 && !rel.includes("..");
40998
+ return typeof rel === "string" && rel.length > 0 && !pathHasDotDotSegment(rel);
40909
40999
  }
40910
41000
  function newUntrackedPaths(raw, baselineUntracked, seen) {
40911
41001
  const baseline = new Set(baselineUntracked);
@@ -41235,6 +41325,19 @@ async function sendPromptToAgent(options) {
41235
41325
  attachments,
41236
41326
  isNewSession = false
41237
41327
  } = options;
41328
+ const finalize2 = (result) => finalizeAndSendPromptResult({
41329
+ result,
41330
+ sessionId,
41331
+ runId,
41332
+ promptId,
41333
+ agentType,
41334
+ agentCwd,
41335
+ followUpCatalogPromptId,
41336
+ plugin,
41337
+ sendResult,
41338
+ sendSessionUpdate,
41339
+ log: log2
41340
+ });
41238
41341
  try {
41239
41342
  const prepared = await prepareAgentPromptText({
41240
41343
  promptText,
@@ -41255,7 +41358,10 @@ async function sendPromptToAgent(options) {
41255
41358
  log: log2
41256
41359
  });
41257
41360
  if (!imagesResolved.ok) {
41258
- sendResult(imagesResolved.errorResult);
41361
+ await finalize2({
41362
+ success: false,
41363
+ error: imagesResolved.errorResult.error
41364
+ });
41259
41365
  return;
41260
41366
  }
41261
41367
  const promptStartedAt = Date.now();
@@ -41264,32 +41370,11 @@ async function sendPromptToAgent(options) {
41264
41370
  if (promptDurationMs >= SLOW_ACP_PROMPT_MS) {
41265
41371
  log2(`[Agent] ACP session/prompt completed after ${promptDurationMs}ms.`);
41266
41372
  }
41267
- await finalizeAndSendPromptResult({
41268
- result,
41269
- sessionId,
41270
- runId,
41271
- promptId,
41272
- agentType,
41273
- agentCwd,
41274
- followUpCatalogPromptId,
41275
- plugin,
41276
- sendResult,
41277
- sendSessionUpdate,
41278
- log: log2
41279
- });
41373
+ await finalize2(result);
41280
41374
  } catch (err) {
41281
41375
  const errMsg = err instanceof Error ? err.message : String(err);
41282
41376
  log2(`[Agent] Send failed: ${errMsg}`);
41283
- sendResult({
41284
- type: "prompt_result",
41285
- id: promptId,
41286
- ...sessionId ? { sessionId } : {},
41287
- ...runId ? { runId } : {},
41288
- success: false,
41289
- error: errMsg,
41290
- ...followUpCatalogPromptId != null && followUpCatalogPromptId !== "" ? { followUpCatalogPromptId } : {},
41291
- ...augmentPromptResultAuthFields(agentType, errMsg)
41292
- });
41377
+ await finalize2({ success: false, error: errMsg });
41293
41378
  }
41294
41379
  }
41295
41380
 
@@ -41409,8 +41494,13 @@ async function ensureAcpPromptClient(ctx, runCtx, opts) {
41409
41494
 
41410
41495
  // ../bridge/src/agents/acp/manager/run-acp-prompt.ts
41411
41496
  async function runAcpPrompt(ctx, runCtx, opts) {
41412
- const handle = await ensureAcpPromptClient(ctx, runCtx, opts);
41413
- if (handle) await dispatchAcpPrompt(ctx, runCtx, opts, handle);
41497
+ ctx.promptRouting.setStreamingRunId(runCtx.activeAcpSessionAgentKey, runCtx.activeRunId);
41498
+ try {
41499
+ const handle = await ensureAcpPromptClient(ctx, runCtx, opts);
41500
+ if (handle) await dispatchAcpPrompt(ctx, runCtx, opts, handle);
41501
+ } finally {
41502
+ ctx.promptRouting.clearStreamingRunId(runCtx.activeAcpSessionAgentKey, runCtx.activeRunId);
41503
+ }
41414
41504
  }
41415
41505
 
41416
41506
  // ../bridge/src/agents/acp/manager/handle-prompt.ts
@@ -42045,63 +42135,95 @@ function hashJsonUtf8Sha256(value) {
42045
42135
  return createHash2("sha256").update(JSON.stringify(value), "utf8").digest("hex");
42046
42136
  }
42047
42137
 
42138
+ // ../bridge/src/sqlite/agent-capability-fields.ts
42139
+ function parseJsonArrayColumn(raw) {
42140
+ if (raw == null || raw === "") return null;
42141
+ try {
42142
+ const parsed = JSON.parse(raw);
42143
+ return Array.isArray(parsed) ? parsed : null;
42144
+ } catch {
42145
+ return null;
42146
+ }
42147
+ }
42148
+ function mergeAgentCapabilityFields(existing, patch) {
42149
+ return {
42150
+ configOptions: patch.configOptions !== void 0 ? patch.configOptions : existing.configOptions,
42151
+ availableCommands: patch.availableCommands !== void 0 ? patch.availableCommands : existing.availableCommands
42152
+ };
42153
+ }
42154
+
42155
+ // ../bridge/src/sqlite/list-cli-agent-capability-cache.ts
42156
+ function listCliAgentCapabilityCacheForWorkspace(db, workspaceId) {
42157
+ const rows = db.all(
42158
+ `SELECT agent_type, config_options_json, available_commands_json FROM agent_capabilities WHERE workspace_id = ?`,
42159
+ [workspaceId]
42160
+ );
42161
+ const out = [];
42162
+ for (const r of rows) {
42163
+ const configOptions = parseJsonArrayColumn(r.config_options_json) ?? [];
42164
+ const availableCommands = parseJsonArrayColumn(r.available_commands_json);
42165
+ if (configOptions.length === 0 && !(availableCommands && availableCommands.length > 0)) continue;
42166
+ out.push({ agentType: r.agent_type, configOptions, availableCommands });
42167
+ }
42168
+ return out;
42169
+ }
42170
+
42048
42171
  // ../bridge/src/sqlite/agent-capability-cache.ts
42049
- function hasNonEmptyAgentCapabilityCache(db, workspaceId, agentType) {
42050
- const t = agentType.trim();
42051
- if (!t) return false;
42172
+ function readExistingFields(db, workspaceId, agentType) {
42052
42173
  try {
42053
42174
  const row = db.get(
42054
- `SELECT config_options_json FROM agent_capabilities WHERE workspace_id = ? AND agent_type = ?`,
42055
- [workspaceId, t]
42175
+ `SELECT config_options_json, available_commands_json, content_hash
42176
+ FROM agent_capabilities WHERE workspace_id = ? AND agent_type = ?`,
42177
+ [workspaceId, agentType]
42056
42178
  );
42057
- if (row?.config_options_json == null || row.config_options_json === "") return false;
42058
- const parsed = JSON.parse(row.config_options_json);
42059
- return Array.isArray(parsed) && parsed.length > 0;
42179
+ if (!row) return { configOptions: null, availableCommands: null };
42180
+ return {
42181
+ configOptions: parseJsonArrayColumn(row.config_options_json),
42182
+ availableCommands: parseJsonArrayColumn(row.available_commands_json),
42183
+ contentHash: row.content_hash
42184
+ };
42060
42185
  } catch {
42061
- return false;
42186
+ return { configOptions: null, availableCommands: null };
42062
42187
  }
42063
42188
  }
42189
+ function hasNonEmptyAgentCapabilityCache(db, workspaceId, agentType) {
42190
+ const t = agentType.trim();
42191
+ if (!t) return false;
42192
+ const existing = readExistingFields(db, workspaceId, t);
42193
+ return Array.isArray(existing.configOptions) && existing.configOptions.length > 0;
42194
+ }
42064
42195
  function upsertCliAgentCapabilityCache(db, row) {
42065
42196
  const t = row.agentType.trim();
42066
42197
  if (!t) return false;
42067
- const hash2 = hashJsonUtf8Sha256(row.configOptions);
42068
- try {
42069
- const prev = db.get(
42070
- `SELECT content_hash FROM agent_capabilities WHERE workspace_id = ? AND agent_type = ?`,
42071
- [row.workspaceId, t]
42072
- );
42073
- if (prev?.content_hash === hash2) return false;
42074
- } catch {
42075
- }
42076
- const json2 = JSON.stringify(row.configOptions);
42198
+ const existing = readExistingFields(db, row.workspaceId, t);
42199
+ const next = mergeAgentCapabilityFields(existing, row);
42200
+ if (!next.configOptions?.length && !next.availableCommands?.length) return false;
42201
+ const hash2 = hashJsonUtf8Sha256({
42202
+ configOptions: next.configOptions,
42203
+ availableCommands: next.availableCommands
42204
+ });
42205
+ if (existing.contentHash === hash2) return false;
42077
42206
  const now = (/* @__PURE__ */ new Date()).toISOString();
42078
42207
  db.run(
42079
- `INSERT INTO agent_capabilities (workspace_id, agent_type, config_options_json, content_hash, updated_at)
42080
- VALUES (?, ?, ?, ?, ?)
42208
+ `INSERT INTO agent_capabilities (
42209
+ workspace_id, agent_type, config_options_json, available_commands_json, content_hash, updated_at
42210
+ ) VALUES (?, ?, ?, ?, ?, ?)
42081
42211
  ON CONFLICT(workspace_id, agent_type) DO UPDATE SET
42082
42212
  config_options_json = excluded.config_options_json,
42213
+ available_commands_json = excluded.available_commands_json,
42083
42214
  content_hash = excluded.content_hash,
42084
42215
  updated_at = excluded.updated_at`,
42085
- [row.workspaceId, t, json2, hash2, now]
42216
+ [
42217
+ row.workspaceId,
42218
+ t,
42219
+ next.configOptions != null ? JSON.stringify(next.configOptions) : null,
42220
+ next.availableCommands != null ? JSON.stringify(next.availableCommands) : null,
42221
+ hash2,
42222
+ now
42223
+ ]
42086
42224
  );
42087
42225
  return true;
42088
42226
  }
42089
- function listCliAgentCapabilityCacheForWorkspace(db, workspaceId) {
42090
- const rows = db.all(
42091
- `SELECT agent_type, config_options_json FROM agent_capabilities WHERE workspace_id = ?`,
42092
- [workspaceId]
42093
- );
42094
- const out = [];
42095
- for (const r of rows) {
42096
- try {
42097
- const parsed = JSON.parse(r.config_options_json);
42098
- if (!Array.isArray(parsed) || parsed.length === 0) continue;
42099
- out.push({ agentType: r.agent_type, configOptions: parsed });
42100
- } catch {
42101
- }
42102
- }
42103
- return out;
42104
- }
42105
42227
 
42106
42228
  // ../bridge/src/agents/capabilities/probe-agent-capabilities-for-types.ts
42107
42229
  init_cli_database();
@@ -42255,7 +42377,11 @@ async function warmupAgentCapabilitiesOnConnect(params) {
42255
42377
  if (!isCurrent() || rows.length === 0) return;
42256
42378
  sendWsMessage(socket, {
42257
42379
  type: "agent_capabilities_batch",
42258
- items: rows.map((r) => ({ agentType: r.agentType, configOptions: r.configOptions }))
42380
+ items: rows.map((r) => ({
42381
+ agentType: r.agentType,
42382
+ configOptions: r.configOptions,
42383
+ ...r.availableCommands != null ? { availableCommands: r.availableCommands } : {}
42384
+ }))
42259
42385
  });
42260
42386
  } catch (e) {
42261
42387
  if (e instanceof CliSqliteInterrupted) return;
@@ -42299,7 +42425,9 @@ init_cli_database();
42299
42425
  function createAgentCapabilitiesReporter(params) {
42300
42426
  const { workspaceId, getWs } = params;
42301
42427
  return (info) => {
42302
- if (!Array.isArray(info.configOptions) || info.configOptions.length === 0) return;
42428
+ const hasConfig = Array.isArray(info.configOptions) && info.configOptions.length > 0;
42429
+ const hasCommands = Array.isArray(info.availableCommands) && info.availableCommands.length > 0;
42430
+ if (!hasConfig && !hasCommands) return;
42303
42431
  setImmediate(() => {
42304
42432
  let changed = false;
42305
42433
  try {
@@ -42307,7 +42435,8 @@ function createAgentCapabilitiesReporter(params) {
42307
42435
  (db) => upsertCliAgentCapabilityCache(db, {
42308
42436
  workspaceId,
42309
42437
  agentType: info.agentType,
42310
- configOptions: info.configOptions
42438
+ ...hasConfig ? { configOptions: info.configOptions } : {},
42439
+ ...hasCommands ? { availableCommands: info.availableCommands } : {}
42311
42440
  })
42312
42441
  );
42313
42442
  } catch (e) {
@@ -42319,7 +42448,8 @@ function createAgentCapabilitiesReporter(params) {
42319
42448
  sendWsMessage(socket, {
42320
42449
  type: "agent_capabilities",
42321
42450
  agentType: info.agentType,
42322
- configOptions: info.configOptions
42451
+ ...hasConfig ? { configOptions: info.configOptions } : {},
42452
+ ...hasCommands ? { availableCommands: info.availableCommands } : {}
42323
42453
  });
42324
42454
  });
42325
42455
  };
@@ -43701,7 +43831,7 @@ function createBridgeHeartbeatController(params) {
43701
43831
  }
43702
43832
 
43703
43833
  // ../bridge/src/cli/cli-version.ts
43704
- var CLI_VERSION2 = "0.1.98".length > 0 ? "0.1.98" : "0.0.0-dev";
43834
+ var CLI_VERSION2 = "0.1.99".length > 0 ? "0.1.99" : "0.0.0-dev";
43705
43835
 
43706
43836
  // ../bridge/src/connection/identify/send-bridge-identify.ts
43707
43837
  function sendBridgeIdentify(ws, params) {