UNPKG

@kya-os/cli

Version:

CLI for MCP-I setup and management

173 lines 7.94 kB
import chalk from "chalk"; import { spawn } from "child_process"; import { existsSync, readFileSync } from "fs"; import { join } from "path"; import { showError, showSuccess, showInfo } from "../utils/prompts.js"; /** * Build the XMCP-I application for production */ export async function build() { console.log(chalk.cyan("\n🔨 Building Application\n")); // Check if we're in a valid XMCP-I project const packageJsonPath = join(process.cwd(), "package.json"); if (!existsSync(packageJsonPath)) { showError("No package.json found. Are you in a valid project directory?"); process.exit(1); } // Check for mcpi dependency try { const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8")); const hasmcpi = packageJson.dependencies?.mcpi || packageJson.devDependencies?.mcpi || packageJson.dependencies?.["@kya-os/mcp-i"] || packageJson.devDependencies?.["@kya-os/mcp-i"] || packageJson.dependencies?.["@kya-os/mcpi"] || packageJson.devDependencies?.["@kya-os/mcpi"]; if (!hasmcpi) { showError("This doesn't appear to be an XMCP-I project. Missing mcpi dependency."); console.log(`\n${chalk.gray("To create a new XMCP-I project:")}`); console.log(`${chalk.cyan("npx @kya-os/create-mcpi-app my-agent")}`); process.exit(1); } } catch (error) { showError("Failed to read package.json"); process.exit(1); } // Check if this is an XMCP project with xmcp.config.ts const xmcpConfigPath = join(process.cwd(), "xmcp.config.ts"); if (existsSync(xmcpConfigPath)) { // Use XMCP compiler for XMCP projects try { showInfo("Building XMCP project..."); // Import and use the XMCP compiler let compile; try { showInfo("Importing XMCP compiler..."); // Try ESM import first const mcpiModule = await import("@kya-os/mcp-i"); compile = mcpiModule.compile || mcpiModule.default?.compile; if (!compile) { // Log available exports for debugging console.log("Available exports:", Object.keys(mcpiModule)); throw new Error("compile function not found in ESM exports"); } } catch (esmError) { showInfo("ESM import failed, trying CommonJS..."); // Fallback to CommonJS require try { const mcpiModule = require("@kya-os/mcp-i"); compile = mcpiModule.compile; if (!compile) { console.log("Available exports:", Object.keys(mcpiModule)); throw new Error("compile function not found in CJS exports"); } } catch (cjsError) { const esmErrorMsg = esmError instanceof Error ? esmError.message : String(esmError); const cjsErrorMsg = cjsError instanceof Error ? cjsError.message : String(cjsError); showError("Failed to import XMCP compiler"); console.log("ESM error:", esmErrorMsg); console.log("CJS error:", cjsErrorMsg); console.log("\nDebugging info:"); console.log("- Make sure @kya-os/mcp-i is built: pnpm --filter=@kya-os/mcp-i build"); console.log("- Check if dist/index.js exists in packages/mcp-i/"); console.log("- Verify compile function is exported from mcpi"); throw new Error(`Failed to import XMCP compiler. ESM: ${esmErrorMsg}, CJS: ${cjsErrorMsg}`); } } if (typeof compile !== "function") { showError(`XMCP compiler 'compile' is not a function. Got: ${typeof compile}`); throw new Error(`XMCP compiler 'compile' is not a function. Got: ${typeof compile}`); } showInfo("XMCP compiler imported successfully"); // Set production mode for build process.env.NODE_ENV = "production"; // Wait for compilation to fully complete await compile(); // Show success messages after compilation is done showSuccess("Build completed successfully!"); console.log(`\n${chalk.gray("Next steps:")}`); console.log(`${chalk.gray("• Deploy to your platform of choice")}`); console.log(`${chalk.gray("• Set production environment variables")}`); console.log(`${chalk.gray("• Test with: mcpi start")}`); // Exit CLI after successful build // This is necessary because webpack may have lingering handles even after compiler.close() process.exit(0); } catch (error) { showError(`XMCP build failed: ${error}`); process.exit(1); } } // Fallback to npm/tsc for non-XMCP projects let command = "npm"; let args = ["run", "build"]; try { const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8")); if (!packageJson.scripts?.build) { // Try alternative build approaches if (existsSync(join(process.cwd(), "tsconfig.json"))) { // Use TypeScript compiler directly command = "npx"; args = ["tsc"]; showInfo("No build script found, using TypeScript compiler directly."); } else { showError("No build script found and no TypeScript configuration detected."); console.log(`\n${chalk.gray("Expected one of:")}`); console.log(`${chalk.gray("• xmcp.config.ts for XMCP projects")}`); console.log(`${chalk.gray("• npm script 'build' in package.json")}`); console.log(`${chalk.gray("• tsconfig.json for TypeScript compilation")}`); process.exit(1); } } } catch (error) { showError("Failed to parse package.json"); process.exit(1); } console.log(`${chalk.gray("Running:")} ${chalk.cyan(`${command} ${args.join(" ")}`)}`); // Spawn the build process const child = spawn(command, args, { stdio: "inherit", shell: true, env: { ...process.env, NODE_ENV: "production", }, }); // Handle process termination process.on("SIGINT", () => { console.log(chalk.yellow("\n\n🛑 Stopping build process...")); child.kill("SIGINT"); }); process.on("SIGTERM", () => { child.kill("SIGTERM"); }); child.on("error", (error) => { showError(`Failed to start build process: ${error.message}`); process.exit(1); }); child.on("exit", (code) => { if (code === 0) { showSuccess("Build completed successfully!"); // Check for common output directories const outputDirs = ["dist", "build", "out"]; const foundOutput = outputDirs.find((dir) => existsSync(join(process.cwd(), dir))); if (foundOutput) { console.log(`\n${chalk.gray("Output directory:")} ${chalk.cyan(foundOutput)}`); } console.log(`\n${chalk.gray("Next steps:")}`); console.log(`${chalk.gray("• Deploy to your platform of choice")}`); console.log(`${chalk.gray("• Set production environment variables")}`); console.log(`${chalk.gray("• Test with:")} ${chalk.cyan("mcpi start")}`); } else if (code !== null) { showError(`Build failed with exit code ${code}`); process.exit(code); } }); } //# sourceMappingURL=build.js.map