berget 1.0.0 → 1.2.0

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 (44) hide show
  1. package/README.md +92 -0
  2. package/dist/index.js +49 -467
  3. package/dist/package.json +35 -0
  4. package/dist/src/client.js +210 -102
  5. package/dist/src/commands/api-keys.js +277 -0
  6. package/dist/src/commands/auth.js +65 -0
  7. package/dist/src/commands/autocomplete.js +24 -0
  8. package/dist/src/commands/billing.js +53 -0
  9. package/dist/src/commands/chat.js +342 -0
  10. package/dist/src/commands/clusters.js +69 -0
  11. package/dist/src/commands/index.js +25 -0
  12. package/dist/src/commands/models.js +69 -0
  13. package/dist/src/commands/users.js +43 -0
  14. package/dist/src/constants/command-structure.js +14 -0
  15. package/dist/src/services/api-key-service.js +6 -16
  16. package/dist/src/services/auth-service.js +49 -47
  17. package/dist/src/services/chat-service.js +300 -0
  18. package/dist/src/utils/config-checker.js +50 -0
  19. package/dist/src/utils/default-api-key.js +237 -0
  20. package/dist/src/utils/error-handler.js +4 -4
  21. package/dist/src/utils/token-manager.js +165 -0
  22. package/index.ts +56 -566
  23. package/package.json +8 -2
  24. package/src/client.ts +279 -80
  25. package/src/commands/api-keys.ts +374 -0
  26. package/src/commands/auth.ts +58 -0
  27. package/src/commands/autocomplete.ts +19 -0
  28. package/src/commands/billing.ts +41 -0
  29. package/src/commands/chat.ts +445 -0
  30. package/src/commands/clusters.ts +65 -0
  31. package/src/commands/index.ts +23 -0
  32. package/src/commands/models.ts +63 -0
  33. package/src/commands/users.ts +37 -0
  34. package/src/constants/command-structure.ts +16 -0
  35. package/src/services/api-key-service.ts +12 -20
  36. package/src/services/auth-service.ts +90 -50
  37. package/src/services/chat-service.ts +295 -0
  38. package/src/types/api.d.ts +238 -178
  39. package/src/types/json.d.ts +4 -0
  40. package/src/utils/config-checker.ts +23 -0
  41. package/src/utils/default-api-key.ts +229 -0
  42. package/src/utils/error-handler.ts +4 -4
  43. package/src/utils/token-manager.ts +150 -0
  44. package/tsconfig.json +1 -1
package/README.md ADDED
@@ -0,0 +1,92 @@
1
+ # Berget CLI
2
+
3
+ A command-line interface for interacting with the Berget AI infrastructure.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g berget
9
+ ```
10
+
11
+ ## Authentication
12
+
13
+ The CLI uses OAuth-based authentication with automatic token refresh.
14
+
15
+ ### Login
16
+
17
+ ```bash
18
+ berget auth login
19
+ ```
20
+
21
+ This will open a browser window to authenticate with Berget. After successful authentication, your access token and refresh token will be stored securely in `~/.berget/auth.json`.
22
+
23
+ ### Token Refresh
24
+
25
+ The CLI automatically handles token refresh when:
26
+
27
+ 1. The access token is about to expire (within 10 minutes of expiration)
28
+ 2. A request returns a 401 Unauthorized error
29
+
30
+ The refresh mechanism uses the stored refresh token to obtain a new access token without requiring you to log in again. If the refresh token itself is expired or invalid, you'll be prompted to log in again.
31
+
32
+ ## Development
33
+
34
+ ### Setup
35
+
36
+ Clone the repository and install dependencies:
37
+
38
+ ```bash
39
+ git clone https://github.com/berget/cli.git
40
+ cd cli
41
+ npm install
42
+ ```
43
+
44
+ ### Testing Locally
45
+
46
+ Use the `start` script to test the CLI locally with the `--local` flag:
47
+
48
+ ```bash
49
+ npm start -- <command> [options]
50
+ ```
51
+
52
+ For example:
53
+
54
+ ```bash
55
+ # Test login
56
+ npm start -- auth login
57
+
58
+ # Test whoami
59
+ npm start -- auth whoami
60
+
61
+ # Test with debug output
62
+ npm start -- auth whoami --debug
63
+ ```
64
+
65
+ The `--debug` flag provides detailed information about token refresh attempts and API responses.
66
+
67
+ ### Testing Token Refresh
68
+
69
+ To test the token refresh mechanism:
70
+
71
+ 1. Log in with `npm start -- auth login`
72
+ 2. Make a request that requires authentication, like `npm start -- auth whoami`
73
+ 3. To force a token refresh, you can:
74
+ - Wait until the token is close to expiration
75
+ - Manually edit `~/.berget/auth.json` and set `expires_at` to a past timestamp
76
+ - Use the `--debug` flag to see the token refresh process in action
77
+
78
+ ## Commands
79
+
80
+ - `auth login` - Log in to Berget
81
+ - `auth logout` - Log out from Berget
82
+ - `auth whoami` - Show current user information
83
+ - `api-keys list` - List API keys
84
+ - `api-keys create` - Create a new API key
85
+ - `models list` - List available AI models
86
+ - `chat run` - Start a chat session with an AI model
87
+
88
+ For a complete list of commands, run:
89
+
90
+ ```bash
91
+ berget --help
92
+ ```
package/dist/index.js CHANGED
@@ -1,48 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
- if (k2 === undefined) k2 = k;
5
- var desc = Object.getOwnPropertyDescriptor(m, k);
6
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
- desc = { enumerable: true, get: function() { return m[k]; } };
8
- }
9
- Object.defineProperty(o, k2, desc);
10
- }) : (function(o, m, k, k2) {
11
- if (k2 === undefined) k2 = k;
12
- o[k2] = m[k];
13
- }));
14
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
- Object.defineProperty(o, "default", { enumerable: true, value: v });
16
- }) : function(o, v) {
17
- o["default"] = v;
18
- });
19
- var __importStar = (this && this.__importStar) || function (mod) {
20
- if (mod && mod.__esModule) return mod;
21
- var result = {};
22
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
23
- __setModuleDefault(result, mod);
24
- return result;
25
- };
26
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
27
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
28
- return new (P || (P = Promise))(function (resolve, reject) {
29
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
30
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
31
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
32
- step((generator = generator.apply(thisArg, _arguments || [])).next());
33
- });
34
- };
35
3
  var __importDefault = (this && this.__importDefault) || function (mod) {
36
4
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
5
  };
38
6
  Object.defineProperty(exports, "__esModule", { value: true });
39
7
  const commander_1 = require("commander");
40
- const fs = __importStar(require("fs"));
41
- const path = __importStar(require("path"));
42
- const client_1 = require("./src/client");
43
- const error_handler_1 = require("./src/utils/error-handler");
8
+ const commands_1 = require("./src/commands");
9
+ const config_checker_1 = require("./src/utils/config-checker");
44
10
  const chalk_1 = __importDefault(require("chalk"));
45
- const command_structure_1 = require("./src/constants/command-structure");
11
+ const package_json_1 = require("./package.json");
46
12
  // Set version and description
47
13
  commander_1.program
48
14
  .name('berget')
@@ -54,438 +20,54 @@ commander_1.program
54
20
  \\____/ \\___|_| \\__, |\\___|\\_\\_ \\_| |_/\\___/
55
21
  __/ |
56
22
  |___/ AI on European terms`)
57
- .version(process.env.npm_package_version || '0.0.1', '-v, --version')
58
- .option('--local', 'Use local API endpoint (hidden)', false);
59
- // Import services
60
- const auth_service_1 = require("./src/services/auth-service");
61
- const api_key_service_1 = require("./src/services/api-key-service");
62
- const cluster_service_1 = require("./src/services/cluster-service");
63
- // Auth commands
64
- const auth = commander_1.program
65
- .command(auth_service_1.AuthService.COMMAND_GROUP)
66
- .description('Manage authentication and authorization');
67
- auth
68
- .command(auth_service_1.AuthService.COMMANDS.LOGIN)
69
- .description('Log in to Berget')
70
- .action(() => __awaiter(void 0, void 0, void 0, function* () {
71
- const authService = auth_service_1.AuthService.getInstance();
72
- yield authService.login();
73
- }));
74
- auth
75
- .command(auth_service_1.AuthService.COMMANDS.LOGOUT)
76
- .description('Log out from Berget')
77
- .action(() => {
78
- const { clearAuthToken } = require('./src/client');
79
- clearAuthToken();
80
- console.log(chalk_1.default.green('You have been logged out from Berget'));
81
- });
82
- auth
83
- .command(auth_service_1.AuthService.COMMANDS.WHOAMI)
84
- .description('Show information about the logged in user')
85
- .action(() => __awaiter(void 0, void 0, void 0, function* () {
86
- try {
87
- const authService = auth_service_1.AuthService.getInstance();
88
- const profile = yield authService.whoami();
89
- if (profile) {
90
- console.log(chalk_1.default.bold(`Logged in as: ${profile.name || profile.login}`));
91
- console.log(`Email: ${chalk_1.default.cyan(profile.email || 'Not available')}`);
92
- console.log(`Role: ${chalk_1.default.cyan(profile.role || 'Not available')}`);
93
- if (profile.company) {
94
- console.log(`Company: ${chalk_1.default.cyan(profile.company.name)}`);
95
- }
96
- }
97
- else {
98
- console.log(chalk_1.default.yellow('You are not logged in. Use `berget login` to log in.'));
99
- }
100
- }
101
- catch (error) {
102
- (0, error_handler_1.handleError)('You are not logged in or an error occurred', error);
103
- }
104
- }));
105
- // API Key commands
106
- const apiKey = commander_1.program
107
- .command(api_key_service_1.ApiKeyService.COMMAND_GROUP)
108
- .description('Manage API keys');
109
- apiKey
110
- .command(api_key_service_1.ApiKeyService.COMMANDS.LIST)
111
- .description('List all API keys')
112
- .action(() => __awaiter(void 0, void 0, void 0, function* () {
113
- try {
114
- const apiKeyService = api_key_service_1.ApiKeyService.getInstance();
115
- const keys = yield apiKeyService.list();
116
- if (keys.length === 0) {
117
- console.log(chalk_1.default.yellow('No API keys found. Create one with `berget api-key create --name <name>`'));
118
- return;
119
- }
120
- console.log(chalk_1.default.bold('Your API keys:'));
121
- console.log('');
122
- // Create a table-like format with headers
123
- console.log(chalk_1.default.dim('ID'.padEnd(10)) +
124
- chalk_1.default.dim('NAME'.padEnd(25)) +
125
- chalk_1.default.dim('PREFIX'.padEnd(12)) +
126
- chalk_1.default.dim('STATUS'.padEnd(12)) +
127
- chalk_1.default.dim('CREATED'.padEnd(12)) +
128
- chalk_1.default.dim('LAST USED'));
129
- console.log(chalk_1.default.dim('─'.repeat(85)));
130
- keys.forEach((key) => {
131
- const lastUsed = key.lastUsed ? key.lastUsed.substring(0, 10) : 'Never';
132
- const status = key.active
133
- ? chalk_1.default.green('● Active')
134
- : chalk_1.default.red('● Inactive');
135
- console.log(String(key.id).padEnd(10) +
136
- key.name.padEnd(25) +
137
- key.prefix.padEnd(12) +
138
- status.padEnd(12) +
139
- key.created.substring(0, 10).padEnd(12) +
140
- lastUsed);
141
- });
142
- console.log('');
143
- console.log(chalk_1.default.dim('Use `berget api-key create --name <name>` to create a new API key'));
144
- console.log(chalk_1.default.dim('Use `berget api-key delete <id>` to delete an API key'));
145
- console.log(chalk_1.default.dim('Use `berget api-key rotate <id>` to rotate an API key'));
146
- }
147
- catch (error) {
148
- (0, error_handler_1.handleError)('Failed to list API keys', error);
149
- }
150
- }));
151
- apiKey
152
- .command(api_key_service_1.ApiKeyService.COMMANDS.CREATE)
153
- .description('Create a new API key')
154
- .option('--name <name>', 'Name of the API key')
155
- .option('--description <description>', 'Description of the API key')
156
- .action((options) => __awaiter(void 0, void 0, void 0, function* () {
157
- try {
158
- if (!options.name) {
159
- console.error(chalk_1.default.red('Error: --name is required'));
160
- console.log('');
161
- console.log('Usage: berget api-key create --name <name> [--description <description>]');
162
- return;
163
- }
164
- console.log(chalk_1.default.blue('Creating API key...'));
165
- const apiKeyService = api_key_service_1.ApiKeyService.getInstance();
166
- const result = yield apiKeyService.create({
167
- name: options.name,
168
- description: options.description,
169
- });
170
- console.log('');
171
- console.log(chalk_1.default.green('✓ API key created'));
172
- console.log('');
173
- console.log(chalk_1.default.bold('API key details:'));
174
- console.log('');
175
- console.log(`${chalk_1.default.dim('ID:')} ${result.id}`);
176
- console.log(`${chalk_1.default.dim('Name:')} ${result.name}`);
177
- if (result.description) {
178
- console.log(`${chalk_1.default.dim('Description:')} ${result.description}`);
179
- }
180
- console.log(`${chalk_1.default.dim('Created:')} ${new Date(result.created).toLocaleString()}`);
181
- console.log('');
182
- console.log(chalk_1.default.bold('API key:'));
183
- console.log(chalk_1.default.cyan(result.key));
184
- console.log('');
185
- console.log(chalk_1.default.yellow('⚠️ IMPORTANT: Save this API key in a secure location.'));
186
- console.log(chalk_1.default.yellow(' It will not be displayed again.'));
187
- console.log('');
188
- console.log(chalk_1.default.dim('Use this key in your applications to authenticate with the Berget API.'));
189
- }
190
- catch (error) {
191
- (0, error_handler_1.handleError)('Failed to create API key', error);
192
- }
193
- }));
194
- apiKey
195
- .command(api_key_service_1.ApiKeyService.COMMANDS.DELETE)
196
- .description('Delete an API key')
197
- .argument('<id>', 'ID of the API key to delete')
198
- .action((id) => __awaiter(void 0, void 0, void 0, function* () {
199
- try {
200
- console.log(chalk_1.default.blue(`Deleting API key ${id}...`));
201
- const apiKeyService = api_key_service_1.ApiKeyService.getInstance();
202
- yield apiKeyService.delete(id);
203
- console.log(chalk_1.default.green(`✓ API key ${id} has been deleted`));
204
- console.log('');
205
- console.log(chalk_1.default.dim('Applications using this key will no longer be able to authenticate.'));
206
- console.log(chalk_1.default.dim('Use `berget api-key list` to see your remaining API keys.'));
207
- }
208
- catch (error) {
209
- (0, error_handler_1.handleError)('Failed to delete API key', error);
210
- }
211
- }));
212
- apiKey
213
- .command(api_key_service_1.ApiKeyService.COMMANDS.ROTATE)
214
- .description('Rotate an API key (creates a new one and invalidates the old one)')
215
- .argument('<id>', 'ID of the API key to rotate')
216
- .action((id) => __awaiter(void 0, void 0, void 0, function* () {
217
- try {
218
- console.log(chalk_1.default.blue(`Rotating API key ${id}...`));
219
- console.log(chalk_1.default.dim('This will invalidate the old key and generate a new one.'));
220
- const apiKeyService = api_key_service_1.ApiKeyService.getInstance();
221
- const result = yield apiKeyService.rotate(id);
222
- console.log('');
223
- console.log(chalk_1.default.green('✓ API key rotated'));
224
- console.log('');
225
- console.log(chalk_1.default.bold('New API key details:'));
226
- console.log('');
227
- console.log(`${chalk_1.default.dim('ID:')} ${result.id}`);
228
- console.log(`${chalk_1.default.dim('Name:')} ${result.name}`);
229
- if (result.description) {
230
- console.log(`${chalk_1.default.dim('Description:')} ${result.description}`);
231
- }
232
- console.log(`${chalk_1.default.dim('Created:')} ${new Date(result.created).toLocaleString()}`);
233
- console.log('');
234
- console.log(chalk_1.default.bold('New API key:'));
235
- console.log(chalk_1.default.cyan(result.key));
236
- console.log('');
237
- console.log(chalk_1.default.yellow('⚠️ IMPORTANT: Update your applications with this new API key.'));
238
- console.log(chalk_1.default.yellow(' The old key has been invalidated and will no longer work.'));
239
- console.log(chalk_1.default.yellow(' This new key will not be displayed again.'));
240
- }
241
- catch (error) {
242
- (0, error_handler_1.handleError)('Failed to rotate API key', error);
243
- }
244
- }));
245
- apiKey
246
- .command(api_key_service_1.ApiKeyService.COMMANDS.DESCRIBE)
247
- .description('Show usage statistics for an API key')
248
- .argument('<id>', 'ID of the API key')
249
- .option('--start <date>', 'Start date (YYYY-MM-DD)')
250
- .option('--end <date>', 'End date (YYYY-MM-DD)')
251
- .action((id, options) => __awaiter(void 0, void 0, void 0, function* () {
252
- try {
253
- console.log(chalk_1.default.blue(`Fetching usage statistics for API key ${id}...`));
254
- const apiKeyService = api_key_service_1.ApiKeyService.getInstance();
255
- const usage = yield apiKeyService.describe(id);
256
- console.log('');
257
- console.log(chalk_1.default.bold(`Usage statistics for API key: ${usage.name} (${id})`));
258
- console.log('');
259
- // Period information
260
- console.log(chalk_1.default.dim(`Period: ${usage.period.start} to ${usage.period.end}`));
261
- console.log('');
262
- // Request statistics
263
- console.log(chalk_1.default.bold('Request statistics:'));
264
- console.log(`Total requests: ${chalk_1.default.cyan(usage.requests.total.toLocaleString())}`);
265
- // Daily breakdown if available
266
- if (usage.requests.daily && usage.requests.daily.length > 0) {
267
- console.log('');
268
- console.log(chalk_1.default.bold('Daily breakdown:'));
269
- console.log(chalk_1.default.dim('─'.repeat(30)));
270
- console.log(chalk_1.default.dim('DATE'.padEnd(12) + 'REQUESTS'));
271
- usage.requests.daily.forEach((day) => {
272
- console.log(`${day.date.padEnd(12)}${day.count.toLocaleString()}`);
273
- });
274
- }
275
- // Model usage if available
276
- if (usage.models && usage.models.length > 0) {
277
- console.log('');
278
- console.log(chalk_1.default.bold('Model usage:'));
279
- console.log(chalk_1.default.dim('─'.repeat(70)));
280
- console.log(chalk_1.default.dim('MODEL'.padEnd(20)) +
281
- chalk_1.default.dim('REQUESTS'.padEnd(10)) +
282
- chalk_1.default.dim('INPUT'.padEnd(12)) +
283
- chalk_1.default.dim('OUTPUT'.padEnd(12)) +
284
- chalk_1.default.dim('TOTAL TOKENS'));
285
- usage.models.forEach((model) => {
286
- console.log(model.name.padEnd(20) +
287
- model.requests.toString().padEnd(10) +
288
- model.tokens.input.toLocaleString().padEnd(12) +
289
- model.tokens.output.toLocaleString().padEnd(12) +
290
- model.tokens.total.toLocaleString());
23
+ .version(package_json_1.version, '-v, --version')
24
+ .option('--local', 'Use local API endpoint (hidden)', false)
25
+ .option('--debug', 'Enable debug output', false);
26
+ // Register all commands
27
+ (0, commands_1.registerCommands)(commander_1.program);
28
+ // Check for .bergetconfig if not running a command
29
+ if (process.argv.length <= 2) {
30
+ (0, config_checker_1.checkBergetConfig)();
31
+ // Show helpful welcome message
32
+ console.log(chalk_1.default.blue('\nWelcome to the Berget CLI!'));
33
+ console.log(chalk_1.default.blue('Common commands:'));
34
+ console.log(chalk_1.default.blue(` ${chalk_1.default.bold('berget auth login')} - Log in to Berget`));
35
+ console.log(chalk_1.default.blue(` ${chalk_1.default.bold('berget models list')} - List available AI models`));
36
+ console.log(chalk_1.default.blue(` ${chalk_1.default.bold('berget chat run')} - Start a chat session`));
37
+ console.log(chalk_1.default.blue(` ${chalk_1.default.bold('berget api-keys list')} - List your API keys`));
38
+ console.log(chalk_1.default.blue(`\nRun ${chalk_1.default.bold('berget --help')} for a complete list of commands.`));
39
+ }
40
+ // Add helpful suggestions for common command mistakes
41
+ const commonMistakes = {
42
+ 'login': 'auth login',
43
+ 'logout': 'auth logout',
44
+ 'whoami': 'auth whoami',
45
+ 'list-models': 'models list',
46
+ 'list-keys': 'api-keys list',
47
+ 'create-key': 'api-keys create',
48
+ 'list-clusters': 'clusters list',
49
+ 'usage': 'billing usage'
50
+ };
51
+ // Add error handler for unknown commands
52
+ commander_1.program.on('command:*', (operands) => {
53
+ const unknownCommand = operands[0];
54
+ console.error(chalk_1.default.red(`Error: unknown command '${unknownCommand}'`));
55
+ // Check if this is a known mistake and suggest the correct command
56
+ if (unknownCommand in commonMistakes) {
57
+ console.log(chalk_1.default.yellow(`Did you mean? ${chalk_1.default.bold(`berget ${commonMistakes[unknownCommand]}`)}`));
58
+ }
59
+ else {
60
+ // Try to find similar commands
61
+ const availableCommands = commander_1.program.commands.map(cmd => cmd.name());
62
+ const similarCommands = availableCommands.filter(cmd => cmd.includes(unknownCommand) || unknownCommand.includes(cmd));
63
+ if (similarCommands.length > 0) {
64
+ console.log(chalk_1.default.yellow('Similar commands:'));
65
+ similarCommands.forEach(cmd => {
66
+ console.log(chalk_1.default.yellow(` ${chalk_1.default.bold(`berget ${cmd}`)}`));
291
67
  });
292
68
  }
293
- console.log('');
294
- console.log(chalk_1.default.dim('Use these statistics to understand your API usage and optimize your costs.'));
295
- }
296
- catch (error) {
297
- (0, error_handler_1.handleError)('Failed to get API key usage', error);
69
+ console.log(chalk_1.default.blue('\nRun `berget --help` for a list of available commands.'));
298
70
  }
299
- }));
300
- // Cluster commands
301
- const cluster = commander_1.program
302
- .command(cluster_service_1.ClusterService.COMMAND_GROUP)
303
- .description('Manage Berget clusters');
304
- // Removed cluster create command as it's not available in the API
305
- cluster
306
- .command(cluster_service_1.ClusterService.COMMANDS.LIST)
307
- .description('List all Berget clusters')
308
- .action(() => __awaiter(void 0, void 0, void 0, function* () {
309
- try {
310
- const clusterService = cluster_service_1.ClusterService.getInstance();
311
- const clusters = yield clusterService.list();
312
- console.log('NAME STATUS NODES CREATED');
313
- clusters.forEach((cluster) => {
314
- console.log(`${cluster.name.padEnd(22)} ${cluster.status.padEnd(9)} ${String(cluster.nodes).padEnd(8)} ${cluster.created}`);
315
- });
316
- }
317
- catch (error) {
318
- (0, error_handler_1.handleError)('Failed to list clusters', error);
319
- }
320
- }));
321
- cluster
322
- .command(cluster_service_1.ClusterService.COMMANDS.GET_USAGE)
323
- .description('Get usage metrics for a specific cluster')
324
- .argument('<clusterId>', 'Cluster ID')
325
- .action((clusterId) => __awaiter(void 0, void 0, void 0, function* () {
326
- try {
327
- const clusterService = cluster_service_1.ClusterService.getInstance();
328
- const usage = yield clusterService.getUsage(clusterId);
329
- console.log('Cluster Usage:');
330
- console.log(JSON.stringify(usage, null, 2));
331
- }
332
- catch (error) {
333
- (0, error_handler_1.handleError)('Failed to get cluster usage', error);
334
- }
335
- }));
336
- cluster
337
- .command(cluster_service_1.ClusterService.COMMANDS.DESCRIBE)
338
- .description('Get detailed information about a cluster')
339
- .argument('<clusterId>', 'Cluster ID')
340
- .action((clusterId) => __awaiter(void 0, void 0, void 0, function* () {
341
- try {
342
- const clusterService = cluster_service_1.ClusterService.getInstance();
343
- const clusterInfo = yield clusterService.describe(clusterId);
344
- console.log('Cluster Details:');
345
- console.log(JSON.stringify(clusterInfo, null, 2));
346
- }
347
- catch (error) {
348
- (0, error_handler_1.handleError)('Failed to describe cluster', error);
349
- }
350
- }));
351
- // Autocomplete command
352
- commander_1.program
353
- .command('autocomplete')
354
- .command('install')
355
- .description('Install shell autocompletion')
356
- .action(() => {
357
- console.log(chalk_1.default.green('✓ Berget autocomplete installed in your shell'));
358
- console.log(chalk_1.default.green('✓ Shell completion for kubectl also installed'));
359
- console.log('');
360
- console.log('Restart your shell or run:');
361
- console.log(' source ~/.bashrc');
71
+ process.exit(1);
362
72
  });
363
- // Removed flux commands as they're not available in the API
364
- // Removed collaborator commands as they're not available in the API
365
- // Removed helm commands as they're not available in the API
366
- // Removed kubernetes-like commands as they're not available in the API
367
- // Add token usage command
368
- const billing = commander_1.program
369
- .command(command_structure_1.COMMAND_GROUPS.BILLING)
370
- .description('Manage billing and usage');
371
- billing
372
- .command(command_structure_1.SUBCOMMANDS.BILLING.GET_USAGE)
373
- .description('Get token usage statistics')
374
- .option('--model <modelId>', 'Get usage for a specific model')
375
- .action((options) => __awaiter(void 0, void 0, void 0, function* () {
376
- try {
377
- const client = (0, client_1.createAuthenticatedClient)();
378
- let response;
379
- if (options.model) {
380
- const { data, error } = yield client.GET('/v1/usage/tokens/{modelId}', {
381
- params: { path: { modelId: options.model } },
382
- });
383
- if (error)
384
- throw new Error(JSON.stringify(error));
385
- response = data;
386
- }
387
- else {
388
- const { data, error } = yield client.GET('/v1/usage/tokens');
389
- if (error)
390
- throw new Error(JSON.stringify(error));
391
- response = data;
392
- }
393
- console.log('Token Usage:');
394
- console.log(JSON.stringify(response, null, 2));
395
- }
396
- catch (error) {
397
- (0, error_handler_1.handleError)('Failed to get token usage', error);
398
- }
399
- }));
400
- // Add models command
401
- const models = commander_1.program
402
- .command(command_structure_1.COMMAND_GROUPS.MODELS)
403
- .description('Manage AI models');
404
- models
405
- .command(command_structure_1.SUBCOMMANDS.MODELS.LIST)
406
- .description('List available AI models')
407
- .option('--id <modelId>', 'Get details for a specific model')
408
- .action((options) => __awaiter(void 0, void 0, void 0, function* () {
409
- try {
410
- const client = (0, client_1.createAuthenticatedClient)();
411
- let response;
412
- if (options.id) {
413
- const { data, error } = yield client.GET('/v1/models/{modelId}', {
414
- params: { path: { modelId: options.id } },
415
- });
416
- if (error)
417
- throw new Error(JSON.stringify(error));
418
- response = data;
419
- console.log('Model Details:');
420
- console.log(JSON.stringify(response, null, 2));
421
- }
422
- else {
423
- const { data, error } = yield client.GET('/v1/models');
424
- if (error)
425
- throw new Error(JSON.stringify(error));
426
- response = data;
427
- console.log('Available Models:');
428
- console.log('ID OWNED BY CAPABILITIES');
429
- response.data.forEach((model) => {
430
- const capabilities = [];
431
- if (model.capabilities.vision)
432
- capabilities.push('vision');
433
- if (model.capabilities.function_calling)
434
- capabilities.push('function_calling');
435
- if (model.capabilities.json_mode)
436
- capabilities.push('json_mode');
437
- console.log(`${model.id.padEnd(24)} ${model.owned_by.padEnd(25)} ${capabilities.join(', ')}`);
438
- });
439
- }
440
- }
441
- catch (error) {
442
- (0, error_handler_1.handleError)('Failed to get models', error);
443
- }
444
- }));
445
- // Add team command
446
- const users = commander_1.program
447
- .command(command_structure_1.COMMAND_GROUPS.USERS)
448
- .description('Manage users');
449
- users
450
- .command(command_structure_1.SUBCOMMANDS.USERS.LIST)
451
- .description('List team members')
452
- .action(() => __awaiter(void 0, void 0, void 0, function* () {
453
- try {
454
- const client = (0, client_1.createAuthenticatedClient)();
455
- const { data, error } = yield client.GET('/v1/users');
456
- if (error)
457
- throw new Error(JSON.stringify(error));
458
- console.log('Team Members:');
459
- console.log('NAME EMAIL ROLE');
460
- data.forEach((user) => {
461
- console.log(`${user.name.padEnd(24)} ${user.email.padEnd(30)} ${user.role}`);
462
- });
463
- }
464
- catch (error) {
465
- (0, error_handler_1.handleError)('Failed to list team members', error);
466
- }
467
- }));
468
- // Auto-detect .bergetconfig and switch clusters
469
- const checkBergetConfig = () => {
470
- const configPath = path.join(process.cwd(), '.bergetconfig');
471
- if (fs.existsSync(configPath)) {
472
- try {
473
- const config = fs.readFileSync(configPath, 'utf8');
474
- const match = config.match(/cluster:\s*(.+)/);
475
- if (match && match[1]) {
476
- const clusterName = match[1].trim();
477
- console.log(`🔄 Berget: Switched to cluster "${clusterName}"`);
478
- console.log('✓ kubectl config updated');
479
- console.log('');
480
- }
481
- }
482
- catch (error) {
483
- // Silently ignore errors reading config
484
- }
485
- }
486
- };
487
- // Check for .bergetconfig if not running a command
488
- if (process.argv.length <= 2) {
489
- checkBergetConfig();
490
- }
491
73
  commander_1.program.parse(process.argv);
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "berget",
3
+ "version": "1.2.0",
4
+ "main": "dist/index.js",
5
+ "bin": {
6
+ "berget": "dist/index.js"
7
+ },
8
+ "private": false,
9
+ "scripts": {
10
+ "start": "node --import tsx ./index.ts --local",
11
+ "login": "node --import tsx ./index.ts --local auth login",
12
+ "logout": "node --import tsx ./index.ts --local auth logout",
13
+ "whoami": "node --import tsx ./index.ts --local auth whoami",
14
+ "build": "tsc",
15
+ "prepublishOnly": "npm run build",
16
+ "generate-types": "openapi-typescript https://api.berget.ai/openapi.json -o src/types/api.d.ts"
17
+ },
18
+ "author": "Berget AI AB",
19
+ "license": "MIT",
20
+ "description": "This is a cli command for interacting with the AI infrastructure provider Berget",
21
+ "devDependencies": {
22
+ "@types/node": "^20.11.20",
23
+ "tsx": "^4.19.3",
24
+ "typescript": "^5.3.3"
25
+ },
26
+ "dependencies": {
27
+ "chalk": "^4.1.2",
28
+ "commander": "^12.0.0",
29
+ "fs-extra": "^11.3.0",
30
+ "open": "^9.1.0",
31
+ "openapi-fetch": "^0.9.1",
32
+ "openapi-typescript": "^6.7.4",
33
+ "readline": "^1.3.0"
34
+ }
35
+ }