@kya-os/cli
Version:
CLI for MCP-I setup and management
129 lines ⢠5.49 kB
JavaScript
import chalk from "chalk";
import { spawn } from "child_process";
import { existsSync, readFileSync } from "fs";
import { join } from "path";
import { showError, showInfo } from "../utils/prompts.js";
/**
* Start the XMCP-I application in production mode
*/
export async function start() {
console.log(chalk.cyan("\nš Starting Production Server\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 for production environment variables
const requiredEnvVars = [
"AGENT_PRIVATE_KEY",
"AGENT_KEY_ID",
"AGENT_DID",
"KYA_VOUCHED_API_KEY",
];
const missingVars = requiredEnvVars.filter((varName) => !process.env[varName]);
if (missingVars.length > 0) {
showError("Missing required production environment variables:");
missingVars.forEach((varName) => {
console.log(` ${chalk.red("ā")} ${chalk.gray(varName)}`);
});
console.log(`\n${chalk.gray("Set these environment variables or run in development mode:")}`);
console.log(`${chalk.cyan("mcpi dev")}`);
console.log(`\n${chalk.gray("For platform-specific variable names:")}`);
console.log(`${chalk.cyan("mcpi env show")}`);
process.exit(21); // XMCP_I_ENOIDENTITY
}
// Determine start command
let command = "npm";
let args = ["run", "start"];
try {
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
if (!packageJson.scripts?.start) {
// Try alternative start approaches
const outputDirs = ["dist", "build", "out"];
const foundOutput = outputDirs.find((dir) => existsSync(join(process.cwd(), dir)));
if (foundOutput) {
// Look for entry points in output directory
const entryPoints = ["server.js", "index.js", "main.js"];
const entryPoint = entryPoints.find((entry) => existsSync(join(process.cwd(), foundOutput, entry)));
if (entryPoint) {
command = "node";
args = [join(foundOutput, entryPoint)];
showInfo(`No start script found, running ${foundOutput}/${entryPoint} directly.`);
}
else {
showError(`Build output found in ${foundOutput}/ but no entry point detected.`);
console.log(`\n${chalk.gray("Expected one of:")}`);
entryPoints.forEach((entry) => {
console.log(`${chalk.gray(`⢠${foundOutput}/${entry}`)}`);
});
process.exit(1);
}
}
else {
showError("No start script found and no build output detected.");
console.log(`\n${chalk.gray("Expected one of:")}`);
console.log(`${chalk.gray("⢠npm script 'start' in package.json")}`);
console.log(`${chalk.gray("⢠Built output in dist/, build/, or out/")}`);
console.log(`\n${chalk.gray("Try building first:")}`);
console.log(`${chalk.cyan("mcpi build")}`);
process.exit(1);
}
}
}
catch (error) {
showError("Failed to parse package.json");
process.exit(1);
}
console.log(`${chalk.gray("Running:")} ${chalk.cyan(`${command} ${args.join(" ")}`)}`);
console.log(`${chalk.gray("Environment:")} ${chalk.green("production")}`);
console.log(`${chalk.gray("Press Ctrl+C to stop")}\n`);
// Spawn the production 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 production server..."));
child.kill("SIGINT");
});
process.on("SIGTERM", () => {
child.kill("SIGTERM");
});
child.on("error", (error) => {
showError(`Failed to start production server: ${error.message}`);
process.exit(1);
});
child.on("exit", (code) => {
if (code !== 0 && code !== null) {
showError(`Production server exited with code ${code}`);
process.exit(code);
}
});
}
//# sourceMappingURL=start.js.map