UNPKG

@botpress/adk-cli

Version:

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

972 lines (966 loc) 33.6 kB
// @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 };