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.
- package/.env.example +5 -0
- package/AGENTS.md +184 -0
- package/TODO.md +2 -0
- package/blog-post.md +176 -0
- package/dist/index.js +11 -8
- package/dist/package.json +7 -2
- package/dist/src/commands/api-keys.js +4 -2
- package/dist/src/commands/chat.js +21 -11
- package/dist/src/commands/code.js +1424 -0
- package/dist/src/commands/index.js +2 -0
- package/dist/src/constants/command-structure.js +12 -0
- package/dist/src/schemas/opencode-schema.json +1121 -0
- package/dist/src/services/cluster-service.js +1 -1
- package/dist/src/utils/default-api-key.js +2 -2
- package/dist/src/utils/env-manager.js +86 -0
- package/dist/src/utils/error-handler.js +10 -3
- package/dist/src/utils/markdown-renderer.js +4 -4
- package/dist/src/utils/opencode-validator.js +122 -0
- package/dist/src/utils/token-manager.js +2 -2
- package/dist/tests/commands/chat.test.js +20 -18
- package/dist/tests/commands/code.test.js +414 -0
- package/dist/tests/utils/env-manager.test.js +148 -0
- package/dist/tests/utils/opencode-validator.test.js +103 -0
- package/index.ts +67 -32
- package/opencode.json +182 -0
- package/package.json +7 -2
- package/src/client.ts +20 -20
- package/src/commands/api-keys.ts +93 -60
- package/src/commands/auth.ts +4 -2
- package/src/commands/billing.ts +6 -3
- package/src/commands/chat.ts +149 -107
- package/src/commands/clusters.ts +2 -2
- package/src/commands/code.ts +1696 -0
- package/src/commands/index.ts +2 -0
- package/src/commands/models.ts +3 -3
- package/src/commands/users.ts +2 -2
- package/src/constants/command-structure.ts +112 -58
- package/src/schemas/opencode-schema.json +991 -0
- package/src/services/api-key-service.ts +1 -1
- package/src/services/auth-service.ts +27 -25
- package/src/services/chat-service.ts +26 -23
- package/src/services/cluster-service.ts +5 -5
- package/src/services/collaborator-service.ts +3 -3
- package/src/services/flux-service.ts +2 -2
- package/src/services/helm-service.ts +2 -2
- package/src/services/kubectl-service.ts +3 -6
- package/src/types/api.d.ts +1032 -1010
- package/src/types/json.d.ts +3 -3
- package/src/utils/default-api-key.ts +54 -42
- package/src/utils/env-manager.ts +98 -0
- package/src/utils/error-handler.ts +24 -15
- package/src/utils/logger.ts +12 -12
- package/src/utils/markdown-renderer.ts +18 -18
- package/src/utils/opencode-validator.ts +134 -0
- package/src/utils/token-manager.ts +35 -23
- package/tests/commands/chat.test.ts +43 -31
- package/tests/commands/code.test.ts +505 -0
- package/tests/utils/env-manager.test.ts +199 -0
- package/tests/utils/opencode-validator.test.ts +118 -0
- package/tsconfig.json +8 -8
- package/-27b-it +0 -0
- package/examples/README.md +0 -95
- package/examples/ai-review.sh +0 -30
- package/examples/install-global-security-hook.sh +0 -170
- package/examples/security-check.sh +0 -102
- package/examples/smart-commit.sh +0 -26
package/src/commands/chat.ts
CHANGED
|
@@ -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 {
|
|
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(
|
|
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
|
-
|
|
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 =
|
|
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(
|
|
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(
|
|
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 =
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
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(
|
|
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 (
|
|
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(
|
|
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 =
|
|
310
|
-
|
|
311
|
-
|
|
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 =
|
|
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 (
|
|
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(
|
|
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 =
|
|
435
|
-
|
|
436
|
-
|
|
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 =
|
|
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(
|
|
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(
|
|
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)
|
package/src/commands/clusters.ts
CHANGED
|
@@ -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) {
|