@botpress/adk-cli
Version:
Command-line interface for the Botpress Agent Development Kit (ADK)
972 lines (966 loc) • 33.6 kB
JavaScript
// @bun
import {
adkLink,
linkSetup
} from "./chunk-x18pe56z.js";
import {
adkLogin
} from "./chunk-1pszjja4.js";
import"./chunk-fr1k79kd.js";
import"./chunk-6zha718h.js";
import"./chunk-vn4dmn3x.js";
import {
select
} from "./chunk-seyt2a5p.js";
import {
adkLogo
} from "./chunk-5agyx08n.js";
import {
execAsync,
execSync
} from "./chunk-bmbzs4s8.js";
import {
userInput
} from "./chunk-tefbm840.js";
import"./chunk-bexyahs9.js";
import"./chunk-33cg4pm3.js";
import {
ensureJsonOnlyFormat
} from "./chunk-7sfagm12.js";
import {
ensureTemplatesAvailable
} from "./chunk-h652feqd.js";
import"./chunk-4cgz94zj.js";
import {
installExternalHarnessCapabilities
} from "./chunk-whkrdhta.js";
import {
telemetry_default
} from "./chunk-kwmsaz7n.js";
import {
installAgent0Capabilities
} from "./chunk-tt572q4r.js";
import"./chunk-26vqkz52.js";
import {
resolveCommandContext
} from "./chunk-3ahwp6fe.js";
import"./chunk-9e2nksab.js";
import {
bind,
bold,
box,
createScope,
fg,
getActiveTheme,
interval,
mount,
router,
signal,
t,
text
} from "./chunk-m2h26j5f.js";
import"./chunk-8gqzjqmb.js";
import {
checkNodeVersion,
getNodeVersionInfo
} from "./chunk-5ky86nkb.js";
import {
detectPackageManagers,
getPreferredPackageManager
} from "./chunk-nbasj5jm.js";
import"./chunk-kk3h6qaj.js";
import {
createCliLogger
} from "./chunk-gzwt1qdr.js";
import"./chunk-nxy2ya5r.js";
import"./chunk-wzj4dc7n.js";
import {
AdkError,
AgentProject,
AgentProjectGenerator,
auth
} from "./chunk-p0hjqn4r.js";
import"./chunk-np5wcwfv.js";
import"./chunk-dq2xpa24.js";
import"./chunk-6w0knnta.js";
import"./chunk-40x04ckt.js";
import"./chunk-t76d8fxx.js";
import"./chunk-nh2akp42.js";
import"./chunk-0fdvzjbh.js";
import"./chunk-2a5b6azq.js";
import"./chunk-vay209b5.js";
import"./chunk-3xrpxgq4.js";
import"./chunk-rfm3jr1m.js";
import"./chunk-w346ejn9.js";
import"./chunk-knvm2anf.js";
import"./chunk-65h5trb5.js";
import"./chunk-s2akeqpw.js";
import"./chunk-6771vrjp.js";
import"./chunk-g8mm42v1.js";
import"./chunk-50hzjdck.js";
import"./chunk-nn2jb0x0.js";
import"./chunk-v8xvth6j.js";
import"./chunk-kkk13rcb.js";
import"./chunk-ytpp1kam.js";
import"./chunk-na956zz3.js";
import"./chunk-f4bw8q7c.js";
import"./chunk-0v8vgrns.js";
import"./chunk-54qt5g7m.js";
import {
__require
} from "./chunk-dhs2bg35.js";
// src/commands/adk-init.ts
import { resolve as resolve2, basename } from "path";
import { existsSync as existsSync2 } from "fs";
// src/components/init-wizard.ts
import { existsSync } from "fs";
import { resolve } from "path";
function initWizard(renderer, scope, props) {
const { templates, packageManagers, defaultAgentName, defaultTemplate, onComplete, onCancel } = props;
const theme = getActiveTheme();
const availablePackageManagers = packageManagers.filter((pm) => pm.available);
const singlePackageManager = availablePackageManagers.length === 1 ? availablePackageManagers[0] : null;
const wizardSteps = [];
if (!defaultAgentName)
wizardSteps.push("name");
if (!defaultTemplate)
wizardSteps.push("template");
if (!singlePackageManager)
wizardSteps.push("package-manager");
const totalSteps = Math.max(wizardSteps.length, 1);
const currentStep = signal(defaultAgentName ? "template" : "name");
let selectedTemplate = defaultTemplate || "";
let agentName = defaultAgentName || "";
const historyBox = box(renderer, { flexDirection: "column" });
const recordStep = (label, value) => {
historyBox.add(text(renderer, t`${fg(theme.status.success)(theme.symbols.checkmark)} ${fg(theme.text.dim)(`${label}:`)} ${fg(theme.text.primary)(value)}`));
};
const completeInit = (nextAgentName, nextTemplate) => {
if (singlePackageManager) {
onComplete({ agentName: nextAgentName, template: nextTemplate, packageManager: singlePackageManager.command });
return true;
}
return false;
};
const handleNameSubmit = (value) => {
recordStep("Agent name", value);
agentName = value;
if (defaultTemplate && completeInit(value, selectedTemplate))
return;
currentStep.set(defaultTemplate ? "package-manager" : "template");
};
const handleTemplateSelect = (value) => {
recordStep("Template", value);
selectedTemplate = value;
if (completeInit(agentName, value))
return;
currentStep.set("package-manager");
};
const handlePackageManagerSelect = (value) => {
recordStep("Package manager", value);
onComplete({ agentName, template: selectedTemplate, packageManager: value });
};
const stepCounter = text(renderer, "");
scope.add(bind(() => {
const idx = Math.max(wizardSteps.indexOf(currentStep()) + 1, 1);
stepCounter.content = t`${fg(theme.text.dim)(`Step ${idx} of ${totalSteps}`)}`;
}, [currentStep]));
const activeStep = router(renderer, scope, currentStep, (step, viewScope) => {
if (step === "name") {
return box(renderer, { flexDirection: "column" }, [
userInput(renderer, viewScope, {
prompt: "What would you like to name your agent?",
placeholder: "my-agent",
initialValue: defaultAgentName,
validate: (value) => {
if (!value || value.trim() === "")
return "Agent name is required";
if (!/^[a-zA-Z0-9_-]+$/.test(value)) {
return "Agent name can only contain letters, numbers, hyphens, and underscores";
}
if (existsSync(resolve(process.cwd(), value))) {
return `"${value}" already exists \u2014 choose a different agent name`;
}
return null;
},
onSubmit: handleNameSubmit,
onCancel
})
]);
}
if (step === "template") {
return box(renderer, { flexDirection: "column" }, [
text(renderer, t`${fg(theme.text.primary)(bold("Select a template:"))}`),
select(renderer, viewScope, {
options: templates.map((tpl) => ({ id: tpl.id, label: tpl.id, value: tpl.id, description: tpl.description })),
onSubmit: handleTemplateSelect,
onCancel
})
]);
}
if (availablePackageManagers.length === 0) {
return box(renderer, { flexDirection: "column" }, [
text(renderer, t`${fg(theme.text.primary)(bold("Select a package manager:"))}`),
box(renderer, { marginTop: 1 }, [
text(renderer, t`${fg(theme.status.error)("No package managers found. Please install npm, pnpm, bun, or yarn.")}`)
])
]);
}
return box(renderer, { flexDirection: "column" }, [
text(renderer, t`${fg(theme.text.primary)(bold("Select a package manager:"))}`),
select(renderer, viewScope, {
options: availablePackageManagers.map((pm) => ({
id: pm.command,
label: pm.name,
value: pm.command,
description: `Install with ${pm.command}`
})),
onSubmit: handlePackageManagerSelect,
onCancel
})
]);
});
return box(renderer, { flexDirection: "column" }, [
box(renderer, { paddingX: 1, paddingY: 1 }, [
box(renderer, { flexDirection: "column" }, [
adkLogo(renderer, {
title: "Botpress ADK",
subtitle: "Initialize New Agent",
logoColor: theme.accent.purple,
titleColor: theme.text.primary,
subtitleColor: theme.text.dim
}),
box(renderer, { marginTop: 1 }, [stepCounter])
])
]),
box(renderer, { paddingX: 1, flexDirection: "column" }, [historyBox]),
box(renderer, { marginTop: 1, paddingX: 1, flexDirection: "column" }, [activeStep])
]);
}
// src/components/init-steps.ts
var SPINNER = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
function initSteps(ctx, scope) {
const theme = getActiveTheme();
const root = box(ctx, { flexDirection: "column" });
const frame = signal(0);
interval(scope, 80, () => frame.set(frame() + 1));
const symbolFor = (s) => {
if (s === "ok")
return theme.symbols.checkmark;
if (s === "warn")
return theme.symbols.warning;
if (s === "fail")
return theme.symbols.cross;
return SPINNER[frame() % SPINNER.length];
};
const colorFor = (s) => {
if (s === "ok")
return theme.status.success;
if (s === "warn")
return theme.status.warning;
if (s === "fail")
return theme.status.error;
return theme.status.info;
};
const createStep = (label, interactive) => {
const status = signal("run");
const labelSig = signal(label);
const hintSig = signal(null);
const row = box(ctx, { flexDirection: "column" });
root.add(row);
const lineNode = text(ctx, "");
let lineMounted = false;
let childEl = null;
const mountLine = () => {
if (!lineMounted && !childEl) {
row.add(lineNode);
lineMounted = true;
}
};
const setChild = (el) => {
if (childEl) {
row.remove(childEl.id);
childEl.destroyRecursively();
childEl = null;
}
if (el) {
if (lineMounted) {
row.remove(lineNode.id);
lineMounted = false;
}
childEl = el;
row.add(el);
} else {
mountLine();
}
};
scope.add(bind(() => {
const s = status();
const sym = symbolFor(s);
const textColor = s === "run" || s === "ok" ? theme.text.primary : colorFor(s);
lineNode.content = t`${fg(colorFor(s))(sym)} ${fg(textColor)(labelSig())}`;
}, [status, labelSig, frame]));
const hintNode = text(ctx, "", { marginLeft: 2 });
let hintMounted = false;
scope.add(bind(() => {
const h = hintSig();
if (h) {
hintNode.content = t`${fg(theme.text.dim)(h)}`;
if (!hintMounted) {
row.add(hintNode);
hintMounted = true;
}
} else if (hintMounted) {
row.remove(hintNode.id);
hintMounted = false;
}
}, [hintSig]));
if (!interactive) {
mountLine();
}
const settle = (next, label2, hint) => {
if (label2 !== undefined)
labelSig.set(label2);
if (hint !== undefined)
hintSig.set(hint);
setChild(null);
status.set(next);
};
const handle = {
setLabel: (l) => labelSig.set(l),
ok: (l) => settle("ok", l),
warn: (l, hint) => settle("warn", l, hint),
fail: (l, hint) => settle("fail", l, hint)
};
return { handle, setChild };
};
return {
el: root,
begin: (label) => createStep(label, false).handle,
beginInteractive: (label) => createStep(label, true),
note: (content) => root.add(content)
};
}
// src/commands/adk-init.ts
function formatInitError(err) {
if (err instanceof Error)
return err.message;
if (err && typeof err === "object") {
const message = err.message;
if (typeof message === "string")
return message;
try {
return JSON.stringify(err);
} catch {
return Object.prototype.toString.call(err);
}
}
return String(err);
}
function parseRef(ref) {
const at = ref.indexOf("@");
if (at < 0)
return { name: ref, version: "latest" };
return { name: ref.slice(0, at), version: ref.slice(at + 1) };
}
var logger = createCliLogger({ level: "debug" });
var NON_INTERACTIVE_INIT_HINT = "Non-interactive shell detected. Use --yes for defaults, or provide a name and template with --skip-link for unattended setup.";
function requiresInteractiveInit(requestedName, template, options, isInteractiveShell = Boolean(process.stdin.isTTY && process.stdout.isTTY)) {
const requiresUnattendedFlow = options?.format === "json" || !isInteractiveShell;
if (!requiresUnattendedFlow) {
return false;
}
const needsWizard = !requestedName || !template;
const skipsLink = Boolean(options?.skipLink || options?.yes || options?.defaults);
return needsWizard || !skipsLink;
}
function getTemplates() {
const configs = AgentProjectGenerator.getAvailableTemplates();
return configs.map((t2) => ({ id: t2.name, description: t2.description }));
}
function failInitValidation(message, isJson) {
if (isJson) {
throw new AdkError({ code: "INIT_VALIDATION", message, expected: true });
}
return logger.fatal(new AdkError({ code: "INIT_VALIDATION", message, expected: true }));
}
function buildNextSteps(projectName, linked) {
const nextSteps = [`cd ${projectName}`];
if (!linked) {
nextSteps.push("adk link");
}
nextSteps.push("adk dev");
return nextSteps;
}
async function adkInit(nameArg, options) {
await ensureTemplatesAvailable();
ensureJsonOnlyFormat(options?.format);
const isJson = options?.format === "json";
const jsonLogger = createCliLogger({ format: options?.format });
if (options?.listTemplates) {
const templates = getTemplates();
const configs = AgentProjectGenerator.getAvailableTemplates();
logger.info(`
Available templates:
`);
for (const t2 of templates) {
logger.info(` ${t2.id.padEnd(24)} ${t2.description}`, "cyan");
}
logger.newline();
jsonLogger.info("Available templates").result(configs.length > 0 ? configs : templates);
return;
}
const TEMPLATES = getTemplates();
const useDefaults = Boolean(options?.yes || options?.defaults);
const template = options?.template || (useDefaults ? "hello-world" : undefined);
const requestedName = nameArg || (useDefaults ? "my-agent" : undefined);
const skipLink = Boolean(options?.skipLink || useDefaults);
if (isJson && !useDefaults && !options?.skipLink) {
throw new AdkError({
code: "JSON_REQUIRES_FLAGS",
message: "--format json requires --yes, --defaults, or --skip-link for project creation.",
expected: true
});
}
if (isJson && useDefaults) {
const missing = [];
if (!nameArg) {
missing.push("a project name (positional argument)");
}
if (!options?.template) {
missing.push("a --template");
}
if (!options?.skipLink) {
missing.push("the --skip-link flag");
}
if (missing.length > 0) {
throw new AdkError({
code: "JSON_REQUIRES_FLAGS",
message: `--format json with --yes/--defaults requires ${missing.join(", ")}.`,
expected: true
});
}
}
if (!checkNodeVersion(true)) {
if (isJson) {
const nodeVersion = getNodeVersionInfo();
if (!nodeVersion.current) {
throw new AdkError({
code: "NODE_VERSION",
message: `Node.js ${nodeVersion.required} or newer is required to initialize a project.`,
expected: true
});
}
throw new AdkError({
code: "NODE_VERSION",
message: `Node.js ${nodeVersion.required} or newer is required to initialize a project. Current version: ${nodeVersion.current}.`,
expected: true
});
}
checkNodeVersion(false);
process.exit(1);
}
if (requiresInteractiveInit(requestedName, template, options)) {
throw new AdkError({ code: "INIT_NON_INTERACTIVE", message: NON_INTERACTIVE_INIT_HINT, expected: true });
}
if (!skipLink) {
try {
await auth.getActiveCredentials();
} catch {
logger.info(`
\uD83D\uDD10 Authentication required
`, "blue");
await adkLogin({ profile: "default", exitAfterLogin: false });
logger.newline();
}
}
const packageManagers = detectPackageManagers();
const availablePackageManagers = packageManagers.filter((pm) => pm.available);
if (availablePackageManagers.length === 0) {
failInitValidation("No package manager found. Please install npm, pnpm, bun, or yarn.", isJson);
}
const preferredPackageManager = getPreferredPackageManager(process.cwd(), availablePackageManagers);
if (!preferredPackageManager) {
failInitValidation("No compatible package manager found.", isJson);
}
if (requestedName) {
if (!/^[a-zA-Z0-9_-]+$/.test(requestedName)) {
failInitValidation("Agent name can only contain letters, numbers, hyphens, and underscores", isJson);
}
if (existsSync2(resolve2(process.cwd(), requestedName))) {
failInitValidation(`Directory "${requestedName}" already exists`, isJson);
}
}
if (template) {
if (!TEMPLATES.some((t2) => t2.id === template)) {
const templateIds = TEMPLATES.map((t2) => ` - ${t2.id}: ${t2.description}`).join(`
`);
failInitValidation(`Unknown template: "${template}"
Available templates:
${templateIds}`, isJson);
}
}
if (requestedName && template) {
const projectPath = resolve2(process.cwd(), requestedName);
const result = await initializeProject(projectPath, template, preferredPackageManager.command, preferredPackageManager.installCommand, {
skipLink,
json: isJson
});
jsonLogger.info("Project initialized").result(result);
return result;
}
return new Promise((resolvePromise, reject) => {
let appRef = null;
let wizardScope = null;
const handleComplete = async (result) => {
const app = appRef;
if (!app)
return;
const projectPath = resolve2(process.cwd(), result.agentName);
const packageManager = availablePackageManagers.find((pm) => pm.command === result.packageManager);
if (!packageManager) {
app.unmount();
logger.error("\u274C Selected package manager not found");
reject(new AdkError({ code: "NO_PACKAGE_MANAGER", message: "Package manager not found", expected: true }));
return;
}
try {
wizardScope?.dispose();
for (const child of [...app.renderer.root.getChildren()]) {
app.renderer.root.remove(child.id);
child.destroyRecursively();
}
const stepScope = app.scope.child();
const controller = initSteps(app.renderer, stepScope);
app.renderer.root.add(controller.el);
await initializeProject(projectPath, result.template, packageManager.command, packageManager.installCommand, {
skipLink: Boolean(options?.skipLink),
host: { renderer: app.renderer, scope: stepScope, controller }
});
resolvePromise();
} catch (error) {
reject(error);
} finally {
app.unmount();
process.stdout.write(`
`);
}
};
const handleCancel = () => {
appRef?.unmount();
logger.warn(`
Initialization cancelled`);
resolvePromise();
};
mount((renderer, scope) => {
wizardScope = createScope();
scope.add(() => wizardScope?.dispose());
return initWizard(renderer, wizardScope, {
templates: TEMPLATES,
packageManagers,
defaultAgentName: requestedName,
defaultTemplate: template,
onComplete: handleComplete,
onCancel: handleCancel
});
}, { exitOnCtrlC: true, clearOnShutdown: false }).then((app) => {
appRef = app;
});
});
}
function loggingReporter(log) {
const settledStep = (label) => ({
setLabel: () => {},
ok: (l) => log.info(`\u2705 ${l ?? label}`, "green"),
warn: (l, hint) => {
log.warn(`\u26A0\uFE0F ${l ?? label}`);
if (hint)
log.info(` ${hint}`, "cyan");
},
fail: (l, hint) => {
log.error(`\u274C ${l ?? label}`);
if (hint)
log.debug(` ${hint}`);
}
});
return {
header: (label) => log.info(`
\u2728 ${label}`, "blue"),
begin: (label) => settledStep(label),
note: (content, color) => log.info(content, color),
blank: () => log.newline(),
link: async (projectPath, projectName) => {
const originalCwd = process.cwd();
try {
process.chdir(projectPath);
await adkLink({ fromInit: true, projectName });
} finally {
process.chdir(originalCwd);
}
return null;
}
};
}
function stepListReporter(renderer, scope, controller) {
const theme = getActiveTheme();
const toToken = (color) => {
switch (color) {
case "green":
return theme.status.success;
case "red":
return theme.status.error;
case "yellow":
return theme.status.warning;
case "blue":
return theme.status.info;
case "cyan":
return theme.text.link;
case "gray":
return theme.text.dim;
default:
return theme.text.primary;
}
};
return {
header: (label) => controller.note(text(renderer, t`${fg(theme.status.info)(`\u2728 ${label}`)}`)),
begin: (label) => controller.begin(label),
note: (content, color) => controller.note(text(renderer, t`${fg(toToken(color))(content)}`)),
blank: () => controller.note(text(renderer, " ")),
link: async (projectPath, projectName) => {
const { handle, setChild } = controller.beginInteractive("Link to Botpress");
const linkScope = createScope();
scope.add(() => linkScope.dispose());
const originalCwd = process.cwd();
process.chdir(projectPath);
try {
const info = await new Promise((resolvePromise) => {
setChild(linkSetup(renderer, linkScope, {
fromInit: true,
projectName,
onComplete: (result) => resolvePromise(result ?? null)
}));
});
const label = info?.botName ? `Linked to ${info.botName}${info.workspaceName ? ` (${info.workspaceName})` : ""}` : "Linked to Botpress";
handle.ok(label);
return info;
} finally {
linkScope.dispose();
process.chdir(originalCwd);
}
}
};
}
async function performInit(ctx) {
const { projectPath, projectName, template, packageManager, installCommand, skipLink, isJson, log, reporter } = ctx;
const warnings = [];
log.debug(`Location: ${projectPath}`);
log.debug(`Template: ${template}`);
log.debug(`Package Manager: ${packageManager}`);
const generator = new AgentProjectGenerator(projectPath, packageManager, template);
const genStep = reporter.begin("Creating project structure\u2026");
await generator.generate();
genStep.ok("Project structure created");
const packageInstall = { attempted: true, success: true, command: installCommand };
const pkgStep = reporter.begin(`Installing packages with ${packageManager}\u2026`);
try {
await ctx.runInstall();
pkgStep.ok(`Packages installed (${packageManager})`);
} catch (error) {
packageInstall.success = false;
const stderr = error instanceof Error && "stderr" in error && error.stderr ? String(error.stderr).trim() : undefined;
packageInstall.error = stderr || (error instanceof Error ? error.message : String(error));
warnings.push(`Failed to install packages automatically. Please run '${installCommand}' manually.`);
pkgStep.warn("Could not install packages automatically", `Run '${installCommand}' manually`);
if (stderr)
log.debug(stderr);
}
const declared = generator.getDependencies();
const dependenciesResult = {
attempted: declared.integrations.length + declared.plugins.length,
succeeded: 0,
failed: 0,
failedRefs: []
};
const upgradeCommand = "adk agent0 upgrade";
let capabilitiesInstall;
let capabilitiesError;
const capStep = reporter.begin("Creating Agent(0) capabilities\u2026");
try {
capabilitiesInstall = await installAgent0Capabilities(projectPath);
capStep.ok(`Agent(0) capabilities created (${capabilitiesInstall.skills.installed} skills, ${capabilitiesInstall.playbooks.installed} commands)`);
} catch (error) {
capabilitiesError = error instanceof Error ? error.message : String(error);
warnings.push("Failed to create Agent(0) capabilities automatically.");
capStep.warn("Could not create Agent(0) capabilities", `Run: ${upgradeCommand}`);
}
const capabilities = capabilitiesInstall ? {
attempted: true,
success: true,
command: upgradeCommand,
capabilitiesRoot: capabilitiesInstall.capabilitiesRoot,
manifestPath: capabilitiesInstall.manifestPath,
version: capabilitiesInstall.currentVersion,
source: capabilitiesInstall.source,
skills: capabilitiesInstall.skills.installed,
playbooks: capabilitiesInstall.playbooks.installed
} : {
attempted: true,
success: false,
command: upgradeCommand,
error: capabilitiesError ?? "Failed to create Agent(0) capabilities automatically."
};
let externalHarness = {
success: false,
skills: {
attempted: true,
success: false,
command: "",
error: "External harness capability installer did not run."
},
commands: { attempted: false, success: false, installedCommands: 0, failed: 0 }
};
const harnessStep = reporter.begin("Installing ADK skills and commands\u2026");
try {
externalHarness = await installExternalHarnessCapabilities({
projectPath,
packageManagerCommand: packageManager,
commandTargets: ["claude-code", "opencode"]
});
} catch (error) {
externalHarness.skills.error = error instanceof Error ? error.message : String(error);
externalHarness.commands.error = error instanceof Error ? error.message : String(error);
}
const skills = externalHarness.skills;
const commands = externalHarness.commands;
if (externalHarness.success) {
harnessStep.ok(`ADK skills and commands installed (${commands.installedCommands} commands)`);
} else {
const hint = !skills.success && skills.command ? `Run: ${skills.command}` : undefined;
harnessStep.warn("Could not install ADK skills and commands", hint);
}
if (!skills.success)
warnings.push("Failed to install ADK skills automatically.");
if (!commands.success)
warnings.push("Failed to install ADK commands automatically.");
const link = { attempted: false, skipped: skipLink, linked: false, success: skipLink };
if (skipLink) {
link.reason = "Link skipped for unattended initialization.";
reporter.begin("Link to Botpress").warn("Skipped 'adk link' (requested)");
} else {
link.attempted = true;
try {
await reporter.link(projectPath, projectName);
} catch (error) {
link.reason = error instanceof Error ? error.message : String(error);
warnings.push(`Failed to link agent automatically: ${link.reason}`);
}
}
let linked = false;
try {
const project = await AgentProject.load(projectPath);
const agentCred = project.agentInfo;
linked = Boolean(agentCred?.botId && agentCred?.workspaceId && agentCred?.apiUrl);
} catch (err) {
logger.debug(`Could not reload project to confirm link: ${err instanceof Error ? err.message : String(err)}`);
}
link.linked = linked;
link.success = link.skipped || linked;
if (!linked && !link.skipped && !link.reason) {
link.reason = "Project was not linked during initialization.";
}
if (dependenciesResult.attempted > 0) {
if (!linked) {
const refs = [...declared.integrations, ...declared.plugins];
dependenciesResult.failed = dependenciesResult.attempted;
dependenciesResult.failedRefs = refs;
const skipMsg = `Template dependencies skipped (no linked bot): ${refs.join(", ")}. Run 'adk integrations add <name>' / 'adk plugins add <name>' after linking.`;
warnings.push(skipMsg);
reporter.begin("Installing template dependencies\u2026").warn("Template dependencies skipped (no linked bot)", "Run 'adk integrations add <name>' after linking");
} else {
const { dependencies: adkDeps } = await import("./chunk-ka3e16hs.js");
try {
AgentProject.clearCacheForPath(projectPath);
const context = await resolveCommandContext({
cwd: projectPath,
target: "prod",
require: ["project", "credentials", "workspace", "bot"]
});
const client = context.client;
const dm = await adkDeps.DependencyManager.fromProject({
projectPath,
env: "dev",
client
});
for (const ref of declared.integrations) {
const step = reporter.begin(`Installing integration ${ref}\u2026`);
try {
const { name, version } = parseRef(ref);
const result2 = await dm.add("integration", { name, version });
dependenciesResult.succeeded += 1;
if (result2.installedDisabled) {
const missing = result2.installedDisabled.missingFields.join(", ");
step.ok(`Installed integration ${ref} (disabled \u2014 missing config: ${missing})`);
} else {
step.ok(`Installed integration ${ref}`);
}
} catch (err) {
dependenciesResult.failed += 1;
dependenciesResult.failedRefs.push(ref);
const msg = formatInitError(err);
warnings.push(`Failed to install integration ${ref}: ${msg}`);
step.warn(`Could not install integration ${ref}`, msg);
}
}
for (const ref of declared.plugins) {
const step = reporter.begin(`Installing plugin ${ref}\u2026`);
try {
const { name, version } = parseRef(ref);
await dm.add("plugin", { name, version });
dependenciesResult.succeeded += 1;
step.ok(`Installed plugin ${ref}`);
} catch (err) {
dependenciesResult.failed += 1;
dependenciesResult.failedRefs.push(ref);
const msg = formatInitError(err);
warnings.push(`Failed to install plugin ${ref}: ${msg}`);
step.warn(`Could not install plugin ${ref}`, msg);
}
}
} catch (err) {
const msg = formatInitError(err);
warnings.push(`Failed to initialize dependency manager: ${msg}`);
reporter.begin("Installing template dependencies\u2026").fail("Could not initialize dependency manager", msg);
dependenciesResult.failed = dependenciesResult.attempted;
dependenciesResult.failedRefs = [...declared.integrations, ...declared.plugins];
}
}
}
telemetry_default.track("project_init", {
template: template || "",
has_existing_config: linked
});
const result = {
success: true,
projectPath,
name: projectName,
template,
nextSteps: buildNextSteps(projectName, linked),
packageManager,
packageInstall,
dependencies: dependenciesResult,
capabilities,
skills,
commands,
link,
...warnings.length > 0 ? { warnings } : {}
};
if (isJson) {
return result;
}
reporter.blank();
reporter.note(`\u2728 ${projectName} is ready!`, "green");
reporter.blank();
reporter.note("Get started:");
reporter.note(` cd ${projectName}`, "cyan");
reporter.note(" adk dev", "cyan");
if (!linked) {
reporter.blank();
reporter.note("\u26A0\uFE0F Your agent is not linked to Botpress.", "yellow");
reporter.note(" Run adk link inside the project directory to connect your agent.", "gray");
}
return result;
}
async function initializeProject(projectPath, template, packageManager, installCommand, options) {
const projectName = basename(projectPath) || "my-agent";
const isJson = Boolean(options?.json);
const skipLink = Boolean(options?.skipLink);
const host = options?.host;
const useStepList = host != null || !isJson && Boolean(process.stdout.isTTY);
if (!useStepList) {
const log2 = createCliLogger({ silent: isJson, level: "debug" });
const reporter2 = loggingReporter(log2);
const runInstall2 = async () => {
execSync(installCommand, { cwd: projectPath, stdio: "pipe", env: { ...process.env } });
};
reporter2.header(`Initializing ADK project: ${projectName}`);
try {
return await performInit({
projectPath,
projectName,
template,
packageManager,
installCommand,
skipLink,
isJson,
log: log2,
reporter: reporter2,
runInstall: runInstall2
});
} catch (error) {
if (!isJson) {
log2.error(`\u274C Failed to initialize project: ${error instanceof Error ? error.message : String(error)}`);
}
throw error;
}
}
let controller;
let renderer;
let scope;
let ownApp = null;
if (host) {
renderer = host.renderer;
scope = host.scope;
controller = host.controller;
} else {
let capturedController;
let capturedRenderer;
let capturedScope;
ownApp = await mount((r, s) => {
capturedRenderer = r;
capturedScope = s;
capturedController = initSteps(r, s);
return capturedController.el;
}, { exitOnCtrlC: true, clearOnShutdown: false });
renderer = capturedRenderer;
scope = capturedScope;
controller = capturedController;
}
const log = createCliLogger({ silent: true, level: "debug" });
const reporter = stepListReporter(renderer, scope, controller);
const runInstall = async () => {
await execAsync(installCommand, { cwd: projectPath, env: { ...process.env } });
};
reporter.header(`Initializing ADK project: ${projectName}`);
try {
const result = await performInit({
projectPath,
projectName,
template,
packageManager,
installCommand,
skipLink,
isJson,
log,
reporter,
runInstall
});
await new Promise((r) => setTimeout(r, 150));
if (ownApp) {
ownApp.unmount();
process.stdout.write(`
`);
}
return result;
} catch (error) {
if (ownApp) {
ownApp.unmount();
createCliLogger({ level: "debug" }).error(`\u274C Failed to initialize project: ${error instanceof Error ? error.message : String(error)}`);
}
throw error;
}
}
export {
requiresInteractiveInit,
adkInit,
NON_INTERACTIVE_INIT_HINT
};