UNPKG

@botpress/adk-cli

Version:

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

143 lines (140 loc) 5.71 kB
// @bun import { box, fg, getActiveTheme, renderToString, t, text } from "./chunk-m2h26j5f.js"; import { ValidationErrorCode } from "./chunk-p0hjqn4r.js"; // src/utils/assert-valid-project.ts class ProjectValidationError extends Error { validation; constructor(message, validation) { super(message); this.validation = validation; this.name = "ProjectValidationError"; } } function normalizeOptions(exitOnErrorOrOptions = true, skipRender = false) { if (typeof exitOnErrorOrOptions === "object") { return { exitOnError: exitOnErrorOrOptions.exitOnError ?? true, skipRender: exitOnErrorOrOptions.skipRender ?? false, throwOnError: exitOnErrorOrOptions.throwOnError ?? false, filterCodes: exitOnErrorOrOptions.filterCodes ?? [] }; } return { exitOnError: exitOnErrorOrOptions, skipRender, throwOnError: false, filterCodes: [] }; } function buildAgentNotLinked(ctx, theme) { return box(ctx, { flexDirection: "column", paddingY: 1 }, [ text(ctx, t`${fg(theme.status.error)(`${theme.symbols.cross} Agent not linked to a bot`)}`), text(ctx, t`${fg(theme.text.dim)("Your local agent needs to be linked to a remote bot.")}`, { marginTop: 1 }), text(ctx, t`${fg(theme.text.dim)("Run the following command to link it:")}`, { marginTop: 1 }), text(ctx, t`${fg(theme.syntax.keyword)("adk link")}`, { marginTop: 1, marginLeft: 2 }) ]); } function buildValidationReport(ctx, theme, errors, warnings, info) { const sections = []; if (errors.length > 0) { const children = [ text(ctx, t`${fg(theme.status.error)(`${theme.symbols.cross} Project validation failed:`)}`) ]; for (const error of errors) { const item = [ text(ctx, t`${fg(theme.status.error)(`${error.file || "Project"}:`)}`, { marginLeft: 2 }), text(ctx, t`${fg(theme.status.error)(error.message)}`, { marginLeft: 4 }) ]; if (error.hint) { item.push(text(ctx, t`${fg(theme.text.dim)(`${theme.symbols.info} ${error.hint}`)}`, { marginLeft: 4 })); } children.push(box(ctx, { flexDirection: "column", marginTop: 1 }, item)); } sections.push(box(ctx, { flexDirection: "column" }, children)); } if (warnings.length > 0) { const children = [text(ctx, t`${fg(theme.status.warning)(`${theme.symbols.warning} Warnings:`)}`)]; for (const warning of warnings) { const item = [ text(ctx, t`${fg(theme.status.warning)(`${warning.file || "Project"}: ${warning.message}`)}`, { marginLeft: 2 }) ]; if (warning.hint) { item.push(text(ctx, t`${fg(theme.text.dim)(`${theme.symbols.info} ${warning.hint}`)}`, { marginLeft: 4 })); } children.push(box(ctx, { flexDirection: "column", marginTop: 1 }, item)); } sections.push(box(ctx, { flexDirection: "column", marginTop: errors.length > 0 ? 1 : 0 }, children)); } if (info.length > 0) { const children = [text(ctx, t`${fg(theme.status.info)(`${theme.symbols.info} Info:`)}`)]; for (const entry of info) { const item = [ text(ctx, t`${fg(theme.status.info)(`${entry.file || "Project"}: ${entry.message}`)}`, { marginLeft: 2 }) ]; if (entry.hint) { item.push(text(ctx, t`${fg(theme.text.dim)(`${theme.symbols.info} ${entry.hint}`)}`, { marginLeft: 4 })); } children.push(box(ctx, { flexDirection: "column", marginTop: 1 }, item)); } sections.push(box(ctx, { flexDirection: "column", marginTop: errors.length > 0 || warnings.length > 0 ? 1 : 0 }, children)); } return box(ctx, { flexDirection: "column", paddingY: 1 }, sections); } async function assertValidProject(project, exitOnErrorOrOptions = true, skipRender = false) { const options = normalizeOptions(exitOnErrorOrOptions, skipRender); const info = project.info; const validationResult = await project.validate(); const codeFilter = (item) => options.filterCodes.length === 0 || !options.filterCodes.includes(item.code); const allErrors = [...info.errors, ...validationResult.errors].filter(codeFilter); const allWarnings = [...info.warnings, ...validationResult.warnings].filter(codeFilter); const allInfo = validationResult.info.filter(codeFilter); const hasErrors = allErrors.length > 0; const hasLinkingError = allErrors.some((error) => error.code === ValidationErrorCode.AGENT_NOT_LINKED); if (hasLinkingError) { if (!options.skipRender) { const theme = getActiveTheme(); console.log(await renderToString((ctx) => buildAgentNotLinked(ctx, theme))); } if (options.throwOnError) { throw new ProjectValidationError("Agent not linked to a bot", { errors: allErrors, warnings: allWarnings, info: allInfo }); } if (options.exitOnError) { process.exit(1); } return { ...validationResult, errors: allErrors, warnings: allWarnings, info: allInfo }; } if (hasErrors || allWarnings.length > 0 || allInfo.length > 0) { if (!options.skipRender) { const theme = getActiveTheme(); console.log(await renderToString((ctx) => buildValidationReport(ctx, theme, allErrors, allWarnings, allInfo))); } if (hasErrors && options.throwOnError) { const detail = allErrors.map((e) => `${e.file ?? "Project"}: ${e.message}`).join("; "); throw new ProjectValidationError(`Project validation failed \u2014 ${detail}`, { errors: allErrors, warnings: allWarnings, info: allInfo }); } if (hasErrors && options.exitOnError) { process.exit(1); } } return { ...validationResult, errors: allErrors, warnings: allWarnings, info: allInfo }; } export { assertValidProject };