@buildautomaton/cli 0.1.71 → 0.1.73

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/index.js CHANGED
@@ -29997,12 +29997,32 @@ function attachSdkStdioStderrAuthWatch(options) {
29997
29997
 
29998
29998
  // src/agents/acp/clients/sdk/spawn-sdk-stdio-process.ts
29999
29999
  import { spawn } from "node:child_process";
30000
+
30001
+ // src/agents/acp/clients/bridge-installed-agent-auth-env.ts
30002
+ var authEnv = /* @__PURE__ */ new Map();
30003
+ function setBridgeInstalledAgentAuthEnv(entries) {
30004
+ authEnv.clear();
30005
+ for (const entry of entries) {
30006
+ const envVar = typeof entry.envVar === "string" ? entry.envVar.trim() : "";
30007
+ const token = typeof entry.token === "string" ? entry.token.trim() : "";
30008
+ if (envVar && token) authEnv.set(envVar, token);
30009
+ }
30010
+ }
30011
+ function bridgeInstalledAgentAuthProcessEnv(base = process.env) {
30012
+ if (authEnv.size === 0) return base;
30013
+ return { ...base, ...Object.fromEntries(authEnv) };
30014
+ }
30015
+ function cursorAgentUsesApiKeyAuth(env = process.env) {
30016
+ return Boolean(env.CURSOR_API_KEY?.trim() || env.CURSOR_AUTH_TOKEN?.trim());
30017
+ }
30018
+
30019
+ // src/agents/acp/clients/sdk/spawn-sdk-stdio-process.ts
30000
30020
  function spawnSdkStdioProcess(options) {
30001
30021
  const isWindows = process.platform === "win32";
30002
30022
  const child = spawn(options.command[0], options.command.slice(1), {
30003
30023
  cwd: options.cwd,
30004
30024
  stdio: ["pipe", "pipe", "pipe"],
30005
- env: process.env,
30025
+ env: bridgeInstalledAgentAuthProcessEnv(process.env),
30006
30026
  shell: isWindows
30007
30027
  });
30008
30028
  const stderrCapture = createStderrCapture(child);
@@ -30586,7 +30606,7 @@ function installBridgeProcessResilience() {
30586
30606
  }
30587
30607
 
30588
30608
  // src/cli-version.ts
30589
- var CLI_VERSION = "0.1.71".length > 0 ? "0.1.71" : "0.0.0-dev";
30609
+ var CLI_VERSION = "0.1.73".length > 0 ? "0.1.73" : "0.0.0-dev";
30590
30610
 
30591
30611
  // src/connection/heartbeat/constants.ts
30592
30612
  var BRIDGE_APP_HEARTBEAT_INTERVAL_MS = 1e4;
@@ -33032,7 +33052,11 @@ __export(claude_code_acp_client_exports, {
33032
33052
 
33033
33053
  // src/agents/acp/clients/detect-command-on-path.ts
33034
33054
  init_cli_process_interrupt();
33055
+ import { constants } from "node:fs";
33056
+ import { access } from "node:fs/promises";
33035
33057
  import { execFile as execFile6 } from "node:child_process";
33058
+ import { homedir as homedir2 } from "node:os";
33059
+ import { join as join6 } from "node:path";
33036
33060
  import { promisify as promisify7 } from "node:util";
33037
33061
  var execFileAsync5 = promisify7(execFile6);
33038
33062
  var COMMAND_ON_PATH_PROBE_TIMEOUT_MS = 750;
@@ -33049,6 +33073,21 @@ async function execFileShutdownAware(file2, args, timeoutMs) {
33049
33073
  clearInterval(shutdownPoll);
33050
33074
  }
33051
33075
  }
33076
+ async function isExecutableFile(filePath) {
33077
+ try {
33078
+ await access(filePath, constants.X_OK);
33079
+ return true;
33080
+ } catch {
33081
+ return false;
33082
+ }
33083
+ }
33084
+ async function isCommandInBridgeAgentDirs(command) {
33085
+ const home = process.env.HOME ?? homedir2();
33086
+ for (const dir of getBridgeAgentPathEntries(home)) {
33087
+ if (await isExecutableFile(join6(dir, command))) return true;
33088
+ }
33089
+ return false;
33090
+ }
33052
33091
  async function isCommandOnPath(command, timeoutMs = COMMAND_ON_PATH_PROBE_TIMEOUT_MS) {
33053
33092
  if (isCliImmediateShutdownRequested()) return false;
33054
33093
  try {
@@ -33058,8 +33097,18 @@ async function isCommandOnPath(command, timeoutMs = COMMAND_ON_PATH_PROBE_TIMEOU
33058
33097
  });
33059
33098
  return true;
33060
33099
  } catch {
33061
- return false;
33100
+ return isCommandInBridgeAgentDirs(command);
33101
+ }
33102
+ }
33103
+ async function waitForCommandOnPath(command, opts = {}) {
33104
+ const maxAttempts = opts.maxAttempts ?? 8;
33105
+ const delayMs = opts.delayMs ?? 400;
33106
+ const timeoutMs = opts.timeoutMs ?? COMMAND_ON_PATH_PROBE_TIMEOUT_MS;
33107
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
33108
+ if (await isCommandOnPath(command, timeoutMs)) return true;
33109
+ if (attempt < maxAttempts - 1) await new Promise((r) => setTimeout(r, delayMs));
33062
33110
  }
33111
+ return false;
33063
33112
  }
33064
33113
  async function execProbeShutdownAware(file2, args, timeoutMs) {
33065
33114
  if (isCliImmediateShutdownRequested()) return false;
@@ -33440,10 +33489,11 @@ function createCursorAcpIncomingLineHandler(deps) {
33440
33489
 
33441
33490
  // src/agents/acp/clients/cursor/cursor-json-rpc-acp-transport.ts
33442
33491
  function createCursorJsonRpcAcpTransport(deps) {
33443
- const { send, cancelSessionNotification } = deps;
33492
+ const { send, cancelSessionNotification, skipBrowserAuthenticate } = deps;
33444
33493
  return {
33445
33494
  initialize: (request) => send("initialize", request),
33446
33495
  afterInitialize: async () => {
33496
+ if (skipBrowserAuthenticate) return;
33447
33497
  await send("authenticate", { methodId: "cursor_login" });
33448
33498
  },
33449
33499
  resumeSession: (p) => send("session/resume", p),
@@ -33552,7 +33602,8 @@ async function initCursorAcpWire(options) {
33552
33602
  rl.on("line", (line) => incoming.handleLine(line));
33553
33603
  const transport = createCursorJsonRpcAcpTransport({
33554
33604
  send: wire.send,
33555
- cancelSessionNotification: wire.cancelSessionNotification
33605
+ cancelSessionNotification: wire.cancelSessionNotification,
33606
+ skipBrowserAuthenticate: options.skipBrowserAuthenticate
33556
33607
  });
33557
33608
  const established = await bootstrapAcpWireSession(transport, options.sessionCtx, CURSOR_ACP_CLIENT_INFO);
33558
33609
  return { wire, transport, established, incoming, pendingRequests: pendingRequests2 };
@@ -33565,7 +33616,7 @@ function spawnCursorAcpProcess(options) {
33565
33616
  const child = spawn3(options.command[0], options.command.slice(1), {
33566
33617
  cwd: options.cwd,
33567
33618
  stdio: ["pipe", "pipe", "pipe"],
33568
- env: process.env,
33619
+ env: bridgeInstalledAgentAuthProcessEnv(process.env),
33569
33620
  shell: isWindows
33570
33621
  });
33571
33622
  const stderrCapture = createStderrCapture(child);
@@ -33597,11 +33648,13 @@ async function createCursorAcpClient(options) {
33597
33648
  onAgentSubprocessExit
33598
33649
  } = options;
33599
33650
  const dbgFs = process.env.BUILDAUTOMATON_DEBUG_ACP_FS === "1";
33651
+ const spawnEnv = bridgeInstalledAgentAuthProcessEnv(process.env);
33600
33652
  const { child, stderrCapture } = spawnCursorAcpProcess({
33601
33653
  command,
33602
33654
  cwd,
33603
33655
  onAgentSubprocessExit
33604
33656
  });
33657
+ const skipBrowserAuthenticate = cursorAgentUsesApiKeyAuth(spawnEnv);
33605
33658
  const sessionCtx = createCursorAcpSessionContext({
33606
33659
  cwd,
33607
33660
  mcpServers: options.mcpServers,
@@ -33624,6 +33677,7 @@ async function createCursorAcpClient(options) {
33624
33677
  const { wire, transport, established, incoming, pendingRequests: pendingRequests2 } = await initCursorAcpWire({
33625
33678
  child,
33626
33679
  sessionCtx,
33680
+ skipBrowserAuthenticate,
33627
33681
  incomingDeps: { dbgFs, sessionCtx, onSessionUpdate, onRequest }
33628
33682
  });
33629
33683
  resolve35(
@@ -34700,11 +34754,11 @@ init_cli_process_interrupt();
34700
34754
  var BRIDGE_MCP_SERVER_NAME2 = "buildautomaton-bridge";
34701
34755
 
34702
34756
  // src/mcp/resolve-bridge-mcp-server-path.ts
34703
- import { dirname as dirname7, join as join6 } from "node:path";
34757
+ import { dirname as dirname7, join as join7 } from "node:path";
34704
34758
  import { fileURLToPath as fileURLToPath7 } from "node:url";
34705
34759
  function resolveBridgeMcpServerScriptPath() {
34706
34760
  const cliDir = dirname7(fileURLToPath7(import.meta.url));
34707
- return join6(cliDir, "bridge-mcp-server.js");
34761
+ return join7(cliDir, "bridge-mcp-server.js");
34708
34762
  }
34709
34763
 
34710
34764
  // src/mcp/build-acp-mcp-servers.ts
@@ -48479,6 +48533,7 @@ function buildBridgeUrl(apiUrl, workspaceId, authToken) {
48479
48533
  var API_TO_BRIDGE_MESSAGE_TYPES = [
48480
48534
  "auth_token",
48481
48535
  "bridge_identified",
48536
+ "installed_agent_auth_sync",
48482
48537
  "ha",
48483
48538
  "preview_environments_config",
48484
48539
  "preview_environment_control",
@@ -48567,6 +48622,16 @@ var handleBridgeIdentified = (msg, deps) => {
48567
48622
  });
48568
48623
  };
48569
48624
 
48625
+ // src/routing/handlers/installed-agent-auth-sync.ts
48626
+ var handleInstalledAgentAuthSync = (msg) => {
48627
+ const entries = Array.isArray(msg.entries) ? msg.entries : [];
48628
+ setBridgeInstalledAgentAuthEnv(
48629
+ entries.filter(
48630
+ (e) => e != null && typeof e === "object" && typeof e.envVar === "string" && typeof e.token === "string"
48631
+ )
48632
+ );
48633
+ };
48634
+
48570
48635
  // src/connection/heartbeat/ack.ts
48571
48636
  var handleBridgeHeartbeatAck = (msg, deps) => {
48572
48637
  const raw = msg.s;
@@ -48583,6 +48648,9 @@ function dispatchBridgeConnectionMessage(msg, deps) {
48583
48648
  case "bridge_identified":
48584
48649
  handleBridgeIdentified(msg, deps);
48585
48650
  break;
48651
+ case "installed_agent_auth_sync":
48652
+ handleInstalledAgentAuthSync(msg, deps);
48653
+ break;
48586
48654
  case "ha":
48587
48655
  handleBridgeHeartbeatAck(msg, deps);
48588
48656
  break;
@@ -49724,9 +49792,22 @@ var handleInstallSkillsMessage = (msg, deps) => {
49724
49792
  // src/agents/install/commands/run-npm-global-install.ts
49725
49793
  import { execFile as execFile9 } from "node:child_process";
49726
49794
  import { promisify as promisify10 } from "node:util";
49795
+
49796
+ // src/agents/install/format-command-output.ts
49797
+ function formatCommandOutput(stdout, stderr) {
49798
+ const parts = [String(stdout ?? "").trimEnd(), String(stderr ?? "").trimEnd()].filter(Boolean);
49799
+ return parts.join("\n");
49800
+ }
49801
+
49802
+ // src/agents/install/commands/run-npm-global-install.ts
49727
49803
  var execFileAsync8 = promisify10(execFile9);
49728
49804
  async function runNpmGlobalInstall(packageName, env, timeoutMs = 3e5) {
49729
- await execFileAsync8("npm", ["install", "-g", packageName], { timeout: timeoutMs, env: bridgeAgentPathEnv(env) });
49805
+ const { stdout, stderr } = await execFileAsync8("npm", ["install", "-g", packageName], {
49806
+ timeout: timeoutMs,
49807
+ env: bridgeAgentPathEnv(env),
49808
+ maxBuffer: 10 * 1024 * 1024
49809
+ });
49810
+ return formatCommandOutput(stdout, stderr);
49730
49811
  }
49731
49812
 
49732
49813
  // src/agents/install/commands/claude-code.ts
@@ -49734,11 +49815,11 @@ var claudeCodeInstallCommand = {
49734
49815
  agentType: "claude-code",
49735
49816
  detectCommand: "claude",
49736
49817
  async install(ctx) {
49737
- ctx.onProgress?.("Installing Anthropic Claude Code");
49738
- await runNpmGlobalInstall("@anthropic-ai/claude-code", {
49818
+ const logOutput = await runNpmGlobalInstall("@anthropic-ai/claude-code", {
49739
49819
  ...ctx.env,
49740
49820
  ANTHROPIC_API_KEY: ctx.authToken
49741
49821
  });
49822
+ ctx.onProgress?.("Installing Anthropic Claude Code", logOutput || void 0);
49742
49823
  }
49743
49824
  };
49744
49825
 
@@ -49747,11 +49828,11 @@ var codexAcpInstallCommand = {
49747
49828
  agentType: "codex-acp",
49748
49829
  detectCommand: "codex",
49749
49830
  async install(ctx) {
49750
- ctx.onProgress?.("Installing Codex");
49751
- await runNpmGlobalInstall("@openai/codex", {
49831
+ const logOutput = await runNpmGlobalInstall("@openai/codex", {
49752
49832
  ...ctx.env,
49753
49833
  OPENAI_API_KEY: ctx.authToken
49754
49834
  });
49835
+ ctx.onProgress?.("Installing Codex", logOutput || void 0);
49755
49836
  }
49756
49837
  };
49757
49838
 
@@ -49762,12 +49843,19 @@ var execFileAsync9 = promisify11(execFile10);
49762
49843
  var cursorCliInstallCommand = {
49763
49844
  agentType: "cursor-cli",
49764
49845
  detectCommand: "agent",
49846
+ alternateDetectCommands: ["cursor-agent"],
49765
49847
  async install(ctx) {
49766
- ctx.onProgress?.("Installing Cursor CLI");
49767
- await execFileAsync9("bash", ["-lc", "curl -fsSL https://cursor.com/install | bash"], {
49768
- timeout: 3e5,
49769
- env: { ...bridgeAgentPathEnv(ctx.env), CURSOR_API_KEY: ctx.authToken }
49770
- });
49848
+ const { stdout, stderr } = await execFileAsync9(
49849
+ "bash",
49850
+ ["-lc", "curl -fsSL https://cursor.com/install | bash"],
49851
+ {
49852
+ timeout: 3e5,
49853
+ env: { ...bridgeAgentPathEnv(ctx.env), CURSOR_API_KEY: ctx.authToken },
49854
+ maxBuffer: 10 * 1024 * 1024
49855
+ }
49856
+ );
49857
+ const logOutput = formatCommandOutput(stdout, stderr);
49858
+ ctx.onProgress?.("Installing Cursor CLI", logOutput || void 0);
49771
49859
  }
49772
49860
  };
49773
49861
 
@@ -49776,11 +49864,11 @@ var opencodeInstallCommand = {
49776
49864
  agentType: "opencode",
49777
49865
  detectCommand: "opencode",
49778
49866
  async install(ctx) {
49779
- ctx.onProgress?.("Installing OpenCode");
49780
- await runNpmGlobalInstall("opencode-ai", {
49867
+ const logOutput = await runNpmGlobalInstall("opencode-ai", {
49781
49868
  ...ctx.env,
49782
49869
  OPENCODE_API_KEY: ctx.authToken
49783
49870
  });
49871
+ ctx.onProgress?.("Installing OpenCode", logOutput || void 0);
49784
49872
  }
49785
49873
  };
49786
49874
 
@@ -49814,7 +49902,17 @@ async function installLocalAgentOnBridge(params) {
49814
49902
  return { success: false, error: msg };
49815
49903
  }
49816
49904
  ensureBridgeAgentPathInProcessEnv();
49817
- const found = await isCommandOnPath(command.detectCommand);
49905
+ const detectNames = [
49906
+ command.detectCommand,
49907
+ ...command.alternateDetectCommands ?? []
49908
+ ];
49909
+ let found = false;
49910
+ for (const name of detectNames) {
49911
+ if (await waitForCommandOnPath(name)) {
49912
+ found = true;
49913
+ break;
49914
+ }
49915
+ }
49818
49916
  if (!found) {
49819
49917
  return { success: false, error: `${command.detectCommand} not found on PATH after install` };
49820
49918
  }
@@ -49831,7 +49929,7 @@ var handleInstallAgentMessage = (msg, deps) => {
49831
49929
  if (!processId || !agentId || !tokenId || !agentType || !authToken) return;
49832
49930
  void (async () => {
49833
49931
  const socket = deps.getWs();
49834
- const report = (step, message) => {
49932
+ const report = (step, message, logOutput) => {
49835
49933
  if (socket) {
49836
49934
  sendWsMessage(socket, {
49837
49935
  type: "install_agent_progress",
@@ -49840,14 +49938,15 @@ var handleInstallAgentMessage = (msg, deps) => {
49840
49938
  tokenId,
49841
49939
  agentType,
49842
49940
  step,
49843
- message
49941
+ message,
49942
+ ...logOutput ? { logOutput } : {}
49844
49943
  });
49845
49944
  }
49846
49945
  };
49847
49946
  const result = await installLocalAgentOnBridge({
49848
49947
  agentType,
49849
49948
  authToken,
49850
- onProgress: (message) => report("agent_install_package", message)
49949
+ onProgress: (message, logOutput) => report("agent_install_package", message, logOutput)
49851
49950
  });
49852
49951
  if (socket) {
49853
49952
  sendWsMessage(socket, {
@@ -50232,6 +50331,7 @@ function dispatchBridgeMessage(msg, deps) {
50232
50331
  switch (msg.type) {
50233
50332
  case "auth_token":
50234
50333
  case "bridge_identified":
50334
+ case "installed_agent_auth_sync":
50235
50335
  case "ha":
50236
50336
  dispatchBridgeConnectionMessage(msg, deps);
50237
50337
  break;