@a3t/rapid 0.1.12 → 0.1.13

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/bin.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  program
4
- } from "./chunk-52NWSTTE.js";
4
+ } from "./chunk-BLH6BAR5.js";
5
5
 
6
6
  // src/bin.ts
7
7
  program.parse(process.argv);
@@ -20,7 +20,8 @@ import {
20
20
  writeOpenCodeConfig,
21
21
  RAPID_METHODOLOGY,
22
22
  MCP_USAGE_GUIDELINES,
23
- GIT_GUIDELINES
23
+ GIT_GUIDELINES,
24
+ formatJson
24
25
  } from "@a3t/rapid-core";
25
26
  import ora from "ora";
26
27
  async function detectProjectType(dir) {
@@ -80,7 +81,11 @@ async function detectProjectType(dir) {
80
81
  }
81
82
  if (fileSet.has("package.json")) {
82
83
  const pkgManager = fileSet.has("pnpm-lock.yaml") ? "pnpm" : fileSet.has("yarn.lock") ? "yarn" : "npm";
83
- return { language: "javascript", packageManager: pkgManager, confidence: "medium" };
84
+ return {
85
+ language: "javascript",
86
+ packageManager: pkgManager,
87
+ confidence: "medium"
88
+ };
84
89
  }
85
90
  return { language: "unknown", confidence: "low" };
86
91
  }
@@ -465,7 +470,7 @@ async function createDevContainer(dir, detected, force = false, usePrebuilt = fa
465
470
  }
466
471
  await mkdir(devcontainerDir, { recursive: true });
467
472
  const config = getDevContainerConfig(detected, usePrebuilt);
468
- await writeFile(devcontainerJsonPath, JSON.stringify(config, null, 2) + "\n");
473
+ await writeFile(devcontainerJsonPath, await formatJson(config));
469
474
  return true;
470
475
  }
471
476
  var initCommand = new Command("init").description("Initialize RAPID in a project").argument("[template]", "Template: builtin name, github:user/repo, npm:package, or URL").option("--force", "Overwrite existing files", false).option("--agent <name>", "Default agent to configure", "claude").option("--no-devcontainer", "Skip devcontainer creation").option("--prebuilt", "Use pre-built devcontainer images from ghcr.io (faster startup)", false).option("--mcp <servers>", "MCP servers to enable (comma-separated)", "context7,tavily").option("--no-mcp", "Skip MCP server configuration").option("--no-detect", "Skip auto-detection of project type").action(async (templateArg, options) => {
@@ -549,7 +554,7 @@ var initCommand = new Command("init").description("Initialize RAPID in a project
549
554
  }
550
555
  }
551
556
  spinner.text = "Writing rapid.json...";
552
- await writeFile(configPath, JSON.stringify(config, null, 2) + "\n");
557
+ await writeFile(configPath, await formatJson(config));
553
558
  if (mcpServers.length > 0) {
554
559
  spinner.text = "Generating MCP configuration files...";
555
560
  await writeMcpConfig(cwd, config);
@@ -763,7 +768,8 @@ import {
763
768
  hasVaultCli,
764
769
  isVaultAuthenticated,
765
770
  buildAgentArgs,
766
- agentSupportsRuntimeInjection
771
+ agentSupportsRuntimeInjection,
772
+ formatJson as formatJson2
767
773
  } from "@a3t/rapid-core";
768
774
  import ora2 from "ora";
769
775
 
@@ -1117,6 +1123,10 @@ async function createLimaConfig(projectDir, options = {}) {
1117
1123
  ${envLines}
1118
1124
  `);
1119
1125
  }
1126
+ if (options.installGh === false) {
1127
+ const ghInstallPattern = /\s*# Install GitHub CLI\n\s*curl -fsSL https:\/\/cli\.github\.com\/packages\/githubcli-archive-keyring\.gpg \| dd of=\/usr\/share\/keyrings\/githubcli-archive-keyring\.gpg\n\s*chmod go\+r \/usr\/share\/keyrings\/githubcli-archive-keyring\.gpg\n\s*echo "deb \[arch=\$\(dpkg --print-architecture\) signed-by=\/usr\/share\/keyrings\/githubcli-archive-keyring\.gpg\] https:\/\/cli\.github\.com\/packages stable main" \| tee \/etc\/apt\/sources\.list\.d\/github-cli\.list > \/dev\/null\n\s*apt-get update\n\s*apt-get install -y gh\n/;
1128
+ config = config.replace(ghInstallPattern, "\n");
1129
+ }
1120
1130
  await writeFile2(configPath, config);
1121
1131
  return configPath;
1122
1132
  }
@@ -1298,6 +1308,56 @@ async function shellInLima(options = {}) {
1298
1308
  }
1299
1309
  await execa2("limactl", args, { stdio: "inherit" });
1300
1310
  }
1311
+ var AGENT_INSTALL_COMMANDS = {
1312
+ claude: ["sudo", "npm", "install", "-g", "@anthropic-ai/claude-code"],
1313
+ opencode: ["bash", "-c", "curl -fsSL https://opencode.ai/install | bash"],
1314
+ aider: ["pip3", "install", "--user", "aider-chat"]
1315
+ };
1316
+ async function isAgentInstalled(agentCli, name = RAPID_LIMA_INSTANCE) {
1317
+ try {
1318
+ const result = await execInLima(["which", agentCli], { name });
1319
+ return result.success && !!result.stdout?.trim();
1320
+ } catch {
1321
+ return false;
1322
+ }
1323
+ }
1324
+ async function installAgent(agentCli, name = RAPID_LIMA_INSTANCE) {
1325
+ const installCmd = AGENT_INSTALL_COMMANDS[agentCli];
1326
+ if (!installCmd) {
1327
+ return {
1328
+ success: false,
1329
+ error: `Unknown agent "${agentCli}". No install command available.`
1330
+ };
1331
+ }
1332
+ try {
1333
+ const result = await execInLima(installCmd, { name });
1334
+ if (!result.success) {
1335
+ return {
1336
+ success: false,
1337
+ error: result.error || result.stderr || `Failed to install ${agentCli}`
1338
+ };
1339
+ }
1340
+ const installed = await isAgentInstalled(agentCli, name);
1341
+ if (!installed) {
1342
+ return {
1343
+ success: false,
1344
+ error: `Installation command succeeded but ${agentCli} is not in PATH`
1345
+ };
1346
+ }
1347
+ return { success: true };
1348
+ } catch (err) {
1349
+ return {
1350
+ success: false,
1351
+ error: err instanceof Error ? err.message : String(err)
1352
+ };
1353
+ }
1354
+ }
1355
+ async function ensureAgentInstalled(agentCli, name = RAPID_LIMA_INSTANCE) {
1356
+ if (await isAgentInstalled(agentCli, name)) {
1357
+ return { success: true };
1358
+ }
1359
+ return installAgent(agentCli, name);
1360
+ }
1301
1361
  async function setupGitSsh(name = RAPID_LIMA_INSTANCE) {
1302
1362
  try {
1303
1363
  const result = await execInLima(["ssh-add", "-l"], { name });
@@ -1511,8 +1571,7 @@ async function prepareMcpEnv(rootDir, mcp) {
1511
1571
  if (Object.keys(mcpServers).length === 0) {
1512
1572
  return void 0;
1513
1573
  }
1514
- await writeFile3(configPath, `${JSON.stringify({ mcpServers }, null, 2)}
1515
- `, "utf-8");
1574
+ await writeFile3(configPath, await formatJson2({ mcpServers }), "utf-8");
1516
1575
  return {
1517
1576
  MCP_CONFIG_FILE: configFile
1518
1577
  };
@@ -1593,7 +1652,7 @@ async function runLocally(agent, agentName, rootDir, config) {
1593
1652
  const mergedEnv = { ...secrets, ...mcpEnv ?? {} };
1594
1653
  const builtArgs = buildAgentArgs(agent, { injectSystemPrompt: true });
1595
1654
  if (isMacOS() && await hasLima()) {
1596
- await runInLimaVm(agent, agentName, rootDir, builtArgs, mergedEnv);
1655
+ await runInLimaVm(agent, agentName, rootDir, builtArgs, mergedEnv, config.lima);
1597
1656
  return;
1598
1657
  }
1599
1658
  logger2.info(`Launching ${logger2.brand(agentName)}...`);
@@ -1611,14 +1670,15 @@ async function runLocally(agent, agentName, rootDir, config) {
1611
1670
  }
1612
1671
  });
1613
1672
  }
1614
- async function runInLimaVm(agent, agentName, rootDir, args, env) {
1673
+ async function runInLimaVm(agent, agentName, rootDir, args, env, limaConfig) {
1615
1674
  const spinner = ora2();
1616
1675
  if (!await isRunning()) {
1617
1676
  spinner.start(`Starting Lima VM (${RAPID_LIMA_INSTANCE})...`);
1618
1677
  const result = await startInstance(rootDir, {
1619
1678
  env,
1620
- timeout: 600
1679
+ timeout: 600,
1621
1680
  // 10 minutes for first-time setup
1681
+ ...limaConfig?.installGh !== void 0 && { installGh: limaConfig.installGh }
1622
1682
  });
1623
1683
  if (!result.success) {
1624
1684
  spinner.fail("Failed to start Lima VM");
@@ -1641,6 +1701,26 @@ async function runInLimaVm(agent, agentName, rootDir, args, env) {
1641
1701
  } else {
1642
1702
  logger2.info(`Lima VM (${RAPID_LIMA_INSTANCE}) is running`);
1643
1703
  }
1704
+ spinner.start(`Checking if ${agentName} is installed in Lima VM...`);
1705
+ const installResult = await ensureAgentInstalled(agent.cli);
1706
+ if (!installResult.success) {
1707
+ spinner.fail(`Failed to install ${agentName} in Lima VM`);
1708
+ logger2.error(installResult.error ?? "Unknown error");
1709
+ logger2.blank();
1710
+ logger2.info("Falling back to running directly on host...");
1711
+ logger2.blank();
1712
+ const { execa: execa4 } = await import("execa");
1713
+ await execa4(agent.cli, args, {
1714
+ cwd: rootDir,
1715
+ stdio: "inherit",
1716
+ env: {
1717
+ ...process.env,
1718
+ ...env
1719
+ }
1720
+ });
1721
+ return;
1722
+ }
1723
+ spinner.succeed(`${agentName} is available in Lima VM`);
1644
1724
  logger2.info(`Launching ${logger2.brand(agentName)} in Lima VM...`);
1645
1725
  logger2.dim(`Working directory: ${rootDir}`);
1646
1726
  logger2.dim("SSH agent forwarded for commit signing");
@@ -1967,7 +2047,7 @@ var statusCommand = new Command3("status").description("Show environment status"
1967
2047
  // src/commands/agent.ts
1968
2048
  import { writeFile as writeFile4 } from "fs/promises";
1969
2049
  import { Command as Command4 } from "commander";
1970
- import { loadConfig as loadConfig3, checkAllAgents as checkAllAgents2, logger as logger4 } from "@a3t/rapid-core";
2050
+ import { loadConfig as loadConfig3, checkAllAgents as checkAllAgents2, logger as logger4, formatJson as formatJson3 } from "@a3t/rapid-core";
1971
2051
  var agentCommand = new Command4("agent").description("Manage AI agents");
1972
2052
  agentCommand.command("list").description("List available agents").action(async () => {
1973
2053
  try {
@@ -2021,7 +2101,7 @@ agentCommand.command("default [name]").description("Get or set default agent").a
2021
2101
  process.exit(1);
2022
2102
  }
2023
2103
  config.agents.default = name;
2024
- await writeFile4(loaded.filepath, JSON.stringify(config, null, 2) + "\n");
2104
+ await writeFile4(loaded.filepath, await formatJson3(config));
2025
2105
  logger4.success(`Default agent set to "${name}"`);
2026
2106
  } catch (error) {
2027
2107
  logger4.error(error instanceof Error ? error.message : String(error));
@@ -2052,7 +2132,7 @@ agentCommand.command("yolo [name]").description("Enable YOLO mode (skip all perm
2052
2132
  logger4.info("Continuing anyway...");
2053
2133
  }
2054
2134
  agent.yolo = enabling;
2055
- await writeFile4(loaded.filepath, JSON.stringify(config, null, 2) + "\n");
2135
+ await writeFile4(loaded.filepath, await formatJson3(config));
2056
2136
  if (enabling) {
2057
2137
  logger4.success(`YOLO mode enabled for "${agentName}"`);
2058
2138
  logger4.dim("Permission prompts will be skipped (--dangerously-skip-permissions)");
@@ -2752,7 +2832,8 @@ import {
2752
2832
  writeMcpConfig as writeMcpConfig2,
2753
2833
  writeOpenCodeConfig as writeOpenCodeConfig2,
2754
2834
  MCP_SERVER_TEMPLATES as MCP_SERVER_TEMPLATES2,
2755
- getMcpTemplate
2835
+ getMcpTemplate,
2836
+ formatJson as formatJson4
2756
2837
  } from "@a3t/rapid-core";
2757
2838
  import ora8 from "ora";
2758
2839
  var mcpCommand = new Command9("mcp").description(
@@ -2760,7 +2841,7 @@ var mcpCommand = new Command9("mcp").description(
2760
2841
  );
2761
2842
  async function saveConfig(rootDir, config) {
2762
2843
  const configPath = join5(rootDir, "rapid.json");
2763
- await writeFile5(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
2844
+ await writeFile5(configPath, await formatJson4(config), "utf-8");
2764
2845
  }
2765
2846
  mcpCommand.command("list").description("List configured MCP servers").option("--json", "Output as JSON").option("--templates", "Show available templates instead of configured servers").action(async (options) => {
2766
2847
  try {
@@ -3670,4 +3751,4 @@ program.action(() => {
3670
3751
  export {
3671
3752
  program
3672
3753
  };
3673
- //# sourceMappingURL=chunk-52NWSTTE.js.map
3754
+ //# sourceMappingURL=chunk-BLH6BAR5.js.map