@nestbox-ai/cli 1.0.48 → 1.0.49

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 (100) hide show
  1. package/package.json +7 -1
  2. package/.github/workflows/generate-client.yml +0 -43
  3. package/.github/workflows/test.yml +0 -54
  4. package/.nestboxrc +0 -5
  5. package/src/commands/agent/apiUtils.ts +0 -113
  6. package/src/commands/agent/create.ts +0 -271
  7. package/src/commands/agent/deploy.ts +0 -523
  8. package/src/commands/agent/index.ts +0 -8
  9. package/src/commands/agent/list.ts +0 -104
  10. package/src/commands/agent/remove.ts +0 -103
  11. package/src/commands/agent/yaml-schema.ts +0 -57
  12. package/src/commands/agent.ts +0 -21
  13. package/src/commands/auth/index.ts +0 -3
  14. package/src/commands/auth/login.ts +0 -184
  15. package/src/commands/auth/logout.ts +0 -110
  16. package/src/commands/auth.ts +0 -12
  17. package/src/commands/compute/apiUtils.ts +0 -28
  18. package/src/commands/compute/create.ts +0 -195
  19. package/src/commands/compute/delete.ts +0 -147
  20. package/src/commands/compute/index.ts +0 -7
  21. package/src/commands/compute/list.ts +0 -117
  22. package/src/commands/compute.ts +0 -19
  23. package/src/commands/document/apiUtils.ts +0 -22
  24. package/src/commands/document/collectionCreate.ts +0 -46
  25. package/src/commands/document/collectionDelete.ts +0 -45
  26. package/src/commands/document/collectionGet.ts +0 -47
  27. package/src/commands/document/collectionList.ts +0 -52
  28. package/src/commands/document/collectionUpdate.ts +0 -53
  29. package/src/commands/document/docAdd.ts +0 -56
  30. package/src/commands/document/docDelete.ts +0 -47
  31. package/src/commands/document/docGet.ts +0 -49
  32. package/src/commands/document/docSearch.ts +0 -70
  33. package/src/commands/document/docUpdate.ts +0 -56
  34. package/src/commands/document/docUploadFile.ts +0 -55
  35. package/src/commands/document/index.ts +0 -17
  36. package/src/commands/document.ts +0 -48
  37. package/src/commands/generate/project.ts +0 -199
  38. package/src/commands/generate.ts +0 -15
  39. package/src/commands/image/apiUtils.ts +0 -22
  40. package/src/commands/image/display.ts +0 -34
  41. package/src/commands/image/index.ts +0 -4
  42. package/src/commands/image/list.ts +0 -61
  43. package/src/commands/image.ts +0 -15
  44. package/src/commands/project/add.ts +0 -47
  45. package/src/commands/project/apiUtils.ts +0 -20
  46. package/src/commands/project/index.ts +0 -5
  47. package/src/commands/project/list.ts +0 -78
  48. package/src/commands/project/use.ts +0 -45
  49. package/src/commands/project.ts +0 -19
  50. package/src/index.ts +0 -39
  51. package/src/types/agentType.ts +0 -7
  52. package/src/types/agentYaml.ts +0 -107
  53. package/src/types/auth.ts +0 -12
  54. package/src/types/statusMapping.ts +0 -8
  55. package/src/utils/agent.ts +0 -170
  56. package/src/utils/api.ts +0 -64
  57. package/src/utils/auth.ts +0 -140
  58. package/src/utils/config.ts +0 -37
  59. package/src/utils/error.ts +0 -168
  60. package/src/utils/plopGenerator.ts +0 -133
  61. package/src/utils/project.ts +0 -88
  62. package/src/utils/user.ts +0 -28
  63. package/src/utils/validation.ts +0 -22
  64. package/templates/base-js/index.js.hbs +0 -30
  65. package/templates/base-js/nestbox-agents.yaml.hbs +0 -12
  66. package/templates/base-js/package.json +0 -15
  67. package/templates/base-py/main.py.hbs +0 -42
  68. package/templates/base-py/nestbox-agents.yaml.hbs +0 -12
  69. package/templates/base-py/pyproject.toml +0 -19
  70. package/templates/base-ts/eslint.config.mjs +0 -27
  71. package/templates/base-ts/nestbox-agents.yaml.hbs +0 -12
  72. package/templates/base-ts/nestbox.config.json +0 -9
  73. package/templates/base-ts/package.json +0 -24
  74. package/templates/base-ts/src/index.ts.hbs +0 -29
  75. package/templates/base-ts/tsconfig.json +0 -14
  76. package/templates/chatbot-js/index.js.hbs +0 -18
  77. package/templates/chatbot-js/package-lock.json +0 -1571
  78. package/templates/chatbot-js/package.json +0 -15
  79. package/templates/chatbot-py/main.py.hbs +0 -42
  80. package/templates/chatbot-py/nestbox-agents.yaml.hbs +0 -12
  81. package/templates/chatbot-py/pyproject.toml +0 -19
  82. package/templates/chatbot-ts/eslint.config.mjs +0 -27
  83. package/templates/chatbot-ts/package.json +0 -24
  84. package/templates/chatbot-ts/src/index.ts.hbs +0 -18
  85. package/templates/chatbot-ts/tsconfig.json +0 -14
  86. package/test/README.md +0 -52
  87. package/test/agent.test.ts +0 -154
  88. package/test/auth.test.ts +0 -71
  89. package/test/compute.test.ts +0 -135
  90. package/test/document.test.ts +0 -217
  91. package/test/generate.test.ts +0 -67
  92. package/test/image.test.ts +0 -107
  93. package/test/mocks.ts +0 -122
  94. package/test/project.test.ts +0 -108
  95. package/test/setup.ts +0 -121
  96. package/tsconfig.json +0 -118
  97. package/vitest.config.d.ts +0 -2
  98. package/vitest.config.js +0 -23
  99. package/vitest.config.js.map +0 -1
  100. package/vitest.config.ts +0 -21
@@ -1,103 +0,0 @@
1
- import { Command } from "commander";
2
- import { withTokenRefresh } from "../../utils/error";
3
- import chalk from "chalk";
4
- import ora from "ora";
5
- import { resolveProject } from "../../utils/project";
6
- import { AgentType } from "../../types/agentType";
7
- import { createApis } from "./apiUtils";
8
-
9
- export function registerRemoveCommand(agentCommand: Command): void {
10
- agentCommand
11
- .command("remove")
12
- .description("Remove an AI agent")
13
- .requiredOption("--agent <agentId>", "Agent ID to remove")
14
- .option(
15
- "--project <projectName>",
16
- "Project name (defaults to the current project)"
17
- )
18
- .action(async (options) => {
19
- try {
20
- let apis = createApis();
21
- const { agent } = options;
22
-
23
- await withTokenRefresh(
24
- async () => {
25
- // Resolve project
26
- const projectData = await resolveProject(apis.projectsApi, options);
27
-
28
- const spinner = ora(
29
- `Finding agent ${agent} in project ${projectData.name}...`
30
- ).start();
31
-
32
- try {
33
- // Get the list of agents to find the correct modelbaseId
34
- const agentsResponse: any =
35
- await apis.agentsApi.machineAgentControllerGetMachineAgentByProjectId(
36
- projectData.id,
37
- 0,
38
- 100,
39
- AgentType.REGULAR
40
- );
41
-
42
- const agents = agentsResponse.data?.machineAgents || [];
43
- const targetAgent = agents.find(
44
- (a: any) => a.id.toString() === agent.toString()
45
- );
46
-
47
- if (!targetAgent) {
48
- spinner.fail(
49
- `Agent with ID ${agent} not found in project ${projectData.name}`
50
- );
51
- return;
52
- }
53
-
54
- const modelbaseId = targetAgent.modelBaseId;
55
- if (!modelbaseId) {
56
- spinner.fail(
57
- `Could not find modelbaseId for agent ${agent}. Please try again.`
58
- );
59
- return;
60
- }
61
-
62
- spinner.text = `Removing agent ${agent} from project ${projectData.name}...`;
63
-
64
- // Remove the agent
65
- const payload: any = [
66
- {
67
- id: parseInt(agent, 10),
68
- modelbaseId: modelbaseId,
69
- },
70
- ];
71
-
72
- await apis.agentsApi.machineAgentControllerDeleteMachineAgents(
73
- projectData.id,
74
- agent,
75
- payload
76
- );
77
-
78
- spinner.succeed("Successfully removed agent");
79
- console.log(
80
- chalk.green(
81
- `Agent ${agent} removed successfully from project ${projectData.name}`
82
- )
83
- );
84
- } catch (error: any) {
85
- spinner.fail("Failed to remove agent");
86
- throw error;
87
- }
88
- },
89
- () => {
90
- apis = createApis();
91
- }
92
- );
93
- } catch (error: any) {
94
- if (error.message && error.message.includes('Authentication')) {
95
- console.error(chalk.red(error.message));
96
- } else if (error.response?.data?.message) {
97
- console.error(chalk.red("API Error:"), error.response.data.message);
98
- } else {
99
- console.error(chalk.red("Error:"), error.message || "Unknown error");
100
- }
101
- }
102
- });
103
- }
@@ -1,57 +0,0 @@
1
- export const yamlSchema = {
2
- type: "object",
3
- properties: {
4
- agents: {
5
- type: "array",
6
- items: {
7
- type: "object",
8
- properties: {
9
- name: { type: "string", minLength: 1 },
10
- description: { type: "string", minLength: 1 },
11
- entry: { type: "string", minLength: 1 },
12
- type: {
13
- type: "string",
14
- enum: ["REGULAR", "CHATBOT", "WORKFLOW"],
15
- },
16
- inputSchema: {
17
- type: "object",
18
- properties: {
19
- type: { type: "string", const: "object" },
20
- properties: {
21
- type: "object",
22
- additionalProperties: {
23
- type: "object",
24
- properties: {
25
- type: { type: "string", minLength: 1 },
26
- description: { type: "string" },
27
- default: {
28
- type: [
29
- "string",
30
- "number",
31
- "boolean",
32
- "null",
33
- ],
34
- },
35
- },
36
- required: ["type"],
37
- additionalProperties: true,
38
- },
39
- },
40
- required: {
41
- type: "array",
42
- items: { type: "string", minLength: 1 },
43
- uniqueItems: true,
44
- },
45
- },
46
- required: ["type", "properties"],
47
- additionalProperties: true,
48
- },
49
- },
50
- required: ["name", "description", "entry", "inputSchema"],
51
- additionalProperties: true,
52
- },
53
- },
54
- },
55
- required: ["agents"],
56
- additionalProperties: true,
57
- } as const;
@@ -1,21 +0,0 @@
1
- import { Command } from "commander";
2
- import { registerListCommand } from "./agent/list";
3
- import { registerRemoveCommand } from "./agent/remove";
4
- import { registerDeployCommand } from "./agent/deploy";
5
- import { registerCreateCommand } from "./agent/create";
6
-
7
- /**
8
- * Register all agent-related commands
9
- */
10
- export function registerAgentCommands(program: Command): void {
11
- // Create the main agent command
12
- const agentCommand = program
13
- .command("agent")
14
- .description("Manage Nestbox agents");
15
-
16
- // Register all subcommands
17
- registerListCommand(agentCommand);
18
- registerRemoveCommand(agentCommand);
19
- registerDeployCommand(agentCommand);
20
- registerCreateCommand(agentCommand);
21
- }
@@ -1,3 +0,0 @@
1
- // Auth command exports
2
- export { registerLoginCommand } from "./login";
3
- export { registerLogoutCommand } from "./logout";
@@ -1,184 +0,0 @@
1
- import { Command } from 'commander';
2
- import chalk from 'chalk';
3
- import inquirer from 'inquirer';
4
- import open from 'open';
5
- import ora from 'ora';
6
- import fs from 'fs';
7
- import os from 'os';
8
- import path from 'path';
9
- import { AuthApi, Configuration, OAuthLoginRequestDTOTypeEnum } from '@nestbox-ai/admin';
10
- import axios from 'axios';
11
-
12
- export function registerLoginCommand(program: Command): void {
13
- program
14
- .command('login <nestbox-domain>')
15
- .description('Login using Google SSO')
16
- .action(async (domain: string) => {
17
- console.log('Login command triggered for domain:', domain);
18
- const spinner = ora('Initiating Google login...').start();
19
-
20
- try {
21
- // Determine the protocol and construct the auth URL based on the provided domain
22
- let authUrl;
23
- if (domain.includes('localhost')) {
24
- // Use HTTP for localhost and specific port
25
- authUrl = `http://${domain}/cli/auth`;
26
- } else {
27
- // Use HTTPS for all other domains
28
- authUrl = `https://${domain}/cli/auth`;
29
- }
30
-
31
- spinner.text = 'Opening browser for Google authentication...';
32
-
33
- // Open the browser for authentication
34
- await open(authUrl);
35
- spinner.succeed('Browser opened for authentication');
36
-
37
- // Prompt user to paste the combined token and API URL
38
- const { combinedInput } = await inquirer.prompt<{ combinedInput: string }>([
39
- {
40
- type: 'input',
41
- name: 'combinedInput',
42
- message: 'After authenticating, please paste the data here:',
43
- validate: (input) => input.trim().length > 0 || 'Input is required'
44
- }
45
- ]);
46
-
47
- // Split the input by comma
48
- const [accessToken, apiServerUrl] = combinedInput.split(',').map(item => item.trim());
49
-
50
- if (!accessToken || !apiServerUrl) {
51
- spinner.fail('Invalid input format. Expected: token,apiServerUrl');
52
- return;
53
- }
54
-
55
- console.log(chalk.green('Credentials received. Extracting user information...'));
56
-
57
- // Fetch user data from the token
58
- let email = '';
59
- let name = '';
60
- let picture = '';
61
- try {
62
- // Try to decode JWT to get user data (email, name, picture, etc.)
63
- const tokenParts = accessToken.split('.');
64
- if (tokenParts.length === 3) {
65
- // Base64 decode the payload part of JWT
66
- const base64Payload = tokenParts[1].replace(/-/g, '+').replace(/_/g, '/');
67
- const decodedPayload = Buffer.from(base64Payload, 'base64').toString('utf-8');
68
- const tokenPayload = JSON.parse(decodedPayload);
69
-
70
- // Extract user information
71
- email = tokenPayload.email || '';
72
- name = tokenPayload.name || '';
73
- picture = tokenPayload.picture || '';
74
- }
75
- } catch (e) {
76
- console.log(chalk.yellow('Could not decode token payload. Will prompt for email.'));
77
- }
78
-
79
- // If email couldn't be extracted from token, prompt user
80
- if (!email) {
81
- const response = await inquirer.prompt<{ email: string }>([
82
- {
83
- type: 'input',
84
- name: 'email',
85
- message: 'Enter your email address:',
86
- validate: (input) => /\S+@\S+\.\S+/.test(input) || 'Please enter a valid email'
87
- }
88
- ]);
89
- email = response.email;
90
- }
91
-
92
- spinner.start('Verifying access token...');
93
-
94
- if (apiServerUrl && email && accessToken) {
95
- // Verify the access token
96
- const configuration = new Configuration({
97
- basePath: apiServerUrl,
98
- accessToken: accessToken,
99
- });
100
- const authApi = new AuthApi(configuration);
101
- try {
102
- const response = await authApi.authControllerOAuthLogin({
103
- providerId: accessToken,
104
- type: OAuthLoginRequestDTOTypeEnum.Google,
105
- email,
106
- profilePictureUrl: picture || '',
107
- });
108
- const authResponse = response.data;
109
-
110
- // Save credentials to file
111
- try {
112
- // Create directory structure
113
- const configDir = path.join(os.homedir(), '.config', '.nestbox');
114
- if (!fs.existsSync(configDir)) {
115
- fs.mkdirSync(configDir, { recursive: true });
116
- }
117
-
118
- // Create the file path
119
- const fileName = `${email.replace('@', '_at_')}_${domain}.json`;
120
- const filePath = path.join(configDir, fileName);
121
-
122
- // Create credentials object
123
- const credentials = {
124
- domain,
125
- email,
126
- token: authResponse.token,
127
- accessToken, // Save the original accessToken
128
- apiServerUrl,
129
- name,
130
- picture,
131
- timestamp: new Date().toISOString()
132
- };
133
-
134
- // Write to file
135
- fs.writeFileSync(filePath, JSON.stringify(credentials, null, 2));
136
-
137
- spinner.succeed('Authentication successful');
138
- console.log(chalk.green(`Successfully logged in as ${email}`));
139
- console.log(chalk.blue(`Credentials saved to: ${filePath}`));
140
- } catch (fileError) {
141
- spinner.warn('Authentication successful, but failed to save credentials file');
142
- console.error(chalk.yellow('File error:'), fileError instanceof Error ? fileError.message : 'Unknown error');
143
-
144
- }
145
- } catch (authError) {
146
- spinner.fail('Failed to verify access token');
147
- if (axios.isAxiosError(authError) && authError.response) {
148
- if (authError.response.data.message === "user.not_found") {
149
- console.error(chalk.red('Authentication Error:'), "You need to register your email with the Nestbox platform");
150
- const { openSignup } = await inquirer.prompt<{ openSignup: boolean }>([
151
- {
152
- type: 'confirm',
153
- name: 'openSignup',
154
- message: 'Would you like to open the signup page to register?',
155
- default: true
156
- }
157
- ]);
158
-
159
- if (openSignup) {
160
- // Construct signup URL with the same protocol logic as login
161
- let signupUrl;
162
- if (domain.includes('localhost')) {
163
- signupUrl = `http://${domain}`;
164
- } else {
165
- signupUrl = `https://${domain}`;
166
- }
167
-
168
- console.log(chalk.blue(`Opening signup page: ${signupUrl}`));
169
- await open(signupUrl);
170
- }
171
- }
172
- } else {
173
- console.error(chalk.red('Authentication Error:'), authError instanceof Error ? authError.message : 'Unknown error');
174
- }
175
- }
176
- } else {
177
- spinner.fail('Missing required information for authentication');
178
- }
179
- } catch (error) {
180
- spinner.fail('Authentication failed');
181
- console.error(chalk.red('Error:'), error instanceof Error ? error.message : 'Unknown error');
182
- }
183
- });
184
- }
@@ -1,110 +0,0 @@
1
- import { Command } from 'commander';
2
- import chalk from 'chalk';
3
- import inquirer from 'inquirer';
4
- import fs from 'fs';
5
- import os from 'os';
6
- import path from 'path';
7
- import { getAuthToken, listCredentials, removeCredentials } from '../../utils/auth';
8
-
9
- export function registerLogoutCommand(program: Command): void {
10
- program
11
- .command('logout [nestbox-domain]')
12
- .description('Logout from Nestbox platform')
13
- .action(async (domain?: string) => {
14
- try {
15
- const authToken = getAuthToken(domain);
16
- if (!authToken) {
17
- console.log(chalk.yellow('No authentication token found. Please log in first.'));
18
- return;
19
- }
20
-
21
- // Function to remove all credential files for a domain
22
- const removeCredentialFiles = (domain: string) => {
23
- try {
24
- const configDir = path.join(os.homedir(), '.config', '.nestbox');
25
- if (!fs.existsSync(configDir)) {
26
- return false;
27
- }
28
-
29
- // Sanitize domain for file matching
30
- // Replace characters that are problematic in filenames
31
- const sanitizedDomain = domain.replace(/:/g, '_');
32
-
33
- // Get all files in the directory
34
- const files = fs.readdirSync(configDir);
35
-
36
- // Find and remove all files that match the domain
37
- let removedCount = 0;
38
- for (const file of files) {
39
- // Check if the file matches any of the possible domain formats
40
- if (
41
- file.endsWith(`_${domain}.json`) ||
42
- file.endsWith(`_${sanitizedDomain}.json`)
43
- ) {
44
- fs.unlinkSync(path.join(configDir, file));
45
- removedCount++;
46
- }
47
- }
48
-
49
- return removedCount > 0;
50
- } catch (error) {
51
- console.warn(chalk.yellow(`Warning: Could not remove credential files. ${error instanceof Error ? error.message : ''}`));
52
- return false;
53
- }
54
- };
55
-
56
- if (domain) {
57
- // Logout from specific domain
58
- // Remove credentials using utility function
59
- const removed = removeCredentials(domain);
60
-
61
- // Also remove all credential files for this domain
62
- const filesRemoved = removeCredentialFiles(domain);
63
-
64
- if (removed || filesRemoved) {
65
- console.log(chalk.green(`Successfully logged out from ${domain}`));
66
- } else {
67
- console.log(chalk.yellow(`No credentials found for ${domain}`));
68
- }
69
- } else {
70
- // Ask which domain to logout from
71
- const credentials = listCredentials();
72
-
73
- if (credentials.length === 0) {
74
- console.log(chalk.yellow('No credentials found'));
75
- return;
76
- }
77
-
78
- // Group credentials by domain
79
- const domains = Array.from(new Set(credentials.map(cred => cred.domain)));
80
- const domainChoices = domains.map(domain => {
81
- const accounts = credentials.filter(cred => cred.domain === domain);
82
- return `${domain} (${accounts.length} account${accounts.length > 1 ? 's' : ''})`;
83
- });
84
-
85
- const { selected } = await inquirer.prompt<{ selected: string }>([
86
- {
87
- type: 'list',
88
- name: 'selected',
89
- message: 'Select domain to logout from:',
90
- choices: domainChoices,
91
- }
92
- ]);
93
-
94
- // Extract domain from the selected choice
95
- const selectedDomain = selected.split(' ')[0];
96
-
97
- // Remove credentials using utility function
98
- removeCredentials(selectedDomain);
99
-
100
- // Also remove all credential files for this domain
101
- removeCredentialFiles(selectedDomain);
102
-
103
- console.log(chalk.green(`Successfully logged out from ${selectedDomain}`));
104
- }
105
- } catch (error) {
106
- const err = error as Error;
107
- console.error(chalk.red('Error:'), err.message);
108
- }
109
- });
110
- }
@@ -1,12 +0,0 @@
1
- import { Command } from "commander";
2
- import { registerLoginCommand } from "./auth/login";
3
- import { registerLogoutCommand } from "./auth/logout";
4
-
5
- /**
6
- * Register all auth-related commands
7
- */
8
- export function registerAuthCommands(program: Command): void {
9
- // Register auth commands directly on the program (not as subcommands)
10
- registerLoginCommand(program);
11
- registerLogoutCommand(program);
12
- }
@@ -1,28 +0,0 @@
1
- import { MachineInstancesApi, MiscellaneousApi, ProjectsApi } from "@nestbox-ai/admin";
2
- import { setupAuthAndConfig } from "../../utils/api";
3
-
4
- export interface ComputeApiInstances {
5
- machineInstanceApi: MachineInstancesApi;
6
- miscellaneousApi: MiscellaneousApi;
7
- projectsApi: ProjectsApi;
8
- authToken: any;
9
- }
10
-
11
- /**
12
- * Create API instances for compute commands using setupAuthAndConfig
13
- */
14
- export function createComputeApis(): ComputeApiInstances | null {
15
- const authResult = setupAuthAndConfig();
16
- if (!authResult) {
17
- return null;
18
- }
19
-
20
- const { authToken, configuration } = authResult;
21
-
22
- return {
23
- machineInstanceApi: new MachineInstancesApi(configuration),
24
- miscellaneousApi: new MiscellaneousApi(configuration),
25
- projectsApi: new ProjectsApi(configuration),
26
- authToken
27
- };
28
- }