@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.
- package/.nestboxrc +5 -0
- package/dist/commands/agent.js +592 -173
- package/dist/commands/agent.js.map +1 -1
- package/dist/commands/auth.js +1 -0
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/compute.js +38 -8
- package/dist/commands/compute.js.map +1 -1
- package/dist/commands/document.js +2 -0
- package/dist/commands/document.js.map +1 -1
- package/dist/commands/image.js +107 -110
- package/dist/commands/image.js.map +1 -1
- package/dist/commands/projects.js +118 -30
- package/dist/commands/projects.js.map +1 -1
- package/dist/types/agentType.d.ts +1 -1
- package/dist/types/agentType.js +1 -1
- package/dist/types/agentType.js.map +1 -1
- package/dist/types/agentYaml.d.ts +91 -0
- package/dist/types/agentYaml.js +6 -0
- package/dist/types/agentYaml.js.map +1 -0
- package/dist/types/auth.d.ts +4 -6
- package/dist/types/auth.js +1 -0
- package/dist/types/auth.js.map +1 -1
- package/dist/utils/agent.d.ts +11 -0
- package/dist/utils/agent.js +72 -0
- package/dist/utils/agent.js.map +1 -1
- package/dist/utils/auth.d.ts +4 -0
- package/dist/utils/auth.js +31 -3
- package/dist/utils/auth.js.map +1 -1
- package/dist/utils/error.d.ts +8 -0
- package/dist/utils/error.js +163 -0
- package/dist/utils/error.js.map +1 -0
- package/dist/utils/project.d.ts +4 -1
- package/dist/utils/project.js +17 -10
- package/dist/utils/project.js.map +1 -1
- package/package.json +3 -1
- package/sample-agents.yaml +0 -0
- package/src/commands/agent.ts +770 -303
- package/src/commands/auth.ts +1 -0
- package/src/commands/compute.ts +30 -8
- package/src/commands/document.ts +2 -2
- package/src/commands/image.ts +121 -129
- package/src/commands/projects.ts +125 -34
- package/src/types/agentType.ts +1 -1
- package/src/types/agentYaml.ts +107 -0
- package/src/types/auth.ts +10 -10
- package/src/utils/agent.ts +82 -0
- package/src/utils/auth.ts +33 -3
- package/src/utils/error.ts +168 -0
- package/src/utils/project.ts +20 -13
- package/templates/template-base-js.zip +0 -0
- package/templates/template-base-ts.zip +0 -0
- package/templates/template-chatbot-js.zip +0 -0
- package/templates/template-chatbot-ts.zip +0 -0
package/src/commands/auth.ts
CHANGED
package/src/commands/compute.ts
CHANGED
|
@@ -129,14 +129,20 @@ export function registerComputeProgram(program: Command): void {
|
|
|
129
129
|
|
|
130
130
|
} catch (error: any) {
|
|
131
131
|
spinner.fail('Failed to retrieve compute instances');
|
|
132
|
-
if (error.response) {
|
|
132
|
+
if (error.response && error.response.status === 401) {
|
|
133
|
+
console.error(chalk.red('Authentication token has expired. Please login again using "nestbox login <domain>".'));
|
|
134
|
+
} else if (error.response) {
|
|
133
135
|
console.error(chalk.red('API Error:'), error.response.data?.message || 'Unknown error');
|
|
134
136
|
} else {
|
|
135
137
|
console.error(chalk.red('Error:'), error.message || 'Unknown error');
|
|
136
138
|
}
|
|
137
139
|
}
|
|
138
140
|
} catch (error: any) {
|
|
139
|
-
|
|
141
|
+
if (error.response && error.response.status === 401) {
|
|
142
|
+
console.error(chalk.red('Authentication token has expired. Please login again using "nestbox login <domain>".'));
|
|
143
|
+
} else {
|
|
144
|
+
console.error(chalk.red('Error:'), error.message || 'Unknown error');
|
|
145
|
+
}
|
|
140
146
|
}
|
|
141
147
|
});
|
|
142
148
|
|
|
@@ -293,7 +299,9 @@ export function registerComputeProgram(program: Command): void {
|
|
|
293
299
|
console.log(chalk.green("Instance created successfully!"));
|
|
294
300
|
} catch (createError: any) {
|
|
295
301
|
creationSpinner.fail('Failed to create compute instance');
|
|
296
|
-
if (createError.response) {
|
|
302
|
+
if (createError.response && createError.response.status === 401) {
|
|
303
|
+
console.error(chalk.red('Authentication token has expired. Please login again using "nestbox login <domain>".'));
|
|
304
|
+
} else if (createError.response) {
|
|
297
305
|
console.error(chalk.red('API Error:'), createError.response.data?.message || 'Unknown error');
|
|
298
306
|
} else {
|
|
299
307
|
console.error(chalk.red('Error:'), createError.message || 'Unknown error');
|
|
@@ -302,14 +310,20 @@ export function registerComputeProgram(program: Command): void {
|
|
|
302
310
|
|
|
303
311
|
} catch (error: any) {
|
|
304
312
|
spinner.fail('Failed to fetch available images');
|
|
305
|
-
if (error.response) {
|
|
313
|
+
if (error.response && error.response.status === 401) {
|
|
314
|
+
console.error(chalk.red('Authentication token has expired. Please login again using "nestbox login <domain>".'));
|
|
315
|
+
} else if (error.response) {
|
|
306
316
|
console.error(chalk.red('API Error:'), error.response.data?.message || 'Unknown error');
|
|
307
317
|
} else {
|
|
308
318
|
console.error(chalk.red('Error:'), error.message || 'Unknown error');
|
|
309
319
|
}
|
|
310
320
|
}
|
|
311
321
|
} catch (error: any) {
|
|
312
|
-
|
|
322
|
+
if (error.response && error.response.status === 401) {
|
|
323
|
+
console.error(chalk.red('Authentication token has expired. Please login again using "nestbox login <domain>".'));
|
|
324
|
+
} else {
|
|
325
|
+
console.error(chalk.red('Error:'), error.message || 'Unknown error');
|
|
326
|
+
}
|
|
313
327
|
}
|
|
314
328
|
});
|
|
315
329
|
|
|
@@ -417,7 +431,9 @@ export function registerComputeProgram(program: Command): void {
|
|
|
417
431
|
|
|
418
432
|
} catch (error: any) {
|
|
419
433
|
deleteSpinner.fail(`Failed to delete instances`);
|
|
420
|
-
if (error.response) {
|
|
434
|
+
if (error.response && error.response.status === 401) {
|
|
435
|
+
console.error(chalk.red('Authentication token has expired. Please login again using "nestbox login <domain>".'));
|
|
436
|
+
} else if (error.response) {
|
|
421
437
|
console.error(chalk.red('API Error:'), error.response.data?.message || 'Unknown error');
|
|
422
438
|
} else {
|
|
423
439
|
console.error(chalk.red('Error:'), error.message || 'Unknown error');
|
|
@@ -426,14 +442,20 @@ export function registerComputeProgram(program: Command): void {
|
|
|
426
442
|
|
|
427
443
|
} catch (error: any) {
|
|
428
444
|
spinner.fail('Failed to retrieve compute instances');
|
|
429
|
-
if (error.response) {
|
|
445
|
+
if (error.response && error.response.status === 401) {
|
|
446
|
+
console.error(chalk.red('Authentication token has expired. Please login again using "nestbox login <domain>".'));
|
|
447
|
+
} else if (error.response) {
|
|
430
448
|
console.error(chalk.red('API Error:'), error.response.data?.message || 'Unknown error');
|
|
431
449
|
} else {
|
|
432
450
|
console.error(chalk.red('Error:'), error.message || 'Unknown error');
|
|
433
451
|
}
|
|
434
452
|
}
|
|
435
453
|
} catch (error: any) {
|
|
436
|
-
|
|
454
|
+
if (error.response && error.response.status === 401) {
|
|
455
|
+
console.error(chalk.red('Authentication token has expired. Please login again using "nestbox login <domain>".'));
|
|
456
|
+
} else {
|
|
457
|
+
console.error(chalk.red('Error:'), error.message || 'Unknown error');
|
|
458
|
+
}
|
|
437
459
|
}
|
|
438
460
|
});
|
|
439
461
|
}
|
package/src/commands/document.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { getAuthToken } from '../utils/auth';
|
|
|
5
5
|
import { Configuration, DocumentsApi, ProjectsApi } from '@nestbox-ai/admin';
|
|
6
6
|
import { readNestboxConfig } from './projects';
|
|
7
7
|
import { resolveProject } from '../utils/project';
|
|
8
|
+
import { handle401Error } from '../utils/error';
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
/**
|
|
@@ -23,13 +24,12 @@ async function executeCommand<T>(
|
|
|
23
24
|
return result;
|
|
24
25
|
} catch (error: any) {
|
|
25
26
|
spinner.fail('Operation failed');
|
|
26
|
-
|
|
27
|
+
handle401Error(error);
|
|
27
28
|
if (error.response?.data?.message) {
|
|
28
29
|
console.error(chalk.red('API Error:'), error.response.data.message);
|
|
29
30
|
} else {
|
|
30
31
|
console.error(chalk.red('Error:'), error.message || 'Unknown error');
|
|
31
32
|
}
|
|
32
|
-
|
|
33
33
|
throw error;
|
|
34
34
|
}
|
|
35
35
|
}
|
package/src/commands/image.ts
CHANGED
|
@@ -5,151 +5,143 @@ import Table from 'cli-table3';
|
|
|
5
5
|
import { getAuthToken } from '../utils/auth';
|
|
6
6
|
import { Configuration, MiscellaneousApi, ProjectsApi } from '@nestbox-ai/admin';
|
|
7
7
|
import { resolveProject } from '../utils/project';
|
|
8
|
+
import { withTokenRefresh } from '../utils/error';
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
successMessage: string
|
|
16
|
-
): Promise<T> {
|
|
17
|
-
const spinner = ora(description).start();
|
|
18
|
-
|
|
19
|
-
try {
|
|
20
|
-
const result = await command();
|
|
21
|
-
spinner.succeed(successMessage);
|
|
22
|
-
return result;
|
|
23
|
-
} catch (error: any) {
|
|
24
|
-
spinner.fail('Operation failed');
|
|
25
|
-
|
|
26
|
-
if (error.response?.data?.message) {
|
|
27
|
-
console.error(chalk.red('API Error:'), error.response.data.message);
|
|
28
|
-
} else {
|
|
29
|
-
console.error(chalk.red('Error:'), error.message || 'Unknown error');
|
|
10
|
+
export function registerImageCommands(program: Command): void {
|
|
11
|
+
// Function to create/recreate API instances
|
|
12
|
+
const createApis = () => {
|
|
13
|
+
const authToken = getAuthToken();
|
|
14
|
+
if (!authToken) {
|
|
15
|
+
throw new Error('No authentication token found. Please log in first.');
|
|
30
16
|
}
|
|
31
17
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (!authToken) {
|
|
40
|
-
console.error(chalk.red('No authentication token found. Please login first.'));
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const configuration = new Configuration({
|
|
45
|
-
basePath: authToken.serverUrl,
|
|
46
|
-
baseOptions: {
|
|
47
|
-
headers: {
|
|
48
|
-
Authorization: authToken.token,
|
|
18
|
+
const configuration = new Configuration({
|
|
19
|
+
basePath: authToken.serverUrl,
|
|
20
|
+
baseOptions: {
|
|
21
|
+
headers: {
|
|
22
|
+
Authorization: authToken.token,
|
|
23
|
+
},
|
|
49
24
|
},
|
|
50
|
-
}
|
|
51
|
-
});
|
|
25
|
+
});
|
|
52
26
|
|
|
53
|
-
|
|
54
|
-
|
|
27
|
+
return {
|
|
28
|
+
miscellaneousApi: new MiscellaneousApi(configuration),
|
|
29
|
+
projectsApi: new ProjectsApi(configuration)
|
|
30
|
+
};
|
|
31
|
+
};
|
|
55
32
|
|
|
56
33
|
const imageCommand = program.command('image').description('Manage Nestbox images');
|
|
57
34
|
|
|
58
35
|
// LIST command
|
|
59
|
-
|
|
36
|
+
imageCommand
|
|
60
37
|
.command('list')
|
|
61
38
|
.description('List images for a project')
|
|
62
|
-
.option('--project <projectId>', 'Project ID or name (defaults to the current project)')
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
try {
|
|
66
|
-
const project = await resolveProject(projectsApi, options);
|
|
39
|
+
.option('--project <projectId>', 'Project ID or name (defaults to the current project)')
|
|
40
|
+
.action(async (options) => {
|
|
41
|
+
const spinner = ora('Processing...').start();
|
|
67
42
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
43
|
+
try {
|
|
44
|
+
let apis = createApis();
|
|
45
|
+
|
|
46
|
+
// Execute all operations with token refresh support
|
|
47
|
+
const result = await withTokenRefresh(
|
|
48
|
+
async () => {
|
|
49
|
+
// Resolve project without showing its own spinner
|
|
50
|
+
spinner.text = 'Resolving project...';
|
|
51
|
+
const project = await resolveProject(apis.projectsApi, {
|
|
52
|
+
...options,
|
|
53
|
+
showSpinner: false // Disable resolveProject's spinner
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Fetch images
|
|
57
|
+
spinner.text = `Listing images for project ${project.name}...`;
|
|
58
|
+
const response = await apis.miscellaneousApi.miscellaneousControllerGetData();
|
|
59
|
+
|
|
60
|
+
return { project, images: response.data };
|
|
61
|
+
},
|
|
62
|
+
() => {
|
|
63
|
+
// Recreate APIs after token refresh
|
|
64
|
+
apis = createApis();
|
|
65
|
+
}
|
|
66
|
+
);
|
|
76
67
|
|
|
77
|
-
|
|
78
|
-
console.log(chalk.yellow('No images found for this project.'));
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
68
|
+
spinner.succeed('Successfully retrieved images');
|
|
81
69
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
chalk.
|
|
87
|
-
|
|
88
|
-
chalk.white.bold('Status'),
|
|
89
|
-
chalk.white.bold('Region'),
|
|
90
|
-
chalk.white.bold('API Key'),
|
|
91
|
-
chalk.white.bold('Internal IP')
|
|
92
|
-
],
|
|
93
|
-
style: {
|
|
94
|
-
head: [], // Disable the default styling
|
|
95
|
-
border: []
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
// Status mappings
|
|
100
|
-
const statusMappings: Record<string, string> = {
|
|
101
|
-
'Job Scheduled': 'Scheduled',
|
|
102
|
-
'Job Executed': 'Ready',
|
|
103
|
-
'Job in Progress': 'Initializing',
|
|
104
|
-
'Job Failed': 'Failed',
|
|
105
|
-
'Deleting': 'Deleting',
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
// Add rows to the table
|
|
109
|
-
images.forEach((image: any) => {
|
|
110
|
-
// Map the status if a mapping exists
|
|
111
|
-
const originalStatus = image.runningStatus || 'unknown';
|
|
112
|
-
const displayStatus = statusMappings[originalStatus] || originalStatus;
|
|
113
|
-
|
|
114
|
-
// Color the status based on its mapped value
|
|
115
|
-
let statusColor;
|
|
116
|
-
|
|
117
|
-
switch(displayStatus.toLowerCase()) {
|
|
118
|
-
case 'ready':
|
|
119
|
-
statusColor = chalk.green(displayStatus);
|
|
120
|
-
break;
|
|
121
|
-
case 'failed':
|
|
122
|
-
statusColor = chalk.red(displayStatus);
|
|
123
|
-
break;
|
|
124
|
-
case 'initializing':
|
|
125
|
-
statusColor = chalk.yellow(displayStatus);
|
|
126
|
-
break;
|
|
127
|
-
case 'scheduled':
|
|
128
|
-
statusColor = chalk.blue(displayStatus);
|
|
129
|
-
break;
|
|
130
|
-
case 'deleting':
|
|
131
|
-
statusColor = chalk.red(displayStatus);
|
|
132
|
-
break;
|
|
133
|
-
default:
|
|
134
|
-
statusColor = chalk.gray(displayStatus);
|
|
70
|
+
const project: any = result.project;
|
|
71
|
+
const images: any = result.images;
|
|
72
|
+
|
|
73
|
+
if (!images || images.length === 0) {
|
|
74
|
+
console.log(chalk.yellow(`No images found for project ${project.name}.`));
|
|
75
|
+
return;
|
|
135
76
|
}
|
|
136
|
-
|
|
137
|
-
table.push([
|
|
138
|
-
image.id || 'N/A',
|
|
139
|
-
image.instanceName || 'N/A',
|
|
140
|
-
image.machineTitle || 'N/A',
|
|
141
|
-
statusColor,
|
|
142
|
-
image.region || 'N/A',
|
|
143
|
-
image.instanceApiKey || 'N/A',
|
|
144
|
-
image.internalIP || 'N/A'
|
|
145
|
-
]);
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
// Display the table
|
|
149
|
-
console.log(table.toString());
|
|
150
77
|
|
|
151
|
-
|
|
152
|
-
|
|
78
|
+
// Create and display the table
|
|
79
|
+
displayImagesTable(images);
|
|
80
|
+
|
|
81
|
+
} catch (error: any) {
|
|
82
|
+
spinner.fail('Operation failed');
|
|
83
|
+
handleError(error);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Additional commands can be added here following the same pattern
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Helper function to display images in a table
|
|
91
|
+
function displayImagesTable(images: any[]): void {
|
|
92
|
+
const table = new Table({
|
|
93
|
+
head: [
|
|
94
|
+
chalk.white.bold('Name'),
|
|
95
|
+
chalk.white.bold('Type'),
|
|
96
|
+
chalk.white.bold('License'),
|
|
97
|
+
chalk.white.bold('Category'),
|
|
98
|
+
chalk.white.bold('Pricing'),
|
|
99
|
+
chalk.white.bold('Source')
|
|
100
|
+
],
|
|
101
|
+
style: {
|
|
102
|
+
head: [],
|
|
103
|
+
border: []
|
|
153
104
|
}
|
|
154
105
|
});
|
|
106
|
+
|
|
107
|
+
// Status mappings (kept from original code for potential future use)
|
|
108
|
+
const statusMappings: Record<string, string> = {
|
|
109
|
+
'Job Scheduled': 'Scheduled',
|
|
110
|
+
'Job Executed': 'Ready',
|
|
111
|
+
'Job in Progress': 'Initializing',
|
|
112
|
+
'Job Failed': 'Failed',
|
|
113
|
+
'Deleting': 'Deleting',
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// Add rows to the table
|
|
117
|
+
images.forEach((image: any) => {
|
|
118
|
+
table.push([
|
|
119
|
+
image.name || 'N/A',
|
|
120
|
+
image.type || 'N/A',
|
|
121
|
+
image.metadata?.License || 'N/A',
|
|
122
|
+
image.metadata?.Type || 'N/A',
|
|
123
|
+
image.metadata?.Pricing || 'N/A',
|
|
124
|
+
image.source || 'N/A'
|
|
125
|
+
]);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
console.log(table.toString());
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Helper function to handle errors
|
|
132
|
+
function handleError(error: any): void {
|
|
133
|
+
if (error.message) {
|
|
134
|
+
if (error.message.includes('Authentication')) {
|
|
135
|
+
console.error(chalk.red(error.message));
|
|
136
|
+
} else if (error.message.includes('No project')) {
|
|
137
|
+
// Project-related errors are already well-formatted
|
|
138
|
+
console.error(chalk.red(error.message));
|
|
139
|
+
} else {
|
|
140
|
+
console.error(chalk.red('Error:'), error.message);
|
|
141
|
+
}
|
|
142
|
+
} else if (error.response?.data?.message) {
|
|
143
|
+
console.error(chalk.red('API Error:'), error.response.data.message);
|
|
144
|
+
} else {
|
|
145
|
+
console.error(chalk.red('Error:'), 'Unknown error occurred');
|
|
146
|
+
}
|
|
155
147
|
}
|
package/src/commands/projects.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
+
import { withTokenRefresh } from '../utils/error';
|
|
3
4
|
import fs from 'fs';
|
|
4
5
|
import path from 'path';
|
|
5
6
|
import { getAuthToken } from '../utils/auth';
|
|
@@ -39,18 +40,24 @@ export function writeNestboxConfig(config: NestboxConfig): void {
|
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
export function registerProjectCommands(program: Command): void {
|
|
42
|
-
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
headers: {
|
|
48
|
-
"Authorization": authToken?.token,
|
|
49
|
-
}
|
|
43
|
+
// Function to create/recreate the ProjectsApi instance
|
|
44
|
+
const createProjectsApi = () => {
|
|
45
|
+
const authToken = getAuthToken();
|
|
46
|
+
if (!authToken) {
|
|
47
|
+
throw new Error('No authentication token found. Please log in first.');
|
|
50
48
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
49
|
+
|
|
50
|
+
const configuration = new Configuration({
|
|
51
|
+
basePath: authToken.serverUrl,
|
|
52
|
+
baseOptions: {
|
|
53
|
+
headers: {
|
|
54
|
+
"Authorization": authToken.token,
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
return new ProjectsApi(configuration);
|
|
60
|
+
};
|
|
54
61
|
|
|
55
62
|
// Create the main project command
|
|
56
63
|
const projectCommand = program
|
|
@@ -61,35 +68,43 @@ export function registerProjectCommands(program: Command): void {
|
|
|
61
68
|
projectCommand
|
|
62
69
|
.command('use <project-name>')
|
|
63
70
|
.description('Set default project for all commands')
|
|
64
|
-
.action((projectName: string) => {
|
|
71
|
+
.action(async (projectName: string) => {
|
|
65
72
|
try {
|
|
66
|
-
if (!authToken) {
|
|
67
|
-
console.error(chalk.red('No authentication token found. Please log in first.'));
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
73
|
const config = readNestboxConfig();
|
|
71
|
-
|
|
72
|
-
// Set the default project
|
|
73
74
|
config.projects = config.projects || {};
|
|
74
75
|
config.projects.default = projectName;
|
|
75
76
|
|
|
76
|
-
projectsApi
|
|
77
|
-
.then((response) => {
|
|
78
|
-
// Check if the project exists
|
|
79
|
-
const projectExists = response.data.data.projects.some((project: any) => project.name === projectName);
|
|
80
|
-
if (!projectExists) {
|
|
81
|
-
throw new Error(`Project '${projectName}' does not exist.`);
|
|
82
|
-
}
|
|
83
|
-
// Write the configuration
|
|
84
|
-
writeNestboxConfig(config);
|
|
85
|
-
console.log(chalk.green(`Default project set to '${projectName}'`));
|
|
86
|
-
})
|
|
87
|
-
.catch((error) => {
|
|
88
|
-
console.error(error.message);
|
|
89
|
-
});
|
|
77
|
+
let projectsApi = createProjectsApi();
|
|
90
78
|
|
|
91
|
-
|
|
92
|
-
|
|
79
|
+
// Use withTokenRefresh wrapper for automatic retry
|
|
80
|
+
const response = await withTokenRefresh(
|
|
81
|
+
async () => {
|
|
82
|
+
return await projectsApi.projectControllerGetAllProjects();
|
|
83
|
+
},
|
|
84
|
+
// Recreate the API client after token refresh
|
|
85
|
+
() => {
|
|
86
|
+
projectsApi = createProjectsApi();
|
|
87
|
+
}
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
// Check if the project exists
|
|
91
|
+
const projectExists = response.data.data.projects.some((project: any) => project.name === projectName);
|
|
92
|
+
if (!projectExists) {
|
|
93
|
+
console.error(chalk.red(`Project '${projectName}' does not exist.`));
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Write the configuration
|
|
98
|
+
writeNestboxConfig(config);
|
|
99
|
+
console.log(chalk.green(`Default project set to '${projectName}'`));
|
|
100
|
+
} catch (error: any) {
|
|
101
|
+
if (error.message && error.message.includes('Authentication')) {
|
|
102
|
+
console.error(chalk.red(error.message));
|
|
103
|
+
} else if (error.message) {
|
|
104
|
+
console.error(chalk.red('Error setting default project:'), error.message);
|
|
105
|
+
} else {
|
|
106
|
+
console.error(chalk.red('Error setting default project:'), 'Unknown error');
|
|
107
|
+
}
|
|
93
108
|
}
|
|
94
109
|
});
|
|
95
110
|
|
|
@@ -99,6 +114,7 @@ export function registerProjectCommands(program: Command): void {
|
|
|
99
114
|
.description('Add a project with optional alias')
|
|
100
115
|
.action((projectName: string, alias?: string) => {
|
|
101
116
|
try {
|
|
117
|
+
const authToken = getAuthToken();
|
|
102
118
|
if (!authToken) {
|
|
103
119
|
console.error(chalk.red('No authentication token found. Please log in first.'));
|
|
104
120
|
return;
|
|
@@ -136,4 +152,79 @@ export function registerProjectCommands(program: Command): void {
|
|
|
136
152
|
console.error(chalk.red('Error adding project:'), error instanceof Error ? error.message : 'Unknown error');
|
|
137
153
|
}
|
|
138
154
|
});
|
|
155
|
+
|
|
156
|
+
projectCommand
|
|
157
|
+
.command('list')
|
|
158
|
+
.description('List all projects')
|
|
159
|
+
.action(async () => {
|
|
160
|
+
try {
|
|
161
|
+
let projectsApi = createProjectsApi();
|
|
162
|
+
|
|
163
|
+
// Use withTokenRefresh wrapper for automatic retry
|
|
164
|
+
const response = await withTokenRefresh(
|
|
165
|
+
async () => {
|
|
166
|
+
return await projectsApi.projectControllerGetAllProjects();
|
|
167
|
+
},
|
|
168
|
+
// Recreate the API client after token refresh
|
|
169
|
+
() => {
|
|
170
|
+
projectsApi = createProjectsApi();
|
|
171
|
+
}
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
const apiProjects = response.data.data.projects;
|
|
175
|
+
|
|
176
|
+
if (!apiProjects || apiProjects.length === 0) {
|
|
177
|
+
console.log(chalk.yellow('No projects found.'));
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Read local config to get default project and aliases
|
|
182
|
+
const config = readNestboxConfig();
|
|
183
|
+
const localProjects = config.projects || {};
|
|
184
|
+
const defaultProject = localProjects.default;
|
|
185
|
+
|
|
186
|
+
console.log(chalk.blue('Available Projects:'));
|
|
187
|
+
console.log(''); // Empty line for better formatting
|
|
188
|
+
|
|
189
|
+
// Display each project from the API
|
|
190
|
+
apiProjects.forEach((project: any) => {
|
|
191
|
+
const projectName = project.name;
|
|
192
|
+
const isDefault = defaultProject === projectName;
|
|
193
|
+
|
|
194
|
+
// Find aliases for this project
|
|
195
|
+
const aliases = Object.entries(localProjects)
|
|
196
|
+
.filter(([key, value]) => value === projectName && key !== 'default' && key !== projectName)
|
|
197
|
+
.map(([alias]) => alias);
|
|
198
|
+
|
|
199
|
+
// Build the display line
|
|
200
|
+
let displayLine = ` ${projectName}`;
|
|
201
|
+
|
|
202
|
+
if (aliases.length > 0) {
|
|
203
|
+
displayLine += chalk.gray(` (aliases: ${aliases.join(', ')})`);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (isDefault) {
|
|
207
|
+
displayLine += chalk.green(' [DEFAULT]');
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
console.log(displayLine);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
// Show summary
|
|
214
|
+
console.log(''); // Empty line
|
|
215
|
+
if (defaultProject) {
|
|
216
|
+
console.log(chalk.gray(`Default project: ${defaultProject}`));
|
|
217
|
+
} else {
|
|
218
|
+
console.log(chalk.gray('No default project set. Use "nestbox project use <project-name>" to set one.'));
|
|
219
|
+
}
|
|
220
|
+
} catch (error: any) {
|
|
221
|
+
if (error.message && error.message.includes('Authentication')) {
|
|
222
|
+
console.error(chalk.red(error.message));
|
|
223
|
+
} else if (error.message) {
|
|
224
|
+
console.error(chalk.red('Error listing projects:'), error.message);
|
|
225
|
+
} else {
|
|
226
|
+
console.error(chalk.red('Error listing projects:'), 'Unknown error');
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
});
|
|
139
230
|
}
|
package/src/types/agentType.ts
CHANGED