UNPKG

@nestbox-ai/cli

Version:

The cli tools that helps developers to build agents

319 lines 18.9 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.selectTargetAgent = selectTargetAgent; exports.registerDeployCommand = registerDeployCommand; const chalk_1 = __importDefault(require("chalk")); const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const auth_1 = require("../../utils/auth"); const error_1 = require("../../utils/error"); const ora_1 = __importDefault(require("ora")); const project_1 = require("../../utils/project"); const agent_1 = require("../../utils/agent"); const axios_1 = __importDefault(require("axios")); const apiUtils_1 = require("./apiUtils"); const inquirer_1 = __importDefault(require("inquirer")); function selectTargetAgent(agents, agentName, instance) { const matchingByName = agents.filter(agent => agent.agentName === agentName); if (!matchingByName.length) { return undefined; } if (instance.id !== undefined) { const byInstanceId = matchingByName.find(agent => agent.machineInstanceId === instance.id); if (byInstanceId && byInstanceId.id !== undefined) { return byInstanceId; } } if (instance.instanceName) { const byInstanceName = matchingByName.find(agent => agent.machineName === instance.instanceName); if (byInstanceName && byInstanceName.id !== undefined) { return byInstanceName; } } if (instance.id !== undefined || instance.instanceName) { return undefined; } if (matchingByName.length === 1 && matchingByName[0].id !== undefined) { return matchingByName[0]; } return undefined; } function buildAgentData(options_1) { return __awaiter(this, arguments, void 0, function* (options, machineInstanceData = {}) { const deployAgentData = { agentName: "", goal: "", inputSchema: {}, machineManifestId: machineInstanceData.machineId, machineName: options.instance, machineInstanceId: machineInstanceData.id, instanceIP: machineInstanceData.internalIP, projectId: options.project, type: (options === null || options === void 0 ? void 0 : options.type) || "REGULAR", userId: 0, modelBaseId: "", entryFunctionName: "", }; if (!options.agent) { throw new Error("Missing required argument <agent>."); } deployAgentData.agentName = options.prefix ? options.prefix + "-" + options.agent : options.agent; if (options.description || options.inputSchema || options.entryFunction) { if (!options.description) { throw new Error("Missing required argument <description>."); } if (!options.inputSchema) { throw new Error("Missing required argument <inputSchema>."); } if (!options.entryFunction) { throw new Error("Missing required argument <entryFunction>."); } deployAgentData.goal = options.description; deployAgentData.inputSchema = JSON.parse(options.inputSchema); deployAgentData.entryFunctionName = options.entryFunction; } else { const manifestAgent = yield (0, apiUtils_1.loadAgentFromYaml)(options.agent); if (!manifestAgent) { throw new Error("Could not find a yaml file definition of an agent or agent not defined in yaml file."); } deployAgentData.entryFunctionName = manifestAgent.entry; deployAgentData.goal = manifestAgent.description; deployAgentData.inputSchema = manifestAgent.inputSchema || {}; deployAgentData.type = options.type || (manifestAgent === null || manifestAgent === void 0 ? void 0 : manifestAgent.type) || "REGULAR"; } return deployAgentData; }); } function registerDeployCommand(agentCommand) { agentCommand .command("deploy") .description("Deploy an AI agent to the Nestbox platform") .option("--prefix <prefix>", "A prefix added to beginning of the agent name.") .option("--agent <agent>", "Agent name to deploy") .option("--description <description>", "Goal/description of the agent") .option("--inputSchema <inputSchema>", "Agent input schema") .option("--project <project>", "Project ID (defaults to current project)") .option("--type <type>", "Agent type (e.g. CHAT, AGENT, REGULAR)") .option("--entryFunction <entryFunction>", "Entry function name") .option("--instance <instance>", "Machine name") .option("--log", "Show detailed logs during deployment") .option("--silent", "Disable automatic agent creation.") .option("--all", "Deploy all agents defined in nestbox-agents.yaml") .action((options) => __awaiter(this, void 0, void 0, function* () { var _a; try { let apis = (0, apiUtils_1.createApis)(); yield (0, error_1.withTokenRefresh)(() => __awaiter(this, void 0, void 0, function* () { var _a, _b, _c, _d, _e; let names = []; if (options.all) { names = yield (0, apiUtils_1.loadAllAgentNamesFromYaml)(); if (!names.length) { console.log(chalk_1.default.yellow("No agents found in YAML manifest.")); return; } } else { if (!(options === null || options === void 0 ? void 0 : options.agent)) { console.log(chalk_1.default.red("Parameter <agent> not provided.")); return; } names = [options.agent]; } const projectData = yield (0, project_1.resolveProject)(apis.projectsApi, Object.assign({ project: options.project, instance: "" }, options)); const projectRoot = process.cwd(); const config = (0, agent_1.loadNestboxConfig)(projectRoot); if (!(options === null || options === void 0 ? void 0 : options.instance) && !(config === null || config === void 0 ? void 0 : config.instance)) { console.log(chalk_1.default.red("Parameter <instance> not provided.")); return; } const machineName = options.instance || config.instance; const instanceData = yield apis.instanceApi.machineInstancesControllerGetMachineInstanceByUserId(projectData.id, 0, 10); const targetInstance = instanceData.data.machineInstances.find((instance) => instance.instanceName === machineName); if (!targetInstance) { console.error(chalk_1.default.red(`Instance with name "${machineName}" not found in project "${projectData.name}".`)); console.log(chalk_1.default.yellow("Available instances:")); instanceData.data.machineInstances.forEach((instance) => { console.log(chalk_1.default.yellow(` - ${instance.instanceName} (ID: ${instance.id})`)); }); return; } for (const name of names) { const data = yield buildAgentData(Object.assign(Object.assign({}, options), { project: projectData.id, instance: machineName, agent: name }), targetInstance); const agentsData = yield apis.agentsApi.machineAgentControllerGetMachineAgentByProjectId(projectData.id, 0, 100, data.type); let targetAgent = selectTargetAgent(agentsData.data.machineAgents, data.agentName, { id: targetInstance.id, instanceName: targetInstance.instanceName, }); if (!targetAgent && !options.silent) { const { confirmCreation } = yield inquirer_1.default.prompt([ { type: "confirm", name: "confirmCreation", message: chalk_1.default.red(`No agent with specified name "${data.agentName}" found. Would you like to create one first before deployment?`), default: false, }, ]); if (!confirmCreation) { continue; } } if (!targetAgent) { const response = yield apis.agentsApi.machineAgentControllerCreateMachineAgent(projectData.id, Object.assign({}, data)); targetAgent = response.data; console.log(chalk_1.default.green(`Created agent ${data.agentName} before deploying.`)); } const agentId = targetAgent === null || targetAgent === void 0 ? void 0 : targetAgent.id; if (agentId === undefined) { throw new Error(`Unable to resolve an agent ID for ${data.agentName} on instance ${machineName}.`); } const resolvedEntry = data.entryFunctionName || (targetAgent === null || targetAgent === void 0 ? void 0 : targetAgent.entryFunctionName) || "main"; const instanceId = targetInstance.id; const spinner = (0, ora_1.default)(`Preparing to deploy ${data.agentName.toLowerCase()} ${agentId} to instance ${instanceId}...`).start(); try { let zipFilePath; spinner.text = `Using project root: ${projectRoot}`; const isTypeScript = (0, agent_1.isTypeScriptProject)(projectRoot); if (isTypeScript && (((_a = config === null || config === void 0 ? void 0 : config.agent) === null || _a === void 0 ? void 0 : _a.predeploy) || ((_b = config === null || config === void 0 ? void 0 : config.agents) === null || _b === void 0 ? void 0 : _b.predeploy))) { const predeployScripts = ((_c = config === null || config === void 0 ? void 0 : config.agent) === null || _c === void 0 ? void 0 : _c.predeploy) || ((_d = config === null || config === void 0 ? void 0 : config.agents) === null || _d === void 0 ? void 0 : _d.predeploy); spinner.text = `Running predeploy scripts on project root...`; yield (0, agent_1.runPredeployScripts)(predeployScripts, projectRoot); } spinner.text = `Creating zip archive from project root ${projectRoot}...`; const excludePatterns = (0, agent_1.getAgentExcludePatterns)(config); zipFilePath = (0, agent_1.createZipFromDirectory)(projectRoot, excludePatterns); const authToken = (0, auth_1.getAuthToken)(); const baseUrl = ((_e = authToken === null || authToken === void 0 ? void 0 : authToken.serverUrl) === null || _e === void 0 ? void 0 : _e.endsWith("/")) ? authToken.serverUrl.slice(0, -1) : authToken === null || authToken === void 0 ? void 0 : authToken.serverUrl; const { default: FormData } = yield Promise.resolve().then(() => __importStar(require("form-data"))); const form = new FormData(); form.append("file", fs_1.default.createReadStream(zipFilePath)); form.append("machineAgentId", agentId.toString()); form.append("instanceId", instanceId.toString()); form.append("entryFunctionName", resolvedEntry); form.append("isSourceCodeUpdate", "true"); form.append("projectId", projectData.id); if (options.log) { console.log(chalk_1.default.blue("Form Details ")); console.log(chalk_1.default.blue(` - File: ${path_1.default.basename(zipFilePath)}`)); console.log(chalk_1.default.blue(` - Agent ID: ${agentId}`)); console.log(chalk_1.default.blue(` - Instance ID: ${instanceId}`)); console.log(chalk_1.default.blue(` - Entry Function: ${resolvedEntry}`)); console.log(chalk_1.default.blue(` - Project ID: ${projectData.id}`)); } const axiosInstance = axios_1.default.create({ baseURL: baseUrl, headers: Object.assign(Object.assign({}, form.getHeaders()), { Authorization: authToken === null || authToken === void 0 ? void 0 : authToken.token }), }); const endpoint = `/projects/${projectData.id}/agents/${agentId}`; spinner.text = `Deploying ${data.agentName.toLowerCase()} ${agentId} to instance ${instanceId} with file ${zipFilePath}...`; const res = yield axiosInstance.patch(endpoint, form); yield axios_1.default.patch(baseUrl + endpoint, { projectId: data.projectId, id: agentId, agentName: data.agentName, goal: data.goal, inputSchema: data.inputSchema, }, { headers: { Authorization: authToken === null || authToken === void 0 ? void 0 : authToken.token, }, }); if (options.log) { console.log(chalk_1.default.blue("\nDeployment request:")); console.log(chalk_1.default.blue(` URL: ${baseUrl}${endpoint}`)); console.log(chalk_1.default.blue(` Method: PATCH`)); console.log(chalk_1.default.blue(` File: ${path_1.default.basename(zipFilePath)}`)); console.log(chalk_1.default.blue(` Response status: ${res.status} ${res.statusText}`)); const lines = res.data.logEntries || []; console.log(chalk_1.default.blue(` Deployment log entries (${lines.length} lines):`)); lines.forEach((line) => { console.log(chalk_1.default.blue(` - [${line.type} ${line.timestamp}] ${line.message} `)); }); } spinner.succeed("Successfully deployed"); console.log(chalk_1.default.green(`${data.agentName} deployed successfully!`)); console.log(chalk_1.default.cyan(`📍 Instance: ${data.machineName}`)); console.log(chalk_1.default.cyan(`🤖 Agent: ${name} (${agentId})`)); console.log(chalk_1.default.cyan(`⚙️ Entry: ${resolvedEntry}`)); console.log(chalk_1.default.cyan(`🔄 Process: ${res.data.processName}`)); } catch (error) { spinner.fail(`Failed to deploy ${data.agentName.toLowerCase()} with Error: ${error.message || "Unknown error"}`); } } }), () => { apis = (0, apiUtils_1.createApis)(); }); } catch (error) { if (error.message && error.message.includes("Authentication")) { console.error(chalk_1.default.red(error.message)); } else if (error.response) { console.error(chalk_1.default.red(`API Error (${error.response.status}): ${((_a = error.response.data) === null || _a === void 0 ? void 0 : _a.message) || "Unknown error"}`)); if (error.response.data) { console.error(chalk_1.default.red(`Error Data: ${JSON.stringify(error.response.data, null, 2)}`)); } } else { console.error(chalk_1.default.red("Error:"), error.message || "Unknown error"); } } })); } //# sourceMappingURL=deploy.js.map