berget 1.4.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/.env.example +5 -0
  2. package/AGENTS.md +184 -0
  3. package/TODO.md +2 -0
  4. package/blog-post.md +176 -0
  5. package/dist/index.js +11 -8
  6. package/dist/package.json +7 -2
  7. package/dist/src/commands/api-keys.js +4 -2
  8. package/dist/src/commands/chat.js +21 -11
  9. package/dist/src/commands/code.js +1424 -0
  10. package/dist/src/commands/index.js +2 -0
  11. package/dist/src/constants/command-structure.js +12 -0
  12. package/dist/src/schemas/opencode-schema.json +1121 -0
  13. package/dist/src/services/cluster-service.js +1 -1
  14. package/dist/src/utils/default-api-key.js +2 -2
  15. package/dist/src/utils/env-manager.js +86 -0
  16. package/dist/src/utils/error-handler.js +10 -3
  17. package/dist/src/utils/markdown-renderer.js +4 -4
  18. package/dist/src/utils/opencode-validator.js +122 -0
  19. package/dist/src/utils/token-manager.js +2 -2
  20. package/dist/tests/commands/chat.test.js +20 -18
  21. package/dist/tests/commands/code.test.js +414 -0
  22. package/dist/tests/utils/env-manager.test.js +148 -0
  23. package/dist/tests/utils/opencode-validator.test.js +103 -0
  24. package/index.ts +67 -32
  25. package/opencode.json +182 -0
  26. package/package.json +7 -2
  27. package/src/client.ts +20 -20
  28. package/src/commands/api-keys.ts +93 -60
  29. package/src/commands/auth.ts +4 -2
  30. package/src/commands/billing.ts +6 -3
  31. package/src/commands/chat.ts +149 -107
  32. package/src/commands/clusters.ts +2 -2
  33. package/src/commands/code.ts +1696 -0
  34. package/src/commands/index.ts +2 -0
  35. package/src/commands/models.ts +3 -3
  36. package/src/commands/users.ts +2 -2
  37. package/src/constants/command-structure.ts +112 -58
  38. package/src/schemas/opencode-schema.json +991 -0
  39. package/src/services/api-key-service.ts +1 -1
  40. package/src/services/auth-service.ts +27 -25
  41. package/src/services/chat-service.ts +26 -23
  42. package/src/services/cluster-service.ts +5 -5
  43. package/src/services/collaborator-service.ts +3 -3
  44. package/src/services/flux-service.ts +2 -2
  45. package/src/services/helm-service.ts +2 -2
  46. package/src/services/kubectl-service.ts +3 -6
  47. package/src/types/api.d.ts +1032 -1010
  48. package/src/types/json.d.ts +3 -3
  49. package/src/utils/default-api-key.ts +54 -42
  50. package/src/utils/env-manager.ts +98 -0
  51. package/src/utils/error-handler.ts +24 -15
  52. package/src/utils/logger.ts +12 -12
  53. package/src/utils/markdown-renderer.ts +18 -18
  54. package/src/utils/opencode-validator.ts +134 -0
  55. package/src/utils/token-manager.ts +35 -23
  56. package/tests/commands/chat.test.ts +43 -31
  57. package/tests/commands/code.test.ts +505 -0
  58. package/tests/utils/env-manager.test.ts +199 -0
  59. package/tests/utils/opencode-validator.test.ts +118 -0
  60. package/tsconfig.json +8 -8
  61. package/-27b-it +0 -0
  62. package/examples/README.md +0 -95
  63. package/examples/ai-review.sh +0 -30
  64. package/examples/install-global-security-hook.sh +0 -170
  65. package/examples/security-check.sh +0 -102
  66. package/examples/smart-commit.sh +0 -26
@@ -2,7 +2,11 @@ import { Command } from 'commander'
2
2
  import chalk from 'chalk'
3
3
  import readline from 'readline'
4
4
  import { COMMAND_GROUPS, SUBCOMMANDS } from '../constants/command-structure'
5
- import { ChatService, ChatMessage, ChatCompletionOptions } from '../services/chat-service'
5
+ import {
6
+ ChatService,
7
+ ChatMessage,
8
+ ChatCompletionOptions,
9
+ } from '../services/chat-service'
6
10
  import { ApiKeyService } from '../services/api-key-service'
7
11
  import { AuthService } from '../services/auth-service'
8
12
  import { handleError } from '../utils/error-handler'
@@ -45,9 +49,12 @@ export function registerChatCommands(program: Command): void {
45
49
  .option('-k, --api-key <key>', 'API key to use for this chat session')
46
50
  .option(
47
51
  '--api-key-id <id>',
48
- 'ID of the API key to use from your saved keys'
52
+ 'ID of the API key to use from your saved keys',
53
+ )
54
+ .option(
55
+ '--no-stream',
56
+ 'Disable streaming (streaming is enabled by default)',
49
57
  )
50
- .option('--no-stream', 'Disable streaming (streaming is enabled by default)')
51
58
  .action(async (model, message, options) => {
52
59
  try {
53
60
  const chatService = ChatService.getInstance()
@@ -55,49 +62,54 @@ export function registerChatCommands(program: Command): void {
55
62
  // Check if we have an API key or need to get one
56
63
  let apiKey = options.apiKey
57
64
  let apiKeyId = options.apiKeyId
58
-
65
+
59
66
  // Check for environment variable first
60
- const envApiKey = process.env.BERGET_API_KEY;
67
+ const envApiKey = process.env.BERGET_API_KEY
61
68
  if (envApiKey) {
62
69
  console.log(
63
- chalk.dim(`Using API key from BERGET_API_KEY environment variable`)
70
+ chalk.dim(`Using API key from BERGET_API_KEY environment variable`),
64
71
  )
65
- apiKey = envApiKey;
66
-
72
+ apiKey = envApiKey
73
+
67
74
  // Debug the API key (first few characters only)
68
75
  if (process.argv.includes('--debug')) {
69
76
  console.log(
70
- chalk.yellow(`DEBUG: API key from env starts with: ${envApiKey.substring(0, 4)}...`)
77
+ chalk.yellow(
78
+ `DEBUG: API key from env starts with: ${envApiKey.substring(0, 4)}...`,
79
+ ),
71
80
  )
72
81
  }
73
82
  }
74
83
  // If API key is already provided via command line, use it
75
84
  else if (options.apiKey) {
76
- console.log(
77
- chalk.dim(`Using API key from command line argument`)
78
- )
79
- apiKey = options.apiKey;
85
+ console.log(chalk.dim(`Using API key from command line argument`))
86
+ apiKey = options.apiKey
80
87
  }
81
88
  // If no API key or API key ID provided and no env var, check for default API key
82
89
  else if (!apiKey && !apiKeyId) {
83
90
  try {
84
91
  const defaultApiKeyManager = DefaultApiKeyManager.getInstance()
85
- const defaultApiKeyData = defaultApiKeyManager.getDefaultApiKeyData()
92
+ const defaultApiKeyData =
93
+ defaultApiKeyManager.getDefaultApiKeyData()
86
94
 
87
95
  if (defaultApiKeyData) {
88
96
  apiKeyId = defaultApiKeyData.id
89
97
  apiKey = defaultApiKeyData.key
90
-
98
+
91
99
  if (apiKey) {
92
100
  console.log(
93
- chalk.dim(`Using default API key: ${defaultApiKeyData.name}`)
101
+ chalk.dim(`Using default API key: ${defaultApiKeyData.name}`),
94
102
  )
95
103
  } else {
96
104
  console.log(
97
- chalk.yellow(`Default API key "${defaultApiKeyData.name}" exists but the key value is missing.`)
105
+ chalk.yellow(
106
+ `Default API key "${defaultApiKeyData.name}" exists but the key value is missing.`,
107
+ ),
98
108
  )
99
109
  console.log(
100
- chalk.yellow(`Try rotating the key with: berget api-keys rotate ${defaultApiKeyData.id}`)
110
+ chalk.yellow(
111
+ `Try rotating the key with: berget api-keys rotate ${defaultApiKeyData.id}`,
112
+ ),
101
113
  )
102
114
  }
103
115
  } else {
@@ -110,24 +122,24 @@ export function registerChatCommands(program: Command): void {
110
122
  if (!apiKey) {
111
123
  console.log(
112
124
  chalk.red(
113
- 'Error: An API key is required to use the chat command.'
114
- )
125
+ 'Error: An API key is required to use the chat command.',
126
+ ),
115
127
  )
116
128
  console.log(chalk.yellow('You can:'))
117
129
  console.log(
118
130
  chalk.yellow(
119
- '1. Create an API key with: berget api-keys create --name "My Key"'
120
- )
131
+ '1. Create an API key with: berget api-keys create --name "My Key"',
132
+ ),
121
133
  )
122
134
  console.log(
123
135
  chalk.yellow(
124
- '2. Set a default API key with: berget api-keys set-default <id>'
125
- )
136
+ '2. Set a default API key with: berget api-keys set-default <id>',
137
+ ),
126
138
  )
127
139
  console.log(
128
140
  chalk.yellow(
129
- '3. Provide an API key with the --api-key option'
130
- )
141
+ '3. Provide an API key with the --api-key option',
142
+ ),
131
143
  )
132
144
  return
133
145
  }
@@ -135,7 +147,7 @@ export function registerChatCommands(program: Command): void {
135
147
  } catch (error) {
136
148
  if (process.argv.includes('--debug')) {
137
149
  console.log(
138
- chalk.yellow('DEBUG: Error checking default API key:')
150
+ chalk.yellow('DEBUG: Error checking default API key:'),
139
151
  )
140
152
  console.log(chalk.yellow(String(error)))
141
153
  }
@@ -148,14 +160,14 @@ export function registerChatCommands(program: Command): void {
148
160
  const apiKeyService = ApiKeyService.getInstance()
149
161
  const keys = await apiKeyService.list()
150
162
  const selectedKey = keys.find(
151
- (key) => key.id.toString() === options.apiKeyId
163
+ (key) => key.id.toString() === options.apiKeyId,
152
164
  )
153
165
 
154
166
  if (!selectedKey) {
155
167
  console.log(
156
168
  chalk.yellow(
157
- `API key with ID ${options.apiKeyId} not found. Using default authentication.`
158
- )
169
+ `API key with ID ${options.apiKeyId} not found. Using default authentication.`,
170
+ ),
159
171
  )
160
172
  } else {
161
173
  console.log(chalk.dim(`Using API key: ${selectedKey.name}`))
@@ -164,37 +176,43 @@ export function registerChatCommands(program: Command): void {
164
176
  if (
165
177
  await confirm(
166
178
  chalk.yellow(
167
- `To use API key "${selectedKey.name}", it needs to be rotated. This will invalidate the current key. Continue? (y/n)`
168
- )
179
+ `To use API key "${selectedKey.name}", it needs to be rotated. This will invalidate the current key. Continue? (y/n)`,
180
+ ),
169
181
  )
170
182
  ) {
171
183
  const rotatedKey = await apiKeyService.rotate(options.apiKeyId)
172
184
  apiKey = rotatedKey.key
173
185
  console.log(
174
186
  chalk.green(
175
- `API key "${selectedKey.name}" rotated successfully.`
176
- )
187
+ `API key "${selectedKey.name}" rotated successfully.`,
188
+ ),
177
189
  )
178
190
  } else {
179
191
  console.log(
180
- chalk.yellow('Using default authentication instead.')
192
+ chalk.yellow('Using default authentication instead.'),
181
193
  )
182
194
  }
183
195
  }
184
196
  } catch (error) {
185
197
  // Check if this is an authentication error
186
- const errorMessage = error instanceof Error ? error.message : String(error);
187
- const isAuthError = errorMessage.includes('Unauthorized') ||
188
- errorMessage.includes('Authentication failed') ||
189
- errorMessage.includes('AUTH_FAILED');
190
-
198
+ const errorMessage =
199
+ error instanceof Error ? error.message : String(error)
200
+ const isAuthError =
201
+ errorMessage.includes('Unauthorized') ||
202
+ errorMessage.includes('Authentication failed') ||
203
+ errorMessage.includes('AUTH_FAILED')
204
+
191
205
  if (isAuthError) {
192
- console.log(chalk.yellow('Authentication required. Please run `berget auth login` first.'));
206
+ console.log(
207
+ chalk.yellow(
208
+ 'Authentication required. Please run `berget auth login` first.',
209
+ ),
210
+ )
193
211
  } else {
194
- console.error(chalk.red('Error fetching API key:'));
195
- console.error(error);
212
+ console.error(chalk.red('Error fetching API key:'))
213
+ console.error(error)
196
214
  }
197
- console.log(chalk.yellow('Using default authentication instead.'));
215
+ console.log(chalk.yellow('Using default authentication instead.'))
198
216
  }
199
217
  }
200
218
 
@@ -208,12 +226,12 @@ export function registerChatCommands(program: Command): void {
208
226
  console.log(chalk.yellow('1. Log in with `berget auth login`'))
209
227
  console.log(chalk.yellow('2. Provide an API key with `--api-key`'))
210
228
  console.log(
211
- chalk.yellow('3. Provide an API key ID with `--api-key-id`')
229
+ chalk.yellow('3. Provide an API key ID with `--api-key-id`'),
212
230
  )
213
231
  console.log(
214
232
  chalk.yellow(
215
- '4. Set a default API key with `berget api-keys set-default <id>`'
216
- )
233
+ '4. Set a default API key with `berget api-keys set-default <id>`',
234
+ ),
217
235
  )
218
236
  return
219
237
  }
@@ -233,7 +251,7 @@ export function registerChatCommands(program: Command): void {
233
251
  // Check if input is being piped in
234
252
  let inputMessage = message
235
253
  let stdinContent = ''
236
-
254
+
237
255
  if (!process.stdin.isTTY) {
238
256
  // Read from stdin (piped input)
239
257
  const chunks = []
@@ -266,21 +284,26 @@ export function registerChatCommands(program: Command): void {
266
284
  temperature:
267
285
  options.temperature !== undefined ? options.temperature : 0.7,
268
286
  max_tokens: options.maxTokens || 4096,
269
- stream: options.stream !== false
287
+ stream: options.stream !== false,
270
288
  }
271
289
 
272
290
  // Only add apiKey if it actually exists
273
291
  if (apiKey) {
274
292
  completionOptions.apiKey = apiKey
275
293
  }
276
-
294
+
277
295
  // Add streaming support (now default)
278
296
  if (completionOptions.stream) {
279
297
  let assistantResponse = ''
280
-
298
+
281
299
  // Stream the response in real-time
282
300
  completionOptions.onChunk = (chunk: any) => {
283
- if (chunk.choices && chunk.choices[0] && chunk.choices[0].delta && chunk.choices[0].delta.content) {
301
+ if (
302
+ chunk.choices &&
303
+ chunk.choices[0] &&
304
+ chunk.choices[0].delta &&
305
+ chunk.choices[0].delta.content
306
+ ) {
284
307
  const content = chunk.choices[0].delta.content
285
308
  try {
286
309
  process.stdout.write(content)
@@ -295,20 +318,28 @@ export function registerChatCommands(program: Command): void {
295
318
  assistantResponse += content
296
319
  }
297
320
  }
298
-
321
+
299
322
  try {
300
323
  await chatService.createCompletion(completionOptions)
301
324
  } catch (streamError) {
302
325
  console.error(chalk.red('\nStreaming error:'), streamError)
303
-
326
+
304
327
  // Fallback to non-streaming if streaming fails
305
- console.log(chalk.yellow('Falling back to non-streaming mode...'))
328
+ console.log(
329
+ chalk.yellow('Falling back to non-streaming mode...'),
330
+ )
306
331
  completionOptions.stream = false
307
332
  delete completionOptions.onChunk
308
-
309
- const response = await chatService.createCompletion(completionOptions)
310
-
311
- if (response && response.choices && response.choices[0] && response.choices[0].message) {
333
+
334
+ const response =
335
+ await chatService.createCompletion(completionOptions)
336
+
337
+ if (
338
+ response &&
339
+ response.choices &&
340
+ response.choices[0] &&
341
+ response.choices[0].message
342
+ ) {
312
343
  assistantResponse = response.choices[0].message.content
313
344
  console.log(assistantResponse)
314
345
  }
@@ -316,10 +347,9 @@ export function registerChatCommands(program: Command): void {
316
347
  console.log() // Add newline at the end
317
348
  return
318
349
  }
319
-
320
- const response = await chatService.createCompletion(
321
- completionOptions
322
- )
350
+
351
+ const response =
352
+ await chatService.createCompletion(completionOptions)
323
353
 
324
354
  // Check if response has the expected structure
325
355
  if (
@@ -329,10 +359,10 @@ export function registerChatCommands(program: Command): void {
329
359
  !response.choices[0].message
330
360
  ) {
331
361
  console.error(
332
- chalk.red('Error: Unexpected response format from API')
362
+ chalk.red('Error: Unexpected response format from API'),
333
363
  )
334
364
  console.error(
335
- chalk.red('Response:', JSON.stringify(response, null, 2))
365
+ chalk.red('Response:', JSON.stringify(response, null, 2)),
336
366
  )
337
367
  throw new Error('Unexpected response format from API')
338
368
  }
@@ -346,7 +376,7 @@ export function registerChatCommands(program: Command): void {
346
376
  } else {
347
377
  console.log(assistantMessage)
348
378
  }
349
-
379
+
350
380
  return
351
381
  } catch (error) {
352
382
  console.error(chalk.red('Error: Failed to get response'))
@@ -390,22 +420,27 @@ export function registerChatCommands(program: Command): void {
390
420
  temperature:
391
421
  options.temperature !== undefined ? options.temperature : 0.7,
392
422
  max_tokens: options.maxTokens || 4096,
393
- stream: options.stream !== false
423
+ stream: options.stream !== false,
394
424
  }
395
425
 
396
426
  // Only add apiKey if it actually exists
397
427
  if (apiKey) {
398
428
  completionOptions.apiKey = apiKey
399
429
  }
400
-
430
+
401
431
  // Add streaming support (now default)
402
432
  if (completionOptions.stream) {
403
433
  let assistantResponse = ''
404
434
  console.log(chalk.blue('Assistant: '))
405
-
435
+
406
436
  // Stream the response in real-time
407
437
  completionOptions.onChunk = (chunk: any) => {
408
- if (chunk.choices && chunk.choices[0] && chunk.choices[0].delta && chunk.choices[0].delta.content) {
438
+ if (
439
+ chunk.choices &&
440
+ chunk.choices[0] &&
441
+ chunk.choices[0].delta &&
442
+ chunk.choices[0].delta.content
443
+ ) {
409
444
  const content = chunk.choices[0].delta.content
410
445
  try {
411
446
  process.stdout.write(content)
@@ -420,40 +455,47 @@ export function registerChatCommands(program: Command): void {
420
455
  assistantResponse += content
421
456
  }
422
457
  }
423
-
458
+
424
459
  try {
425
460
  await chatService.createCompletion(completionOptions)
426
461
  } catch (streamError) {
427
462
  console.error(chalk.red('\nStreaming error:'), streamError)
428
-
463
+
429
464
  // Fallback to non-streaming if streaming fails
430
- console.log(chalk.yellow('Falling back to non-streaming mode...'))
465
+ console.log(
466
+ chalk.yellow('Falling back to non-streaming mode...'),
467
+ )
431
468
  completionOptions.stream = false
432
469
  delete completionOptions.onChunk
433
-
434
- const response = await chatService.createCompletion(completionOptions)
435
-
436
- if (response && response.choices && response.choices[0] && response.choices[0].message) {
470
+
471
+ const response =
472
+ await chatService.createCompletion(completionOptions)
473
+
474
+ if (
475
+ response &&
476
+ response.choices &&
477
+ response.choices[0] &&
478
+ response.choices[0].message
479
+ ) {
437
480
  assistantResponse = response.choices[0].message.content
438
481
  console.log(assistantResponse)
439
482
  }
440
483
  }
441
484
  console.log('\n')
442
-
485
+
443
486
  // Add assistant response to messages
444
487
  messages.push({
445
488
  role: 'assistant',
446
- content: assistantResponse
489
+ content: assistantResponse,
447
490
  })
448
-
491
+
449
492
  // Continue the conversation
450
493
  askQuestion()
451
494
  return
452
495
  }
453
-
454
- const response = await chatService.createCompletion(
455
- completionOptions
456
- )
496
+
497
+ const response =
498
+ await chatService.createCompletion(completionOptions)
457
499
 
458
500
  // Debug output
459
501
  if (program.opts().debug) {
@@ -469,10 +511,10 @@ export function registerChatCommands(program: Command): void {
469
511
  !response.choices[0].message
470
512
  ) {
471
513
  console.error(
472
- chalk.red('Error: Unexpected response format from API')
514
+ chalk.red('Error: Unexpected response format from API'),
473
515
  )
474
516
  console.error(
475
- chalk.red('Response:', JSON.stringify(response, null, 2))
517
+ chalk.red('Response:', JSON.stringify(response, null, 2)),
476
518
  )
477
519
  throw new Error('Unexpected response format from API')
478
520
  }
@@ -488,14 +530,14 @@ export function registerChatCommands(program: Command): void {
488
530
 
489
531
  // Display the response
490
532
  console.log(chalk.blue('Assistant: '))
491
-
533
+
492
534
  // Check if the response contains markdown and render it if it does
493
535
  if (containsMarkdown(assistantMessage)) {
494
536
  console.log(renderMarkdown(assistantMessage))
495
537
  } else {
496
538
  console.log(assistantMessage)
497
539
  }
498
-
540
+
499
541
  console.log() // Empty line for better readability
500
542
 
501
543
  // Continue the conversation
@@ -524,7 +566,7 @@ export function registerChatCommands(program: Command): void {
524
566
  .option('-k, --api-key <key>', 'API key to use for this request')
525
567
  .option(
526
568
  '--api-key-id <id>',
527
- 'ID of the API key to use from your saved keys'
569
+ 'ID of the API key to use from your saved keys',
528
570
  )
529
571
  .action(async (options) => {
530
572
  try {
@@ -540,7 +582,7 @@ export function registerChatCommands(program: Command): void {
540
582
  if (defaultApiKeyData) {
541
583
  apiKeyId = defaultApiKeyData.id
542
584
  console.log(
543
- chalk.dim(`Using default API key: ${defaultApiKeyData.name}`)
585
+ chalk.dim(`Using default API key: ${defaultApiKeyData.name}`),
544
586
  )
545
587
  }
546
588
  }
@@ -550,14 +592,14 @@ export function registerChatCommands(program: Command): void {
550
592
  const apiKeyService = ApiKeyService.getInstance()
551
593
  const keys = await apiKeyService.list()
552
594
  const selectedKey = keys.find(
553
- (key) => key.id.toString() === options.apiKeyId
595
+ (key) => key.id.toString() === options.apiKeyId,
554
596
  )
555
597
 
556
598
  if (!selectedKey) {
557
599
  console.log(
558
600
  chalk.yellow(
559
- `API key with ID ${options.apiKeyId} not found. Using default authentication.`
560
- )
601
+ `API key with ID ${options.apiKeyId} not found. Using default authentication.`,
602
+ ),
561
603
  )
562
604
  } else {
563
605
  console.log(chalk.dim(`Using API key: ${selectedKey.name}`))
@@ -566,20 +608,20 @@ export function registerChatCommands(program: Command): void {
566
608
  if (
567
609
  await confirm(
568
610
  chalk.yellow(
569
- `To use API key "${selectedKey.name}", it needs to be rotated. This will invalidate the current key. Continue? (y/n)`
570
- )
611
+ `To use API key "${selectedKey.name}", it needs to be rotated. This will invalidate the current key. Continue? (y/n)`,
612
+ ),
571
613
  )
572
614
  ) {
573
615
  const rotatedKey = await apiKeyService.rotate(options.apiKeyId)
574
616
  apiKey = rotatedKey.key
575
617
  console.log(
576
618
  chalk.green(
577
- `API key "${selectedKey.name}" rotated successfully.`
578
- )
619
+ `API key "${selectedKey.name}" rotated successfully.`,
620
+ ),
579
621
  )
580
622
  } else {
581
623
  console.log(
582
- chalk.yellow('Using default authentication instead.')
624
+ chalk.yellow('Using default authentication instead.'),
583
625
  )
584
626
  }
585
627
  }
@@ -602,14 +644,15 @@ export function registerChatCommands(program: Command): void {
602
644
  console.log(chalk.bold('Available Chat Models:'))
603
645
  console.log(chalk.dim('─'.repeat(70)))
604
646
  console.log(
605
- chalk.dim('MODEL ID'.padEnd(40)) +
606
- chalk.dim('CAPABILITIES')
647
+ chalk.dim('MODEL ID'.padEnd(40)) + chalk.dim('CAPABILITIES'),
607
648
  )
608
649
  console.log(chalk.dim('─'.repeat(70)))
609
650
 
610
651
  // Filter to only show active models
611
- const activeModels = models.data.filter((model: any) => model.active === true);
612
-
652
+ const activeModels = models.data.filter(
653
+ (model: any) => model.active === true,
654
+ )
655
+
613
656
  activeModels.forEach((model: any) => {
614
657
  const capabilities = []
615
658
  if (model.capabilities.vision) capabilities.push('vision')
@@ -618,12 +661,11 @@ export function registerChatCommands(program: Command): void {
618
661
  if (model.capabilities.json_mode) capabilities.push('json_mode')
619
662
 
620
663
  // Format model ID in Huggingface compatible format (owner/model)
621
- const modelId = `${model.owned_by.toLowerCase()}/${model.id}`.padEnd(40)
622
-
623
- console.log(
624
- modelId +
625
- capabilities.join(', ')
664
+ const modelId = `${model.owned_by.toLowerCase()}/${model.id}`.padEnd(
665
+ 40,
626
666
  )
667
+
668
+ console.log(modelId + capabilities.join(', '))
627
669
  })
628
670
  } catch (error) {
629
671
  handleError('Failed to list chat models', error)
@@ -22,8 +22,8 @@ export function registerClusterCommands(program: Command): void {
22
22
  clusters.forEach((cluster: Cluster) => {
23
23
  console.log(
24
24
  `${cluster.name.padEnd(22)} ${cluster.status.padEnd(9)} ${String(
25
- cluster.nodes
26
- ).padEnd(8)} ${cluster.created}`
25
+ cluster.nodes,
26
+ ).padEnd(8)} ${cluster.created}`,
27
27
  )
28
28
  })
29
29
  } catch (error) {