berget 1.2.0 → 1.3.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/-27b-it +0 -0
- package/dist/package.json +1 -1
- package/dist/src/client.js +33 -43
- package/dist/src/commands/chat.js +32 -16
- package/dist/src/services/chat-service.js +230 -125
- package/dist/src/utils/default-api-key.js +20 -37
- package/dist/src/utils/logger.js +160 -0
- package/dist/src/utils/token-manager.js +6 -9
- package/package.json +1 -1
- package/src/client.ts +75 -90
- package/src/commands/chat.ts +42 -22
- package/src/services/chat-service.ts +386 -184
- package/src/utils/default-api-key.ts +20 -37
- package/src/utils/logger.ts +159 -0
- package/src/utils/token-manager.ts +6 -5
|
@@ -42,13 +42,10 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
42
42
|
}
|
|
43
43
|
return t;
|
|
44
44
|
};
|
|
45
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
46
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
47
|
-
};
|
|
48
45
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
46
|
exports.ChatService = void 0;
|
|
50
47
|
const client_1 = require("../client");
|
|
51
|
-
const
|
|
48
|
+
const logger_1 = require("../utils/logger");
|
|
52
49
|
/**
|
|
53
50
|
* Service for interacting with the chat API
|
|
54
51
|
* Command group: chat
|
|
@@ -70,154 +67,95 @@ class ChatService {
|
|
|
70
67
|
createCompletion(options) {
|
|
71
68
|
return __awaiter(this, void 0, void 0, function* () {
|
|
72
69
|
try {
|
|
73
|
-
|
|
74
|
-
//
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
70
|
+
logger_1.logger.debug('Starting createCompletion method');
|
|
71
|
+
// Initialize options if undefined
|
|
72
|
+
const optionsCopy = options ? Object.assign({}, options) : { messages: [] };
|
|
73
|
+
// Check if messages are defined
|
|
74
|
+
if (!optionsCopy.messages || !Array.isArray(optionsCopy.messages)) {
|
|
75
|
+
logger_1.logger.error('messages is undefined or not an array');
|
|
76
|
+
optionsCopy.messages = [];
|
|
78
77
|
}
|
|
79
|
-
// Log the
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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
|
-
}
|
|
78
|
+
// Log the options object
|
|
79
|
+
logger_1.logger.debug('Starting createCompletion with options:');
|
|
80
|
+
try {
|
|
81
|
+
logger_1.logger.debug(JSON.stringify(Object.assign(Object.assign({}, optionsCopy), { apiKey: optionsCopy.apiKey ? '***' : undefined, messages: optionsCopy.messages
|
|
82
|
+
? `${optionsCopy.messages.length} messages`
|
|
83
|
+
: '0 messages' }), null, 2));
|
|
92
84
|
}
|
|
93
|
-
|
|
94
|
-
|
|
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}`));
|
|
85
|
+
catch (error) {
|
|
86
|
+
logger_1.logger.error('Failed to stringify options:', error);
|
|
98
87
|
}
|
|
88
|
+
const headers = {};
|
|
99
89
|
// Check for environment variables first - prioritize this over everything else
|
|
100
90
|
const envApiKey = process.env.BERGET_API_KEY;
|
|
101
91
|
if (envApiKey) {
|
|
102
|
-
|
|
103
|
-
console.log(chalk_1.default.yellow('DEBUG: Using API key from BERGET_API_KEY environment variable'));
|
|
104
|
-
}
|
|
92
|
+
logger_1.logger.debug('Using API key from BERGET_API_KEY environment variable');
|
|
105
93
|
optionsCopy.apiKey = envApiKey;
|
|
94
|
+
// Skip the default API key logic if we already have a key
|
|
95
|
+
return this.executeCompletion(optionsCopy, headers);
|
|
96
|
+
}
|
|
97
|
+
// If API key is already provided, use it directly
|
|
98
|
+
else if (optionsCopy.apiKey) {
|
|
99
|
+
logger_1.logger.debug('Using API key provided in options');
|
|
100
|
+
// Skip the default API key logic if we already have a key
|
|
101
|
+
return this.executeCompletion(optionsCopy, headers);
|
|
106
102
|
}
|
|
107
103
|
// Only try to get the default API key if no API key is provided and no env var is set
|
|
108
|
-
else
|
|
109
|
-
|
|
110
|
-
console.log(chalk_1.default.yellow('DEBUG: No API key provided, trying to get default'));
|
|
111
|
-
}
|
|
104
|
+
else {
|
|
105
|
+
logger_1.logger.debug('No API key provided, trying to get default');
|
|
112
106
|
try {
|
|
113
107
|
// Import the DefaultApiKeyManager directly
|
|
114
|
-
|
|
115
|
-
console.log(chalk_1.default.yellow('DEBUG: Importing DefaultApiKeyManager'));
|
|
116
|
-
}
|
|
108
|
+
logger_1.logger.debug('Importing DefaultApiKeyManager');
|
|
117
109
|
const DefaultApiKeyManager = (yield Promise.resolve().then(() => __importStar(require('../utils/default-api-key')))).DefaultApiKeyManager;
|
|
118
110
|
const defaultApiKeyManager = DefaultApiKeyManager.getInstance();
|
|
119
|
-
|
|
120
|
-
console.log(chalk_1.default.yellow('DEBUG: Got DefaultApiKeyManager instance'));
|
|
121
|
-
}
|
|
111
|
+
logger_1.logger.debug('Got DefaultApiKeyManager instance');
|
|
122
112
|
// Try to get the default API key
|
|
123
|
-
|
|
124
|
-
console.log(chalk_1.default.yellow('DEBUG: Calling promptForDefaultApiKey'));
|
|
125
|
-
}
|
|
113
|
+
logger_1.logger.debug('Calling promptForDefaultApiKey');
|
|
126
114
|
const defaultApiKeyData = defaultApiKeyManager.getDefaultApiKeyData();
|
|
127
|
-
const apiKey = (defaultApiKeyData === null || defaultApiKeyData === void 0 ? void 0 : defaultApiKeyData.key) ||
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}
|
|
115
|
+
const apiKey = (defaultApiKeyData === null || defaultApiKeyData === void 0 ? void 0 : defaultApiKeyData.key) ||
|
|
116
|
+
(yield defaultApiKeyManager.promptForDefaultApiKey());
|
|
117
|
+
logger_1.logger.debug(`Default API key data exists: ${!!defaultApiKeyData}`);
|
|
118
|
+
logger_1.logger.debug(`promptForDefaultApiKey returned: ${apiKey ? 'a key' : 'null'}`);
|
|
132
119
|
if (apiKey) {
|
|
133
|
-
|
|
134
|
-
console.log(chalk_1.default.yellow('DEBUG: Using API key from default API key manager'));
|
|
135
|
-
}
|
|
120
|
+
logger_1.logger.debug('Using API key from default API key manager');
|
|
136
121
|
optionsCopy.apiKey = apiKey;
|
|
137
122
|
}
|
|
138
123
|
else {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
124
|
+
logger_1.logger.warn('No API key available. You need to either:');
|
|
125
|
+
logger_1.logger.warn('1. Create an API key with: berget api-keys create --name "My Key"');
|
|
126
|
+
logger_1.logger.warn('2. Set a default API key with: berget api-keys set-default <id>');
|
|
127
|
+
logger_1.logger.warn('3. Provide an API key with the --api-key option');
|
|
128
|
+
logger_1.logger.warn('4. Set the BERGET_API_KEY environment variable');
|
|
129
|
+
logger_1.logger.warn('\nExample:');
|
|
130
|
+
logger_1.logger.warn(' export BERGET_API_KEY=your_api_key_here');
|
|
131
|
+
logger_1.logger.warn(' # or for a single command:');
|
|
132
|
+
logger_1.logger.warn(' BERGET_API_KEY=your_api_key_here berget chat run google/gemma-3-27b-it');
|
|
148
133
|
throw new Error('No API key provided and no default API key set');
|
|
149
134
|
}
|
|
150
135
|
// Set the API key in the options
|
|
151
|
-
|
|
152
|
-
console.log(chalk_1.default.yellow('DEBUG: Setting API key in options'));
|
|
153
|
-
}
|
|
136
|
+
logger_1.logger.debug('Setting API key in options');
|
|
154
137
|
// Only set the API key if it's not null
|
|
155
138
|
if (apiKey) {
|
|
156
139
|
optionsCopy.apiKey = apiKey;
|
|
157
140
|
}
|
|
158
141
|
}
|
|
159
142
|
catch (error) {
|
|
160
|
-
|
|
143
|
+
logger_1.logger.error('Error getting API key:');
|
|
161
144
|
if (error instanceof Error) {
|
|
162
|
-
|
|
145
|
+
logger_1.logger.error(error.message);
|
|
163
146
|
}
|
|
164
|
-
|
|
147
|
+
logger_1.logger.warn('Please create an API key with: berget api-keys create --name "My Key"');
|
|
165
148
|
throw new Error('Failed to get API key');
|
|
166
149
|
}
|
|
167
150
|
}
|
|
168
|
-
if
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}
|
|
173
|
-
// If an API key is provided, use it for this request
|
|
174
|
-
if (optionsCopy.apiKey) {
|
|
175
|
-
headers['Authorization'] = `Bearer ${optionsCopy.apiKey}`;
|
|
176
|
-
// Remove apiKey from options before sending to API
|
|
177
|
-
const { apiKey } = optionsCopy, requestOptions = __rest(optionsCopy, ["apiKey"]);
|
|
178
|
-
if (isDebug) {
|
|
179
|
-
console.log(chalk_1.default.yellow('DEBUG: Using provided API key'));
|
|
180
|
-
console.log(chalk_1.default.yellow('DEBUG: Request options:'));
|
|
181
|
-
console.log(chalk_1.default.yellow(JSON.stringify(requestOptions, null, 2)));
|
|
182
|
-
}
|
|
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;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
else {
|
|
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.');
|
|
151
|
+
// Set default model if not provided
|
|
152
|
+
if (!optionsCopy.model) {
|
|
153
|
+
logger_1.logger.debug('No model specified, using default: google/gemma-3-27b-it');
|
|
154
|
+
optionsCopy.model = 'google/gemma-3-27b-it';
|
|
220
155
|
}
|
|
156
|
+
logger_1.logger.debug('Chat completion options:');
|
|
157
|
+
logger_1.logger.debug(JSON.stringify(Object.assign(Object.assign({}, optionsCopy), { apiKey: optionsCopy.apiKey ? '***' : undefined }), null, 2));
|
|
158
|
+
return this.executeCompletion(optionsCopy, headers);
|
|
221
159
|
}
|
|
222
160
|
catch (error) {
|
|
223
161
|
// Improved error handling
|
|
@@ -235,11 +173,178 @@ class ChatService {
|
|
|
235
173
|
errorMessage = `Chat error: ${error.message}`;
|
|
236
174
|
}
|
|
237
175
|
}
|
|
238
|
-
|
|
176
|
+
logger_1.logger.error(errorMessage);
|
|
239
177
|
throw new Error(errorMessage);
|
|
240
178
|
}
|
|
241
179
|
});
|
|
242
180
|
}
|
|
181
|
+
/**
|
|
182
|
+
* Execute the completion request with the provided options
|
|
183
|
+
* @param options The completion options
|
|
184
|
+
* @param headers Additional headers to include
|
|
185
|
+
* @returns The completion response
|
|
186
|
+
*/
|
|
187
|
+
executeCompletion(options, headers = {}) {
|
|
188
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
189
|
+
try {
|
|
190
|
+
// If an API key is provided, use it for this request
|
|
191
|
+
if (options.apiKey) {
|
|
192
|
+
// API keys should be sent directly, not with Bearer prefix
|
|
193
|
+
headers['Authorization'] = options.apiKey;
|
|
194
|
+
}
|
|
195
|
+
// Remove apiKey and onChunk from options before sending to API
|
|
196
|
+
const { apiKey, onChunk } = options, requestOptions = __rest(options, ["apiKey", "onChunk"]);
|
|
197
|
+
logger_1.logger.debug('Request options:');
|
|
198
|
+
logger_1.logger.debug(JSON.stringify(Object.assign(Object.assign({}, requestOptions), { messages: requestOptions.messages
|
|
199
|
+
? `${requestOptions.messages.length} messages`
|
|
200
|
+
: '0 messages' }), null, 2));
|
|
201
|
+
// Handle streaming responses differently
|
|
202
|
+
if (requestOptions.stream && onChunk) {
|
|
203
|
+
return yield this.handleStreamingResponse(Object.assign(Object.assign({}, requestOptions), { onChunk }), headers);
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
// Ensure model is always defined for the API call
|
|
207
|
+
const requestBody = Object.assign(Object.assign({}, requestOptions), { model: requestOptions.model || 'google/gemma-3-27b-it' });
|
|
208
|
+
// Debug the headers being sent
|
|
209
|
+
logger_1.logger.debug('Headers being sent:');
|
|
210
|
+
logger_1.logger.debug(JSON.stringify(headers, null, 2));
|
|
211
|
+
const response = yield this.client.POST('/v1/chat/completions', {
|
|
212
|
+
body: requestBody,
|
|
213
|
+
headers,
|
|
214
|
+
});
|
|
215
|
+
// Check if response has an error property
|
|
216
|
+
const responseAny = response;
|
|
217
|
+
if (responseAny && responseAny.error)
|
|
218
|
+
throw new Error(JSON.stringify(responseAny.error));
|
|
219
|
+
logger_1.logger.debug('API response:');
|
|
220
|
+
logger_1.logger.debug(JSON.stringify(response, null, 2));
|
|
221
|
+
// Output the complete response data for debugging
|
|
222
|
+
logger_1.logger.debug('Complete response data:');
|
|
223
|
+
logger_1.logger.debug(JSON.stringify(response.data, null, 2));
|
|
224
|
+
return response.data;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
catch (requestError) {
|
|
228
|
+
logger_1.logger.debug(`Request error: ${requestError instanceof Error
|
|
229
|
+
? requestError.message
|
|
230
|
+
: String(requestError)}`);
|
|
231
|
+
throw requestError;
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Handle the case when no API key is available
|
|
237
|
+
*/
|
|
238
|
+
handleNoApiKey() {
|
|
239
|
+
// We've exhausted all options for getting an API key
|
|
240
|
+
logger_1.logger.warn('No API key available. You need to either:');
|
|
241
|
+
logger_1.logger.warn('1. Create an API key with: berget api-keys create --name "My Key"');
|
|
242
|
+
logger_1.logger.warn('2. Set a default API key with: berget api-keys set-default <id>');
|
|
243
|
+
logger_1.logger.warn('3. Provide an API key with the --api-key option');
|
|
244
|
+
logger_1.logger.warn('4. Set the BERGET_API_KEY environment variable');
|
|
245
|
+
logger_1.logger.warn('\nExample:');
|
|
246
|
+
logger_1.logger.warn(' export BERGET_API_KEY=your_api_key_here');
|
|
247
|
+
logger_1.logger.warn(' # or for a single command:');
|
|
248
|
+
logger_1.logger.warn(' BERGET_API_KEY=your_api_key_here berget chat run google/gemma-3-27b-it');
|
|
249
|
+
throw new Error('No API key available. Please provide an API key or set a default API key.');
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Handle streaming response from the API
|
|
253
|
+
* @param options Request options
|
|
254
|
+
* @param headers Request headers
|
|
255
|
+
* @returns A promise that resolves when the stream is complete
|
|
256
|
+
*/
|
|
257
|
+
handleStreamingResponse(options, headers) {
|
|
258
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
259
|
+
logger_1.logger.debug('Handling streaming response');
|
|
260
|
+
// Create URL with query parameters
|
|
261
|
+
const url = new URL(`${client_1.API_BASE_URL}/v1/chat/completions`);
|
|
262
|
+
// Debug the headers and options
|
|
263
|
+
logger_1.logger.debug('Streaming headers:');
|
|
264
|
+
logger_1.logger.debug(JSON.stringify(headers, null, 2));
|
|
265
|
+
logger_1.logger.debug('Streaming options:');
|
|
266
|
+
logger_1.logger.debug(JSON.stringify(Object.assign(Object.assign({}, options), { onChunk: options.onChunk ? 'function present' : 'no function' }), null, 2));
|
|
267
|
+
try {
|
|
268
|
+
// Make fetch request directly to handle streaming
|
|
269
|
+
const response = yield fetch(url.toString(), {
|
|
270
|
+
method: 'POST',
|
|
271
|
+
headers: Object.assign({ 'Content-Type': 'application/json', Accept: 'text/event-stream' }, headers),
|
|
272
|
+
body: JSON.stringify(options),
|
|
273
|
+
});
|
|
274
|
+
if (!response.ok) {
|
|
275
|
+
const errorText = yield response.text();
|
|
276
|
+
logger_1.logger.error(`Stream request failed: ${response.status} ${response.statusText}`);
|
|
277
|
+
logger_1.logger.debug(`Error response: ${errorText}`);
|
|
278
|
+
throw new Error(`Stream request failed: ${response.status} ${response.statusText}`);
|
|
279
|
+
}
|
|
280
|
+
if (!response.body) {
|
|
281
|
+
throw new Error('No response body received');
|
|
282
|
+
}
|
|
283
|
+
// Process the stream
|
|
284
|
+
const reader = response.body.getReader();
|
|
285
|
+
const decoder = new TextDecoder();
|
|
286
|
+
let fullContent = '';
|
|
287
|
+
let fullResponse = null;
|
|
288
|
+
while (true) {
|
|
289
|
+
const { done, value } = yield reader.read();
|
|
290
|
+
if (done)
|
|
291
|
+
break;
|
|
292
|
+
const chunk = decoder.decode(value, { stream: true });
|
|
293
|
+
logger_1.logger.debug(`Received chunk: ${chunk.length} bytes`);
|
|
294
|
+
// Process the chunk - it may contain multiple SSE events
|
|
295
|
+
const lines = chunk.split('\n');
|
|
296
|
+
for (const line of lines) {
|
|
297
|
+
if (line.startsWith('data:')) {
|
|
298
|
+
const jsonData = line.slice(5).trim();
|
|
299
|
+
// Skip empty data or [DONE] marker
|
|
300
|
+
if (jsonData === '' || jsonData === '[DONE]')
|
|
301
|
+
continue;
|
|
302
|
+
try {
|
|
303
|
+
const parsedData = JSON.parse(jsonData);
|
|
304
|
+
// Call the onChunk callback with the parsed data
|
|
305
|
+
if (options.onChunk) {
|
|
306
|
+
options.onChunk(parsedData);
|
|
307
|
+
}
|
|
308
|
+
// Keep track of the full response
|
|
309
|
+
if (!fullResponse) {
|
|
310
|
+
fullResponse = parsedData;
|
|
311
|
+
}
|
|
312
|
+
else if (parsedData.choices &&
|
|
313
|
+
parsedData.choices[0] &&
|
|
314
|
+
parsedData.choices[0].delta) {
|
|
315
|
+
// Accumulate content for the full response
|
|
316
|
+
if (parsedData.choices[0].delta.content) {
|
|
317
|
+
fullContent += parsedData.choices[0].delta.content;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
catch (e) {
|
|
322
|
+
logger_1.logger.error(`Error parsing chunk: ${e}`);
|
|
323
|
+
logger_1.logger.debug(`Problematic chunk: ${jsonData}`);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
// Construct the final response object similar to non-streaming response
|
|
329
|
+
if (fullResponse) {
|
|
330
|
+
if (fullContent) {
|
|
331
|
+
fullResponse.choices[0].message = {
|
|
332
|
+
role: 'assistant',
|
|
333
|
+
content: fullContent,
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
return fullResponse;
|
|
337
|
+
}
|
|
338
|
+
return {
|
|
339
|
+
choices: [{ message: { role: 'assistant', content: fullContent } }],
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
catch (error) {
|
|
343
|
+
logger_1.logger.error(`Streaming error: ${error instanceof Error ? error.message : String(error)}`);
|
|
344
|
+
throw error;
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
}
|
|
243
348
|
/**
|
|
244
349
|
* List available models
|
|
245
350
|
* Command: berget chat list
|
|
@@ -252,7 +357,7 @@ class ChatService {
|
|
|
252
357
|
const effectiveApiKey = envApiKey || apiKey;
|
|
253
358
|
if (effectiveApiKey) {
|
|
254
359
|
const headers = {
|
|
255
|
-
|
|
360
|
+
Authorization: effectiveApiKey,
|
|
256
361
|
};
|
|
257
362
|
const { data, error } = yield this.client.GET('/v1/models', { headers });
|
|
258
363
|
if (error)
|
|
@@ -274,9 +379,9 @@ class ChatService {
|
|
|
274
379
|
// Try to parse the error message as JSON
|
|
275
380
|
const parsedError = JSON.parse(error.message);
|
|
276
381
|
if (parsedError.error) {
|
|
277
|
-
errorMessage = `Models error: ${typeof parsedError.error === 'string'
|
|
278
|
-
parsedError.error
|
|
279
|
-
|
|
382
|
+
errorMessage = `Models error: ${typeof parsedError.error === 'string'
|
|
383
|
+
? parsedError.error
|
|
384
|
+
: parsedError.error.message || JSON.stringify(parsedError.error)}`;
|
|
280
385
|
}
|
|
281
386
|
}
|
|
282
387
|
catch (e) {
|
|
@@ -284,7 +389,7 @@ class ChatService {
|
|
|
284
389
|
errorMessage = `Models error: ${error.message}`;
|
|
285
390
|
}
|
|
286
391
|
}
|
|
287
|
-
|
|
392
|
+
logger_1.logger.error(errorMessage);
|
|
288
393
|
throw new Error(errorMessage);
|
|
289
394
|
}
|
|
290
395
|
});
|
|
@@ -296,5 +401,5 @@ ChatService.COMMAND_GROUP = 'chat';
|
|
|
296
401
|
// Subcommands for this service
|
|
297
402
|
ChatService.COMMANDS = {
|
|
298
403
|
RUN: 'run',
|
|
299
|
-
LIST: 'list'
|
|
404
|
+
LIST: 'list',
|
|
300
405
|
};
|
|
@@ -39,9 +39,9 @@ exports.DefaultApiKeyManager = void 0;
|
|
|
39
39
|
const fs = __importStar(require("fs"));
|
|
40
40
|
const path = __importStar(require("path"));
|
|
41
41
|
const os = __importStar(require("os"));
|
|
42
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
43
42
|
const api_key_service_1 = require("../services/api-key-service");
|
|
44
43
|
const readline_1 = __importDefault(require("readline"));
|
|
44
|
+
const logger_1 = require("./logger");
|
|
45
45
|
/**
|
|
46
46
|
* Manages the default API key for chat commands
|
|
47
47
|
*/
|
|
@@ -73,9 +73,7 @@ class DefaultApiKeyManager {
|
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
catch (error) {
|
|
76
|
-
|
|
77
|
-
console.error(chalk_1.default.dim('Failed to load default API key configuration'));
|
|
78
|
-
}
|
|
76
|
+
logger_1.logger.debug('Failed to load default API key configuration');
|
|
79
77
|
this.defaultApiKey = null;
|
|
80
78
|
}
|
|
81
79
|
}
|
|
@@ -97,9 +95,7 @@ class DefaultApiKeyManager {
|
|
|
97
95
|
}
|
|
98
96
|
}
|
|
99
97
|
catch (error) {
|
|
100
|
-
|
|
101
|
-
console.error(chalk_1.default.dim('Failed to save default API key configuration'));
|
|
102
|
-
}
|
|
98
|
+
logger_1.logger.debug('Failed to save default API key configuration');
|
|
103
99
|
}
|
|
104
100
|
}
|
|
105
101
|
/**
|
|
@@ -136,34 +132,23 @@ class DefaultApiKeyManager {
|
|
|
136
132
|
promptForDefaultApiKey() {
|
|
137
133
|
return __awaiter(this, void 0, void 0, function* () {
|
|
138
134
|
try {
|
|
139
|
-
|
|
140
|
-
if (isDebug) {
|
|
141
|
-
console.log(chalk_1.default.yellow('DEBUG: promptForDefaultApiKey called'));
|
|
142
|
-
}
|
|
135
|
+
logger_1.logger.debug('promptForDefaultApiKey called');
|
|
143
136
|
// If we already have a default API key, return it
|
|
144
137
|
if (this.defaultApiKey) {
|
|
145
|
-
|
|
146
|
-
console.log(chalk_1.default.yellow('DEBUG: Using existing default API key'));
|
|
147
|
-
}
|
|
138
|
+
logger_1.logger.debug('Using existing default API key');
|
|
148
139
|
return this.defaultApiKey.key;
|
|
149
140
|
}
|
|
150
|
-
|
|
151
|
-
console.log(chalk_1.default.yellow('DEBUG: No default API key found, getting ApiKeyService'));
|
|
152
|
-
}
|
|
141
|
+
logger_1.logger.debug('No default API key found, getting ApiKeyService');
|
|
153
142
|
const apiKeyService = api_key_service_1.ApiKeyService.getInstance();
|
|
154
143
|
// Get all API keys
|
|
155
144
|
let apiKeys;
|
|
156
145
|
try {
|
|
157
|
-
|
|
158
|
-
console.log(chalk_1.default.yellow('DEBUG: Calling apiKeyService.list()'));
|
|
159
|
-
}
|
|
146
|
+
logger_1.logger.debug('Calling apiKeyService.list()');
|
|
160
147
|
apiKeys = yield apiKeyService.list();
|
|
161
|
-
|
|
162
|
-
console.log(chalk_1.default.yellow(`DEBUG: Got ${apiKeys ? apiKeys.length : 0} API keys`));
|
|
163
|
-
}
|
|
148
|
+
logger_1.logger.debug(`Got ${apiKeys ? apiKeys.length : 0} API keys`);
|
|
164
149
|
if (!apiKeys || apiKeys.length === 0) {
|
|
165
|
-
|
|
166
|
-
|
|
150
|
+
logger_1.logger.warn('No API keys found. Create one with:');
|
|
151
|
+
logger_1.logger.info(' berget api-keys create --name "My Key"');
|
|
167
152
|
return null;
|
|
168
153
|
}
|
|
169
154
|
}
|
|
@@ -174,24 +159,22 @@ class DefaultApiKeyManager {
|
|
|
174
159
|
errorMessage.includes('Authentication failed') ||
|
|
175
160
|
errorMessage.includes('AUTH_FAILED');
|
|
176
161
|
if (isAuthError) {
|
|
177
|
-
|
|
162
|
+
logger_1.logger.warn('Authentication required. Please run `berget auth login` first.');
|
|
178
163
|
}
|
|
179
164
|
else {
|
|
180
|
-
|
|
165
|
+
logger_1.logger.error('Error fetching API keys:');
|
|
181
166
|
if (error instanceof Error) {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
console.log(chalk_1.default.yellow(`DEBUG: Stack: ${error.stack}`));
|
|
186
|
-
}
|
|
167
|
+
logger_1.logger.error(error.message);
|
|
168
|
+
logger_1.logger.debug(`API key list error: ${error.message}`);
|
|
169
|
+
logger_1.logger.debug(`Stack: ${error.stack}`);
|
|
187
170
|
}
|
|
188
171
|
}
|
|
189
172
|
return null;
|
|
190
173
|
}
|
|
191
|
-
|
|
174
|
+
logger_1.logger.info('Select an API key to use as default:');
|
|
192
175
|
// Display available API keys
|
|
193
176
|
apiKeys.forEach((key, index) => {
|
|
194
|
-
|
|
177
|
+
logger_1.logger.log(` ${index + 1}. ${key.name} (${key.prefix}...)`);
|
|
195
178
|
});
|
|
196
179
|
// Create readline interface for user input
|
|
197
180
|
const rl = readline_1.default.createInterface({
|
|
@@ -212,7 +195,7 @@ class DefaultApiKeyManager {
|
|
|
212
195
|
});
|
|
213
196
|
});
|
|
214
197
|
if (selection === -1) {
|
|
215
|
-
|
|
198
|
+
logger_1.logger.warn('No API key selected');
|
|
216
199
|
return null;
|
|
217
200
|
}
|
|
218
201
|
const selectedKey = apiKeys[selection];
|
|
@@ -224,11 +207,11 @@ class DefaultApiKeyManager {
|
|
|
224
207
|
// Save the new key as default
|
|
225
208
|
this.setDefaultApiKey(newKey.id.toString(), newKey.name, newKey.key.substring(0, 8), // Use first 8 chars as prefix
|
|
226
209
|
newKey.key);
|
|
227
|
-
|
|
210
|
+
logger_1.logger.success(`✓ Default API key set to: ${newKey.name}`);
|
|
228
211
|
return newKey.key;
|
|
229
212
|
}
|
|
230
213
|
catch (error) {
|
|
231
|
-
|
|
214
|
+
logger_1.logger.error('Failed to set default API key:', error);
|
|
232
215
|
return null;
|
|
233
216
|
}
|
|
234
217
|
});
|