@nestbox-ai/cli 1.0.13 → 1.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/.nestboxrc +5 -0
  2. package/dist/commands/agent.js +592 -173
  3. package/dist/commands/agent.js.map +1 -1
  4. package/dist/commands/auth.js +1 -0
  5. package/dist/commands/auth.js.map +1 -1
  6. package/dist/commands/compute.js +38 -8
  7. package/dist/commands/compute.js.map +1 -1
  8. package/dist/commands/document.js +2 -0
  9. package/dist/commands/document.js.map +1 -1
  10. package/dist/commands/image.js +107 -110
  11. package/dist/commands/image.js.map +1 -1
  12. package/dist/commands/projects.js +118 -30
  13. package/dist/commands/projects.js.map +1 -1
  14. package/dist/types/agentType.d.ts +1 -1
  15. package/dist/types/agentType.js +1 -1
  16. package/dist/types/agentType.js.map +1 -1
  17. package/dist/types/agentYaml.d.ts +91 -0
  18. package/dist/types/agentYaml.js +6 -0
  19. package/dist/types/agentYaml.js.map +1 -0
  20. package/dist/types/auth.d.ts +4 -6
  21. package/dist/types/auth.js +1 -0
  22. package/dist/types/auth.js.map +1 -1
  23. package/dist/utils/agent.d.ts +11 -0
  24. package/dist/utils/agent.js +72 -0
  25. package/dist/utils/agent.js.map +1 -1
  26. package/dist/utils/auth.d.ts +4 -0
  27. package/dist/utils/auth.js +31 -3
  28. package/dist/utils/auth.js.map +1 -1
  29. package/dist/utils/error.d.ts +8 -0
  30. package/dist/utils/error.js +163 -0
  31. package/dist/utils/error.js.map +1 -0
  32. package/dist/utils/project.d.ts +4 -1
  33. package/dist/utils/project.js +17 -10
  34. package/dist/utils/project.js.map +1 -1
  35. package/package.json +3 -1
  36. package/sample-agents.yaml +0 -0
  37. package/src/commands/agent.ts +770 -303
  38. package/src/commands/auth.ts +1 -0
  39. package/src/commands/compute.ts +30 -8
  40. package/src/commands/document.ts +2 -2
  41. package/src/commands/image.ts +121 -129
  42. package/src/commands/projects.ts +125 -34
  43. package/src/types/agentType.ts +1 -1
  44. package/src/types/agentYaml.ts +107 -0
  45. package/src/types/auth.ts +10 -10
  46. package/src/utils/agent.ts +82 -0
  47. package/src/utils/auth.ts +33 -3
  48. package/src/utils/error.ts +168 -0
  49. package/src/utils/project.ts +20 -13
  50. package/templates/template-base-js.zip +0 -0
  51. package/templates/template-base-ts.zip +0 -0
  52. package/templates/template-chatbot-js.zip +0 -0
  53. package/templates/template-chatbot-ts.zip +0 -0
@@ -1,4 +1,37 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
36
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
37
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -13,6 +46,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
13
46
  };
14
47
  Object.defineProperty(exports, "__esModule", { value: true });
15
48
  exports.registerAgentCommands = registerAgentCommands;
49
+ const error_1 = require("../utils/error");
16
50
  const chalk_1 = __importDefault(require("chalk"));
17
51
  const ora_1 = __importDefault(require("ora"));
18
52
  const cli_table3_1 = __importDefault(require("cli-table3"));
@@ -20,22 +54,109 @@ const auth_1 = require("../utils/auth");
20
54
  const admin_1 = require("@nestbox-ai/admin");
21
55
  const project_1 = require("../utils/project");
22
56
  const fs_1 = __importDefault(require("fs"));
57
+ const js_yaml_1 = __importDefault(require("js-yaml"));
23
58
  const agent_1 = require("../utils/agent");
24
59
  const axios_1 = __importDefault(require("axios"));
25
60
  const agentType_1 = require("../types/agentType");
61
+ const inquirer_1 = __importDefault(require("inquirer"));
62
+ const path_1 = __importDefault(require("path"));
63
+ const user_1 = require("../utils/user");
64
+ /**
65
+ * Create a new agent in the Nestbox platform
66
+ *
67
+ * @param agentName The name of the agent
68
+ * @param options Options including lang, template, and project
69
+ * @param agentsApi The MachineAgentApi instance
70
+ * @param projectsApi The ProjectsApi instance
71
+ */
72
+ function createAgent(agentName, options, agentsApi, projectsApi) {
73
+ return __awaiter(this, void 0, void 0, function* () {
74
+ var _a, _b, _c;
75
+ const authToken = (0, auth_1.getAuthToken)();
76
+ if (!authToken) {
77
+ throw new Error("No authentication token found. Please login first.");
78
+ }
79
+ // Create API instances if not provided
80
+ if (!agentsApi || !projectsApi) {
81
+ const configuration = new admin_1.Configuration({
82
+ basePath: authToken === null || authToken === void 0 ? void 0 : authToken.serverUrl,
83
+ baseOptions: {
84
+ headers: {
85
+ Authorization: authToken === null || authToken === void 0 ? void 0 : authToken.token,
86
+ },
87
+ },
88
+ });
89
+ agentsApi = agentsApi || new admin_1.MachineAgentApi(configuration);
90
+ projectsApi = projectsApi || new admin_1.ProjectsApi(configuration);
91
+ }
92
+ // Resolve project - convert options to match CommandOptions interface
93
+ const projectData = yield (0, project_1.resolveProject)(projectsApi, Object.assign({ project: options.project, instance: options.instanceName || '' }, options));
94
+ // Prepare agent creation payload
95
+ // Determine the correct type value based on options.type
96
+ const agentTypeValue = ((_a = options.type) === null || _a === void 0 ? void 0 : _a.includes("AGENT")) ? "REGULAR" : options.type || "CHAT";
97
+ const payload = {
98
+ agentName,
99
+ goal: options.goal || `AI agent for ${agentName}`,
100
+ modelBaseId: options.modelBaseId || "",
101
+ machineName: options.machineName,
102
+ machineInstanceId: options.machineInstanceId,
103
+ instanceIP: options.instanceIP,
104
+ machineManifestId: options.machineManifestId,
105
+ parameters: ((_b = options.parameters) === null || _b === void 0 ? void 0 : _b.map((param) => ({
106
+ name: param.name,
107
+ description: param.description,
108
+ default_value: param.default || "",
109
+ isUserParam: param.isUserParam !== undefined ? param.isUserParam : true
110
+ }))) || [],
111
+ projectId: projectData.id,
112
+ type: agentTypeValue,
113
+ userId: options.userId || 0,
114
+ };
115
+ // Determine the type of resource (Agent or Chat)
116
+ const agentType = options.type || "CHAT";
117
+ const resourceType = agentType === "AGENT" || agentType === "REGULAR" ? "Agent" : "Chatbot";
118
+ // Create the agent
119
+ const spinner = (0, ora_1.default)(`Creating ${resourceType.toLowerCase()} ${agentName}...`).start();
120
+ try {
121
+ const response = yield agentsApi.machineAgentControllerCreateMachineAgent(projectData.id, payload);
122
+ spinner.succeed(`${resourceType} '${agentName}' created successfully`);
123
+ return response.data;
124
+ }
125
+ catch (error) {
126
+ spinner.fail(`Failed to create ${resourceType.toLowerCase()} ${agentName}`);
127
+ if (error.response && error.response.status === 401) {
128
+ throw new Error('Authentication token has expired. Please login again using "nestbox login <domain>".');
129
+ }
130
+ else if (error.response) {
131
+ throw new Error(`API Error (${error.response.status}): ${((_c = error.response.data) === null || _c === void 0 ? void 0 : _c.message) || "Unknown error"}`);
132
+ }
133
+ else {
134
+ throw new Error(error.message || "Unknown error");
135
+ }
136
+ }
137
+ });
138
+ }
26
139
  function registerAgentCommands(program) {
27
- // Get authentication token and create API configuration
28
- const authToken = (0, auth_1.getAuthToken)();
29
- const configuration = new admin_1.Configuration({
30
- basePath: authToken === null || authToken === void 0 ? void 0 : authToken.serverUrl,
31
- baseOptions: {
32
- headers: {
33
- Authorization: authToken === null || authToken === void 0 ? void 0 : authToken.token,
140
+ // Function to create/recreate API instances
141
+ const createApis = () => {
142
+ const authToken = (0, auth_1.getAuthToken)();
143
+ if (!authToken) {
144
+ throw new Error('No authentication token found. Please log in first.');
145
+ }
146
+ const configuration = new admin_1.Configuration({
147
+ basePath: authToken.serverUrl,
148
+ baseOptions: {
149
+ headers: {
150
+ Authorization: authToken.token,
151
+ },
34
152
  },
35
- },
36
- });
37
- const agentsApi = new admin_1.MachineAgentApi(configuration);
38
- const projectsApi = new admin_1.ProjectsApi(configuration);
153
+ });
154
+ return {
155
+ agentsApi: new admin_1.MachineAgentApi(configuration),
156
+ projectsApi: new admin_1.ProjectsApi(configuration),
157
+ instanceApi: new admin_1.MachineInstancesApi(configuration)
158
+ };
159
+ };
39
160
  // Create the main agent command
40
161
  const agentCommand = program
41
162
  .command("agent")
@@ -48,17 +169,16 @@ function registerAgentCommands(program) {
48
169
  .action((options) => __awaiter(this, void 0, void 0, function* () {
49
170
  var _a, _b;
50
171
  try {
51
- if (!authToken) {
52
- console.error(chalk_1.default.red("No authentication token found. Please login first."));
53
- return;
54
- }
55
- try {
56
- // Use the resolveProject helper to get project information
57
- const projectData = yield (0, project_1.resolveProject)(projectsApi, options);
172
+ let apis = createApis();
173
+ // Execute with token refresh support
174
+ yield (0, error_1.withTokenRefresh)(() => __awaiter(this, void 0, void 0, function* () {
175
+ var _a;
176
+ // Resolve project
177
+ const projectData = yield (0, project_1.resolveProject)(apis.projectsApi, options);
58
178
  const spinner = (0, ora_1.default)(`Listing agents in project ${projectData.name}...`).start();
59
179
  try {
60
- // Now get the agents for the specific project
61
- const agentsResponse = yield agentsApi.machineAgentControllerGetMachineAgentByProjectId(projectData.id, 0, 10, agentType_1.AgentType.REGULAR);
180
+ // Get the agents for the specific project
181
+ const agentsResponse = yield apis.agentsApi.machineAgentControllerGetMachineAgentByProjectId(projectData.id, 0, 10, agentType_1.AgentType.REGULAR);
62
182
  spinner.succeed("Successfully retrieved agents");
63
183
  // Display the results
64
184
  const agents = ((_a = agentsResponse.data) === null || _a === void 0 ? void 0 : _a.machineAgents) || [];
@@ -67,7 +187,7 @@ function registerAgentCommands(program) {
67
187
  return;
68
188
  }
69
189
  console.log(chalk_1.default.blue(`\nAgents in project ${projectData.name}:\n`));
70
- // Create a formatted table focusing on id, name, and URL
190
+ // Create a formatted table
71
191
  const table = new cli_table3_1.default({
72
192
  head: [
73
193
  chalk_1.default.white.bold("ID"),
@@ -75,46 +195,40 @@ function registerAgentCommands(program) {
75
195
  chalk_1.default.white.bold("URL"),
76
196
  ],
77
197
  style: {
78
- head: [], // Disable the default styling
198
+ head: [],
79
199
  border: [],
80
200
  },
81
201
  });
82
- // Add agents to the table with the requested info
202
+ // Add agents to the table
83
203
  agents.forEach((agent) => {
84
- // Format the agent URL
85
204
  let url = "N/A";
86
205
  if (agent.instanceIP) {
87
- // Construct an agent-specific URL if possible
88
206
  url = `${agent.instanceIP}/v1/agents/${agent.modelBaseId}/query`;
89
207
  }
90
- // Format date for readability
91
- let createdAt = agent.createdAt || "N/A";
92
- if (createdAt !== "N/A") {
93
- createdAt = new Date(createdAt).toLocaleString();
94
- }
95
208
  table.push([agent.id || "N/A", agent.agentName || "N/A", url]);
96
209
  });
97
- // Display the table
98
210
  console.log(table.toString());
99
- // Display totals
100
211
  console.log(`\nTotal agents: ${agents.length}`);
101
212
  }
102
213
  catch (error) {
103
214
  spinner.fail("Failed to retrieve agents");
104
- if (error.response) {
105
- console.error(chalk_1.default.red("API Error:"), ((_b = error.response.data) === null || _b === void 0 ? void 0 : _b.message) || "Unknown error");
106
- }
107
- else {
108
- console.error(chalk_1.default.red("Error:"), error.message || "Unknown error");
109
- }
215
+ throw error;
110
216
  }
111
- }
112
- catch (error) {
113
- console.error(chalk_1.default.red("Error:"), error instanceof Error ? error.message : "Unknown error");
114
- }
217
+ }), () => {
218
+ // Recreate APIs after token refresh
219
+ apis = createApis();
220
+ });
115
221
  }
116
222
  catch (error) {
117
- console.error(chalk_1.default.red("Error:"), error instanceof Error ? error.message : "Unknown error");
223
+ if (error.message && error.message.includes('Authentication')) {
224
+ console.error(chalk_1.default.red(error.message));
225
+ }
226
+ else if ((_b = (_a = error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.message) {
227
+ console.error(chalk_1.default.red("API Error:"), error.response.data.message);
228
+ }
229
+ else {
230
+ console.error(chalk_1.default.red("Error:"), error.message || "Unknown error");
231
+ }
118
232
  }
119
233
  }));
120
234
  // Remove agent
@@ -126,168 +240,468 @@ function registerAgentCommands(program) {
126
240
  .action((options) => __awaiter(this, void 0, void 0, function* () {
127
241
  var _a, _b;
128
242
  try {
129
- if (!authToken) {
130
- console.error(chalk_1.default.red("No authentication token found. Please login first."));
131
- return;
132
- }
243
+ let apis = createApis();
133
244
  const { agent } = options;
134
- // Use the resolveProject helper to get project information
135
- const projectData = yield (0, project_1.resolveProject)(projectsApi, options);
136
- const spinner = (0, ora_1.default)(`Finding agent ${agent} in project ${projectData.name}...`).start();
137
- try {
138
- // First, get the list of agents to find the correct modelbaseId
139
- const agentsResponse = yield agentsApi.machineAgentControllerGetMachineAgentByProjectId(projectData.id, 0, 100, agentType_1.AgentType.REGULAR);
140
- // Get the agents array
141
- const agents = ((_a = agentsResponse.data) === null || _a === void 0 ? void 0 : _a.machineAgents) || [];
142
- // Find the specific agent by ID
143
- const targetAgent = agents.find((a) => a.id.toString() === agent.toString());
144
- if (!targetAgent) {
145
- spinner.fail(`Agent with ID ${agent} not found in project ${projectData.name}`);
146
- return;
147
- }
148
- // Extract the modelbaseId from the found agent
149
- const modelbaseId = targetAgent.modelBaseId;
150
- if (!modelbaseId) {
151
- spinner.fail(`Could not find modelbaseId for agent ${agent}. Please try again.`);
152
- return;
153
- }
154
- spinner.text = `Removing agent ${agent} from project ${projectData.name}...`;
155
- // Now remove the agent with the dynamically retrieved modelbaseId
156
- const payload = [
157
- {
158
- id: parseInt(agent, 10),
159
- modelbaseId: modelbaseId,
160
- },
161
- ];
162
- const removeResponse = yield agentsApi.machineAgentControllerDeleteMachineAgents(projectData.id, agent, payload);
163
- spinner.succeed("Successfully removed agent");
164
- // Display the results
165
- console.log(chalk_1.default.green(`Agent ${agent} removed successfully from project ${projectData.name}`));
166
- }
167
- catch (error) {
168
- spinner.fail("Failed to remove agent");
169
- if (error.response) {
170
- console.error(chalk_1.default.red("API Error:"), ((_b = error.response.data) === null || _b === void 0 ? void 0 : _b.message) || "Unknown error");
245
+ yield (0, error_1.withTokenRefresh)(() => __awaiter(this, void 0, void 0, function* () {
246
+ var _a;
247
+ // Resolve project
248
+ const projectData = yield (0, project_1.resolveProject)(apis.projectsApi, options);
249
+ const spinner = (0, ora_1.default)(`Finding agent ${agent} in project ${projectData.name}...`).start();
250
+ try {
251
+ // Get the list of agents to find the correct modelbaseId
252
+ const agentsResponse = yield apis.agentsApi.machineAgentControllerGetMachineAgentByProjectId(projectData.id, 0, 100, agentType_1.AgentType.REGULAR);
253
+ const agents = ((_a = agentsResponse.data) === null || _a === void 0 ? void 0 : _a.machineAgents) || [];
254
+ const targetAgent = agents.find((a) => a.id.toString() === agent.toString());
255
+ if (!targetAgent) {
256
+ spinner.fail(`Agent with ID ${agent} not found in project ${projectData.name}`);
257
+ return;
258
+ }
259
+ const modelbaseId = targetAgent.modelBaseId;
260
+ if (!modelbaseId) {
261
+ spinner.fail(`Could not find modelbaseId for agent ${agent}. Please try again.`);
262
+ return;
263
+ }
264
+ spinner.text = `Removing agent ${agent} from project ${projectData.name}...`;
265
+ // Remove the agent
266
+ const payload = [
267
+ {
268
+ id: parseInt(agent, 10),
269
+ modelbaseId: modelbaseId,
270
+ },
271
+ ];
272
+ yield apis.agentsApi.machineAgentControllerDeleteMachineAgents(projectData.id, agent, payload);
273
+ spinner.succeed("Successfully removed agent");
274
+ console.log(chalk_1.default.green(`Agent ${agent} removed successfully from project ${projectData.name}`));
171
275
  }
172
- else {
173
- console.error(chalk_1.default.red("Error:"), error.message || "Unknown error");
276
+ catch (error) {
277
+ spinner.fail("Failed to remove agent");
278
+ throw error;
174
279
  }
175
- }
280
+ }), () => {
281
+ apis = createApis();
282
+ });
176
283
  }
177
284
  catch (error) {
178
- console.error(chalk_1.default.red("Error:"), error instanceof Error ? error.message : "Unknown error");
285
+ if (error.message && error.message.includes('Authentication')) {
286
+ console.error(chalk_1.default.red(error.message));
287
+ }
288
+ else if ((_b = (_a = error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.message) {
289
+ console.error(chalk_1.default.red("API Error:"), error.response.data.message);
290
+ }
291
+ else {
292
+ console.error(chalk_1.default.red("Error:"), error.message || "Unknown error");
293
+ }
179
294
  }
180
295
  }));
181
296
  agentCommand
182
297
  .command("deploy")
183
298
  .description("Deploy an AI agent to the Nestbox platform")
184
- .requiredOption("--agent <agentId>", "Agent ID to deploy")
185
- .requiredOption("--instance <instanceId>", "Instance ID")
299
+ .option("--agent <agentName>", "Agent name to deploy")
300
+ .option("--chatbot <chatbotName>", "Chatbot name to deploy")
301
+ .requiredOption("--instance <instanceName>", "Instance name")
186
302
  .option("--zip <zipFileOrDirPath>", "Path to the zip file or directory to upload")
187
303
  .option("--project <projectName>", "Project name (defaults to the current project)")
188
304
  .option("--entry <entryFunction>", "Entry function name", "main")
189
305
  .action((options) => __awaiter(this, void 0, void 0, function* () {
190
- var _a, _b, _c, _d, _e, _f;
306
+ var _a;
191
307
  try {
192
- if (!authToken) {
193
- console.error(chalk_1.default.red("No authentication token found. Please login first."));
308
+ const { agent: agentName, chatbot: chatbotName, instance: instanceName, zip: customZipPath, entry, } = options;
309
+ // Ensure either agent or chatbot is provided, but not both
310
+ if ((!agentName && !chatbotName) || (agentName && chatbotName)) {
311
+ console.error(chalk_1.default.red("Please provide either --agent OR --chatbot option, but not both."));
194
312
  return;
195
313
  }
196
- const { agent: agentId, instance: instanceId, zip: customZipPath, entry, } = options;
197
- // Find project root (CLI tools directory)
314
+ let apis = createApis();
315
+ // Find project root
198
316
  const projectRoot = yield (0, agent_1.findProjectRoot)();
199
317
  console.log(chalk_1.default.blue(`Project root detected at: ${projectRoot}`));
200
- // Use the resolveProject helper to get project information
201
- const projectData = yield (0, project_1.resolveProject)(projectsApi, options);
202
- // Load nestbox.config.json from CLI tools directory
203
- const config = (0, agent_1.loadNestboxConfig)(projectRoot);
204
- // Start the deployment process
205
- const spinner = (0, ora_1.default)(`Preparing to deploy agent ${agentId} to instance ${instanceId}...`).start();
206
- try {
207
- // Determine the source path (custom path or project root)
208
- const sourcePath = customZipPath || projectRoot;
209
- let zipFilePath;
210
- // Check if the specified path exists
211
- if (!fs_1.default.existsSync(sourcePath)) {
212
- spinner.fail(`Path not found: ${sourcePath}`);
318
+ // Main deployment logic with token refresh
319
+ yield (0, error_1.withTokenRefresh)(() => __awaiter(this, void 0, void 0, function* () {
320
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
321
+ // Resolve project
322
+ const projectData = yield (0, project_1.resolveProject)(apis.projectsApi, options);
323
+ // Determine if we're deploying an agent or chatbot
324
+ const isAgent = !!agentName;
325
+ const resourceName = isAgent ? agentName : chatbotName;
326
+ const resourceType = isAgent ? "Agent" : "Chatbot";
327
+ const agentType = isAgent ? agentType_1.AgentType.REGULAR : "CHAT";
328
+ // Get agents data and find agent/chatbot by name
329
+ const agentsData = yield apis.agentsApi.machineAgentControllerGetMachineAgentByProjectId(projectData.id, 0, 10, agentType);
330
+ const targetAgent = agentsData.data.machineAgents.find((agent) => agent.agentName === resourceName);
331
+ if (!targetAgent) {
332
+ console.error(chalk_1.default.red(`${resourceType} with name "${resourceName}" not found in project "${projectData.name}".`));
333
+ console.log(chalk_1.default.yellow(`Available ${resourceType.toLowerCase()}s:`));
334
+ agentsData.data.machineAgents.forEach((agent) => {
335
+ console.log(chalk_1.default.yellow(` - ${agent.agentName} (ID: ${agent.id})`));
336
+ });
213
337
  return;
214
338
  }
215
- // Check if the path is a zip file or directory
216
- const stats = fs_1.default.statSync(sourcePath);
217
- if (stats.isFile()) {
218
- // Case 1: It's a file - verify it's a zip and use directly
219
- if (!sourcePath.toLowerCase().endsWith(".zip")) {
220
- spinner.fail(`File is not a zip archive: ${sourcePath}`);
221
- return;
222
- }
223
- // Use the zip file directly
224
- spinner.text = `Using provided zip file: ${sourcePath}`;
225
- zipFilePath = sourcePath;
339
+ // Get instance data and find instance by name
340
+ const instanceData = yield apis.instanceApi.machineInstancesControllerGetMachineInstanceByUserId(projectData.id, 0, 10);
341
+ const targetInstance = instanceData.data.machineInstances.find((instance) => instance.instanceName === instanceName);
342
+ if (!targetInstance) {
343
+ console.error(chalk_1.default.red(`Instance with name "${instanceName}" not found in project "${projectData.name}".`));
344
+ console.log(chalk_1.default.yellow("Available instances:"));
345
+ instanceData.data.machineInstances.forEach((instance) => {
346
+ console.log(chalk_1.default.yellow(` - ${instance.instanceName} (ID: ${instance.id})`));
347
+ });
348
+ return;
226
349
  }
227
- else if (stats.isDirectory()) {
228
- // Case 2: It's a directory - check for predeploy scripts in CLI config
229
- // Determine if it's a TypeScript project
230
- const isTypeScript = (0, agent_1.isTypeScriptProject)(sourcePath);
231
- if (isTypeScript) {
232
- spinner.text = `TypeScript project detected. Checking for predeploy scripts...`;
233
- // Run predeploy scripts if defined in CLI tools config
234
- if (((_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)) {
235
- 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);
236
- spinner.text = `Running predeploy scripts on target directory...`;
237
- yield (0, agent_1.runPredeployScripts)(predeployScripts, sourcePath);
350
+ // Extract IDs
351
+ const agentId = targetAgent.id;
352
+ const instanceId = targetInstance.id;
353
+ // Load nestbox.config.json
354
+ const config = (0, agent_1.loadNestboxConfig)(projectRoot);
355
+ // Start the deployment process
356
+ const spinner = (0, ora_1.default)(`Preparing to deploy ${resourceType.toLowerCase()} ${agentId} to instance ${instanceId}...`).start();
357
+ try {
358
+ let zipFilePath;
359
+ if (customZipPath) {
360
+ // Process custom zip path
361
+ if (!fs_1.default.existsSync(customZipPath)) {
362
+ spinner.fail(`Path not found: ${customZipPath}`);
363
+ return;
238
364
  }
239
- else {
240
- spinner.info("No predeploy scripts found in CLI tools nestbox.config.json");
365
+ const stats = fs_1.default.statSync(customZipPath);
366
+ if (stats.isFile()) {
367
+ if (!customZipPath.toLowerCase().endsWith(".zip")) {
368
+ spinner.fail(`File is not a zip archive: ${customZipPath}`);
369
+ return;
370
+ }
371
+ spinner.text = `Using provided zip file: ${customZipPath}`;
372
+ zipFilePath = customZipPath;
373
+ }
374
+ else if (stats.isDirectory()) {
375
+ // Process directory
376
+ spinner.text = `Processing directory: ${customZipPath}`;
377
+ const isTypeScript = (0, agent_1.isTypeScriptProject)(customZipPath);
378
+ 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))) {
379
+ 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);
380
+ spinner.text = `Running predeploy scripts on target directory...`;
381
+ yield (0, agent_1.runPredeployScripts)(predeployScripts, customZipPath);
382
+ }
383
+ spinner.text = `Creating zip archive from directory ${customZipPath}...`;
384
+ zipFilePath = (0, agent_1.createZipFromDirectory)(customZipPath);
385
+ spinner.text = `Directory zipped successfully to ${zipFilePath}`;
241
386
  }
242
387
  }
243
388
  else {
244
- // JavaScript directory - just zip it
245
- spinner.text = `JavaScript project detected. Skipping predeploy scripts.`;
389
+ // Use project root
390
+ spinner.text = `Using project root: ${projectRoot}`;
391
+ const isTypeScript = (0, agent_1.isTypeScriptProject)(projectRoot);
392
+ if (isTypeScript && (((_e = config === null || config === void 0 ? void 0 : config.agent) === null || _e === void 0 ? void 0 : _e.predeploy) || ((_f = config === null || config === void 0 ? void 0 : config.agents) === null || _f === void 0 ? void 0 : _f.predeploy))) {
393
+ const predeployScripts = ((_g = config === null || config === void 0 ? void 0 : config.agent) === null || _g === void 0 ? void 0 : _g.predeploy) || ((_h = config === null || config === void 0 ? void 0 : config.agents) === null || _h === void 0 ? void 0 : _h.predeploy);
394
+ spinner.text = `Running predeploy scripts on project root...`;
395
+ yield (0, agent_1.runPredeployScripts)(predeployScripts, projectRoot);
396
+ }
397
+ spinner.text = `Creating zip archive from project root ${projectRoot}...`;
398
+ zipFilePath = (0, agent_1.createZipFromDirectory)(projectRoot);
399
+ spinner.text = `Directory zipped successfully to ${zipFilePath}`;
246
400
  }
247
- // Create zip archive with node_modules excluded
248
- spinner.text = `Creating zip archive from directory ${sourcePath}...`;
249
- zipFilePath = (0, agent_1.createZipFromDirectory)(sourcePath);
250
- spinner.text = `Directory zipped successfully to ${zipFilePath}`;
401
+ spinner.text = `Deploying ${resourceType.toLowerCase()} ${agentId} to instance ${instanceId}...`;
402
+ // Prepare deployment
403
+ const authToken = (0, auth_1.getAuthToken)();
404
+ const baseUrl = ((_j = authToken === null || authToken === void 0 ? void 0 : authToken.serverUrl) === null || _j === void 0 ? void 0 : _j.endsWith("/"))
405
+ ? authToken.serverUrl.slice(0, -1)
406
+ : authToken === null || authToken === void 0 ? void 0 : authToken.serverUrl;
407
+ const { default: FormData } = yield Promise.resolve().then(() => __importStar(require("form-data")));
408
+ const form = new FormData();
409
+ form.append("file", fs_1.default.createReadStream(zipFilePath));
410
+ form.append("machineAgentId", agentId.toString());
411
+ form.append("instanceId", instanceId.toString());
412
+ form.append("entryFunctionName", entry);
413
+ form.append("isSourceCodeUpdate", "true");
414
+ form.append("projectId", projectData.id);
415
+ const axiosInstance = axios_1.default.create({
416
+ baseURL: baseUrl,
417
+ headers: Object.assign(Object.assign({}, form.getHeaders()), { Authorization: authToken === null || authToken === void 0 ? void 0 : authToken.token }),
418
+ });
419
+ const endpoint = `/projects/${projectData.id}/agents/${agentId}`;
420
+ console.log(chalk_1.default.blue("\nMaking API request:"));
421
+ console.log(chalk_1.default.blue(` URL: ${baseUrl}${endpoint}`));
422
+ console.log(chalk_1.default.blue(` Method: PATCH`));
423
+ console.log(chalk_1.default.blue(` File: ${path_1.default.basename(zipFilePath)}`));
424
+ spinner.text = `Sending API request to deploy ${resourceType.toLowerCase()}...`;
425
+ const res = yield axiosInstance.patch(endpoint, form);
426
+ console.log(chalk_1.default.green("\nAPI Response received:"));
427
+ console.log(chalk_1.default.green(` Status: ${res.status} ${res.statusText}`));
428
+ if (!customZipPath && zipFilePath && fs_1.default.existsSync(zipFilePath)) {
429
+ fs_1.default.unlinkSync(zipFilePath);
430
+ }
431
+ spinner.succeed(`Successfully deployed ${resourceType.toLowerCase()} ${agentId} to instance ${instanceId}`);
432
+ console.log(chalk_1.default.green(`${resourceType} deployed successfully`));
251
433
  }
252
- else {
253
- spinner.fail(`Unsupported file type: ${sourcePath}`);
434
+ catch (error) {
435
+ spinner.fail(`Failed to deploy ${resourceType.toLowerCase()}`);
436
+ throw error;
437
+ }
438
+ }), () => {
439
+ apis = createApis();
440
+ });
441
+ }
442
+ catch (error) {
443
+ if (error.message && error.message.includes('Authentication')) {
444
+ console.error(chalk_1.default.red(error.message));
445
+ }
446
+ else if (error.response) {
447
+ 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"}`));
448
+ if (error.response.data) {
449
+ console.error(chalk_1.default.red(`Error Data: ${JSON.stringify(error.response.data, null, 2)}`));
450
+ }
451
+ }
452
+ else {
453
+ console.error(chalk_1.default.red("Error:"), error.message || "Unknown error");
454
+ }
455
+ }
456
+ }));
457
+ agentCommand
458
+ .command("generate <folder>")
459
+ .description("Generate a new project from templates")
460
+ .option("--lang <language>", "Project language (ts|js)")
461
+ .option("--template <type>", "Template type (agent|chatbot)")
462
+ .option("--project <projectId>", "Project ID")
463
+ .action((folder, options) => __awaiter(this, void 0, void 0, function* () {
464
+ try {
465
+ const spinner = (0, ora_1.default)("Initializing project generation...").start();
466
+ // Ensure target folder doesn't exist
467
+ if (fs_1.default.existsSync(folder)) {
468
+ spinner.fail(`Folder ${folder} already exists`);
469
+ return;
470
+ }
471
+ let selectedLang = options.lang;
472
+ let selectedTemplate = options.template;
473
+ // Interactive selection if not provided
474
+ if (!selectedLang || !selectedTemplate) {
475
+ spinner.stop();
476
+ const answers = yield inquirer_1.default.prompt([
477
+ {
478
+ type: 'list',
479
+ name: 'lang',
480
+ message: 'Select project language:',
481
+ choices: [
482
+ { name: 'TypeScript', value: 'ts' },
483
+ { name: 'JavaScript', value: 'js' }
484
+ ],
485
+ when: () => !selectedLang
486
+ },
487
+ {
488
+ type: 'list',
489
+ name: 'template',
490
+ message: 'Select template type:',
491
+ choices: [
492
+ { name: 'Agent', value: 'agent' },
493
+ { name: 'Chatbot', value: 'chatbot' }
494
+ ],
495
+ when: () => !selectedTemplate
496
+ }
497
+ ]);
498
+ selectedLang = selectedLang || answers.lang;
499
+ selectedTemplate = selectedTemplate || answers.template;
500
+ spinner.start("Generating project...");
501
+ }
502
+ // Find matching template in local templates folder
503
+ const templateMapping = {
504
+ 'agent': 'base',
505
+ 'chatbot': 'chatbot'
506
+ };
507
+ const mappedTemplateType = templateMapping[selectedTemplate] || selectedTemplate;
508
+ const templateKey = `template-${mappedTemplateType}-${selectedLang}.zip`;
509
+ // Try process.cwd() first, then __dirname fallback
510
+ let templatePath = path_1.default.resolve(process.cwd(), 'templates', templateKey);
511
+ if (!fs_1.default.existsSync(templatePath)) {
512
+ // fallback to __dirname
513
+ templatePath = path_1.default.resolve(__dirname, '../../templates', templateKey);
514
+ }
515
+ if (!fs_1.default.existsSync(templatePath)) {
516
+ spinner.fail(`Template not found: ${templatePath}`);
517
+ // Show available templates in both locations
518
+ const cwdTemplates = path_1.default.resolve(process.cwd(), 'templates');
519
+ const dirTemplates = path_1.default.resolve(__dirname, '../../templates');
520
+ let shown = false;
521
+ if (fs_1.default.existsSync(cwdTemplates)) {
522
+ console.log(chalk_1.default.yellow('Available templates in ./templates:'));
523
+ fs_1.default.readdirSync(cwdTemplates).forEach(file => {
524
+ console.log(chalk_1.default.yellow(` - ${file}`));
525
+ });
526
+ shown = true;
527
+ }
528
+ if (fs_1.default.existsSync(dirTemplates)) {
529
+ console.log(chalk_1.default.yellow('Available templates in src/commands/../../templates:'));
530
+ fs_1.default.readdirSync(dirTemplates).forEach(file => {
531
+ console.log(chalk_1.default.yellow(` - ${file}`));
532
+ });
533
+ shown = true;
534
+ }
535
+ if (!shown) {
536
+ console.log(chalk_1.default.red('No templates directory found. Please add your templates.'));
537
+ }
538
+ return;
539
+ }
540
+ spinner.text = `Extracting template to ${folder}...`;
541
+ try {
542
+ // Extract template to target folder
543
+ (0, agent_1.extractZip)(templatePath, folder);
544
+ // Create nestbox.config.json for TypeScript projects
545
+ (0, agent_1.createNestboxConfig)(folder, selectedLang === 'ts');
546
+ // Update package.json with project name if it exists
547
+ const packageJsonPath = path_1.default.join(folder, 'package.json');
548
+ if (fs_1.default.existsSync(packageJsonPath)) {
549
+ const packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath, 'utf8'));
550
+ packageJson.name = path_1.default.basename(folder);
551
+ fs_1.default.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
552
+ }
553
+ spinner.succeed(`Successfully generated ${mappedTemplateType} project in ${folder}`);
554
+ console.log(chalk_1.default.green("\nNext steps:"));
555
+ console.log(chalk_1.default.yellow(` cd ${folder}`));
556
+ console.log(chalk_1.default.yellow(" npm install"));
557
+ if (selectedLang === 'ts') {
558
+ console.log(chalk_1.default.yellow(" npm run build"));
559
+ }
560
+ console.log(chalk_1.default.yellow(" nestbox agent deploy --agent <agent-name> --instance <instance-name>"));
561
+ }
562
+ catch (error) {
563
+ // Clean up on error
564
+ if (fs_1.default.existsSync(folder)) {
565
+ fs_1.default.rmSync(folder, { recursive: true, force: true });
566
+ }
567
+ throw error;
568
+ }
569
+ }
570
+ catch (error) {
571
+ console.error(chalk_1.default.red("Error:"), error.message || "Failed to generate project");
572
+ }
573
+ }));
574
+ // Command for creating agents from YAML files
575
+ agentCommand
576
+ .command("create [firstArg] [secondArg]")
577
+ .description("Create multiple agents from a YAML configuration file")
578
+ .option("--project <projectId>", "Project ID (defaults to the current project)")
579
+ .action((firstArg, secondArg, options) => __awaiter(this, void 0, void 0, function* () {
580
+ try {
581
+ let apis = createApis();
582
+ // Determine which argument is the YAML file path
583
+ let yamlFilePath;
584
+ if (firstArg === 'file' && secondArg) {
585
+ yamlFilePath = secondArg;
586
+ }
587
+ else if (firstArg) {
588
+ yamlFilePath = firstArg;
589
+ if (typeof secondArg === 'object' && !options) {
590
+ options = secondArg;
591
+ }
592
+ }
593
+ else {
594
+ console.error(chalk_1.default.red("Missing YAML file path. Usage: nestbox agent create <yamlFile> OR nestbox agent create file <yamlFile>"));
595
+ return;
596
+ }
597
+ // Check if file exists
598
+ if (!fs_1.default.existsSync(yamlFilePath)) {
599
+ console.error(chalk_1.default.red(`YAML file not found: ${yamlFilePath}`));
600
+ return;
601
+ }
602
+ // Read and parse the YAML file
603
+ const spinner = (0, ora_1.default)(`Reading agents configuration from ${yamlFilePath}...`).start();
604
+ try {
605
+ const fileContents = fs_1.default.readFileSync(yamlFilePath, 'utf8');
606
+ const config = js_yaml_1.default.load(fileContents);
607
+ if (!config || !config.agents || !Array.isArray(config.agents)) {
608
+ spinner.fail("Invalid YAML configuration: Missing 'agents' array");
609
+ console.error(chalk_1.default.red("The YAML file should contain an 'agents' array with agent configurations"));
254
610
  return;
255
611
  }
256
- spinner.text = `Deploying agent ${agentId} to instance ${instanceId}...`;
257
- // Clean the base URL to avoid path duplication
258
- const baseUrl = ((_e = authToken === null || authToken === void 0 ? void 0 : authToken.serverUrl) === null || _e === void 0 ? void 0 : _e.endsWith("/"))
259
- ? authToken.serverUrl.slice(0, -1)
260
- : authToken === null || authToken === void 0 ? void 0 : authToken.serverUrl;
261
- const FormData = require("form-data");
262
- const form = new FormData();
263
- // Add file as a readable stream
264
- form.append("file", fs_1.default.createReadStream(zipFilePath));
265
- // Add all the required fields
266
- form.append("machineAgentId", agentId.toString());
267
- form.append("instanceId", instanceId.toString());
268
- form.append("entryFunctionName", entry);
269
- form.append("isSourceCodeUpdate", "true");
270
- form.append("projectId", projectData.id);
271
- // Create a custom axios instance with form-data headers
272
- const axiosInstance = axios_1.default.create({
273
- baseURL: baseUrl,
274
- headers: Object.assign(Object.assign({}, form.getHeaders()), { Authorization: authToken === null || authToken === void 0 ? void 0 : authToken.token }),
275
- });
276
- // Construct the endpoint URL
277
- const endpoint = `/projects/${projectData.id}/agents/${agentId}`;
278
- // Make direct axios request
279
- yield axiosInstance.patch(endpoint, form);
280
- // Clean up temporary zip file if we created one
281
- if (zipFilePath !== sourcePath && fs_1.default.existsSync(zipFilePath)) {
282
- fs_1.default.unlinkSync(zipFilePath);
612
+ spinner.succeed(`Found ${config.agents.length} agents in configuration file`);
613
+ // Process each agent with token refresh support
614
+ const results = {
615
+ success: 0,
616
+ failed: 0,
617
+ agents: []
618
+ };
619
+ // Get user data once
620
+ const user = yield (0, user_1.userData)();
621
+ for (const agent of config.agents) {
622
+ if (!agent.name) {
623
+ console.log(chalk_1.default.yellow("Skipping agent with no name defined"));
624
+ results.failed++;
625
+ results.agents.push({
626
+ name: "unnamed",
627
+ success: false,
628
+ message: "Name is required"
629
+ });
630
+ continue;
631
+ }
632
+ let agentType = agent.type || "CHAT";
633
+ const resourceType = agentType === "AGENT" ? "Agent" : "Chatbot";
634
+ const agentSpinner = (0, ora_1.default)(`Creating ${resourceType.toLowerCase()} '${agent.name}'...`).start();
635
+ try {
636
+ // Create agent with token refresh support
637
+ yield (0, error_1.withTokenRefresh)(() => __awaiter(this, void 0, void 0, function* () {
638
+ // Map YAML config to createAgent options
639
+ const createOptions = Object.assign(Object.assign({}, options), { goal: agent.goal || "No goal specified", modelBaseId: agent.modelBaseId || "", instanceIP: agent.instanceIP || "localhost", machineInstanceId: agent.machineInstanceId || 1, machineManifestId: agent.machineManifestId || "default", machineName: agent.machineName || `agent-${agent.name.toLowerCase()}`, type: agentType, userId: user.id, parameters: agent.parameters ? agent.parameters.map((p) => {
640
+ return {
641
+ name: p.name || "unnamed",
642
+ description: p.description || "",
643
+ default: p.default || "",
644
+ isUserParam: p.isUserParam !== undefined ? p.isUserParam : true
645
+ };
646
+ }) : [] });
647
+ yield createAgent(agent.name, createOptions, apis.agentsApi, apis.projectsApi);
648
+ }), () => {
649
+ apis = createApis();
650
+ });
651
+ agentSpinner.stop();
652
+ results.success++;
653
+ results.agents.push({
654
+ name: agent.name,
655
+ success: true,
656
+ message: `Created successfully`
657
+ });
658
+ }
659
+ catch (error) {
660
+ agentSpinner.fail(`Failed to create ${resourceType.toLowerCase()} '${agent.name}'`);
661
+ console.error(chalk_1.default.red(`Error: ${error.message}`));
662
+ results.failed++;
663
+ results.agents.push({
664
+ name: agent.name,
665
+ success: false,
666
+ message: error.message
667
+ });
668
+ }
283
669
  }
284
- spinner.succeed(`Successfully deployed agent ${agentId} to instance ${instanceId}`);
285
- console.log(chalk_1.default.green("Agent deployed successfully"));
670
+ // Final summary
671
+ console.log(chalk_1.default.blue("\nResource creation summary:"));
672
+ const table = new cli_table3_1.default({
673
+ head: [
674
+ chalk_1.default.white.bold("Name"),
675
+ chalk_1.default.white.bold("Type"),
676
+ chalk_1.default.white.bold("Status"),
677
+ chalk_1.default.white.bold("Message"),
678
+ ],
679
+ style: {
680
+ head: [],
681
+ border: [],
682
+ },
683
+ });
684
+ results.agents.forEach((agent, index) => {
685
+ const agentConfig = config.agents.find(a => a.name === agent.name) || config.agents[index];
686
+ const agentType = (agentConfig === null || agentConfig === void 0 ? void 0 : agentConfig.type) || "CHAT";
687
+ const resourceType = agentType === "AGENT" ? "Agent" : "Chatbot";
688
+ table.push([
689
+ agent.name,
690
+ resourceType,
691
+ agent.success ? chalk_1.default.green("Success") : chalk_1.default.red("Failed"),
692
+ agent.message
693
+ ]);
694
+ });
695
+ console.log(table.toString());
696
+ console.log(`\nTotal: ${results.success + results.failed}, Successful: ${results.success}, Failed: ${results.failed}`);
286
697
  }
287
698
  catch (error) {
288
- spinner.fail("Failed to deploy agent");
289
- if (error.response) {
290
- console.error(chalk_1.default.red(`API Error (${error.response.status}): ${((_f = error.response.data) === null || _f === void 0 ? void 0 : _f.message) || "Unknown error"}`));
699
+ spinner.fail("Failed to process YAML file");
700
+ if (error.code === 'ENOENT') {
701
+ console.error(chalk_1.default.red(`File not found: ${yamlFilePath}`));
702
+ }
703
+ else if (error.name === 'YAMLException') {
704
+ console.error(chalk_1.default.red(`Invalid YAML format: ${error.message}`));
291
705
  }
292
706
  else {
293
707
  console.error(chalk_1.default.red("Error:"), error.message || "Unknown error");
@@ -295,7 +709,12 @@ function registerAgentCommands(program) {
295
709
  }
296
710
  }
297
711
  catch (error) {
298
- console.error(chalk_1.default.red("Error:"), error instanceof Error ? error.message : "Unknown error");
712
+ if (error.message && error.message.includes('Authentication')) {
713
+ console.error(chalk_1.default.red(error.message));
714
+ }
715
+ else {
716
+ console.error(chalk_1.default.red("Error:"), error instanceof Error ? error.message : "Unknown error");
717
+ }
299
718
  }
300
719
  }));
301
720
  }