UNPKG

@botpress/adk-cli

Version:

Command-line interface for the Botpress Agent Development Kit (ADK)

193 lines (186 loc) 5.64 kB
// @bun import { getAdkVersion } from "./chunk-26vqkz52.js"; import { detectPackageManagers, getPreferredPackageManager } from "./chunk-nbasj5jm.js"; import { ne } from "./chunk-6w0knnta.js"; // src/utils/external-harness-capabilities.ts import { exec } from "child_process"; import { promisify } from "util"; // src/utils/fetch-commands.ts import { existsSync, mkdirSync, writeFileSync } from "fs"; import { basename, join } from "path"; // src/utils/skills-ref.ts function getSkillsGitRef() { const version = getAdkVersion(); if (version === "0.0.0") { return "dev"; } return `v${version}`; } function getSkillsRepoRef() { const version = getAdkVersion(); if (version === "0.0.0") { return "botpress/skills#dev"; } return `botpress/skills@v${version}`; } // src/utils/fetch-commands.ts var REPO = "botpress/skills"; var COMMANDS_DIR = "commands"; var REQUEST_TIMEOUT_MS = 15000; function getGithubRawBase() { return `https://raw.githubusercontent.com/${REPO}/${getSkillsGitRef()}/${COMMANDS_DIR}`; } var TARGET_DIRS = { "claude-code": ".claude/commands", opencode: ".opencode/commands", cursor: ".cursor/commands" }; var ALL_TARGETS = Object.keys(TARGET_DIRS); var ManifestEntrySchema = ne.object({ name: ne.string(), path: ne.string(), description: ne.string() }); var ManifestSchema = ne.object({ commands: ne.array(ManifestEntrySchema) }); function isManifest(value) { return ManifestSchema.safeParse(value).success; } async function fetchWithTimeout(url, timeoutMs) { const controller = new AbortController; const timer = setTimeout(() => controller.abort(), timeoutMs); try { return await fetch(url, { signal: controller.signal }); } finally { clearTimeout(timer); } } async function fetchManifest() { try { const res = await fetchWithTimeout(`${getGithubRawBase()}/manifest.json`, REQUEST_TIMEOUT_MS); if (!res.ok) { return null; } const data = await res.json(); if (!isManifest(data)) { return null; } return data; } catch { return null; } } function listCommandFiles(manifest) { if (manifest && manifest.commands.length > 0) { return manifest.commands.map((entry) => entry.path); } return []; } async function downloadCommand(filePath) { try { const res = await fetchWithTimeout(`${getGithubRawBase()}/${filePath}`, REQUEST_TIMEOUT_MS); if (!res.ok) { return null; } return await res.text(); } catch { return null; } } async function installCommands(projectPath, targets) { const result = { attempted: true, success: true, installedCommands: 0, failed: 0 }; const targetPaths = targets.map((t) => join(projectPath, TARGET_DIRS[t])); for (const dir of targetPaths) { if (!existsSync(dir)) { mkdirSync(dir, { recursive: true }); } } const manifest = await fetchManifest(); const filenames = listCommandFiles(manifest); const downloads = await Promise.all(filenames.map(async (filePath) => { const content = await downloadCommand(filePath); return { filePath, content }; })); for (const { filePath, content } of downloads) { if (content === null) { result.failed += 1; continue; } const outputName = basename(filePath); for (const dir of targetPaths) { writeFileSync(join(dir, outputName), content); } result.installedCommands += 1; } if (result.installedCommands === 0) { result.success = false; result.error = "Could not download any command files from GitHub"; } return result; } // src/utils/external-harness-capabilities.ts var execAsync = promisify(exec); async function installExternalHarnessCapabilities(options) { const commandTargets = options.commandTargets ?? ALL_TARGETS; const skillsCommand = buildExternalHarnessSkillsCommand(options.projectPath, options.packageManagerCommand); const skills = { attempted: true, success: true, command: skillsCommand }; try { if (options.runCommand) { await options.runCommand(skillsCommand, options.projectPath); } else { await execAsync(skillsCommand, { cwd: options.projectPath, env: { ...process.env }, timeout: 120000 }); } } catch (error) { skills.success = false; const stderr = error instanceof Error && "stderr" in error && error.stderr ? String(error.stderr).trim() : undefined; skills.error = stderr || (error instanceof Error ? error.message : String(error)); } let commands = { attempted: false, success: true, installedCommands: 0, failed: 0 }; if (commandTargets.length > 0) { try { commands = await installCommands(options.projectPath, commandTargets); } catch (error) { commands = { attempted: true, success: false, installedCommands: 0, failed: 0, error: error instanceof Error ? error.message : String(error) }; } } return { success: skills.success && commands.success, skills, commands }; } function buildExternalHarnessSkillsCommand(projectPath, packageManagerCommand) { const skillsRunner = getSkillsRunner(projectPath, packageManagerCommand); return `${skillsRunner} skills add ${getSkillsRepoRef()} -s '*' -a codex claude-code -y`; } function getSkillsRunner(projectPath, packageManagerCommand) { if (packageManagerCommand) { return packageManagerCommand === "bun" ? "bunx" : "npx"; } const managers = detectPackageManagers(); const preferred = getPreferredPackageManager(projectPath, managers); return preferred?.command === "bun" ? "bunx" : "npx"; } export { installExternalHarnessCapabilities };