berget 1.2.0 → 1.3.1

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.
@@ -7,6 +7,7 @@ import { ApiKeyService } from '../services/api-key-service'
7
7
  import { AuthService } from '../services/auth-service'
8
8
  import { handleError } from '../utils/error-handler'
9
9
  import { DefaultApiKeyManager } from '../utils/default-api-key'
10
+ import { renderMarkdown, containsMarkdown } from '../utils/markdown-renderer'
10
11
 
11
12
  /**
12
13
  * Helper function to get user confirmation
@@ -45,6 +46,7 @@ export function registerChatCommands(program: Command): void {
45
46
  '--api-key-id <id>',
46
47
  'ID of the API key to use from your saved keys'
47
48
  )
49
+ .option('--stream', 'Stream the response')
48
50
  .action(async (options) => {
49
51
  try {
50
52
  const chatService = ChatService.getInstance()
@@ -60,6 +62,20 @@ export function registerChatCommands(program: Command): void {
60
62
  chalk.dim(`Using API key from BERGET_API_KEY environment variable`)
61
63
  )
62
64
  apiKey = envApiKey;
65
+
66
+ // Debug the API key (first few characters only)
67
+ if (process.argv.includes('--debug')) {
68
+ console.log(
69
+ chalk.yellow(`DEBUG: API key from env starts with: ${envApiKey.substring(0, 4)}...`)
70
+ )
71
+ }
72
+ }
73
+ // If API key is already provided via command line, use it
74
+ else if (options.apiKey) {
75
+ console.log(
76
+ chalk.dim(`Using API key from command line argument`)
77
+ )
78
+ apiKey = options.apiKey;
63
79
  }
64
80
  // If no API key or API key ID provided and no env var, check for default API key
65
81
  else if (!apiKey && !apiKeyId) {
@@ -240,41 +256,48 @@ export function registerChatCommands(program: Command): void {
240
256
 
241
257
  try {
242
258
  // Call the API
243
- console.log(chalk.yellow('DEBUG: Preparing completion options'))
244
-
245
259
  const completionOptions: ChatCompletionOptions = {
246
260
  model: options.args?.[0] || 'google/gemma-3-27b-it',
247
261
  messages: messages,
248
262
  temperature:
249
263
  options.temperature !== undefined ? options.temperature : 0.7,
250
264
  max_tokens: options.maxTokens || 4096,
265
+ stream: options.stream || false
251
266
  }
252
267
 
253
268
  // Only add apiKey if it actually exists
254
269
  if (apiKey) {
255
270
  completionOptions.apiKey = apiKey
256
- console.log(chalk.yellow('DEBUG: Using API key from command options or default'))
257
- } else {
258
- console.log(chalk.yellow('DEBUG: No API key available in chat command'))
259
- // If we got this far with defaultApiKeyData but no apiKey, there's a problem
260
- const defaultApiKeyManager = DefaultApiKeyManager.getInstance();
261
- if (defaultApiKeyManager.getDefaultApiKeyData()) {
262
- console.log(chalk.yellow('DEBUG: Default API key data exists but key is missing'))
271
+ }
272
+
273
+ // Add streaming support
274
+ if (options.stream) {
275
+ let assistantResponse = ''
276
+ console.log(chalk.blue('Assistant: '))
277
+
278
+ // For streaming, we'll collect the response and render it at the end
279
+ // since markdown needs the complete text to render properly
280
+ completionOptions.onChunk = (chunk: any) => {
281
+ if (chunk.choices && chunk.choices[0] && chunk.choices[0].delta && chunk.choices[0].delta.content) {
282
+ const content = chunk.choices[0].delta.content
283
+ process.stdout.write(content)
284
+ assistantResponse += content
285
+ }
263
286
  }
287
+
288
+ await chatService.createCompletion(completionOptions)
289
+ console.log('\n')
290
+
291
+ // Add assistant response to messages
292
+ messages.push({
293
+ role: 'assistant',
294
+ content: assistantResponse
295
+ })
296
+
297
+ // Continue the conversation
298
+ askQuestion()
299
+ return
264
300
  }
265
-
266
- // Debug output
267
- console.log(chalk.yellow('DEBUG: Completion options:'))
268
- console.log(chalk.yellow(JSON.stringify({
269
- ...completionOptions,
270
- apiKey: completionOptions.apiKey ? '***' : undefined,
271
- messages: completionOptions.messages.map((m: any) => ({
272
- role: m.role,
273
- content: m.content.length > 50 ? m.content.substring(0, 50) + '...' : m.content
274
- }))
275
- }, null, 2)))
276
-
277
- console.log(chalk.yellow('DEBUG: Calling chatService.createCompletion'))
278
301
 
279
302
  const response = await chatService.createCompletion(
280
303
  completionOptions
@@ -312,7 +335,15 @@ export function registerChatCommands(program: Command): void {
312
335
  })
313
336
 
314
337
  // Display the response
315
- console.log(chalk.blue('Assistant: ') + assistantMessage)
338
+ console.log(chalk.blue('Assistant: '))
339
+
340
+ // Check if the response contains markdown and render it if it does
341
+ if (containsMarkdown(assistantMessage)) {
342
+ console.log(renderMarkdown(assistantMessage))
343
+ } else {
344
+ console.log(assistantMessage)
345
+ }
346
+
316
347
  console.log() // Empty line for better readability
317
348
 
318
349
  // Continue the conversation
@@ -419,23 +450,27 @@ export function registerChatCommands(program: Command): void {
419
450
  console.log(chalk.bold('Available Chat Models:'))
420
451
  console.log(chalk.dim('─'.repeat(70)))
421
452
  console.log(
422
- chalk.dim('MODEL ID'.padEnd(30)) +
423
- chalk.dim('OWNER'.padEnd(25)) +
453
+ chalk.dim('MODEL ID'.padEnd(40)) +
424
454
  chalk.dim('CAPABILITIES')
425
455
  )
426
456
  console.log(chalk.dim('─'.repeat(70)))
427
457
 
428
- models.data.forEach((model: any) => {
458
+ // Filter to only show active models
459
+ const activeModels = models.data.filter((model: any) => model.active === true);
460
+
461
+ activeModels.forEach((model: any) => {
429
462
  const capabilities = []
430
463
  if (model.capabilities.vision) capabilities.push('vision')
431
464
  if (model.capabilities.function_calling)
432
465
  capabilities.push('function_calling')
433
466
  if (model.capabilities.json_mode) capabilities.push('json_mode')
434
467
 
468
+ // Format model ID in Huggingface compatible format (owner/model)
469
+ const modelId = `${model.owned_by.toLowerCase()}/${model.id}`.padEnd(40)
470
+
435
471
  console.log(
436
- model.id.padEnd(30) +
437
- model.owned_by.padEnd(25) +
438
- capabilities.join(', ')
472
+ modelId +
473
+ capabilities.join(', ')
439
474
  )
440
475
  })
441
476
  } catch (error) {
@@ -36,10 +36,10 @@ export function registerModelCommands(program: Command): void {
36
36
 
37
37
  console.log('Available Models:')
38
38
  console.log(
39
- 'ID OWNED BY CAPABILITIES'
39
+ 'ID OWNED BY CAPABILITIES'
40
40
  )
41
41
  // Ensure response has the expected structure
42
- const modelData = response as { data?: any[] };
42
+ const modelData = response as { data?: any[] }
43
43
  if (modelData.data) {
44
44
  modelData.data.forEach((model: any) => {
45
45
  const capabilities = []
@@ -49,8 +49,8 @@ export function registerModelCommands(program: Command): void {
49
49
  if (model.capabilities.json_mode) capabilities.push('json_mode')
50
50
 
51
51
  console.log(
52
- `${model.id.padEnd(24)} ${model.owned_by.padEnd(
53
- 25
52
+ `${model.root.padEnd(50)} ${model.owned_by.padEnd(
53
+ 24
54
54
  )} ${capabilities.join(', ')}`
55
55
  )
56
56
  })