@botpress/adk-cli
Version:
Command-line interface for the Botpress Agent Development Kit (ADK)
314 lines (309 loc) • 11.8 kB
JavaScript
// @bun
import {
CLI_VERSION
} from "./chunk-nxy2ya5r.js";
import {
AdkError
} from "./chunk-p0hjqn4r.js";
import {
__require
} from "./chunk-dhs2bg35.js";
// src/utils/agent0-capabilities.ts
import {
copyFileSync,
existsSync,
mkdirSync,
readdirSync,
readFileSync,
rmSync,
statSync,
writeFileSync
} from "fs";
import { basename, dirname, extname, join, normalize, sep } from "path";
import { fileURLToPath } from "url";
// src/utils/embedded-assets.ts
var _assets;
try {
const mod = await import("./chunk-nt9nzenw.js");
_assets = Array.isArray(mod.embeddedAssets) ? mod.embeddedAssets : [];
} catch (e) {
if (e?.code !== "MODULE_NOT_FOUND" && e?.name !== "ResolveError" && e?.name !== "ResolveMessage")
throw e;
_assets = [];
}
function getEmbeddedAssets() {
return _assets ?? [];
}
function getEmbeddedAsset(path) {
return getEmbeddedAssets().find((asset) => asset.path === path);
}
function hasEmbeddedAssets() {
return getEmbeddedAssets().length > 0;
}
// src/utils/agent0-capabilities.ts
var AGENT0_PROJECT_DIR = ".agent0";
var AGENT0_PROJECT_CAPABILITIES_DIR = "capabilities";
var AGENT0_PROJECT_SKILLS_DIR = "skills";
var AGENT0_PROJECT_PLAYBOOKS_DIR = "playbooks";
var AGENT0_PROJECT_CAPABILITIES_MANIFEST = "manifest.json";
var EMBEDDED_CAPABILITIES_PREFIX = "/agent0-capabilities";
var EMBEDDED_SKILLS_PREFIX = `${EMBEDDED_CAPABILITIES_PREFIX}/skills/`;
var EMBEDDED_PLAYBOOKS_PREFIX = `${EMBEDDED_CAPABILITIES_PREFIX}/playbooks/`;
var EMBEDDED_COMMANDS_PREFIX = `${EMBEDDED_CAPABILITIES_PREFIX}/commands/`;
function getCurrentAgent0CapabilityBundleVersion() {
return CLI_VERSION;
}
function getAgent0ProjectCapabilitiesRoot(projectPath) {
return join(projectPath, AGENT0_PROJECT_DIR, AGENT0_PROJECT_CAPABILITIES_DIR);
}
function getAgent0ProjectCapabilitiesManifestPath(projectPath) {
return join(getAgent0ProjectCapabilitiesRoot(projectPath), AGENT0_PROJECT_CAPABILITIES_MANIFEST);
}
function readAgent0CapabilitiesManifest(projectPath) {
const manifestPath = getAgent0ProjectCapabilitiesManifestPath(projectPath);
if (!existsSync(manifestPath))
return;
try {
const value = JSON.parse(readFileSync(manifestPath, "utf8"));
if (value.schemaVersion !== 1 || typeof value.capabilityBundleVersion !== "string")
return;
return {
schemaVersion: 1,
adkVersion: typeof value.adkVersion === "string" ? value.adkVersion : value.capabilityBundleVersion,
capabilityBundleVersion: value.capabilityBundleVersion,
generatedAt: typeof value.generatedAt === "string" ? value.generatedAt : "",
capabilitiesRoot: typeof value.capabilitiesRoot === "string" ? value.capabilitiesRoot : "",
skills: Array.isArray(value.skills) ? value.skills.filter((item) => typeof item === "string") : [],
playbooks: Array.isArray(value.playbooks) ? value.playbooks.filter((item) => typeof item === "string") : []
};
} catch {
return;
}
}
function checkAgent0CapabilitiesStatus(projectPath) {
const currentVersion = getCurrentAgent0CapabilityBundleVersion();
const manifestPath = getAgent0ProjectCapabilitiesManifestPath(projectPath);
const manifest = readAgent0CapabilitiesManifest(projectPath);
if (!manifest) {
return { state: "missing", currentVersion, manifestPath };
}
if (manifest.capabilityBundleVersion !== currentVersion) {
return {
state: "stale",
currentVersion,
installedVersion: manifest.capabilityBundleVersion,
manifestPath
};
}
if (!manifestHasRequiredCapabilityFiles(projectPath, manifest)) {
return {
state: "stale",
currentVersion,
installedVersion: manifest.capabilityBundleVersion,
manifestPath
};
}
return {
state: "current",
currentVersion,
installedVersion: manifest.capabilityBundleVersion,
manifestPath
};
}
function manifestHasRequiredCapabilityFiles(projectPath, manifest) {
if (manifest.skills.length === 0 || manifest.playbooks.length === 0)
return false;
const capabilitiesRoot = getAgent0ProjectCapabilitiesRoot(projectPath);
return manifest.skills.every((skill) => isFile(join(capabilitiesRoot, AGENT0_PROJECT_SKILLS_DIR, skill, "SKILL.md"))) && manifest.playbooks.every((playbook) => isFile(join(capabilitiesRoot, AGENT0_PROJECT_PLAYBOOKS_DIR, playbook)));
}
function isFile(path) {
return existsSync(path) && statSync(path).isFile();
}
async function installAgent0Capabilities(projectPath) {
const capabilitiesRoot = getAgent0ProjectCapabilitiesRoot(projectPath);
const manifestPath = getAgent0ProjectCapabilitiesManifestPath(projectPath);
const previousManifest = readAgent0CapabilitiesManifest(projectPath);
const status = checkAgent0CapabilitiesStatus(projectPath);
const source = resolveCapabilitySource();
mkdirSync(capabilitiesRoot, { recursive: true });
cleanupManagedCapabilities(projectPath, previousManifest, source);
await copyCapabilitiesToProject(capabilitiesRoot, source);
const manifest = {
schemaVersion: 1,
adkVersion: getCurrentAgent0CapabilityBundleVersion(),
capabilityBundleVersion: getCurrentAgent0CapabilityBundleVersion(),
generatedAt: new Date().toISOString(),
capabilitiesRoot: join(AGENT0_PROJECT_DIR, AGENT0_PROJECT_CAPABILITIES_DIR),
skills: source.skills,
playbooks: source.playbooks
};
writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + `
`);
return {
success: true,
projectPath,
capabilitiesRoot,
manifestPath,
source: source.kind,
currentVersion: getCurrentAgent0CapabilityBundleVersion(),
previousVersion: status.state === "missing" ? undefined : status.installedVersion ?? previousManifest?.capabilityBundleVersion,
wasCurrent: status.state === "current",
skills: {
installed: source.skills.length,
names: source.skills
},
playbooks: {
installed: source.playbooks.length,
files: source.playbooks
}
};
}
function resolveCapabilitySource() {
const embedded = resolveEmbeddedCapabilitySource();
if (embedded)
return embedded;
const skillsRoot = resolveBundledSkillsRoot();
const playbooksRoot = resolveBundledPlaybooksRoot();
if (!skillsRoot || !playbooksRoot) {
throw new AdkError({
code: "AGENT0_BUNDLE_MISSING",
message: "Agent(0) capability bundle is missing from this ADK installation."
});
}
return {
kind: "filesystem",
skillsRoot,
playbooksRoot,
skills: listSkillNames(skillsRoot),
playbooks: listMarkdownFiles(playbooksRoot)
};
}
function resolveBundledSkillsRoot() {
const baseDir = moduleDir();
return firstExistingDirectory([
join(baseDir, "agent0-assets", "skills"),
join(baseDir, "..", "agent0-assets", "skills"),
join(baseDir, "..", "..", "agent0-assets", "skills"),
join(baseDir, "..", "..", "..", "adk", "src", "agent0", "capabilities", "skills"),
join(baseDir, "..", "..", "..", "adk", "dist", "agent0", "capabilities", "skills")
]);
}
function resolveBundledPlaybooksRoot() {
const baseDir = moduleDir();
return firstExistingDirectory([
join(baseDir, "agent0-assets", "playbooks"),
join(baseDir, "..", "agent0-assets", "playbooks"),
join(baseDir, "..", "..", "agent0-assets", "playbooks"),
join(baseDir, "..", "..", "..", "adk", "src", "agent0", "capabilities", "commands"),
join(baseDir, "..", "..", "..", "adk", "dist", "agent0", "capabilities", "commands")
]);
}
function resolveEmbeddedCapabilitySource() {
const files = [];
const skills = new Set;
const playbooks = new Set;
for (const asset of getAvailableEmbeddedAssets()) {
const normalizedPath = asset.path.replace(/\\/g, "/");
const skillRelative = stripPrefix(normalizedPath, EMBEDDED_SKILLS_PREFIX);
if (skillRelative) {
const skillName = firstPathSegment(skillRelative);
if (!skillName)
continue;
skills.add(skillName);
files.push({ asset, relativePath: join(AGENT0_PROJECT_SKILLS_DIR, skillRelative) });
continue;
}
const playbookRelative = stripPrefix(normalizedPath, EMBEDDED_PLAYBOOKS_PREFIX) ?? stripPrefix(normalizedPath, EMBEDDED_COMMANDS_PREFIX);
if (playbookRelative && extname(playbookRelative) === ".md") {
playbooks.add(basename(playbookRelative));
files.push({ asset, relativePath: join(AGENT0_PROJECT_PLAYBOOKS_DIR, playbookRelative) });
}
}
if (skills.size === 0 || playbooks.size === 0)
return;
return {
kind: "embedded",
files,
skills: [...skills].toSorted(),
playbooks: [...playbooks].toSorted()
};
}
function getAvailableEmbeddedAssets() {
const getEmbeddedAssets2 = getEmbeddedAssets;
if (typeof getEmbeddedAssets2 !== "function")
return [];
const assets = getEmbeddedAssets2();
return Array.isArray(assets) ? assets : [];
}
async function copyCapabilitiesToProject(capabilitiesRoot, source) {
if (source.kind === "embedded") {
for (const file of source.files) {
const destination = safeJoin(capabilitiesRoot, file.relativePath);
mkdirSync(dirname(destination), { recursive: true });
const bytes = Buffer.from(await Bun.file(file.asset.file).arrayBuffer());
writeFileSync(destination, bytes);
}
return;
}
const skillsRoot = join(capabilitiesRoot, AGENT0_PROJECT_SKILLS_DIR);
const playbooksRoot = join(capabilitiesRoot, AGENT0_PROJECT_PLAYBOOKS_DIR);
mkdirSync(playbooksRoot, { recursive: true });
for (const skill of source.skills) {
copyTree(join(source.skillsRoot, skill), join(skillsRoot, skill));
}
for (const playbook of source.playbooks) {
copyFileSync(join(source.playbooksRoot, playbook), join(playbooksRoot, playbook));
}
}
function cleanupManagedCapabilities(projectPath, _previousManifest, _source) {
const capabilitiesRoot = getAgent0ProjectCapabilitiesRoot(projectPath);
const skillsRoot = join(capabilitiesRoot, AGENT0_PROJECT_SKILLS_DIR);
const playbooksRoot = join(capabilitiesRoot, AGENT0_PROJECT_PLAYBOOKS_DIR);
rmSync(skillsRoot, { recursive: true, force: true });
rmSync(playbooksRoot, { recursive: true, force: true });
}
function copyTree(source, destination) {
const stats = statSync(source);
if (stats.isDirectory()) {
mkdirSync(destination, { recursive: true });
for (const entry of readdirSync(source)) {
copyTree(join(source, entry), join(destination, entry));
}
return;
}
mkdirSync(dirname(destination), { recursive: true });
copyFileSync(source, destination);
}
function listSkillNames(skillsRoot) {
return readdirSync(skillsRoot).toSorted().filter((entry) => {
const skillDir = join(skillsRoot, entry);
return statSync(skillDir).isDirectory() && existsSync(join(skillDir, "SKILL.md"));
});
}
function listMarkdownFiles(root) {
return readdirSync(root).toSorted().filter((entry) => extname(entry) === ".md" && statSync(join(root, entry)).isFile());
}
function firstExistingDirectory(paths) {
return paths.find((path) => existsSync(path) && statSync(path).isDirectory());
}
function stripPrefix(value, prefix) {
return value.startsWith(prefix) ? value.slice(prefix.length) : undefined;
}
function firstPathSegment(value) {
return value.split("/").find(Boolean);
}
function safeJoin(root, relativePath) {
const destination = normalize(join(root, relativePath));
const normalizedRoot = normalize(root);
if (destination !== normalizedRoot && !destination.startsWith(normalizedRoot + sep)) {
throw new AdkError({
code: "AGENT0_PATH_ESCAPE",
message: `Refusing to write Agent(0) capability outside ${root}: ${relativePath}`
});
}
return destination;
}
function moduleDir() {
return dirname(fileURLToPath(import.meta.url));
}
export { getEmbeddedAssets, getEmbeddedAsset, hasEmbeddedAssets, readAgent0CapabilitiesManifest, checkAgent0CapabilitiesStatus, installAgent0Capabilities };