berget 1.1.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.
- package/dist/index.js +47 -1
- package/dist/package.json +35 -0
- package/dist/src/client.js +24 -7
- package/dist/src/commands/api-keys.js +13 -7
- package/dist/src/commands/chat.js +84 -18
- package/dist/src/services/api-key-service.js +6 -16
- package/dist/src/services/chat-service.js +159 -36
- package/dist/src/utils/default-api-key.js +131 -5
- package/dist/src/utils/error-handler.js +4 -4
- package/index.ts +52 -1
- package/package.json +3 -2
- package/src/client.ts +23 -6
- package/src/commands/api-keys.ts +17 -7
- package/src/commands/chat.ts +122 -22
- package/src/services/api-key-service.ts +12 -20
- package/src/services/chat-service.ts +158 -40
- package/src/types/api.d.ts +203 -9
- package/src/types/json.d.ts +4 -0
- package/src/utils/default-api-key.ts +141 -6
- package/src/utils/error-handler.ts +4 -4
- package/tsconfig.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
3
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
7
|
const commander_1 = require("commander");
|
|
5
8
|
const commands_1 = require("./src/commands");
|
|
6
9
|
const config_checker_1 = require("./src/utils/config-checker");
|
|
10
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
11
|
+
const package_json_1 = require("./package.json");
|
|
7
12
|
// Set version and description
|
|
8
13
|
commander_1.program
|
|
9
14
|
.name('berget')
|
|
@@ -15,7 +20,7 @@ commander_1.program
|
|
|
15
20
|
\\____/ \\___|_| \\__, |\\___|\\_\\_ \\_| |_/\\___/
|
|
16
21
|
__/ |
|
|
17
22
|
|___/ AI on European terms`)
|
|
18
|
-
.version(
|
|
23
|
+
.version(package_json_1.version, '-v, --version')
|
|
19
24
|
.option('--local', 'Use local API endpoint (hidden)', false)
|
|
20
25
|
.option('--debug', 'Enable debug output', false);
|
|
21
26
|
// Register all commands
|
|
@@ -23,5 +28,46 @@ commander_1.program
|
|
|
23
28
|
// Check for .bergetconfig if not running a command
|
|
24
29
|
if (process.argv.length <= 2) {
|
|
25
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.`));
|
|
26
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}`)}`));
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
console.log(chalk_1.default.blue('\nRun `berget --help` for a list of available commands.'));
|
|
70
|
+
}
|
|
71
|
+
process.exit(1);
|
|
72
|
+
});
|
|
27
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
|
+
}
|
package/dist/src/client.js
CHANGED
|
@@ -110,21 +110,38 @@ const createAuthenticatedClient = () => {
|
|
|
110
110
|
// If we get an auth error, try to refresh the token and retry
|
|
111
111
|
if (result.error) {
|
|
112
112
|
// Detect various forms of authentication errors
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
113
|
+
let isAuthError = false;
|
|
114
|
+
try {
|
|
115
|
+
// Standard 401 Unauthorized
|
|
116
|
+
if (typeof result.error === 'object' && result.error.status === 401) {
|
|
117
|
+
isAuthError = true;
|
|
118
|
+
}
|
|
116
119
|
// OAuth specific errors
|
|
117
|
-
(result.error.error &&
|
|
120
|
+
else if (result.error.error &&
|
|
118
121
|
(result.error.error.code === 'invalid_token' ||
|
|
119
122
|
result.error.error.code === 'token_expired' ||
|
|
120
123
|
result.error.error.message === 'Invalid API key' ||
|
|
121
124
|
((_a = result.error.error.message) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes('token')) ||
|
|
122
|
-
((_b = result.error.error.message) === null || _b === void 0 ? void 0 : _b.toLowerCase().includes('unauthorized'))))
|
|
125
|
+
((_b = result.error.error.message) === null || _b === void 0 ? void 0 : _b.toLowerCase().includes('unauthorized')))) {
|
|
126
|
+
isAuthError = true;
|
|
127
|
+
}
|
|
123
128
|
// Message-based detection as fallback
|
|
124
|
-
(typeof result.error === 'string' &&
|
|
129
|
+
else if (typeof result.error === 'string' &&
|
|
125
130
|
(result.error.toLowerCase().includes('unauthorized') ||
|
|
126
131
|
result.error.toLowerCase().includes('token') ||
|
|
127
|
-
result.error.toLowerCase().includes('auth')))
|
|
132
|
+
result.error.toLowerCase().includes('auth'))) {
|
|
133
|
+
isAuthError = true;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
catch (parseError) {
|
|
137
|
+
// If we can't parse the error structure, do a simple string check
|
|
138
|
+
const errorStr = String(result.error);
|
|
139
|
+
if (errorStr.toLowerCase().includes('unauthorized') ||
|
|
140
|
+
errorStr.toLowerCase().includes('token') ||
|
|
141
|
+
errorStr.toLowerCase().includes('auth')) {
|
|
142
|
+
isAuthError = true;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
128
145
|
if (isAuthError && tokenManager.getRefreshToken()) {
|
|
129
146
|
if (process.argv.includes('--debug')) {
|
|
130
147
|
console.log(chalk_1.default.yellow('DEBUG: Auth error detected, attempting token refresh'));
|
|
@@ -50,9 +50,13 @@ function registerApiKeyCommands(program) {
|
|
|
50
50
|
const status = key.active
|
|
51
51
|
? chalk_1.default.green('● Active')
|
|
52
52
|
: chalk_1.default.red('● Inactive');
|
|
53
|
+
// Format the prefix to ensure it's not too long
|
|
54
|
+
const prefixStr = key.prefix.length > 12
|
|
55
|
+
? key.prefix.substring(0, 12) + '...'
|
|
56
|
+
: key.prefix;
|
|
53
57
|
console.log(String(key.id).padEnd(10) +
|
|
54
58
|
key.name.padEnd(25) +
|
|
55
|
-
|
|
59
|
+
prefixStr.padEnd(15) +
|
|
56
60
|
status.padEnd(12) +
|
|
57
61
|
key.created.substring(0, 10).padEnd(12) +
|
|
58
62
|
lastUsed);
|
|
@@ -230,7 +234,9 @@ function registerApiKeyCommands(program) {
|
|
|
230
234
|
}
|
|
231
235
|
// Save the default API key
|
|
232
236
|
const defaultApiKeyManager = default_api_key_1.DefaultApiKeyManager.getInstance();
|
|
233
|
-
|
|
237
|
+
// We need to rotate the key to get the actual key value
|
|
238
|
+
const rotatedKey = yield apiKeyService.rotate(id);
|
|
239
|
+
defaultApiKeyManager.setDefaultApiKey(id, selectedKey.name, selectedKey.prefix, rotatedKey.key);
|
|
234
240
|
console.log(chalk_1.default.green(`✓ API key "${selectedKey.name}" set as default for chat commands`));
|
|
235
241
|
console.log('');
|
|
236
242
|
console.log(chalk_1.default.dim('This API key will be used by default when running chat commands'));
|
|
@@ -246,8 +252,8 @@ function registerApiKeyCommands(program) {
|
|
|
246
252
|
.action(() => {
|
|
247
253
|
try {
|
|
248
254
|
const defaultApiKeyManager = default_api_key_1.DefaultApiKeyManager.getInstance();
|
|
249
|
-
const
|
|
250
|
-
if (!
|
|
255
|
+
const defaultApiKeyData = defaultApiKeyManager.getDefaultApiKeyData();
|
|
256
|
+
if (!defaultApiKeyData) {
|
|
251
257
|
console.log(chalk_1.default.yellow('No default API key set'));
|
|
252
258
|
console.log('');
|
|
253
259
|
console.log('To set a default API key, run:');
|
|
@@ -256,9 +262,9 @@ function registerApiKeyCommands(program) {
|
|
|
256
262
|
}
|
|
257
263
|
console.log(chalk_1.default.bold('Default API key:'));
|
|
258
264
|
console.log('');
|
|
259
|
-
console.log(`${chalk_1.default.dim('ID:')} ${
|
|
260
|
-
console.log(`${chalk_1.default.dim('Name:')} ${
|
|
261
|
-
console.log(`${chalk_1.default.dim('Prefix:')} ${
|
|
265
|
+
console.log(`${chalk_1.default.dim('ID:')} ${defaultApiKeyData.id}`);
|
|
266
|
+
console.log(`${chalk_1.default.dim('Name:')} ${defaultApiKeyData.name}`);
|
|
267
|
+
console.log(`${chalk_1.default.dim('Prefix:')} ${defaultApiKeyData.prefix}`);
|
|
262
268
|
console.log('');
|
|
263
269
|
console.log(chalk_1.default.dim('This API key will be used by default when running chat commands'));
|
|
264
270
|
console.log(chalk_1.default.dim('You can override it with --api-key or --api-key-id options'));
|
|
@@ -48,7 +48,7 @@ function registerChatCommands(program) {
|
|
|
48
48
|
chat
|
|
49
49
|
.command(command_structure_1.SUBCOMMANDS.CHAT.RUN)
|
|
50
50
|
.description('Run a chat session with a specified model')
|
|
51
|
-
.argument('[model]', 'Model to use (default:
|
|
51
|
+
.argument('[model]', 'Model to use (default: google/gemma-3-27b-it)')
|
|
52
52
|
.option('-s, --system <message>', 'System message')
|
|
53
53
|
.option('-t, --temperature <temp>', 'Temperature (0-1)', parseFloat)
|
|
54
54
|
.option('-m, --max-tokens <tokens>', 'Maximum tokens to generate', parseInt)
|
|
@@ -60,13 +60,48 @@ function registerChatCommands(program) {
|
|
|
60
60
|
// Check if we have an API key or need to get one
|
|
61
61
|
let apiKey = options.apiKey;
|
|
62
62
|
let apiKeyId = options.apiKeyId;
|
|
63
|
-
//
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
63
|
+
// Check for environment variable first
|
|
64
|
+
const envApiKey = process.env.BERGET_API_KEY;
|
|
65
|
+
if (envApiKey) {
|
|
66
|
+
console.log(chalk_1.default.dim(`Using API key from BERGET_API_KEY environment variable`));
|
|
67
|
+
apiKey = envApiKey;
|
|
68
|
+
}
|
|
69
|
+
// If no API key or API key ID provided and no env var, check for default API key
|
|
70
|
+
else if (!apiKey && !apiKeyId) {
|
|
71
|
+
try {
|
|
72
|
+
const defaultApiKeyManager = default_api_key_1.DefaultApiKeyManager.getInstance();
|
|
73
|
+
const defaultApiKeyData = defaultApiKeyManager.getDefaultApiKeyData();
|
|
74
|
+
if (defaultApiKeyData) {
|
|
75
|
+
apiKeyId = defaultApiKeyData.id;
|
|
76
|
+
apiKey = defaultApiKeyData.key;
|
|
77
|
+
if (apiKey) {
|
|
78
|
+
console.log(chalk_1.default.dim(`Using default API key: ${defaultApiKeyData.name}`));
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
console.log(chalk_1.default.yellow(`Default API key "${defaultApiKeyData.name}" exists but the key value is missing.`));
|
|
82
|
+
console.log(chalk_1.default.yellow(`Try rotating the key with: berget api-keys rotate ${defaultApiKeyData.id}`));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
// No default API key, prompt the user to create one
|
|
87
|
+
console.log(chalk_1.default.yellow('No default API key set.'));
|
|
88
|
+
// Try to prompt for a default API key
|
|
89
|
+
apiKey = yield defaultApiKeyManager.promptForDefaultApiKey();
|
|
90
|
+
if (!apiKey) {
|
|
91
|
+
console.log(chalk_1.default.red('Error: An API key is required to use the chat command.'));
|
|
92
|
+
console.log(chalk_1.default.yellow('You can:'));
|
|
93
|
+
console.log(chalk_1.default.yellow('1. Create an API key with: berget api-keys create --name "My Key"'));
|
|
94
|
+
console.log(chalk_1.default.yellow('2. Set a default API key with: berget api-keys set-default <id>'));
|
|
95
|
+
console.log(chalk_1.default.yellow('3. Provide an API key with the --api-key option'));
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
if (process.argv.includes('--debug')) {
|
|
102
|
+
console.log(chalk_1.default.yellow('DEBUG: Error checking default API key:'));
|
|
103
|
+
console.log(chalk_1.default.yellow(String(error)));
|
|
104
|
+
}
|
|
70
105
|
}
|
|
71
106
|
}
|
|
72
107
|
// If no direct API key, try to get one from API key ID
|
|
@@ -92,8 +127,18 @@ function registerChatCommands(program) {
|
|
|
92
127
|
}
|
|
93
128
|
}
|
|
94
129
|
catch (error) {
|
|
95
|
-
|
|
96
|
-
|
|
130
|
+
// Check if this is an authentication error
|
|
131
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
132
|
+
const isAuthError = errorMessage.includes('Unauthorized') ||
|
|
133
|
+
errorMessage.includes('Authentication failed') ||
|
|
134
|
+
errorMessage.includes('AUTH_FAILED');
|
|
135
|
+
if (isAuthError) {
|
|
136
|
+
console.log(chalk_1.default.yellow('Authentication required. Please run `berget auth login` first.'));
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
console.error(chalk_1.default.red('Error fetching API key:'));
|
|
140
|
+
console.error(error);
|
|
141
|
+
}
|
|
97
142
|
console.log(chalk_1.default.yellow('Using default authentication instead.'));
|
|
98
143
|
}
|
|
99
144
|
}
|
|
@@ -145,13 +190,34 @@ function registerChatCommands(program) {
|
|
|
145
190
|
});
|
|
146
191
|
try {
|
|
147
192
|
// Call the API
|
|
148
|
-
|
|
149
|
-
|
|
193
|
+
console.log(chalk_1.default.yellow('DEBUG: Preparing completion options'));
|
|
194
|
+
const completionOptions = {
|
|
195
|
+
model: ((_a = options.args) === null || _a === void 0 ? void 0 : _a[0]) || 'google/gemma-3-27b-it',
|
|
150
196
|
messages: messages,
|
|
151
197
|
temperature: options.temperature !== undefined ? options.temperature : 0.7,
|
|
152
198
|
max_tokens: options.maxTokens || 4096,
|
|
153
|
-
|
|
154
|
-
|
|
199
|
+
};
|
|
200
|
+
// Only add apiKey if it actually exists
|
|
201
|
+
if (apiKey) {
|
|
202
|
+
completionOptions.apiKey = apiKey;
|
|
203
|
+
console.log(chalk_1.default.yellow('DEBUG: Using API key from command options or default'));
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
console.log(chalk_1.default.yellow('DEBUG: No API key available in chat command'));
|
|
207
|
+
// If we got this far with defaultApiKeyData but no apiKey, there's a problem
|
|
208
|
+
const defaultApiKeyManager = default_api_key_1.DefaultApiKeyManager.getInstance();
|
|
209
|
+
if (defaultApiKeyManager.getDefaultApiKeyData()) {
|
|
210
|
+
console.log(chalk_1.default.yellow('DEBUG: Default API key data exists but key is missing'));
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
// Debug output
|
|
214
|
+
console.log(chalk_1.default.yellow('DEBUG: Completion options:'));
|
|
215
|
+
console.log(chalk_1.default.yellow(JSON.stringify(Object.assign(Object.assign({}, completionOptions), { apiKey: completionOptions.apiKey ? '***' : undefined, messages: completionOptions.messages.map((m) => ({
|
|
216
|
+
role: m.role,
|
|
217
|
+
content: m.content.length > 50 ? m.content.substring(0, 50) + '...' : m.content
|
|
218
|
+
})) }), null, 2)));
|
|
219
|
+
console.log(chalk_1.default.yellow('DEBUG: Calling chatService.createCompletion'));
|
|
220
|
+
const response = yield chatService.createCompletion(completionOptions);
|
|
155
221
|
// Debug output
|
|
156
222
|
if (program.opts().debug) {
|
|
157
223
|
console.log(chalk_1.default.yellow('DEBUG: Full response:'));
|
|
@@ -209,10 +275,10 @@ function registerChatCommands(program) {
|
|
|
209
275
|
// If no API key or API key ID provided, check for default API key
|
|
210
276
|
if (!apiKey && !apiKeyId) {
|
|
211
277
|
const defaultApiKeyManager = default_api_key_1.DefaultApiKeyManager.getInstance();
|
|
212
|
-
const
|
|
213
|
-
if (
|
|
214
|
-
apiKeyId =
|
|
215
|
-
console.log(chalk_1.default.dim(`Using default API key: ${
|
|
278
|
+
const defaultApiKeyData = defaultApiKeyManager.getDefaultApiKeyData();
|
|
279
|
+
if (defaultApiKeyData) {
|
|
280
|
+
apiKeyId = defaultApiKeyData.id;
|
|
281
|
+
console.log(chalk_1.default.dim(`Using default API key: ${defaultApiKeyData.name}`));
|
|
216
282
|
}
|
|
217
283
|
}
|
|
218
284
|
if (apiKeyId && !apiKey) {
|
|
@@ -35,18 +35,8 @@ class ApiKeyService {
|
|
|
35
35
|
return __awaiter(this, void 0, void 0, function* () {
|
|
36
36
|
try {
|
|
37
37
|
const { data, error } = yield this.client.GET('/v1/api-keys');
|
|
38
|
-
if (error)
|
|
39
|
-
|
|
40
|
-
const errorObj = typeof error === 'string' ? JSON.parse(error) : error;
|
|
41
|
-
if (errorObj.status === 401) {
|
|
42
|
-
throw new Error(JSON.stringify({
|
|
43
|
-
error: "Authentication failed. Your session may have expired.",
|
|
44
|
-
code: "AUTH_FAILED",
|
|
45
|
-
details: "Please run 'berget login' to authenticate again."
|
|
46
|
-
}));
|
|
47
|
-
}
|
|
48
|
-
throw new Error(JSON.stringify(error));
|
|
49
|
-
}
|
|
38
|
+
if (error)
|
|
39
|
+
throw error;
|
|
50
40
|
return data || [];
|
|
51
41
|
}
|
|
52
42
|
catch (error) {
|
|
@@ -63,7 +53,7 @@ class ApiKeyService {
|
|
|
63
53
|
return __awaiter(this, void 0, void 0, function* () {
|
|
64
54
|
try {
|
|
65
55
|
const { data, error } = yield this.client.POST('/v1/api-keys', {
|
|
66
|
-
body: options
|
|
56
|
+
body: options,
|
|
67
57
|
});
|
|
68
58
|
if (error)
|
|
69
59
|
throw new Error(JSON.stringify(error));
|
|
@@ -83,7 +73,7 @@ class ApiKeyService {
|
|
|
83
73
|
return __awaiter(this, void 0, void 0, function* () {
|
|
84
74
|
try {
|
|
85
75
|
const { error } = yield this.client.DELETE('/v1/api-keys/{id}', {
|
|
86
|
-
params: { path: { id } }
|
|
76
|
+
params: { path: { id } },
|
|
87
77
|
});
|
|
88
78
|
if (error)
|
|
89
79
|
throw new Error(JSON.stringify(error));
|
|
@@ -103,7 +93,7 @@ class ApiKeyService {
|
|
|
103
93
|
return __awaiter(this, void 0, void 0, function* () {
|
|
104
94
|
try {
|
|
105
95
|
const { data, error } = yield this.client.PUT('/v1/api-keys/{id}/rotate', {
|
|
106
|
-
params: { path: { id } }
|
|
96
|
+
params: { path: { id } },
|
|
107
97
|
});
|
|
108
98
|
if (error)
|
|
109
99
|
throw new Error(JSON.stringify(error));
|
|
@@ -123,7 +113,7 @@ class ApiKeyService {
|
|
|
123
113
|
return __awaiter(this, void 0, void 0, function* () {
|
|
124
114
|
try {
|
|
125
115
|
const { data, error } = yield this.client.GET('/v1/api-keys/{id}/usage', {
|
|
126
|
-
params: { path: { id } }
|
|
116
|
+
params: { path: { id } },
|
|
127
117
|
});
|
|
128
118
|
if (error)
|
|
129
119
|
throw new Error(JSON.stringify(error));
|
|
@@ -1,4 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (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
|
+
};
|
|
2
25
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
26
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
27
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -47,56 +70,153 @@ class ChatService {
|
|
|
47
70
|
createCompletion(options) {
|
|
48
71
|
return __awaiter(this, void 0, void 0, function* () {
|
|
49
72
|
try {
|
|
73
|
+
console.log(chalk_1.default.yellow('DEBUG: Starting createCompletion method'));
|
|
74
|
+
// Check if options is defined
|
|
75
|
+
if (!options) {
|
|
76
|
+
console.log(chalk_1.default.red('ERROR: options is undefined'));
|
|
77
|
+
throw new Error('Chat completion options are undefined');
|
|
78
|
+
}
|
|
79
|
+
// Log the raw options object
|
|
80
|
+
console.log(chalk_1.default.yellow('DEBUG: Raw options:'), typeof options, options ? 'defined' : 'undefined');
|
|
50
81
|
const headers = {};
|
|
51
82
|
// Check if debug is enabled
|
|
52
83
|
const isDebug = process.argv.includes('--debug');
|
|
84
|
+
if (isDebug) {
|
|
85
|
+
console.log(chalk_1.default.yellow('DEBUG: Starting createCompletion with options:'));
|
|
86
|
+
try {
|
|
87
|
+
console.log(chalk_1.default.yellow(JSON.stringify(Object.assign(Object.assign({}, options), { apiKey: options.apiKey ? '***' : undefined, messages: options.messages ? `${options.messages.length} messages` : undefined }), null, 2)));
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
console.log(chalk_1.default.red('ERROR: Failed to stringify options:'), error);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Create a copy of options to avoid modifying the original
|
|
94
|
+
const optionsCopy = Object.assign({}, options);
|
|
95
|
+
if (isDebug) {
|
|
96
|
+
console.log(chalk_1.default.yellow('DEBUG: Checking for API key'));
|
|
97
|
+
console.log(chalk_1.default.yellow(`DEBUG: optionsCopy.apiKey exists: ${!!optionsCopy.apiKey}`));
|
|
98
|
+
}
|
|
99
|
+
// Check for environment variables first - prioritize this over everything else
|
|
100
|
+
const envApiKey = process.env.BERGET_API_KEY;
|
|
101
|
+
if (envApiKey) {
|
|
102
|
+
if (isDebug) {
|
|
103
|
+
console.log(chalk_1.default.yellow('DEBUG: Using API key from BERGET_API_KEY environment variable'));
|
|
104
|
+
}
|
|
105
|
+
optionsCopy.apiKey = envApiKey;
|
|
106
|
+
}
|
|
107
|
+
// Only try to get the default API key if no API key is provided and no env var is set
|
|
108
|
+
else if (!optionsCopy.apiKey) {
|
|
109
|
+
if (isDebug) {
|
|
110
|
+
console.log(chalk_1.default.yellow('DEBUG: No API key provided, trying to get default'));
|
|
111
|
+
}
|
|
112
|
+
try {
|
|
113
|
+
// Import the DefaultApiKeyManager directly
|
|
114
|
+
if (isDebug) {
|
|
115
|
+
console.log(chalk_1.default.yellow('DEBUG: Importing DefaultApiKeyManager'));
|
|
116
|
+
}
|
|
117
|
+
const DefaultApiKeyManager = (yield Promise.resolve().then(() => __importStar(require('../utils/default-api-key')))).DefaultApiKeyManager;
|
|
118
|
+
const defaultApiKeyManager = DefaultApiKeyManager.getInstance();
|
|
119
|
+
if (isDebug) {
|
|
120
|
+
console.log(chalk_1.default.yellow('DEBUG: Got DefaultApiKeyManager instance'));
|
|
121
|
+
}
|
|
122
|
+
// Try to get the default API key
|
|
123
|
+
if (isDebug) {
|
|
124
|
+
console.log(chalk_1.default.yellow('DEBUG: Calling promptForDefaultApiKey'));
|
|
125
|
+
}
|
|
126
|
+
const defaultApiKeyData = defaultApiKeyManager.getDefaultApiKeyData();
|
|
127
|
+
const apiKey = (defaultApiKeyData === null || defaultApiKeyData === void 0 ? void 0 : defaultApiKeyData.key) || (yield defaultApiKeyManager.promptForDefaultApiKey());
|
|
128
|
+
if (isDebug) {
|
|
129
|
+
console.log(chalk_1.default.yellow(`DEBUG: Default API key data exists: ${!!defaultApiKeyData}`));
|
|
130
|
+
console.log(chalk_1.default.yellow(`DEBUG: promptForDefaultApiKey returned: ${apiKey ? 'a key' : 'null'}`));
|
|
131
|
+
}
|
|
132
|
+
if (apiKey) {
|
|
133
|
+
if (isDebug) {
|
|
134
|
+
console.log(chalk_1.default.yellow('DEBUG: Using API key from default API key manager'));
|
|
135
|
+
}
|
|
136
|
+
optionsCopy.apiKey = apiKey;
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
console.log(chalk_1.default.yellow('No API key available. You need to either:'));
|
|
140
|
+
console.log(chalk_1.default.yellow('1. Create an API key with: berget api-keys create --name "My Key"'));
|
|
141
|
+
console.log(chalk_1.default.yellow('2. Set a default API key with: berget api-keys set-default <id>'));
|
|
142
|
+
console.log(chalk_1.default.yellow('3. Provide an API key with the --api-key option'));
|
|
143
|
+
console.log(chalk_1.default.yellow('4. Set the BERGET_API_KEY environment variable'));
|
|
144
|
+
console.log(chalk_1.default.yellow('\nExample:'));
|
|
145
|
+
console.log(chalk_1.default.yellow(' export BERGET_API_KEY=your_api_key_here'));
|
|
146
|
+
console.log(chalk_1.default.yellow(' # or for a single command:'));
|
|
147
|
+
console.log(chalk_1.default.yellow(' BERGET_API_KEY=your_api_key_here berget chat run google/gemma-3-27b-it'));
|
|
148
|
+
throw new Error('No API key provided and no default API key set');
|
|
149
|
+
}
|
|
150
|
+
// Set the API key in the options
|
|
151
|
+
if (isDebug) {
|
|
152
|
+
console.log(chalk_1.default.yellow('DEBUG: Setting API key in options'));
|
|
153
|
+
}
|
|
154
|
+
// Only set the API key if it's not null
|
|
155
|
+
if (apiKey) {
|
|
156
|
+
optionsCopy.apiKey = apiKey;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
console.log(chalk_1.default.red('Error getting API key:'));
|
|
161
|
+
if (error instanceof Error) {
|
|
162
|
+
console.log(chalk_1.default.red(error.message));
|
|
163
|
+
}
|
|
164
|
+
console.log(chalk_1.default.yellow('Please create an API key with: berget api-keys create --name "My Key"'));
|
|
165
|
+
throw new Error('Failed to get API key');
|
|
166
|
+
}
|
|
167
|
+
}
|
|
53
168
|
if (isDebug) {
|
|
54
169
|
console.log(chalk_1.default.yellow('DEBUG: Chat completion options:'));
|
|
55
|
-
console.log(chalk_1.default.yellow(JSON.stringify(
|
|
170
|
+
console.log(chalk_1.default.yellow(JSON.stringify(Object.assign(Object.assign({}, optionsCopy), { apiKey: optionsCopy.apiKey ? '***' : undefined // Hide the actual API key in debug output
|
|
171
|
+
}), null, 2)));
|
|
56
172
|
}
|
|
57
173
|
// If an API key is provided, use it for this request
|
|
58
|
-
if (
|
|
59
|
-
headers['Authorization'] = `Bearer ${
|
|
174
|
+
if (optionsCopy.apiKey) {
|
|
175
|
+
headers['Authorization'] = `Bearer ${optionsCopy.apiKey}`;
|
|
60
176
|
// Remove apiKey from options before sending to API
|
|
61
|
-
const { apiKey } =
|
|
177
|
+
const { apiKey } = optionsCopy, requestOptions = __rest(optionsCopy, ["apiKey"]);
|
|
62
178
|
if (isDebug) {
|
|
63
179
|
console.log(chalk_1.default.yellow('DEBUG: Using provided API key'));
|
|
64
180
|
console.log(chalk_1.default.yellow('DEBUG: Request options:'));
|
|
65
181
|
console.log(chalk_1.default.yellow(JSON.stringify(requestOptions, null, 2)));
|
|
66
182
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
183
|
+
try {
|
|
184
|
+
const response = yield this.client.POST('/v1/chat/completions', {
|
|
185
|
+
body: requestOptions,
|
|
186
|
+
headers
|
|
187
|
+
});
|
|
188
|
+
// Check if response has an error property
|
|
189
|
+
const responseAny = response;
|
|
190
|
+
if (responseAny && responseAny.error)
|
|
191
|
+
throw new Error(JSON.stringify(responseAny.error));
|
|
192
|
+
if (isDebug) {
|
|
193
|
+
console.log(chalk_1.default.yellow('DEBUG: API response:'));
|
|
194
|
+
console.log(chalk_1.default.yellow(JSON.stringify(response, null, 2)));
|
|
195
|
+
// Output the complete response data for debugging
|
|
196
|
+
console.log(chalk_1.default.yellow('DEBUG: Complete response data:'));
|
|
197
|
+
console.log(chalk_1.default.yellow(JSON.stringify(response.data, null, 2)));
|
|
198
|
+
}
|
|
199
|
+
return response.data;
|
|
200
|
+
}
|
|
201
|
+
catch (requestError) {
|
|
202
|
+
if (process.argv.includes('--debug')) {
|
|
203
|
+
console.log(chalk_1.default.red(`DEBUG: Request error: ${requestError instanceof Error ? requestError.message : String(requestError)}`));
|
|
204
|
+
}
|
|
205
|
+
throw requestError;
|
|
77
206
|
}
|
|
78
|
-
if (error)
|
|
79
|
-
throw new Error(JSON.stringify(error));
|
|
80
|
-
return data;
|
|
81
207
|
}
|
|
82
208
|
else {
|
|
83
|
-
//
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
console.log(chalk_1.default.yellow('DEBUG: Complete response data:'));
|
|
95
|
-
console.log(chalk_1.default.yellow(JSON.stringify(data, null, 2)));
|
|
96
|
-
}
|
|
97
|
-
if (error)
|
|
98
|
-
throw new Error(JSON.stringify(error));
|
|
99
|
-
return data;
|
|
209
|
+
// We've exhausted all options for getting an API key
|
|
210
|
+
console.log(chalk_1.default.yellow('No API key available. You need to either:'));
|
|
211
|
+
console.log(chalk_1.default.yellow('1. Create an API key with: berget api-keys create --name "My Key"'));
|
|
212
|
+
console.log(chalk_1.default.yellow('2. Set a default API key with: berget api-keys set-default <id>'));
|
|
213
|
+
console.log(chalk_1.default.yellow('3. Provide an API key with the --api-key option'));
|
|
214
|
+
console.log(chalk_1.default.yellow('4. Set the BERGET_API_KEY environment variable'));
|
|
215
|
+
console.log(chalk_1.default.yellow('\nExample:'));
|
|
216
|
+
console.log(chalk_1.default.yellow(' export BERGET_API_KEY=your_api_key_here'));
|
|
217
|
+
console.log(chalk_1.default.yellow(' # or for a single command:'));
|
|
218
|
+
console.log(chalk_1.default.yellow(' BERGET_API_KEY=your_api_key_here berget chat run google/gemma-3-27b-it'));
|
|
219
|
+
throw new Error('No API key available. Please provide an API key or set a default API key.');
|
|
100
220
|
}
|
|
101
221
|
}
|
|
102
222
|
catch (error) {
|
|
@@ -127,9 +247,12 @@ class ChatService {
|
|
|
127
247
|
listModels(apiKey) {
|
|
128
248
|
return __awaiter(this, void 0, void 0, function* () {
|
|
129
249
|
try {
|
|
130
|
-
|
|
250
|
+
// Check for environment variable first, then fallback to provided API key
|
|
251
|
+
const envApiKey = process.env.BERGET_API_KEY;
|
|
252
|
+
const effectiveApiKey = envApiKey || apiKey;
|
|
253
|
+
if (effectiveApiKey) {
|
|
131
254
|
const headers = {
|
|
132
|
-
'Authorization': `Bearer ${
|
|
255
|
+
'Authorization': `Bearer ${effectiveApiKey}`
|
|
133
256
|
};
|
|
134
257
|
const { data, error } = yield this.client.GET('/v1/models', { headers });
|
|
135
258
|
if (error)
|