@a3t/rapid 0.1.11 → 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
|
@@ -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 {
|
|
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,
|
|
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,
|
|
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
|
|
|
@@ -991,7 +997,7 @@ async function cleanupMergedWorktrees(repoRoot) {
|
|
|
991
997
|
|
|
992
998
|
// src/isolation/lima.ts
|
|
993
999
|
import { execa as execa2 } from "execa";
|
|
994
|
-
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
1000
|
+
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, access as access3 } from "fs/promises";
|
|
995
1001
|
import { homedir, platform } from "os";
|
|
996
1002
|
import { join as join3, dirname as dirname2 } from "path";
|
|
997
1003
|
import { fileURLToPath } from "url";
|
|
@@ -1061,7 +1067,19 @@ async function getInstance(name = RAPID_LIMA_INSTANCE) {
|
|
|
1061
1067
|
}
|
|
1062
1068
|
async function instanceExists(name = RAPID_LIMA_INSTANCE) {
|
|
1063
1069
|
const instance = await getInstance(name);
|
|
1064
|
-
|
|
1070
|
+
if (instance !== null) {
|
|
1071
|
+
return true;
|
|
1072
|
+
}
|
|
1073
|
+
return instanceDirExists(name);
|
|
1074
|
+
}
|
|
1075
|
+
async function instanceDirExists(name = RAPID_LIMA_INSTANCE) {
|
|
1076
|
+
const instanceDir = join3(homedir(), ".lima", name);
|
|
1077
|
+
try {
|
|
1078
|
+
await access3(instanceDir);
|
|
1079
|
+
return true;
|
|
1080
|
+
} catch {
|
|
1081
|
+
return false;
|
|
1082
|
+
}
|
|
1065
1083
|
}
|
|
1066
1084
|
async function isRunning(name = RAPID_LIMA_INSTANCE) {
|
|
1067
1085
|
const instance = await getInstance(name);
|
|
@@ -1105,6 +1123,10 @@ async function createLimaConfig(projectDir, options = {}) {
|
|
|
1105
1123
|
${envLines}
|
|
1106
1124
|
`);
|
|
1107
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
|
+
}
|
|
1108
1130
|
await writeFile2(configPath, config);
|
|
1109
1131
|
return configPath;
|
|
1110
1132
|
}
|
|
@@ -1182,7 +1204,9 @@ async function startInstance(projectDir, options = {}) {
|
|
|
1182
1204
|
return { success: true };
|
|
1183
1205
|
}
|
|
1184
1206
|
await execa2("limactl", ["start", name], {
|
|
1185
|
-
timeout: (options.timeout ?? 300) * 1e3
|
|
1207
|
+
timeout: (options.timeout ?? 300) * 1e3,
|
|
1208
|
+
stdio: "inherit"
|
|
1209
|
+
// Show progress
|
|
1186
1210
|
});
|
|
1187
1211
|
} else {
|
|
1188
1212
|
const configPath = await createLimaConfig(projectDir, options);
|
|
@@ -1284,6 +1308,56 @@ async function shellInLima(options = {}) {
|
|
|
1284
1308
|
}
|
|
1285
1309
|
await execa2("limactl", args, { stdio: "inherit" });
|
|
1286
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
|
+
}
|
|
1287
1361
|
async function setupGitSsh(name = RAPID_LIMA_INSTANCE) {
|
|
1288
1362
|
try {
|
|
1289
1363
|
const result = await execInLima(["ssh-add", "-l"], { name });
|
|
@@ -1482,22 +1556,22 @@ async function prepareMcpEnv(rootDir, mcp) {
|
|
|
1482
1556
|
}
|
|
1483
1557
|
const configFile = mcp.configFile ?? ".mcp.json";
|
|
1484
1558
|
const configPath = isAbsolute(configFile) ? configFile : join4(rootDir, configFile);
|
|
1485
|
-
const
|
|
1559
|
+
const mcpServers = {};
|
|
1486
1560
|
for (const [name, serverConfig] of Object.entries(mcp.servers)) {
|
|
1487
1561
|
if (!serverConfig || typeof serverConfig !== "object") {
|
|
1488
1562
|
continue;
|
|
1489
1563
|
}
|
|
1490
|
-
const { enabled, ...rest } = serverConfig;
|
|
1564
|
+
const { enabled, type, ...rest } = serverConfig;
|
|
1491
1565
|
if (enabled === false) {
|
|
1492
1566
|
continue;
|
|
1493
1567
|
}
|
|
1494
|
-
|
|
1568
|
+
const outputType = type === "remote" ? "http" : type;
|
|
1569
|
+
mcpServers[name] = { type: outputType, ...rest };
|
|
1495
1570
|
}
|
|
1496
|
-
if (Object.keys(
|
|
1571
|
+
if (Object.keys(mcpServers).length === 0) {
|
|
1497
1572
|
return void 0;
|
|
1498
1573
|
}
|
|
1499
|
-
await writeFile3(configPath,
|
|
1500
|
-
`, "utf-8");
|
|
1574
|
+
await writeFile3(configPath, await formatJson2({ mcpServers }), "utf-8");
|
|
1501
1575
|
return {
|
|
1502
1576
|
MCP_CONFIG_FILE: configFile
|
|
1503
1577
|
};
|
|
@@ -1578,7 +1652,7 @@ async function runLocally(agent, agentName, rootDir, config) {
|
|
|
1578
1652
|
const mergedEnv = { ...secrets, ...mcpEnv ?? {} };
|
|
1579
1653
|
const builtArgs = buildAgentArgs(agent, { injectSystemPrompt: true });
|
|
1580
1654
|
if (isMacOS() && await hasLima()) {
|
|
1581
|
-
await runInLimaVm(agent, agentName, rootDir, builtArgs, mergedEnv);
|
|
1655
|
+
await runInLimaVm(agent, agentName, rootDir, builtArgs, mergedEnv, config.lima);
|
|
1582
1656
|
return;
|
|
1583
1657
|
}
|
|
1584
1658
|
logger2.info(`Launching ${logger2.brand(agentName)}...`);
|
|
@@ -1596,14 +1670,15 @@ async function runLocally(agent, agentName, rootDir, config) {
|
|
|
1596
1670
|
}
|
|
1597
1671
|
});
|
|
1598
1672
|
}
|
|
1599
|
-
async function runInLimaVm(agent, agentName, rootDir, args, env) {
|
|
1673
|
+
async function runInLimaVm(agent, agentName, rootDir, args, env, limaConfig) {
|
|
1600
1674
|
const spinner = ora2();
|
|
1601
1675
|
if (!await isRunning()) {
|
|
1602
1676
|
spinner.start(`Starting Lima VM (${RAPID_LIMA_INSTANCE})...`);
|
|
1603
1677
|
const result = await startInstance(rootDir, {
|
|
1604
1678
|
env,
|
|
1605
|
-
timeout: 600
|
|
1679
|
+
timeout: 600,
|
|
1606
1680
|
// 10 minutes for first-time setup
|
|
1681
|
+
...limaConfig?.installGh !== void 0 && { installGh: limaConfig.installGh }
|
|
1607
1682
|
});
|
|
1608
1683
|
if (!result.success) {
|
|
1609
1684
|
spinner.fail("Failed to start Lima VM");
|
|
@@ -1626,6 +1701,26 @@ async function runInLimaVm(agent, agentName, rootDir, args, env) {
|
|
|
1626
1701
|
} else {
|
|
1627
1702
|
logger2.info(`Lima VM (${RAPID_LIMA_INSTANCE}) is running`);
|
|
1628
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`);
|
|
1629
1724
|
logger2.info(`Launching ${logger2.brand(agentName)} in Lima VM...`);
|
|
1630
1725
|
logger2.dim(`Working directory: ${rootDir}`);
|
|
1631
1726
|
logger2.dim("SSH agent forwarded for commit signing");
|
|
@@ -1952,7 +2047,7 @@ var statusCommand = new Command3("status").description("Show environment status"
|
|
|
1952
2047
|
// src/commands/agent.ts
|
|
1953
2048
|
import { writeFile as writeFile4 } from "fs/promises";
|
|
1954
2049
|
import { Command as Command4 } from "commander";
|
|
1955
|
-
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";
|
|
1956
2051
|
var agentCommand = new Command4("agent").description("Manage AI agents");
|
|
1957
2052
|
agentCommand.command("list").description("List available agents").action(async () => {
|
|
1958
2053
|
try {
|
|
@@ -2006,13 +2101,49 @@ agentCommand.command("default [name]").description("Get or set default agent").a
|
|
|
2006
2101
|
process.exit(1);
|
|
2007
2102
|
}
|
|
2008
2103
|
config.agents.default = name;
|
|
2009
|
-
await writeFile4(loaded.filepath,
|
|
2104
|
+
await writeFile4(loaded.filepath, await formatJson3(config));
|
|
2010
2105
|
logger4.success(`Default agent set to "${name}"`);
|
|
2011
2106
|
} catch (error) {
|
|
2012
2107
|
logger4.error(error instanceof Error ? error.message : String(error));
|
|
2013
2108
|
process.exit(1);
|
|
2014
2109
|
}
|
|
2015
2110
|
});
|
|
2111
|
+
agentCommand.command("yolo [name]").description("Enable YOLO mode (skip all permission prompts) for an agent").option("--off", "Disable YOLO mode").action(async (name, options) => {
|
|
2112
|
+
try {
|
|
2113
|
+
const loaded = await loadConfig3();
|
|
2114
|
+
if (!loaded) {
|
|
2115
|
+
logger4.error("No rapid.json found. Run `rapid init` first.");
|
|
2116
|
+
process.exit(1);
|
|
2117
|
+
}
|
|
2118
|
+
const { config } = loaded;
|
|
2119
|
+
const agentName = name || config.agents.default;
|
|
2120
|
+
if (!config.agents.available[agentName]) {
|
|
2121
|
+
logger4.error(`Agent "${agentName}" not found in configuration`);
|
|
2122
|
+
logger4.info("Available agents:");
|
|
2123
|
+
Object.keys(config.agents.available).forEach((n) => {
|
|
2124
|
+
console.log(` - ${n}`);
|
|
2125
|
+
});
|
|
2126
|
+
process.exit(1);
|
|
2127
|
+
}
|
|
2128
|
+
const agent = config.agents.available[agentName];
|
|
2129
|
+
const enabling = !options.off;
|
|
2130
|
+
if (enabling && agent.cli !== "claude") {
|
|
2131
|
+
logger4.warn(`YOLO mode is only supported for Claude (${agentName} uses ${agent.cli})`);
|
|
2132
|
+
logger4.info("Continuing anyway...");
|
|
2133
|
+
}
|
|
2134
|
+
agent.yolo = enabling;
|
|
2135
|
+
await writeFile4(loaded.filepath, await formatJson3(config));
|
|
2136
|
+
if (enabling) {
|
|
2137
|
+
logger4.success(`YOLO mode enabled for "${agentName}"`);
|
|
2138
|
+
logger4.dim("Permission prompts will be skipped (--dangerously-skip-permissions)");
|
|
2139
|
+
} else {
|
|
2140
|
+
logger4.success(`YOLO mode disabled for "${agentName}"`);
|
|
2141
|
+
}
|
|
2142
|
+
} catch (error) {
|
|
2143
|
+
logger4.error(error instanceof Error ? error.message : String(error));
|
|
2144
|
+
process.exit(1);
|
|
2145
|
+
}
|
|
2146
|
+
});
|
|
2016
2147
|
|
|
2017
2148
|
// src/commands/start.ts
|
|
2018
2149
|
import { Command as Command5 } from "commander";
|
|
@@ -2701,7 +2832,8 @@ import {
|
|
|
2701
2832
|
writeMcpConfig as writeMcpConfig2,
|
|
2702
2833
|
writeOpenCodeConfig as writeOpenCodeConfig2,
|
|
2703
2834
|
MCP_SERVER_TEMPLATES as MCP_SERVER_TEMPLATES2,
|
|
2704
|
-
getMcpTemplate
|
|
2835
|
+
getMcpTemplate,
|
|
2836
|
+
formatJson as formatJson4
|
|
2705
2837
|
} from "@a3t/rapid-core";
|
|
2706
2838
|
import ora8 from "ora";
|
|
2707
2839
|
var mcpCommand = new Command9("mcp").description(
|
|
@@ -2709,7 +2841,7 @@ var mcpCommand = new Command9("mcp").description(
|
|
|
2709
2841
|
);
|
|
2710
2842
|
async function saveConfig(rootDir, config) {
|
|
2711
2843
|
const configPath = join5(rootDir, "rapid.json");
|
|
2712
|
-
await writeFile5(configPath,
|
|
2844
|
+
await writeFile5(configPath, await formatJson4(config), "utf-8");
|
|
2713
2845
|
}
|
|
2714
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) => {
|
|
2715
2847
|
try {
|
|
@@ -3619,4 +3751,4 @@ program.action(() => {
|
|
|
3619
3751
|
export {
|
|
3620
3752
|
program
|
|
3621
3753
|
};
|
|
3622
|
-
//# sourceMappingURL=chunk-
|
|
3754
|
+
//# sourceMappingURL=chunk-BLH6BAR5.js.map
|