@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/cli.js CHANGED
@@ -31064,7 +31064,7 @@ var {
31064
31064
  } = import_index.default;
31065
31065
 
31066
31066
  // src/cli-version.ts
31067
- var CLI_VERSION = "0.1.71".length > 0 ? "0.1.71" : "0.0.0-dev";
31067
+ var CLI_VERSION = "0.1.73".length > 0 ? "0.1.73" : "0.0.0-dev";
31068
31068
 
31069
31069
  // src/cli/defaults.ts
31070
31070
  var DEFAULT_API_URL = process.env.BUILDAUTOMATON_API_URL ?? "https://api.buildautomaton.com";
@@ -34990,7 +34990,11 @@ __export(claude_code_acp_client_exports, {
34990
34990
 
34991
34991
  // src/agents/acp/clients/detect-command-on-path.ts
34992
34992
  init_cli_process_interrupt();
34993
+ import { constants } from "node:fs";
34994
+ import { access } from "node:fs/promises";
34993
34995
  import { execFile as execFile6 } from "node:child_process";
34996
+ import { homedir as homedir2 } from "node:os";
34997
+ import { join as join7 } from "node:path";
34994
34998
  import { promisify as promisify6 } from "node:util";
34995
34999
  var execFileAsync5 = promisify6(execFile6);
34996
35000
  var COMMAND_ON_PATH_PROBE_TIMEOUT_MS = 750;
@@ -35007,6 +35011,21 @@ async function execFileShutdownAware(file2, args, timeoutMs) {
35007
35011
  clearInterval(shutdownPoll);
35008
35012
  }
35009
35013
  }
35014
+ async function isExecutableFile(filePath) {
35015
+ try {
35016
+ await access(filePath, constants.X_OK);
35017
+ return true;
35018
+ } catch {
35019
+ return false;
35020
+ }
35021
+ }
35022
+ async function isCommandInBridgeAgentDirs(command) {
35023
+ const home = process.env.HOME ?? homedir2();
35024
+ for (const dir of getBridgeAgentPathEntries(home)) {
35025
+ if (await isExecutableFile(join7(dir, command))) return true;
35026
+ }
35027
+ return false;
35028
+ }
35010
35029
  async function isCommandOnPath(command, timeoutMs = COMMAND_ON_PATH_PROBE_TIMEOUT_MS) {
35011
35030
  if (isCliImmediateShutdownRequested()) return false;
35012
35031
  try {
@@ -35016,9 +35035,19 @@ async function isCommandOnPath(command, timeoutMs = COMMAND_ON_PATH_PROBE_TIMEOU
35016
35035
  });
35017
35036
  return true;
35018
35037
  } catch {
35019
- return false;
35038
+ return isCommandInBridgeAgentDirs(command);
35020
35039
  }
35021
35040
  }
35041
+ async function waitForCommandOnPath(command, opts = {}) {
35042
+ const maxAttempts = opts.maxAttempts ?? 8;
35043
+ const delayMs = opts.delayMs ?? 400;
35044
+ const timeoutMs = opts.timeoutMs ?? COMMAND_ON_PATH_PROBE_TIMEOUT_MS;
35045
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
35046
+ if (await isCommandOnPath(command, timeoutMs)) return true;
35047
+ if (attempt < maxAttempts - 1) await new Promise((r) => setTimeout(r, delayMs));
35048
+ }
35049
+ return false;
35050
+ }
35022
35051
  async function execProbeShutdownAware(file2, args, timeoutMs) {
35023
35052
  if (isCliImmediateShutdownRequested()) return false;
35024
35053
  try {
@@ -35956,12 +35985,32 @@ function attachSdkStdioStderrAuthWatch(options) {
35956
35985
 
35957
35986
  // src/agents/acp/clients/sdk/spawn-sdk-stdio-process.ts
35958
35987
  import { spawn } from "node:child_process";
35988
+
35989
+ // src/agents/acp/clients/bridge-installed-agent-auth-env.ts
35990
+ var authEnv = /* @__PURE__ */ new Map();
35991
+ function setBridgeInstalledAgentAuthEnv(entries) {
35992
+ authEnv.clear();
35993
+ for (const entry of entries) {
35994
+ const envVar = typeof entry.envVar === "string" ? entry.envVar.trim() : "";
35995
+ const token = typeof entry.token === "string" ? entry.token.trim() : "";
35996
+ if (envVar && token) authEnv.set(envVar, token);
35997
+ }
35998
+ }
35999
+ function bridgeInstalledAgentAuthProcessEnv(base = process.env) {
36000
+ if (authEnv.size === 0) return base;
36001
+ return { ...base, ...Object.fromEntries(authEnv) };
36002
+ }
36003
+ function cursorAgentUsesApiKeyAuth(env = process.env) {
36004
+ return Boolean(env.CURSOR_API_KEY?.trim() || env.CURSOR_AUTH_TOKEN?.trim());
36005
+ }
36006
+
36007
+ // src/agents/acp/clients/sdk/spawn-sdk-stdio-process.ts
35959
36008
  function spawnSdkStdioProcess(options) {
35960
36009
  const isWindows = process.platform === "win32";
35961
36010
  const child = spawn(options.command[0], options.command.slice(1), {
35962
36011
  cwd: options.cwd,
35963
36012
  stdio: ["pipe", "pipe", "pipe"],
35964
- env: process.env,
36013
+ env: bridgeInstalledAgentAuthProcessEnv(process.env),
35965
36014
  shell: isWindows
35966
36015
  });
35967
36016
  const stderrCapture = createStderrCapture(child);
@@ -36421,10 +36470,11 @@ function createCursorAcpIncomingLineHandler(deps) {
36421
36470
 
36422
36471
  // src/agents/acp/clients/cursor/cursor-json-rpc-acp-transport.ts
36423
36472
  function createCursorJsonRpcAcpTransport(deps) {
36424
- const { send, cancelSessionNotification } = deps;
36473
+ const { send, cancelSessionNotification, skipBrowserAuthenticate } = deps;
36425
36474
  return {
36426
36475
  initialize: (request) => send("initialize", request),
36427
36476
  afterInitialize: async () => {
36477
+ if (skipBrowserAuthenticate) return;
36428
36478
  await send("authenticate", { methodId: "cursor_login" });
36429
36479
  },
36430
36480
  resumeSession: (p) => send("session/resume", p),
@@ -36533,7 +36583,8 @@ async function initCursorAcpWire(options) {
36533
36583
  rl.on("line", (line) => incoming.handleLine(line));
36534
36584
  const transport = createCursorJsonRpcAcpTransport({
36535
36585
  send: wire.send,
36536
- cancelSessionNotification: wire.cancelSessionNotification
36586
+ cancelSessionNotification: wire.cancelSessionNotification,
36587
+ skipBrowserAuthenticate: options.skipBrowserAuthenticate
36537
36588
  });
36538
36589
  const established = await bootstrapAcpWireSession(transport, options.sessionCtx, CURSOR_ACP_CLIENT_INFO);
36539
36590
  return { wire, transport, established, incoming, pendingRequests: pendingRequests2 };
@@ -36546,7 +36597,7 @@ function spawnCursorAcpProcess(options) {
36546
36597
  const child = spawn2(options.command[0], options.command.slice(1), {
36547
36598
  cwd: options.cwd,
36548
36599
  stdio: ["pipe", "pipe", "pipe"],
36549
- env: process.env,
36600
+ env: bridgeInstalledAgentAuthProcessEnv(process.env),
36550
36601
  shell: isWindows
36551
36602
  });
36552
36603
  const stderrCapture = createStderrCapture(child);
@@ -36578,11 +36629,13 @@ async function createCursorAcpClient(options) {
36578
36629
  onAgentSubprocessExit
36579
36630
  } = options;
36580
36631
  const dbgFs = process.env.BUILDAUTOMATON_DEBUG_ACP_FS === "1";
36632
+ const spawnEnv = bridgeInstalledAgentAuthProcessEnv(process.env);
36581
36633
  const { child, stderrCapture } = spawnCursorAcpProcess({
36582
36634
  command,
36583
36635
  cwd,
36584
36636
  onAgentSubprocessExit
36585
36637
  });
36638
+ const skipBrowserAuthenticate = cursorAgentUsesApiKeyAuth(spawnEnv);
36586
36639
  const sessionCtx = createCursorAcpSessionContext({
36587
36640
  cwd,
36588
36641
  mcpServers: options.mcpServers,
@@ -36605,6 +36658,7 @@ async function createCursorAcpClient(options) {
36605
36658
  const { wire, transport, established, incoming, pendingRequests: pendingRequests2 } = await initCursorAcpWire({
36606
36659
  child,
36607
36660
  sessionCtx,
36661
+ skipBrowserAuthenticate,
36608
36662
  incomingDeps: { dbgFs, sessionCtx, onSessionUpdate, onRequest }
36609
36663
  });
36610
36664
  resolve37(
@@ -37681,11 +37735,11 @@ init_cli_process_interrupt();
37681
37735
  var BRIDGE_MCP_SERVER_NAME2 = "buildautomaton-bridge";
37682
37736
 
37683
37737
  // src/mcp/resolve-bridge-mcp-server-path.ts
37684
- import { dirname as dirname7, join as join7 } from "node:path";
37738
+ import { dirname as dirname7, join as join8 } from "node:path";
37685
37739
  import { fileURLToPath as fileURLToPath7 } from "node:url";
37686
37740
  function resolveBridgeMcpServerScriptPath() {
37687
37741
  const cliDir = dirname7(fileURLToPath7(import.meta.url));
37688
- return join7(cliDir, "bridge-mcp-server.js");
37742
+ return join8(cliDir, "bridge-mcp-server.js");
37689
37743
  }
37690
37744
 
37691
37745
  // src/mcp/build-acp-mcp-servers.ts
@@ -51525,6 +51579,7 @@ function buildBridgeUrl(apiUrl, workspaceId, authToken) {
51525
51579
  var API_TO_BRIDGE_MESSAGE_TYPES = [
51526
51580
  "auth_token",
51527
51581
  "bridge_identified",
51582
+ "installed_agent_auth_sync",
51528
51583
  "ha",
51529
51584
  "preview_environments_config",
51530
51585
  "preview_environment_control",
@@ -51613,6 +51668,16 @@ var handleBridgeIdentified = (msg, deps) => {
51613
51668
  });
51614
51669
  };
51615
51670
 
51671
+ // src/routing/handlers/installed-agent-auth-sync.ts
51672
+ var handleInstalledAgentAuthSync = (msg) => {
51673
+ const entries = Array.isArray(msg.entries) ? msg.entries : [];
51674
+ setBridgeInstalledAgentAuthEnv(
51675
+ entries.filter(
51676
+ (e) => e != null && typeof e === "object" && typeof e.envVar === "string" && typeof e.token === "string"
51677
+ )
51678
+ );
51679
+ };
51680
+
51616
51681
  // src/connection/heartbeat/ack.ts
51617
51682
  var handleBridgeHeartbeatAck = (msg, deps) => {
51618
51683
  const raw = msg.s;
@@ -51629,6 +51694,9 @@ function dispatchBridgeConnectionMessage(msg, deps) {
51629
51694
  case "bridge_identified":
51630
51695
  handleBridgeIdentified(msg, deps);
51631
51696
  break;
51697
+ case "installed_agent_auth_sync":
51698
+ handleInstalledAgentAuthSync(msg, deps);
51699
+ break;
51632
51700
  case "ha":
51633
51701
  handleBridgeHeartbeatAck(msg, deps);
51634
51702
  break;
@@ -52944,9 +53012,22 @@ var handleInstallSkillsMessage = (msg, deps) => {
52944
53012
  // src/agents/install/commands/run-npm-global-install.ts
52945
53013
  import { execFile as execFile9 } from "node:child_process";
52946
53014
  import { promisify as promisify10 } from "node:util";
53015
+
53016
+ // src/agents/install/format-command-output.ts
53017
+ function formatCommandOutput(stdout, stderr) {
53018
+ const parts = [String(stdout ?? "").trimEnd(), String(stderr ?? "").trimEnd()].filter(Boolean);
53019
+ return parts.join("\n");
53020
+ }
53021
+
53022
+ // src/agents/install/commands/run-npm-global-install.ts
52947
53023
  var execFileAsync8 = promisify10(execFile9);
52948
53024
  async function runNpmGlobalInstall(packageName, env, timeoutMs = 3e5) {
52949
- await execFileAsync8("npm", ["install", "-g", packageName], { timeout: timeoutMs, env: bridgeAgentPathEnv(env) });
53025
+ const { stdout, stderr } = await execFileAsync8("npm", ["install", "-g", packageName], {
53026
+ timeout: timeoutMs,
53027
+ env: bridgeAgentPathEnv(env),
53028
+ maxBuffer: 10 * 1024 * 1024
53029
+ });
53030
+ return formatCommandOutput(stdout, stderr);
52950
53031
  }
52951
53032
 
52952
53033
  // src/agents/install/commands/claude-code.ts
@@ -52954,11 +53035,11 @@ var claudeCodeInstallCommand = {
52954
53035
  agentType: "claude-code",
52955
53036
  detectCommand: "claude",
52956
53037
  async install(ctx) {
52957
- ctx.onProgress?.("Installing Anthropic Claude Code");
52958
- await runNpmGlobalInstall("@anthropic-ai/claude-code", {
53038
+ const logOutput = await runNpmGlobalInstall("@anthropic-ai/claude-code", {
52959
53039
  ...ctx.env,
52960
53040
  ANTHROPIC_API_KEY: ctx.authToken
52961
53041
  });
53042
+ ctx.onProgress?.("Installing Anthropic Claude Code", logOutput || void 0);
52962
53043
  }
52963
53044
  };
52964
53045
 
@@ -52967,11 +53048,11 @@ var codexAcpInstallCommand = {
52967
53048
  agentType: "codex-acp",
52968
53049
  detectCommand: "codex",
52969
53050
  async install(ctx) {
52970
- ctx.onProgress?.("Installing Codex");
52971
- await runNpmGlobalInstall("@openai/codex", {
53051
+ const logOutput = await runNpmGlobalInstall("@openai/codex", {
52972
53052
  ...ctx.env,
52973
53053
  OPENAI_API_KEY: ctx.authToken
52974
53054
  });
53055
+ ctx.onProgress?.("Installing Codex", logOutput || void 0);
52975
53056
  }
52976
53057
  };
52977
53058
 
@@ -52982,12 +53063,19 @@ var execFileAsync9 = promisify11(execFile10);
52982
53063
  var cursorCliInstallCommand = {
52983
53064
  agentType: "cursor-cli",
52984
53065
  detectCommand: "agent",
53066
+ alternateDetectCommands: ["cursor-agent"],
52985
53067
  async install(ctx) {
52986
- ctx.onProgress?.("Installing Cursor CLI");
52987
- await execFileAsync9("bash", ["-lc", "curl -fsSL https://cursor.com/install | bash"], {
52988
- timeout: 3e5,
52989
- env: { ...bridgeAgentPathEnv(ctx.env), CURSOR_API_KEY: ctx.authToken }
52990
- });
53068
+ const { stdout, stderr } = await execFileAsync9(
53069
+ "bash",
53070
+ ["-lc", "curl -fsSL https://cursor.com/install | bash"],
53071
+ {
53072
+ timeout: 3e5,
53073
+ env: { ...bridgeAgentPathEnv(ctx.env), CURSOR_API_KEY: ctx.authToken },
53074
+ maxBuffer: 10 * 1024 * 1024
53075
+ }
53076
+ );
53077
+ const logOutput = formatCommandOutput(stdout, stderr);
53078
+ ctx.onProgress?.("Installing Cursor CLI", logOutput || void 0);
52991
53079
  }
52992
53080
  };
52993
53081
 
@@ -52996,11 +53084,11 @@ var opencodeInstallCommand = {
52996
53084
  agentType: "opencode",
52997
53085
  detectCommand: "opencode",
52998
53086
  async install(ctx) {
52999
- ctx.onProgress?.("Installing OpenCode");
53000
- await runNpmGlobalInstall("opencode-ai", {
53087
+ const logOutput = await runNpmGlobalInstall("opencode-ai", {
53001
53088
  ...ctx.env,
53002
53089
  OPENCODE_API_KEY: ctx.authToken
53003
53090
  });
53091
+ ctx.onProgress?.("Installing OpenCode", logOutput || void 0);
53004
53092
  }
53005
53093
  };
53006
53094
 
@@ -53034,7 +53122,17 @@ async function installLocalAgentOnBridge(params) {
53034
53122
  return { success: false, error: msg };
53035
53123
  }
53036
53124
  ensureBridgeAgentPathInProcessEnv();
53037
- const found = await isCommandOnPath(command.detectCommand);
53125
+ const detectNames = [
53126
+ command.detectCommand,
53127
+ ...command.alternateDetectCommands ?? []
53128
+ ];
53129
+ let found = false;
53130
+ for (const name of detectNames) {
53131
+ if (await waitForCommandOnPath(name)) {
53132
+ found = true;
53133
+ break;
53134
+ }
53135
+ }
53038
53136
  if (!found) {
53039
53137
  return { success: false, error: `${command.detectCommand} not found on PATH after install` };
53040
53138
  }
@@ -53051,7 +53149,7 @@ var handleInstallAgentMessage = (msg, deps) => {
53051
53149
  if (!processId || !agentId || !tokenId || !agentType || !authToken) return;
53052
53150
  void (async () => {
53053
53151
  const socket = deps.getWs();
53054
- const report = (step, message) => {
53152
+ const report = (step, message, logOutput) => {
53055
53153
  if (socket) {
53056
53154
  sendWsMessage(socket, {
53057
53155
  type: "install_agent_progress",
@@ -53060,14 +53158,15 @@ var handleInstallAgentMessage = (msg, deps) => {
53060
53158
  tokenId,
53061
53159
  agentType,
53062
53160
  step,
53063
- message
53161
+ message,
53162
+ ...logOutput ? { logOutput } : {}
53064
53163
  });
53065
53164
  }
53066
53165
  };
53067
53166
  const result = await installLocalAgentOnBridge({
53068
53167
  agentType,
53069
53168
  authToken,
53070
- onProgress: (message) => report("agent_install_package", message)
53169
+ onProgress: (message, logOutput) => report("agent_install_package", message, logOutput)
53071
53170
  });
53072
53171
  if (socket) {
53073
53172
  sendWsMessage(socket, {
@@ -53452,6 +53551,7 @@ function dispatchBridgeMessage(msg, deps) {
53452
53551
  switch (msg.type) {
53453
53552
  case "auth_token":
53454
53553
  case "bridge_identified":
53554
+ case "installed_agent_auth_sync":
53455
53555
  case "ha":
53456
53556
  dispatchBridgeConnectionMessage(msg, deps);
53457
53557
  break;