berget 0.0.2 → 0.0.4
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/.prettierrc +6 -0
- package/TODO.md +17 -0
- package/dist/index.js +447 -8
- package/dist/src/client.js +146 -0
- package/dist/src/services/api-key-service.js +114 -0
- package/dist/src/services/auth-service.js +168 -0
- package/dist/src/services/cluster-service.js +55 -0
- package/dist/src/services/collaborator-service.js +37 -0
- package/dist/src/services/flux-service.js +37 -0
- package/dist/src/services/helm-service.js +37 -0
- package/dist/src/services/kubectl-service.js +43 -0
- package/dist/src/utils/error-handler.js +45 -0
- package/index.ts +545 -12
- package/package.json +13 -7
- package/src/client.ts +123 -0
- package/src/services/api-key-service.ts +114 -0
- package/src/services/auth-service.ts +159 -0
- package/src/services/cluster-service.ts +50 -0
- package/src/services/collaborator-service.ts +34 -0
- package/src/services/flux-service.ts +37 -0
- package/src/services/helm-service.ts +37 -0
- package/src/services/kubectl-service.ts +33 -0
- package/src/types/api.d.ts +2037 -0
- package/src/utils/error-handler.ts +40 -0
package/.prettierrc
ADDED
package/TODO.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Berget CLI - TODO
|
|
2
|
+
|
|
3
|
+
## Implementerade funktioner
|
|
4
|
+
- [x] Inloggning med BankID
|
|
5
|
+
- [x] Skapa och hantera API-nycklar
|
|
6
|
+
|
|
7
|
+
## Kommande funktioner
|
|
8
|
+
- [ ] Implementera riktiga API-anrop för klusterhantering
|
|
9
|
+
- [ ] Implementera riktiga API-anrop för Flux-integration
|
|
10
|
+
- [ ] Implementera riktiga API-anrop för Helm-kommandon
|
|
11
|
+
- [ ] Implementera riktiga API-anrop för Kubectl-kommandon
|
|
12
|
+
- [ ] Implementera riktiga API-anrop för samarbetsfunktioner
|
|
13
|
+
- [ ] Förbättra felhantering och återhämtning
|
|
14
|
+
- [ ] Lägg till enhetstester
|
|
15
|
+
- [ ] Implementera lokal konfigurationshantering
|
|
16
|
+
- [ ] Lägg till stöd för olika miljöer (dev, staging, prod)
|
|
17
|
+
- [ ] Förbättra dokumentation och hjälptexter
|
package/dist/index.js
CHANGED
|
@@ -1,20 +1,459 @@
|
|
|
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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
3
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
39
|
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");
|
|
44
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
45
|
+
// Set version and description
|
|
46
|
+
commander_1.program
|
|
47
|
+
.name('berget')
|
|
48
|
+
.description(`______ _ ___ _____
|
|
49
|
+
| ___ \\ | | / _ \\|_ _|
|
|
50
|
+
| |_/ / ___ _ __ __ _ ___| |_ / /_\\ \\ | |
|
|
51
|
+
| ___ \\/ _ \\ '__/ _\` |/ _ \\ __| | _ | | |
|
|
52
|
+
| |_/ / __/ | | (_| | __/ |_ | | | |_| |_
|
|
53
|
+
\\____/ \\___|_| \\__, |\\___|\\_\\_ \\_| |_/\\___/
|
|
54
|
+
__/ |
|
|
55
|
+
|___/ AI on European terms`)
|
|
56
|
+
.version(process.env.npm_package_version || '0.0.1', '-v, --version')
|
|
57
|
+
.option('--local', 'Use local API endpoint (hidden)', false);
|
|
58
|
+
// Import services
|
|
59
|
+
const auth_service_1 = require("./src/services/auth-service");
|
|
60
|
+
const api_key_service_1 = require("./src/services/api-key-service");
|
|
61
|
+
const cluster_service_1 = require("./src/services/cluster-service");
|
|
62
|
+
// Auth commands
|
|
5
63
|
commander_1.program
|
|
6
64
|
.command('login')
|
|
7
|
-
.description('
|
|
65
|
+
.description('Log in to Berget')
|
|
66
|
+
.action(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
67
|
+
const authService = auth_service_1.AuthService.getInstance();
|
|
68
|
+
yield authService.login();
|
|
69
|
+
}));
|
|
70
|
+
commander_1.program
|
|
71
|
+
.command('logout')
|
|
72
|
+
.description('Log out from Berget')
|
|
8
73
|
.action(() => {
|
|
9
|
-
|
|
10
|
-
|
|
74
|
+
const { clearAuthToken } = require('./src/client');
|
|
75
|
+
clearAuthToken();
|
|
76
|
+
console.log(chalk_1.default.green('You have been logged out from Berget'));
|
|
11
77
|
});
|
|
12
78
|
commander_1.program
|
|
13
|
-
.command('
|
|
14
|
-
.description('
|
|
79
|
+
.command('whoami')
|
|
80
|
+
.description('Show information about the logged in user')
|
|
81
|
+
.action(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
82
|
+
try {
|
|
83
|
+
const authService = auth_service_1.AuthService.getInstance();
|
|
84
|
+
const profile = yield authService.getUserProfile();
|
|
85
|
+
if (profile) {
|
|
86
|
+
console.log(chalk_1.default.bold(`Logged in as: ${profile.name || profile.login}`));
|
|
87
|
+
console.log(`Email: ${chalk_1.default.cyan(profile.email || 'Not available')}`);
|
|
88
|
+
console.log(`Role: ${chalk_1.default.cyan(profile.role || 'Not available')}`);
|
|
89
|
+
if (profile.company) {
|
|
90
|
+
console.log(`Company: ${chalk_1.default.cyan(profile.company.name)}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
console.log(chalk_1.default.yellow('You are not logged in. Use `berget login` to log in.'));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
(0, error_handler_1.handleError)('You are not logged in or an error occurred', error);
|
|
99
|
+
}
|
|
100
|
+
}));
|
|
101
|
+
// API Key commands
|
|
102
|
+
const apiKey = commander_1.program.command('api-key').description('Manage API keys');
|
|
103
|
+
apiKey
|
|
104
|
+
.command('list')
|
|
105
|
+
.description('List all API keys')
|
|
106
|
+
.action(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
107
|
+
try {
|
|
108
|
+
const apiKeyService = api_key_service_1.ApiKeyService.getInstance();
|
|
109
|
+
const keys = yield apiKeyService.listApiKeys();
|
|
110
|
+
if (keys.length === 0) {
|
|
111
|
+
console.log(chalk_1.default.yellow('No API keys found. Create one with `berget api-key create --name <name>`'));
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
console.log(chalk_1.default.bold('Your API keys:'));
|
|
115
|
+
console.log('');
|
|
116
|
+
// Create a table-like format with headers
|
|
117
|
+
console.log(chalk_1.default.dim('ID'.padEnd(10)) +
|
|
118
|
+
chalk_1.default.dim('NAME'.padEnd(25)) +
|
|
119
|
+
chalk_1.default.dim('PREFIX'.padEnd(12)) +
|
|
120
|
+
chalk_1.default.dim('STATUS'.padEnd(12)) +
|
|
121
|
+
chalk_1.default.dim('CREATED'.padEnd(12)) +
|
|
122
|
+
chalk_1.default.dim('LAST USED'));
|
|
123
|
+
console.log(chalk_1.default.dim('─'.repeat(85)));
|
|
124
|
+
keys.forEach((key) => {
|
|
125
|
+
const lastUsed = key.lastUsed ? key.lastUsed.substring(0, 10) : 'Never';
|
|
126
|
+
const status = key.active
|
|
127
|
+
? chalk_1.default.green('● Active')
|
|
128
|
+
: chalk_1.default.red('● Inactive');
|
|
129
|
+
console.log(String(key.id).padEnd(10) +
|
|
130
|
+
key.name.padEnd(25) +
|
|
131
|
+
key.prefix.padEnd(12) +
|
|
132
|
+
status.padEnd(12) +
|
|
133
|
+
key.created.substring(0, 10).padEnd(12) +
|
|
134
|
+
lastUsed);
|
|
135
|
+
});
|
|
136
|
+
console.log('');
|
|
137
|
+
console.log(chalk_1.default.dim('Use `berget api-key create --name <name>` to create a new API key'));
|
|
138
|
+
console.log(chalk_1.default.dim('Use `berget api-key delete <id>` to delete an API key'));
|
|
139
|
+
console.log(chalk_1.default.dim('Use `berget api-key rotate <id>` to rotate an API key'));
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
(0, error_handler_1.handleError)('Failed to list API keys', error);
|
|
143
|
+
}
|
|
144
|
+
}));
|
|
145
|
+
apiKey
|
|
146
|
+
.command('create')
|
|
147
|
+
.description('Create a new API key')
|
|
148
|
+
.option('--name <name>', 'Name of the API key')
|
|
149
|
+
.option('--description <description>', 'Description of the API key')
|
|
150
|
+
.action((options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
151
|
+
try {
|
|
152
|
+
if (!options.name) {
|
|
153
|
+
console.error(chalk_1.default.red('Error: --name is required'));
|
|
154
|
+
console.log('');
|
|
155
|
+
console.log('Usage: berget api-key create --name <name> [--description <description>]');
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
console.log(chalk_1.default.blue('Creating API key...'));
|
|
159
|
+
const apiKeyService = api_key_service_1.ApiKeyService.getInstance();
|
|
160
|
+
const result = yield apiKeyService.createApiKey({
|
|
161
|
+
name: options.name,
|
|
162
|
+
description: options.description,
|
|
163
|
+
});
|
|
164
|
+
console.log('');
|
|
165
|
+
console.log(chalk_1.default.green('✓ API key created'));
|
|
166
|
+
console.log('');
|
|
167
|
+
console.log(chalk_1.default.bold('API key details:'));
|
|
168
|
+
console.log('');
|
|
169
|
+
console.log(`${chalk_1.default.dim('ID:')} ${result.id}`);
|
|
170
|
+
console.log(`${chalk_1.default.dim('Name:')} ${result.name}`);
|
|
171
|
+
if (result.description) {
|
|
172
|
+
console.log(`${chalk_1.default.dim('Description:')} ${result.description}`);
|
|
173
|
+
}
|
|
174
|
+
console.log(`${chalk_1.default.dim('Created:')} ${new Date(result.created).toLocaleString()}`);
|
|
175
|
+
console.log('');
|
|
176
|
+
console.log(chalk_1.default.bold('API key:'));
|
|
177
|
+
console.log(chalk_1.default.cyan(result.key));
|
|
178
|
+
console.log('');
|
|
179
|
+
console.log(chalk_1.default.yellow('⚠️ IMPORTANT: Save this API key in a secure location.'));
|
|
180
|
+
console.log(chalk_1.default.yellow(' It will not be displayed again.'));
|
|
181
|
+
console.log('');
|
|
182
|
+
console.log(chalk_1.default.dim('Use this key in your applications to authenticate with the Berget API.'));
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
(0, error_handler_1.handleError)('Failed to create API key', error);
|
|
186
|
+
}
|
|
187
|
+
}));
|
|
188
|
+
apiKey
|
|
189
|
+
.command('delete')
|
|
190
|
+
.description('Delete an API key')
|
|
191
|
+
.argument('<id>', 'ID of the API key to delete')
|
|
192
|
+
.action((id) => __awaiter(void 0, void 0, void 0, function* () {
|
|
193
|
+
try {
|
|
194
|
+
console.log(chalk_1.default.blue(`Deleting API key ${id}...`));
|
|
195
|
+
const apiKeyService = api_key_service_1.ApiKeyService.getInstance();
|
|
196
|
+
yield apiKeyService.deleteApiKey(id);
|
|
197
|
+
console.log(chalk_1.default.green(`✓ API key ${id} has been deleted`));
|
|
198
|
+
console.log('');
|
|
199
|
+
console.log(chalk_1.default.dim('Applications using this key will no longer be able to authenticate.'));
|
|
200
|
+
console.log(chalk_1.default.dim('Use `berget api-key list` to see your remaining API keys.'));
|
|
201
|
+
}
|
|
202
|
+
catch (error) {
|
|
203
|
+
(0, error_handler_1.handleError)('Failed to delete API key', error);
|
|
204
|
+
}
|
|
205
|
+
}));
|
|
206
|
+
apiKey
|
|
207
|
+
.command('rotate')
|
|
208
|
+
.description('Rotate an API key (creates a new one and invalidates the old one)')
|
|
209
|
+
.argument('<id>', 'ID of the API key to rotate')
|
|
210
|
+
.action((id) => __awaiter(void 0, void 0, void 0, function* () {
|
|
211
|
+
try {
|
|
212
|
+
console.log(chalk_1.default.blue(`Rotating API key ${id}...`));
|
|
213
|
+
console.log(chalk_1.default.dim('This will invalidate the old key and generate a new one.'));
|
|
214
|
+
const apiKeyService = api_key_service_1.ApiKeyService.getInstance();
|
|
215
|
+
const result = yield apiKeyService.rotateApiKey(id);
|
|
216
|
+
console.log('');
|
|
217
|
+
console.log(chalk_1.default.green('✓ API key rotated'));
|
|
218
|
+
console.log('');
|
|
219
|
+
console.log(chalk_1.default.bold('New API key details:'));
|
|
220
|
+
console.log('');
|
|
221
|
+
console.log(`${chalk_1.default.dim('ID:')} ${result.id}`);
|
|
222
|
+
console.log(`${chalk_1.default.dim('Name:')} ${result.name}`);
|
|
223
|
+
if (result.description) {
|
|
224
|
+
console.log(`${chalk_1.default.dim('Description:')} ${result.description}`);
|
|
225
|
+
}
|
|
226
|
+
console.log(`${chalk_1.default.dim('Created:')} ${new Date(result.created).toLocaleString()}`);
|
|
227
|
+
console.log('');
|
|
228
|
+
console.log(chalk_1.default.bold('New API key:'));
|
|
229
|
+
console.log(chalk_1.default.cyan(result.key));
|
|
230
|
+
console.log('');
|
|
231
|
+
console.log(chalk_1.default.yellow('⚠️ IMPORTANT: Update your applications with this new API key.'));
|
|
232
|
+
console.log(chalk_1.default.yellow(' The old key has been invalidated and will no longer work.'));
|
|
233
|
+
console.log(chalk_1.default.yellow(' This new key will not be displayed again.'));
|
|
234
|
+
}
|
|
235
|
+
catch (error) {
|
|
236
|
+
(0, error_handler_1.handleError)('Failed to rotate API key', error);
|
|
237
|
+
}
|
|
238
|
+
}));
|
|
239
|
+
apiKey
|
|
240
|
+
.command('usage')
|
|
241
|
+
.description('Show usage statistics for an API key')
|
|
242
|
+
.argument('<id>', 'ID of the API key')
|
|
243
|
+
.option('--start <date>', 'Start date (YYYY-MM-DD)')
|
|
244
|
+
.option('--end <date>', 'End date (YYYY-MM-DD)')
|
|
245
|
+
.action((id, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
246
|
+
try {
|
|
247
|
+
console.log(chalk_1.default.blue(`Fetching usage statistics for API key ${id}...`));
|
|
248
|
+
const apiKeyService = api_key_service_1.ApiKeyService.getInstance();
|
|
249
|
+
const usage = yield apiKeyService.getApiKeyUsage(id);
|
|
250
|
+
console.log('');
|
|
251
|
+
console.log(chalk_1.default.bold(`Usage statistics for API key: ${usage.name} (${id})`));
|
|
252
|
+
console.log('');
|
|
253
|
+
// Period information
|
|
254
|
+
console.log(chalk_1.default.dim(`Period: ${usage.period.start} to ${usage.period.end}`));
|
|
255
|
+
console.log('');
|
|
256
|
+
// Request statistics
|
|
257
|
+
console.log(chalk_1.default.bold('Request statistics:'));
|
|
258
|
+
console.log(`Total requests: ${chalk_1.default.cyan(usage.requests.total.toLocaleString())}`);
|
|
259
|
+
// Daily breakdown if available
|
|
260
|
+
if (usage.requests.daily && usage.requests.daily.length > 0) {
|
|
261
|
+
console.log('');
|
|
262
|
+
console.log(chalk_1.default.bold('Daily breakdown:'));
|
|
263
|
+
console.log(chalk_1.default.dim('─'.repeat(30)));
|
|
264
|
+
console.log(chalk_1.default.dim('DATE'.padEnd(12) + 'REQUESTS'));
|
|
265
|
+
usage.requests.daily.forEach((day) => {
|
|
266
|
+
console.log(`${day.date.padEnd(12)}${day.count.toLocaleString()}`);
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
// Model usage if available
|
|
270
|
+
if (usage.models && usage.models.length > 0) {
|
|
271
|
+
console.log('');
|
|
272
|
+
console.log(chalk_1.default.bold('Model usage:'));
|
|
273
|
+
console.log(chalk_1.default.dim('─'.repeat(70)));
|
|
274
|
+
console.log(chalk_1.default.dim('MODEL'.padEnd(20)) +
|
|
275
|
+
chalk_1.default.dim('REQUESTS'.padEnd(10)) +
|
|
276
|
+
chalk_1.default.dim('INPUT'.padEnd(12)) +
|
|
277
|
+
chalk_1.default.dim('OUTPUT'.padEnd(12)) +
|
|
278
|
+
chalk_1.default.dim('TOTAL TOKENS'));
|
|
279
|
+
usage.models.forEach((model) => {
|
|
280
|
+
console.log(model.name.padEnd(20) +
|
|
281
|
+
model.requests.toString().padEnd(10) +
|
|
282
|
+
model.tokens.input.toLocaleString().padEnd(12) +
|
|
283
|
+
model.tokens.output.toLocaleString().padEnd(12) +
|
|
284
|
+
model.tokens.total.toLocaleString());
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
console.log('');
|
|
288
|
+
console.log(chalk_1.default.dim('Use these statistics to understand your API usage and optimize your costs.'));
|
|
289
|
+
}
|
|
290
|
+
catch (error) {
|
|
291
|
+
(0, error_handler_1.handleError)('Failed to get API key usage', error);
|
|
292
|
+
}
|
|
293
|
+
}));
|
|
294
|
+
// Cluster commands
|
|
295
|
+
const cluster = commander_1.program.command('cluster').description('Manage Berget clusters');
|
|
296
|
+
// Removed cluster create command as it's not available in the API
|
|
297
|
+
cluster
|
|
298
|
+
.command('list')
|
|
299
|
+
.description('List all Berget clusters')
|
|
300
|
+
.action(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
301
|
+
try {
|
|
302
|
+
const clusterService = cluster_service_1.ClusterService.getInstance();
|
|
303
|
+
const clusters = yield clusterService.listClusters();
|
|
304
|
+
console.log('NAME STATUS NODES CREATED');
|
|
305
|
+
clusters.forEach((cluster) => {
|
|
306
|
+
console.log(`${cluster.name.padEnd(22)} ${cluster.status.padEnd(9)} ${String(cluster.nodes).padEnd(8)} ${cluster.created}`);
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
catch (error) {
|
|
310
|
+
(0, error_handler_1.handleError)('Failed to list clusters', error);
|
|
311
|
+
}
|
|
312
|
+
}));
|
|
313
|
+
cluster
|
|
314
|
+
.command('usage')
|
|
315
|
+
.description('Get usage metrics for a specific cluster')
|
|
316
|
+
.argument('<clusterId>', 'Cluster ID')
|
|
317
|
+
.action((clusterId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
318
|
+
try {
|
|
319
|
+
const clusterService = cluster_service_1.ClusterService.getInstance();
|
|
320
|
+
const usage = yield clusterService.getClusterUsage(clusterId);
|
|
321
|
+
console.log('Cluster Usage:');
|
|
322
|
+
console.log(JSON.stringify(usage, null, 2));
|
|
323
|
+
}
|
|
324
|
+
catch (error) {
|
|
325
|
+
(0, error_handler_1.handleError)('Failed to get cluster usage', error);
|
|
326
|
+
}
|
|
327
|
+
}));
|
|
328
|
+
// Autocomplete command
|
|
329
|
+
commander_1.program
|
|
330
|
+
.command('autocomplete')
|
|
331
|
+
.command('install')
|
|
332
|
+
.description('Install shell autocompletion')
|
|
15
333
|
.action(() => {
|
|
16
|
-
console.log('
|
|
17
|
-
|
|
18
|
-
|
|
334
|
+
console.log(chalk_1.default.green('✓ Berget autocomplete installed in your shell'));
|
|
335
|
+
console.log(chalk_1.default.green('✓ Shell completion for kubectl also installed'));
|
|
336
|
+
console.log('');
|
|
337
|
+
console.log('Restart your shell or run:');
|
|
338
|
+
console.log(' source ~/.bashrc');
|
|
19
339
|
});
|
|
340
|
+
// Removed flux commands as they're not available in the API
|
|
341
|
+
// Removed collaborator commands as they're not available in the API
|
|
342
|
+
// Removed helm commands as they're not available in the API
|
|
343
|
+
// Removed kubernetes-like commands as they're not available in the API
|
|
344
|
+
// Add token usage command
|
|
345
|
+
commander_1.program
|
|
346
|
+
.command('token-usage')
|
|
347
|
+
.description('Get token usage statistics')
|
|
348
|
+
.option('--model <modelId>', 'Get usage for a specific model')
|
|
349
|
+
.action((options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
350
|
+
try {
|
|
351
|
+
const client = (0, client_1.createAuthenticatedClient)();
|
|
352
|
+
let response;
|
|
353
|
+
if (options.model) {
|
|
354
|
+
const { data, error } = yield client.GET('/v1/usage/tokens/{modelId}', {
|
|
355
|
+
params: { path: { modelId: options.model } },
|
|
356
|
+
});
|
|
357
|
+
if (error)
|
|
358
|
+
throw new Error(JSON.stringify(error));
|
|
359
|
+
response = data;
|
|
360
|
+
}
|
|
361
|
+
else {
|
|
362
|
+
const { data, error } = yield client.GET('/v1/usage/tokens');
|
|
363
|
+
if (error)
|
|
364
|
+
throw new Error(JSON.stringify(error));
|
|
365
|
+
response = data;
|
|
366
|
+
}
|
|
367
|
+
console.log('Token Usage:');
|
|
368
|
+
console.log(JSON.stringify(response, null, 2));
|
|
369
|
+
}
|
|
370
|
+
catch (error) {
|
|
371
|
+
(0, error_handler_1.handleError)('Failed to get token usage', error);
|
|
372
|
+
}
|
|
373
|
+
}));
|
|
374
|
+
// Add models command
|
|
375
|
+
commander_1.program
|
|
376
|
+
.command('models')
|
|
377
|
+
.description('List available AI models')
|
|
378
|
+
.option('--id <modelId>', 'Get details for a specific model')
|
|
379
|
+
.action((options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
380
|
+
try {
|
|
381
|
+
const client = (0, client_1.createAuthenticatedClient)();
|
|
382
|
+
let response;
|
|
383
|
+
if (options.id) {
|
|
384
|
+
const { data, error } = yield client.GET('/v1/models/{modelId}', {
|
|
385
|
+
params: { path: { modelId: options.id } },
|
|
386
|
+
});
|
|
387
|
+
if (error)
|
|
388
|
+
throw new Error(JSON.stringify(error));
|
|
389
|
+
response = data;
|
|
390
|
+
console.log('Model Details:');
|
|
391
|
+
console.log(JSON.stringify(response, null, 2));
|
|
392
|
+
}
|
|
393
|
+
else {
|
|
394
|
+
const { data, error } = yield client.GET('/v1/models');
|
|
395
|
+
if (error)
|
|
396
|
+
throw new Error(JSON.stringify(error));
|
|
397
|
+
response = data;
|
|
398
|
+
console.log('Available Models:');
|
|
399
|
+
console.log('ID OWNED BY CAPABILITIES');
|
|
400
|
+
response.data.forEach((model) => {
|
|
401
|
+
const capabilities = [];
|
|
402
|
+
if (model.capabilities.vision)
|
|
403
|
+
capabilities.push('vision');
|
|
404
|
+
if (model.capabilities.function_calling)
|
|
405
|
+
capabilities.push('function_calling');
|
|
406
|
+
if (model.capabilities.json_mode)
|
|
407
|
+
capabilities.push('json_mode');
|
|
408
|
+
console.log(`${model.id.padEnd(24)} ${model.owned_by.padEnd(25)} ${capabilities.join(', ')}`);
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
catch (error) {
|
|
413
|
+
(0, error_handler_1.handleError)('Failed to get models', error);
|
|
414
|
+
}
|
|
415
|
+
}));
|
|
416
|
+
// Add team command
|
|
417
|
+
commander_1.program
|
|
418
|
+
.command('team')
|
|
419
|
+
.description('Manage team members')
|
|
420
|
+
.action(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
421
|
+
try {
|
|
422
|
+
const client = (0, client_1.createAuthenticatedClient)();
|
|
423
|
+
const { data, error } = yield client.GET('/v1/users');
|
|
424
|
+
if (error)
|
|
425
|
+
throw new Error(JSON.stringify(error));
|
|
426
|
+
console.log('Team Members:');
|
|
427
|
+
console.log('NAME EMAIL ROLE');
|
|
428
|
+
data.forEach((user) => {
|
|
429
|
+
console.log(`${user.name.padEnd(24)} ${user.email.padEnd(30)} ${user.role}`);
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
catch (error) {
|
|
433
|
+
(0, error_handler_1.handleError)('Failed to list team members', error);
|
|
434
|
+
}
|
|
435
|
+
}));
|
|
436
|
+
// Auto-detect .bergetconfig and switch clusters
|
|
437
|
+
const checkBergetConfig = () => {
|
|
438
|
+
const configPath = path.join(process.cwd(), '.bergetconfig');
|
|
439
|
+
if (fs.existsSync(configPath)) {
|
|
440
|
+
try {
|
|
441
|
+
const config = fs.readFileSync(configPath, 'utf8');
|
|
442
|
+
const match = config.match(/cluster:\s*(.+)/);
|
|
443
|
+
if (match && match[1]) {
|
|
444
|
+
const clusterName = match[1].trim();
|
|
445
|
+
console.log(`🔄 Berget: Switched to cluster "${clusterName}"`);
|
|
446
|
+
console.log('✓ kubectl config updated');
|
|
447
|
+
console.log('');
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
catch (error) {
|
|
451
|
+
// Silently ignore errors reading config
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
};
|
|
455
|
+
// Check for .bergetconfig if not running a command
|
|
456
|
+
if (process.argv.length <= 2) {
|
|
457
|
+
checkBergetConfig();
|
|
458
|
+
}
|
|
20
459
|
commander_1.program.parse(process.argv);
|
|
@@ -0,0 +1,146 @@
|
|
|
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 (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.createAuthenticatedClient = exports.clearAuthToken = exports.saveAuthToken = exports.isTokenExpired = exports.getAuthToken = exports.apiClient = void 0;
|
|
30
|
+
const openapi_fetch_1 = __importDefault(require("openapi-fetch"));
|
|
31
|
+
const fs = __importStar(require("fs"));
|
|
32
|
+
const path = __importStar(require("path"));
|
|
33
|
+
const os = __importStar(require("os"));
|
|
34
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
35
|
+
// Configuration directory
|
|
36
|
+
const CONFIG_DIR = path.join(os.homedir(), '.berget');
|
|
37
|
+
const TOKEN_FILE = path.join(CONFIG_DIR, 'token.json');
|
|
38
|
+
// API Base URL
|
|
39
|
+
// Use --local flag to test against local API
|
|
40
|
+
const isLocalMode = process.argv.includes('--local');
|
|
41
|
+
const API_BASE_URL = process.env.BERGET_API_URL ||
|
|
42
|
+
(isLocalMode ? 'http://localhost:3000' : 'https://api.berget.ai');
|
|
43
|
+
if (isLocalMode && !process.env.BERGET_API_URL) {
|
|
44
|
+
console.log(chalk_1.default.yellow('Using local API endpoint: http://localhost:3000'));
|
|
45
|
+
}
|
|
46
|
+
// Create a typed client for the Berget API
|
|
47
|
+
exports.apiClient = (0, openapi_fetch_1.default)({
|
|
48
|
+
baseUrl: API_BASE_URL,
|
|
49
|
+
headers: {
|
|
50
|
+
'Content-Type': 'application/json',
|
|
51
|
+
'Accept': 'application/json'
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
// Authentication functions
|
|
55
|
+
const getAuthToken = () => {
|
|
56
|
+
try {
|
|
57
|
+
if (fs.existsSync(TOKEN_FILE)) {
|
|
58
|
+
const tokenData = JSON.parse(fs.readFileSync(TOKEN_FILE, 'utf8'));
|
|
59
|
+
return tokenData.accessToken;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
console.error('Error reading auth token:', error);
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
};
|
|
67
|
+
exports.getAuthToken = getAuthToken;
|
|
68
|
+
// Check if token is expired (JWT tokens have an exp claim)
|
|
69
|
+
const isTokenExpired = (token) => {
|
|
70
|
+
try {
|
|
71
|
+
const base64Url = token.split('.')[1];
|
|
72
|
+
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
|
|
73
|
+
const jsonPayload = decodeURIComponent(atob(base64)
|
|
74
|
+
.split('')
|
|
75
|
+
.map(c => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2))
|
|
76
|
+
.join(''));
|
|
77
|
+
const payload = JSON.parse(jsonPayload);
|
|
78
|
+
// Check if token has expired
|
|
79
|
+
if (payload.exp) {
|
|
80
|
+
return payload.exp * 1000 < Date.now();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
// If we can't decode the token, assume it's expired
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
// If there's no exp claim, assume it's valid
|
|
88
|
+
return false;
|
|
89
|
+
};
|
|
90
|
+
exports.isTokenExpired = isTokenExpired;
|
|
91
|
+
const saveAuthToken = (token) => {
|
|
92
|
+
try {
|
|
93
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
94
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
95
|
+
}
|
|
96
|
+
fs.writeFileSync(TOKEN_FILE, JSON.stringify({ accessToken: token }), 'utf8');
|
|
97
|
+
// Set file permissions to be readable only by the owner
|
|
98
|
+
fs.chmodSync(TOKEN_FILE, 0o600);
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
console.error('Error saving auth token:', error);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
exports.saveAuthToken = saveAuthToken;
|
|
105
|
+
const clearAuthToken = () => {
|
|
106
|
+
try {
|
|
107
|
+
if (fs.existsSync(TOKEN_FILE)) {
|
|
108
|
+
fs.unlinkSync(TOKEN_FILE);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
console.error('Error clearing auth token:', error);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
exports.clearAuthToken = clearAuthToken;
|
|
116
|
+
// Create an authenticated client
|
|
117
|
+
const createAuthenticatedClient = () => {
|
|
118
|
+
const token = (0, exports.getAuthToken)();
|
|
119
|
+
if (!token) {
|
|
120
|
+
console.warn(chalk_1.default.yellow('No authentication token found. Please run `berget login` first.'));
|
|
121
|
+
}
|
|
122
|
+
else if ((0, exports.isTokenExpired)(token)) {
|
|
123
|
+
console.warn(chalk_1.default.yellow('Your authentication token has expired. Please run `berget login` to get a new token.'));
|
|
124
|
+
// Optionally clear the expired token
|
|
125
|
+
(0, exports.clearAuthToken)();
|
|
126
|
+
return (0, openapi_fetch_1.default)({
|
|
127
|
+
baseUrl: API_BASE_URL,
|
|
128
|
+
headers: {
|
|
129
|
+
'Content-Type': 'application/json',
|
|
130
|
+
'Accept': 'application/json'
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
return (0, openapi_fetch_1.default)({
|
|
135
|
+
baseUrl: API_BASE_URL,
|
|
136
|
+
headers: token ? {
|
|
137
|
+
'Authorization': `Bearer ${token}`,
|
|
138
|
+
'Content-Type': 'application/json',
|
|
139
|
+
'Accept': 'application/json'
|
|
140
|
+
} : {
|
|
141
|
+
'Content-Type': 'application/json',
|
|
142
|
+
'Accept': 'application/json'
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
};
|
|
146
|
+
exports.createAuthenticatedClient = createAuthenticatedClient;
|