berget 2.2.5 → 2.2.7
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/.github/workflows/publish.yml +8 -8
- package/.github/workflows/test.yml +12 -6
- package/.husky/pre-commit +1 -0
- package/.prettierignore +15 -0
- package/.prettierrc +5 -3
- package/CONTRIBUTING.md +38 -0
- package/README.md +2 -148
- package/dist/index.js +21 -21
- package/dist/package.json +30 -2
- package/dist/src/agents/app.js +28 -0
- package/dist/src/agents/backend.js +25 -0
- package/dist/src/agents/devops.js +34 -0
- package/dist/src/agents/frontend.js +25 -0
- package/dist/src/agents/fullstack.js +25 -0
- package/dist/src/agents/index.js +61 -0
- package/dist/src/agents/quality.js +70 -0
- package/dist/src/agents/security.js +26 -0
- package/dist/src/agents/types.js +2 -0
- package/dist/src/client.js +54 -62
- package/dist/src/commands/api-keys.js +132 -140
- package/dist/src/commands/auth.js +9 -9
- package/dist/src/commands/autocomplete.js +9 -9
- package/dist/src/commands/billing.js +7 -9
- package/dist/src/commands/chat.js +90 -92
- package/dist/src/commands/clusters.js +12 -12
- package/dist/src/commands/code/__tests__/auth-sync.test.js +348 -0
- package/dist/src/commands/code/__tests__/fake-api-key-service.js +23 -0
- package/dist/src/commands/code/__tests__/fake-auth-service.js +55 -0
- package/dist/src/commands/code/__tests__/fake-command-runner.js +50 -0
- package/dist/src/commands/code/__tests__/fake-file-store.js +55 -0
- package/dist/src/commands/code/__tests__/fake-prompter.js +133 -0
- package/dist/src/commands/code/__tests__/setup-flow.test.js +505 -0
- package/dist/src/commands/code/adapters/clack-prompter.js +81 -0
- package/dist/src/commands/code/adapters/fs-file-store.js +80 -0
- package/dist/src/commands/code/adapters/spawn-command-runner.js +53 -0
- package/dist/src/commands/code/auth-sync.js +283 -0
- package/dist/src/commands/code/errors.js +27 -0
- package/dist/src/commands/code/ports/auth-services.js +2 -0
- package/dist/src/commands/code/ports/command-runner.js +2 -0
- package/dist/src/commands/code/ports/file-store.js +2 -0
- package/dist/src/commands/code/ports/prompter.js +2 -0
- package/dist/src/commands/code/setup.js +533 -0
- package/dist/src/commands/code.js +223 -779
- package/dist/src/commands/models.js +13 -15
- package/dist/src/commands/users.js +6 -8
- package/dist/src/constants/command-structure.js +116 -114
- package/dist/src/services/api-key-service.js +43 -48
- package/dist/src/services/auth-service.js +60 -299
- package/dist/src/services/browser-auth.js +278 -0
- package/dist/src/services/chat-service.js +78 -91
- package/dist/src/services/cluster-service.js +6 -6
- package/dist/src/services/collaborator-service.js +5 -8
- package/dist/src/services/flux-service.js +5 -8
- package/dist/src/services/helm-service.js +5 -8
- package/dist/src/services/kubectl-service.js +7 -10
- package/dist/src/utils/config-checker.js +5 -5
- package/dist/src/utils/config-loader.js +25 -25
- package/dist/src/utils/default-api-key.js +23 -23
- package/dist/src/utils/env-manager.js +7 -7
- package/dist/src/utils/error-handler.js +60 -61
- package/dist/src/utils/logger.js +7 -7
- package/dist/src/utils/markdown-renderer.js +2 -2
- package/dist/src/utils/opencode-validator.js +17 -20
- package/dist/src/utils/token-manager.js +38 -11
- package/dist/tests/commands/chat.test.js +24 -24
- package/dist/tests/commands/code.test.js +169 -138
- package/dist/tests/utils/config-loader.test.js +114 -114
- package/dist/tests/utils/env-manager.test.js +57 -57
- package/dist/tests/utils/opencode-validator.test.js +44 -43
- package/dist/vitest.config.js +1 -1
- package/eslint.config.mjs +47 -0
- package/index.ts +42 -48
- package/package.json +30 -2
- package/src/agents/app.ts +27 -0
- package/src/agents/backend.ts +24 -0
- package/src/agents/devops.ts +33 -0
- package/src/agents/frontend.ts +24 -0
- package/src/agents/fullstack.ts +24 -0
- package/src/agents/index.ts +71 -0
- package/src/agents/quality.ts +69 -0
- package/src/agents/security.ts +26 -0
- package/src/agents/types.ts +17 -0
- package/src/client.ts +125 -167
- package/src/commands/api-keys.ts +261 -358
- package/src/commands/auth.ts +24 -30
- package/src/commands/autocomplete.ts +12 -12
- package/src/commands/billing.ts +22 -27
- package/src/commands/chat.ts +230 -323
- package/src/commands/clusters.ts +33 -33
- package/src/commands/code/__tests__/auth-sync.test.ts +481 -0
- package/src/commands/code/__tests__/fake-api-key-service.ts +13 -0
- package/src/commands/code/__tests__/fake-auth-service.ts +50 -0
- package/src/commands/code/__tests__/fake-command-runner.ts +44 -0
- package/src/commands/code/__tests__/fake-file-store.ts +44 -0
- package/src/commands/code/__tests__/fake-prompter.ts +121 -0
- package/src/commands/code/__tests__/setup-flow.test.ts +628 -0
- package/src/commands/code/adapters/clack-prompter.ts +55 -0
- package/src/commands/code/adapters/fs-file-store.ts +37 -0
- package/src/commands/code/adapters/spawn-command-runner.ts +40 -0
- package/src/commands/code/auth-sync.ts +329 -0
- package/src/commands/code/errors.ts +23 -0
- package/src/commands/code/ports/auth-services.ts +14 -0
- package/src/commands/code/ports/command-runner.ts +10 -0
- package/src/commands/code/ports/file-store.ts +7 -0
- package/src/commands/code/ports/prompter.ts +29 -0
- package/src/commands/code/setup.ts +630 -0
- package/src/commands/code.ts +335 -1074
- package/src/commands/index.ts +19 -19
- package/src/commands/models.ts +32 -37
- package/src/commands/users.ts +15 -22
- package/src/constants/command-structure.ts +120 -140
- package/src/services/api-key-service.ts +96 -113
- package/src/services/auth-service.ts +92 -339
- package/src/services/browser-auth.ts +296 -0
- package/src/services/chat-service.ts +246 -279
- package/src/services/cluster-service.ts +29 -32
- package/src/services/collaborator-service.ts +13 -18
- package/src/services/flux-service.ts +16 -18
- package/src/services/helm-service.ts +16 -18
- package/src/services/kubectl-service.ts +12 -14
- package/src/types/api.d.ts +924 -926
- package/src/types/json.d.ts +3 -3
- package/src/utils/config-checker.ts +10 -10
- package/src/utils/config-loader.ts +110 -127
- package/src/utils/default-api-key.ts +81 -93
- package/src/utils/env-manager.ts +36 -40
- package/src/utils/error-handler.ts +83 -78
- package/src/utils/logger.ts +41 -41
- package/src/utils/markdown-renderer.ts +11 -11
- package/src/utils/opencode-validator.ts +51 -56
- package/src/utils/token-manager.ts +84 -64
- package/templates/agents/app.md +23 -0
- package/templates/agents/backend.md +23 -0
- package/templates/agents/devops.md +30 -0
- package/templates/agents/frontend.md +25 -0
- package/templates/agents/fullstack.md +23 -0
- package/templates/agents/quality.md +69 -0
- package/templates/agents/security.md +21 -0
- package/tests/commands/chat.test.ts +60 -70
- package/tests/commands/code.test.ts +346 -345
- package/tests/utils/config-loader.test.ts +260 -260
- package/tests/utils/env-manager.test.ts +127 -134
- package/tests/utils/opencode-validator.test.ts +65 -69
- package/tsconfig.json +2 -2
- package/vitest.config.ts +3 -3
- package/AGENTS.md +0 -374
- package/TODO.md +0 -19
- package/opencode.json +0 -146
package/src/commands/chat.ts
CHANGED
|
@@ -1,17 +1,13 @@
|
|
|
1
|
-
import { Command } from
|
|
2
|
-
import chalk from
|
|
3
|
-
import readline from
|
|
4
|
-
import { COMMAND_GROUPS, SUBCOMMANDS } from
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
} from
|
|
10
|
-
import {
|
|
11
|
-
import { AuthService } from '../services/auth-service'
|
|
12
|
-
import { handleError } from '../utils/error-handler'
|
|
13
|
-
import { DefaultApiKeyManager } from '../utils/default-api-key'
|
|
14
|
-
import { renderMarkdown, containsMarkdown } from '../utils/markdown-renderer'
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import readline from "readline";
|
|
4
|
+
import { COMMAND_GROUPS, SUBCOMMANDS } from "../constants/command-structure";
|
|
5
|
+
import { ChatService, ChatMessage, ChatCompletionOptions } from "../services/chat-service";
|
|
6
|
+
import { ApiKeyService } from "../services/api-key-service";
|
|
7
|
+
import { AuthService } from "../services/auth-service";
|
|
8
|
+
import { handleError } from "../utils/error-handler";
|
|
9
|
+
import { DefaultApiKeyManager } from "../utils/default-api-key";
|
|
10
|
+
import { renderMarkdown, containsMarkdown } from "../utils/markdown-renderer";
|
|
15
11
|
|
|
16
12
|
/**
|
|
17
13
|
* Helper function to get user confirmation
|
|
@@ -20,139 +16,107 @@ async function confirm(question: string): Promise<boolean> {
|
|
|
20
16
|
const rl = readline.createInterface({
|
|
21
17
|
input: process.stdin,
|
|
22
18
|
output: process.stdout,
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
return new Promise<boolean>(
|
|
26
|
-
rl.question(question,
|
|
27
|
-
rl.close()
|
|
28
|
-
resolve(answer.toLowerCase() ===
|
|
29
|
-
})
|
|
30
|
-
})
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
return new Promise<boolean>(resolve => {
|
|
22
|
+
rl.question(question, answer => {
|
|
23
|
+
rl.close();
|
|
24
|
+
resolve(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
|
|
25
|
+
});
|
|
26
|
+
});
|
|
31
27
|
}
|
|
32
28
|
|
|
33
29
|
/**
|
|
34
30
|
* Register chat commands
|
|
35
31
|
*/
|
|
36
32
|
export function registerChatCommands(program: Command): void {
|
|
37
|
-
const chat = program
|
|
38
|
-
.command(COMMAND_GROUPS.CHAT)
|
|
39
|
-
.description('Interact with AI chat models')
|
|
33
|
+
const chat = program.command(COMMAND_GROUPS.CHAT).description("Interact with AI chat models");
|
|
40
34
|
|
|
41
35
|
chat
|
|
42
36
|
.command(SUBCOMMANDS.CHAT.RUN)
|
|
43
|
-
.description(
|
|
44
|
-
.argument(
|
|
45
|
-
.option(
|
|
46
|
-
|
|
47
|
-
.option(
|
|
48
|
-
.option(
|
|
49
|
-
.option(
|
|
50
|
-
.option(
|
|
51
|
-
|
|
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)'
|
|
57
|
-
)
|
|
37
|
+
.description("Run a chat session with a specified model")
|
|
38
|
+
.argument("[message]", "Message to send directly (skips interactive mode)")
|
|
39
|
+
.option("-m, --model <model>", "Model to use (default: glm-4.7)")
|
|
40
|
+
|
|
41
|
+
.option("-t, --temperature <temp>", "Temperature (0-1)", parseFloat)
|
|
42
|
+
.option("--max-tokens <tokens>", "Maximum tokens to generate", parseInt)
|
|
43
|
+
.option("-k, --api-key <key>", "API key to use for this chat session")
|
|
44
|
+
.option("--api-key-id <id>", "ID of the API key to use from your saved keys")
|
|
45
|
+
.option("--no-stream", "Disable streaming (streaming is enabled by default)")
|
|
58
46
|
.action(async (message, options) => {
|
|
59
47
|
try {
|
|
60
|
-
const chatService = ChatService.getInstance()
|
|
48
|
+
const chatService = ChatService.getInstance();
|
|
61
49
|
|
|
62
50
|
// Check if we have an API key or need to get one
|
|
63
|
-
let apiKey = options.apiKey
|
|
64
|
-
let apiKeyId = options.apiKeyId
|
|
51
|
+
let apiKey = options.apiKey;
|
|
52
|
+
let apiKeyId = options.apiKeyId;
|
|
65
53
|
|
|
66
54
|
// Check for environment variable first
|
|
67
|
-
const envApiKey = process.env.BERGET_API_KEY
|
|
55
|
+
const envApiKey = process.env.BERGET_API_KEY;
|
|
68
56
|
if (envApiKey) {
|
|
69
|
-
console.log(
|
|
70
|
-
|
|
71
|
-
)
|
|
72
|
-
apiKey = envApiKey
|
|
57
|
+
console.log(chalk.dim(`Using API key from BERGET_API_KEY environment variable`));
|
|
58
|
+
apiKey = envApiKey;
|
|
73
59
|
|
|
74
60
|
// Debug the API key (first few characters only)
|
|
75
|
-
if (process.argv.includes(
|
|
61
|
+
if (process.argv.includes("--debug")) {
|
|
76
62
|
console.log(
|
|
77
|
-
chalk.yellow(
|
|
78
|
-
|
|
79
|
-
0,
|
|
80
|
-
4
|
|
81
|
-
)}...`
|
|
82
|
-
)
|
|
83
|
-
)
|
|
63
|
+
chalk.yellow(`DEBUG: API key from env starts with: ${envApiKey.substring(0, 4)}...`)
|
|
64
|
+
);
|
|
84
65
|
}
|
|
85
66
|
}
|
|
86
67
|
// If API key is already provided via command line, use it
|
|
87
68
|
else if (options.apiKey) {
|
|
88
|
-
console.log(chalk.dim(`Using API key from command line argument`))
|
|
89
|
-
apiKey = options.apiKey
|
|
69
|
+
console.log(chalk.dim(`Using API key from command line argument`));
|
|
70
|
+
apiKey = options.apiKey;
|
|
90
71
|
}
|
|
91
72
|
// If no API key or API key ID provided and no env var, check for default API key
|
|
92
73
|
else if (!apiKey && !apiKeyId) {
|
|
93
74
|
try {
|
|
94
|
-
const defaultApiKeyManager = DefaultApiKeyManager.getInstance()
|
|
95
|
-
const defaultApiKeyData =
|
|
96
|
-
defaultApiKeyManager.getDefaultApiKeyData()
|
|
75
|
+
const defaultApiKeyManager = DefaultApiKeyManager.getInstance();
|
|
76
|
+
const defaultApiKeyData = defaultApiKeyManager.getDefaultApiKeyData();
|
|
97
77
|
|
|
98
78
|
if (defaultApiKeyData) {
|
|
99
|
-
apiKeyId = defaultApiKeyData.id
|
|
100
|
-
apiKey = defaultApiKeyData.key
|
|
79
|
+
apiKeyId = defaultApiKeyData.id;
|
|
80
|
+
apiKey = defaultApiKeyData.key;
|
|
101
81
|
|
|
102
82
|
if (apiKey) {
|
|
103
|
-
console.log(
|
|
104
|
-
chalk.dim(`Using default API key: ${defaultApiKeyData.name}`)
|
|
105
|
-
)
|
|
83
|
+
console.log(chalk.dim(`Using default API key: ${defaultApiKeyData.name}`));
|
|
106
84
|
} else {
|
|
107
85
|
console.log(
|
|
108
86
|
chalk.yellow(
|
|
109
87
|
`Default API key "${defaultApiKeyData.name}" exists but the key value is missing.`
|
|
110
88
|
)
|
|
111
|
-
)
|
|
89
|
+
);
|
|
112
90
|
console.log(
|
|
113
91
|
chalk.yellow(
|
|
114
92
|
`Try rotating the key with: berget api-keys rotate ${defaultApiKeyData.id}`
|
|
115
93
|
)
|
|
116
|
-
)
|
|
94
|
+
);
|
|
117
95
|
}
|
|
118
96
|
} else {
|
|
119
97
|
// No default API key, prompt the user to create one
|
|
120
|
-
console.log(chalk.yellow(
|
|
98
|
+
console.log(chalk.yellow("No default API key set."));
|
|
121
99
|
|
|
122
100
|
// Try to prompt for a default API key
|
|
123
|
-
apiKey = await defaultApiKeyManager.promptForDefaultApiKey()
|
|
101
|
+
apiKey = await defaultApiKeyManager.promptForDefaultApiKey();
|
|
124
102
|
|
|
125
103
|
if (!apiKey) {
|
|
104
|
+
console.log(chalk.red("Error: An API key is required to use the chat command."));
|
|
105
|
+
console.log(chalk.yellow("You can:"));
|
|
126
106
|
console.log(
|
|
127
|
-
chalk.
|
|
128
|
-
|
|
129
|
-
)
|
|
130
|
-
)
|
|
131
|
-
console.log(chalk.yellow('You can:'))
|
|
132
|
-
console.log(
|
|
133
|
-
chalk.yellow(
|
|
134
|
-
'1. Create an API key with: berget api-keys create --name "My Key"'
|
|
135
|
-
)
|
|
136
|
-
)
|
|
107
|
+
chalk.yellow('1. Create an API key with: berget api-keys create --name "My Key"')
|
|
108
|
+
);
|
|
137
109
|
console.log(
|
|
138
|
-
chalk.yellow(
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
console.log(
|
|
143
|
-
chalk.yellow(
|
|
144
|
-
'3. Provide an API key with the --api-key option'
|
|
145
|
-
)
|
|
146
|
-
)
|
|
147
|
-
return
|
|
110
|
+
chalk.yellow("2. Set a default API key with: berget api-keys set-default <id>")
|
|
111
|
+
);
|
|
112
|
+
console.log(chalk.yellow("3. Provide an API key with the --api-key option"));
|
|
113
|
+
return;
|
|
148
114
|
}
|
|
149
115
|
}
|
|
150
116
|
} catch (error) {
|
|
151
|
-
if (process.argv.includes(
|
|
152
|
-
console.log(
|
|
153
|
-
|
|
154
|
-
)
|
|
155
|
-
console.log(chalk.yellow(String(error)))
|
|
117
|
+
if (process.argv.includes("--debug")) {
|
|
118
|
+
console.log(chalk.yellow("DEBUG: Error checking default API key:"));
|
|
119
|
+
console.log(chalk.yellow(String(error)));
|
|
156
120
|
}
|
|
157
121
|
}
|
|
158
122
|
}
|
|
@@ -160,20 +124,18 @@ export function registerChatCommands(program: Command): void {
|
|
|
160
124
|
// If no direct API key, try to get one from API key ID
|
|
161
125
|
if (!apiKey && apiKeyId) {
|
|
162
126
|
try {
|
|
163
|
-
const apiKeyService = ApiKeyService.getInstance()
|
|
164
|
-
const keys = await apiKeyService.list()
|
|
165
|
-
const selectedKey = keys.find(
|
|
166
|
-
(key) => key.id.toString() === options.apiKeyId
|
|
167
|
-
)
|
|
127
|
+
const apiKeyService = ApiKeyService.getInstance();
|
|
128
|
+
const keys = await apiKeyService.list();
|
|
129
|
+
const selectedKey = keys.find(key => key.id.toString() === options.apiKeyId);
|
|
168
130
|
|
|
169
131
|
if (!selectedKey) {
|
|
170
132
|
console.log(
|
|
171
133
|
chalk.yellow(
|
|
172
134
|
`API key with ID ${options.apiKeyId} not found. Using default authentication.`
|
|
173
135
|
)
|
|
174
|
-
)
|
|
136
|
+
);
|
|
175
137
|
} else {
|
|
176
|
-
console.log(chalk.dim(`Using API key: ${selectedKey.name}`))
|
|
138
|
+
console.log(chalk.dim(`Using API key: ${selectedKey.name}`));
|
|
177
139
|
|
|
178
140
|
// We need to rotate the key to get the actual key value
|
|
179
141
|
if (
|
|
@@ -183,121 +145,107 @@ export function registerChatCommands(program: Command): void {
|
|
|
183
145
|
)
|
|
184
146
|
)
|
|
185
147
|
) {
|
|
186
|
-
const rotatedKey = await apiKeyService.rotate(options.apiKeyId)
|
|
187
|
-
apiKey = rotatedKey.key
|
|
188
|
-
console.log(
|
|
189
|
-
chalk.green(
|
|
190
|
-
`API key "${selectedKey.name}" rotated successfully.`
|
|
191
|
-
)
|
|
192
|
-
)
|
|
148
|
+
const rotatedKey = await apiKeyService.rotate(options.apiKeyId);
|
|
149
|
+
apiKey = rotatedKey.key;
|
|
150
|
+
console.log(chalk.green(`API key "${selectedKey.name}" rotated successfully.`));
|
|
193
151
|
} else {
|
|
194
|
-
console.log(
|
|
195
|
-
chalk.yellow('Using default authentication instead.')
|
|
196
|
-
)
|
|
152
|
+
console.log(chalk.yellow("Using default authentication instead."));
|
|
197
153
|
}
|
|
198
154
|
}
|
|
199
155
|
} catch (error) {
|
|
200
156
|
// Check if this is an authentication error
|
|
201
|
-
const errorMessage =
|
|
202
|
-
error instanceof Error ? error.message : String(error)
|
|
157
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
203
158
|
const isAuthError =
|
|
204
|
-
errorMessage.includes(
|
|
205
|
-
errorMessage.includes(
|
|
206
|
-
errorMessage.includes(
|
|
159
|
+
errorMessage.includes("Unauthorized") ||
|
|
160
|
+
errorMessage.includes("Authentication failed") ||
|
|
161
|
+
errorMessage.includes("AUTH_FAILED");
|
|
207
162
|
|
|
208
163
|
if (isAuthError) {
|
|
209
164
|
console.log(
|
|
210
|
-
chalk.yellow(
|
|
211
|
-
|
|
212
|
-
)
|
|
213
|
-
)
|
|
165
|
+
chalk.yellow("Authentication required. Please run `berget auth login` first.")
|
|
166
|
+
);
|
|
214
167
|
} else {
|
|
215
|
-
console.error(chalk.red(
|
|
216
|
-
console.error(error)
|
|
168
|
+
console.error(chalk.red("Error fetching API key:"));
|
|
169
|
+
console.error(error);
|
|
217
170
|
}
|
|
218
|
-
console.log(chalk.yellow(
|
|
171
|
+
console.log(chalk.yellow("Using default authentication instead."));
|
|
219
172
|
}
|
|
220
173
|
}
|
|
221
174
|
|
|
222
175
|
// Verify we have authentication before starting chat
|
|
223
176
|
if (!apiKey) {
|
|
224
177
|
try {
|
|
225
|
-
AuthService.getInstance()
|
|
226
|
-
} catch
|
|
227
|
-
console.log(chalk.red(
|
|
228
|
-
console.log(chalk.yellow(
|
|
229
|
-
console.log(chalk.yellow(
|
|
230
|
-
console.log(chalk.yellow(
|
|
178
|
+
AuthService.getInstance();
|
|
179
|
+
} catch {
|
|
180
|
+
console.log(chalk.red("Error: Authentication required for chat"));
|
|
181
|
+
console.log(chalk.yellow("Please either:"));
|
|
182
|
+
console.log(chalk.yellow("1. Log in with `berget auth login`"));
|
|
183
|
+
console.log(chalk.yellow("2. Provide an API key with `--api-key`"));
|
|
184
|
+
console.log(chalk.yellow("3. Provide an API key ID with `--api-key-id`"));
|
|
231
185
|
console.log(
|
|
232
|
-
chalk.yellow(
|
|
233
|
-
)
|
|
234
|
-
|
|
235
|
-
chalk.yellow(
|
|
236
|
-
'4. Set a default API key with `berget api-keys set-default <id>`'
|
|
237
|
-
)
|
|
238
|
-
)
|
|
239
|
-
return
|
|
186
|
+
chalk.yellow("4. Set a default API key with `berget api-keys set-default <id>`")
|
|
187
|
+
);
|
|
188
|
+
return;
|
|
240
189
|
}
|
|
241
190
|
}
|
|
242
191
|
|
|
243
192
|
// Prepare messages array
|
|
244
|
-
const messages: ChatMessage[] = []
|
|
193
|
+
const messages: ChatMessage[] = [];
|
|
245
194
|
|
|
246
195
|
// Add system message if provided
|
|
247
196
|
if (options.system) {
|
|
248
197
|
messages.push({
|
|
249
|
-
role:
|
|
198
|
+
role: "system",
|
|
250
199
|
content: options.system,
|
|
251
|
-
})
|
|
200
|
+
});
|
|
252
201
|
}
|
|
253
202
|
|
|
254
203
|
// Check if input is being piped in
|
|
255
|
-
let inputMessage = message
|
|
256
|
-
let stdinContent =
|
|
204
|
+
let inputMessage = message;
|
|
205
|
+
let stdinContent = "";
|
|
257
206
|
|
|
258
207
|
if (!process.stdin.isTTY) {
|
|
259
208
|
// Read from stdin (piped input)
|
|
260
|
-
const chunks = []
|
|
209
|
+
const chunks = [];
|
|
261
210
|
for await (const chunk of process.stdin) {
|
|
262
|
-
chunks.push(chunk)
|
|
211
|
+
chunks.push(chunk);
|
|
263
212
|
}
|
|
264
|
-
stdinContent = Buffer.concat(chunks).toString(
|
|
213
|
+
stdinContent = Buffer.concat(chunks).toString("utf8").trim();
|
|
265
214
|
}
|
|
266
215
|
|
|
267
216
|
// Combine stdin content with message if both exist
|
|
268
217
|
if (stdinContent && message) {
|
|
269
|
-
inputMessage = `${stdinContent}\n\n${message}
|
|
218
|
+
inputMessage = `${stdinContent}\n\n${message}`;
|
|
270
219
|
} else if (stdinContent && !message) {
|
|
271
|
-
inputMessage = stdinContent
|
|
220
|
+
inputMessage = stdinContent;
|
|
272
221
|
}
|
|
273
222
|
|
|
274
223
|
// If a message is provided (either as argument, from stdin, or both), send it directly and exit
|
|
275
224
|
if (inputMessage) {
|
|
276
225
|
// Add user message
|
|
277
226
|
messages.push({
|
|
278
|
-
role:
|
|
227
|
+
role: "user",
|
|
279
228
|
content: inputMessage,
|
|
280
|
-
})
|
|
229
|
+
});
|
|
281
230
|
|
|
282
231
|
try {
|
|
283
232
|
// Call the API
|
|
284
233
|
const completionOptions: ChatCompletionOptions = {
|
|
285
|
-
model: options.model ||
|
|
234
|
+
model: options.model || "openai/gpt-oss",
|
|
286
235
|
messages: messages,
|
|
287
|
-
temperature:
|
|
288
|
-
options.temperature !== undefined ? options.temperature : 0.7,
|
|
236
|
+
temperature: options.temperature !== undefined ? options.temperature : 0.7,
|
|
289
237
|
max_tokens: options.maxTokens || 4096,
|
|
290
238
|
stream: options.stream !== false,
|
|
291
|
-
}
|
|
239
|
+
};
|
|
292
240
|
|
|
293
241
|
// Only add apiKey if it actually exists
|
|
294
242
|
if (apiKey) {
|
|
295
|
-
completionOptions.apiKey = apiKey
|
|
243
|
+
completionOptions.apiKey = apiKey;
|
|
296
244
|
}
|
|
297
245
|
|
|
298
246
|
// Add streaming support (now default)
|
|
299
247
|
if (completionOptions.stream) {
|
|
300
|
-
let assistantResponse =
|
|
248
|
+
let assistantResponse = "";
|
|
301
249
|
|
|
302
250
|
// Stream the response in real-time
|
|
303
251
|
completionOptions.onChunk = (chunk: any) => {
|
|
@@ -307,36 +255,32 @@ export function registerChatCommands(program: Command): void {
|
|
|
307
255
|
chunk.choices[0].delta &&
|
|
308
256
|
chunk.choices[0].delta.content
|
|
309
257
|
) {
|
|
310
|
-
const content = chunk.choices[0].delta.content
|
|
258
|
+
const content = chunk.choices[0].delta.content;
|
|
311
259
|
try {
|
|
312
|
-
process.stdout.write(content)
|
|
260
|
+
process.stdout.write(content);
|
|
313
261
|
} catch (error: any) {
|
|
314
262
|
// Handle EPIPE errors gracefully (when pipe is closed)
|
|
315
|
-
if (error.code ===
|
|
263
|
+
if (error.code === "EPIPE") {
|
|
316
264
|
// Stop streaming if the pipe is closed
|
|
317
|
-
return
|
|
265
|
+
return;
|
|
318
266
|
}
|
|
319
|
-
throw error
|
|
267
|
+
throw error;
|
|
320
268
|
}
|
|
321
|
-
assistantResponse += content
|
|
269
|
+
assistantResponse += content;
|
|
322
270
|
}
|
|
323
|
-
}
|
|
271
|
+
};
|
|
324
272
|
|
|
325
273
|
try {
|
|
326
|
-
await chatService.createCompletion(completionOptions)
|
|
274
|
+
await chatService.createCompletion(completionOptions);
|
|
327
275
|
} catch (streamError) {
|
|
328
|
-
console.error(chalk.red(
|
|
276
|
+
console.error(chalk.red("\nStreaming error:"), streamError);
|
|
329
277
|
|
|
330
278
|
// Fallback to non-streaming if streaming fails
|
|
331
|
-
console.log(
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
completionOptions.stream = false
|
|
335
|
-
delete completionOptions.onChunk
|
|
279
|
+
console.log(chalk.yellow("Falling back to non-streaming mode..."));
|
|
280
|
+
completionOptions.stream = false;
|
|
281
|
+
delete completionOptions.onChunk;
|
|
336
282
|
|
|
337
|
-
const response = await chatService.createCompletion(
|
|
338
|
-
completionOptions
|
|
339
|
-
)
|
|
283
|
+
const response = await chatService.createCompletion(completionOptions);
|
|
340
284
|
|
|
341
285
|
if (
|
|
342
286
|
response &&
|
|
@@ -344,17 +288,15 @@ export function registerChatCommands(program: Command): void {
|
|
|
344
288
|
response.choices[0] &&
|
|
345
289
|
response.choices[0].message
|
|
346
290
|
) {
|
|
347
|
-
assistantResponse = response.choices[0].message.content
|
|
348
|
-
console.log(assistantResponse)
|
|
291
|
+
assistantResponse = response.choices[0].message.content;
|
|
292
|
+
console.log(assistantResponse);
|
|
349
293
|
}
|
|
350
294
|
}
|
|
351
|
-
console.log() // Add newline at the end
|
|
352
|
-
return
|
|
295
|
+
console.log(); // Add newline at the end
|
|
296
|
+
return;
|
|
353
297
|
}
|
|
354
298
|
|
|
355
|
-
const response = await chatService.createCompletion(
|
|
356
|
-
completionOptions
|
|
357
|
-
)
|
|
299
|
+
const response = await chatService.createCompletion(completionOptions);
|
|
358
300
|
|
|
359
301
|
// Check if response has the expected structure
|
|
360
302
|
if (
|
|
@@ -363,32 +305,28 @@ export function registerChatCommands(program: Command): void {
|
|
|
363
305
|
!response.choices[0] ||
|
|
364
306
|
!response.choices[0].message
|
|
365
307
|
) {
|
|
366
|
-
console.error(
|
|
367
|
-
|
|
368
|
-
)
|
|
369
|
-
console.error(
|
|
370
|
-
chalk.red('Response:', JSON.stringify(response, null, 2))
|
|
371
|
-
)
|
|
372
|
-
throw new Error('Unexpected response format from API')
|
|
308
|
+
console.error(chalk.red("Error: Unexpected response format from API"));
|
|
309
|
+
console.error(chalk.red("Response:", JSON.stringify(response, null, 2)));
|
|
310
|
+
throw new Error("Unexpected response format from API");
|
|
373
311
|
}
|
|
374
312
|
|
|
375
313
|
// Get assistant's response
|
|
376
|
-
const assistantMessage = response.choices[0].message.content
|
|
314
|
+
const assistantMessage = response.choices[0].message.content;
|
|
377
315
|
|
|
378
316
|
// Display the response
|
|
379
317
|
if (containsMarkdown(assistantMessage)) {
|
|
380
|
-
console.log(renderMarkdown(assistantMessage))
|
|
318
|
+
console.log(renderMarkdown(assistantMessage));
|
|
381
319
|
} else {
|
|
382
|
-
console.log(assistantMessage)
|
|
320
|
+
console.log(assistantMessage);
|
|
383
321
|
}
|
|
384
322
|
|
|
385
|
-
return
|
|
323
|
+
return;
|
|
386
324
|
} catch (error) {
|
|
387
|
-
console.error(chalk.red(
|
|
325
|
+
console.error(chalk.red("Error: Failed to get response"));
|
|
388
326
|
if (error instanceof Error) {
|
|
389
|
-
console.error(chalk.red(error.message))
|
|
327
|
+
console.error(chalk.red(error.message));
|
|
390
328
|
}
|
|
391
|
-
process.exit(1)
|
|
329
|
+
process.exit(1);
|
|
392
330
|
}
|
|
393
331
|
}
|
|
394
332
|
|
|
@@ -396,47 +334,46 @@ export function registerChatCommands(program: Command): void {
|
|
|
396
334
|
const rl = readline.createInterface({
|
|
397
335
|
input: process.stdin,
|
|
398
336
|
output: process.stdout,
|
|
399
|
-
})
|
|
337
|
+
});
|
|
400
338
|
|
|
401
|
-
console.log(chalk.cyan('Chat with Berget AI (type "exit" to quit)'))
|
|
402
|
-
console.log(chalk.cyan(
|
|
339
|
+
console.log(chalk.cyan('Chat with Berget AI (type "exit" to quit)'));
|
|
340
|
+
console.log(chalk.cyan("----------------------------------------"));
|
|
403
341
|
|
|
404
342
|
// Start the conversation loop
|
|
405
343
|
const askQuestion = () => {
|
|
406
|
-
rl.question(chalk.green(
|
|
344
|
+
rl.question(chalk.green("You: "), async input => {
|
|
407
345
|
// Check if user wants to exit
|
|
408
|
-
if (input.toLowerCase() ===
|
|
409
|
-
console.log(chalk.cyan(
|
|
410
|
-
rl.close()
|
|
411
|
-
return
|
|
346
|
+
if (input.toLowerCase() === "exit") {
|
|
347
|
+
console.log(chalk.cyan("Goodbye!"));
|
|
348
|
+
rl.close();
|
|
349
|
+
return;
|
|
412
350
|
}
|
|
413
351
|
|
|
414
352
|
// Add user message
|
|
415
353
|
messages.push({
|
|
416
|
-
role:
|
|
354
|
+
role: "user",
|
|
417
355
|
content: input,
|
|
418
|
-
})
|
|
356
|
+
});
|
|
419
357
|
|
|
420
358
|
try {
|
|
421
359
|
// Call the API
|
|
422
360
|
const completionOptions: ChatCompletionOptions = {
|
|
423
|
-
model: options.model ||
|
|
361
|
+
model: options.model || "openai/gpt-oss",
|
|
424
362
|
messages: messages,
|
|
425
|
-
temperature:
|
|
426
|
-
options.temperature !== undefined ? options.temperature : 0.7,
|
|
363
|
+
temperature: options.temperature !== undefined ? options.temperature : 0.7,
|
|
427
364
|
max_tokens: options.maxTokens || 4096,
|
|
428
365
|
stream: options.stream !== false,
|
|
429
|
-
}
|
|
366
|
+
};
|
|
430
367
|
|
|
431
368
|
// Only add apiKey if it actually exists
|
|
432
369
|
if (apiKey) {
|
|
433
|
-
completionOptions.apiKey = apiKey
|
|
370
|
+
completionOptions.apiKey = apiKey;
|
|
434
371
|
}
|
|
435
372
|
|
|
436
373
|
// Add streaming support (now default)
|
|
437
374
|
if (completionOptions.stream) {
|
|
438
|
-
let assistantResponse =
|
|
439
|
-
console.log(chalk.blue(
|
|
375
|
+
let assistantResponse = "";
|
|
376
|
+
console.log(chalk.blue("Assistant: "));
|
|
440
377
|
|
|
441
378
|
// Stream the response in real-time
|
|
442
379
|
completionOptions.onChunk = (chunk: any) => {
|
|
@@ -446,36 +383,32 @@ export function registerChatCommands(program: Command): void {
|
|
|
446
383
|
chunk.choices[0].delta &&
|
|
447
384
|
chunk.choices[0].delta.content
|
|
448
385
|
) {
|
|
449
|
-
const content = chunk.choices[0].delta.content
|
|
386
|
+
const content = chunk.choices[0].delta.content;
|
|
450
387
|
try {
|
|
451
|
-
process.stdout.write(content)
|
|
388
|
+
process.stdout.write(content);
|
|
452
389
|
} catch (error: any) {
|
|
453
390
|
// Handle EPIPE errors gracefully (when pipe is closed)
|
|
454
|
-
if (error.code ===
|
|
391
|
+
if (error.code === "EPIPE") {
|
|
455
392
|
// Stop streaming if the pipe is closed
|
|
456
|
-
return
|
|
393
|
+
return;
|
|
457
394
|
}
|
|
458
|
-
throw error
|
|
395
|
+
throw error;
|
|
459
396
|
}
|
|
460
|
-
assistantResponse += content
|
|
397
|
+
assistantResponse += content;
|
|
461
398
|
}
|
|
462
|
-
}
|
|
399
|
+
};
|
|
463
400
|
|
|
464
401
|
try {
|
|
465
|
-
await chatService.createCompletion(completionOptions)
|
|
402
|
+
await chatService.createCompletion(completionOptions);
|
|
466
403
|
} catch (streamError) {
|
|
467
|
-
console.error(chalk.red(
|
|
404
|
+
console.error(chalk.red("\nStreaming error:"), streamError);
|
|
468
405
|
|
|
469
406
|
// Fallback to non-streaming if streaming fails
|
|
470
|
-
console.log(
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
completionOptions.stream = false
|
|
474
|
-
delete completionOptions.onChunk
|
|
407
|
+
console.log(chalk.yellow("Falling back to non-streaming mode..."));
|
|
408
|
+
completionOptions.stream = false;
|
|
409
|
+
delete completionOptions.onChunk;
|
|
475
410
|
|
|
476
|
-
const response = await chatService.createCompletion(
|
|
477
|
-
completionOptions
|
|
478
|
-
)
|
|
411
|
+
const response = await chatService.createCompletion(completionOptions);
|
|
479
412
|
|
|
480
413
|
if (
|
|
481
414
|
response &&
|
|
@@ -483,31 +416,29 @@ export function registerChatCommands(program: Command): void {
|
|
|
483
416
|
response.choices[0] &&
|
|
484
417
|
response.choices[0].message
|
|
485
418
|
) {
|
|
486
|
-
assistantResponse = response.choices[0].message.content
|
|
487
|
-
console.log(assistantResponse)
|
|
419
|
+
assistantResponse = response.choices[0].message.content;
|
|
420
|
+
console.log(assistantResponse);
|
|
488
421
|
}
|
|
489
422
|
}
|
|
490
|
-
console.log(
|
|
423
|
+
console.log("\n");
|
|
491
424
|
|
|
492
425
|
// Add assistant response to messages
|
|
493
426
|
messages.push({
|
|
494
|
-
role:
|
|
427
|
+
role: "assistant",
|
|
495
428
|
content: assistantResponse,
|
|
496
|
-
})
|
|
429
|
+
});
|
|
497
430
|
|
|
498
431
|
// Continue the conversation
|
|
499
|
-
askQuestion()
|
|
500
|
-
return
|
|
432
|
+
askQuestion();
|
|
433
|
+
return;
|
|
501
434
|
}
|
|
502
435
|
|
|
503
|
-
const response = await chatService.createCompletion(
|
|
504
|
-
completionOptions
|
|
505
|
-
)
|
|
436
|
+
const response = await chatService.createCompletion(completionOptions);
|
|
506
437
|
|
|
507
438
|
// Debug output
|
|
508
439
|
if (program.opts().debug) {
|
|
509
|
-
console.log(chalk.yellow(
|
|
510
|
-
console.log(chalk.yellow(JSON.stringify(response, null, 2)))
|
|
440
|
+
console.log(chalk.yellow("DEBUG: Full response:"));
|
|
441
|
+
console.log(chalk.yellow(JSON.stringify(response, null, 2)));
|
|
511
442
|
}
|
|
512
443
|
|
|
513
444
|
// Check if response has the expected structure
|
|
@@ -517,99 +448,88 @@ export function registerChatCommands(program: Command): void {
|
|
|
517
448
|
!response.choices[0] ||
|
|
518
449
|
!response.choices[0].message
|
|
519
450
|
) {
|
|
520
|
-
console.error(
|
|
521
|
-
|
|
522
|
-
)
|
|
523
|
-
console.error(
|
|
524
|
-
chalk.red('Response:', JSON.stringify(response, null, 2))
|
|
525
|
-
)
|
|
526
|
-
throw new Error('Unexpected response format from API')
|
|
451
|
+
console.error(chalk.red("Error: Unexpected response format from API"));
|
|
452
|
+
console.error(chalk.red("Response:", JSON.stringify(response, null, 2)));
|
|
453
|
+
throw new Error("Unexpected response format from API");
|
|
527
454
|
}
|
|
528
455
|
|
|
529
456
|
// Get assistant's response
|
|
530
|
-
const assistantMessage = response.choices[0].message.content
|
|
457
|
+
const assistantMessage = response.choices[0].message.content;
|
|
531
458
|
|
|
532
459
|
// Add to messages array
|
|
533
460
|
messages.push({
|
|
534
|
-
role:
|
|
461
|
+
role: "assistant",
|
|
535
462
|
content: assistantMessage,
|
|
536
|
-
})
|
|
463
|
+
});
|
|
537
464
|
|
|
538
465
|
// Display the response
|
|
539
|
-
console.log(chalk.blue(
|
|
466
|
+
console.log(chalk.blue("Assistant: "));
|
|
540
467
|
|
|
541
468
|
// Check if the response contains markdown and render it if it does
|
|
542
469
|
if (containsMarkdown(assistantMessage)) {
|
|
543
|
-
console.log(renderMarkdown(assistantMessage))
|
|
470
|
+
console.log(renderMarkdown(assistantMessage));
|
|
544
471
|
} else {
|
|
545
|
-
console.log(assistantMessage)
|
|
472
|
+
console.log(assistantMessage);
|
|
546
473
|
}
|
|
547
474
|
|
|
548
|
-
console.log() // Empty line for better readability
|
|
475
|
+
console.log(); // Empty line for better readability
|
|
549
476
|
|
|
550
477
|
// Continue the conversation
|
|
551
|
-
askQuestion()
|
|
478
|
+
askQuestion();
|
|
552
479
|
} catch (error) {
|
|
553
|
-
console.error(chalk.red(
|
|
480
|
+
console.error(chalk.red("Error: Failed to get response"));
|
|
554
481
|
if (error instanceof Error) {
|
|
555
|
-
console.error(chalk.red(error.message))
|
|
482
|
+
console.error(chalk.red(error.message));
|
|
556
483
|
}
|
|
557
484
|
// Continue despite error
|
|
558
|
-
askQuestion()
|
|
485
|
+
askQuestion();
|
|
559
486
|
}
|
|
560
|
-
})
|
|
561
|
-
}
|
|
487
|
+
});
|
|
488
|
+
};
|
|
562
489
|
|
|
563
490
|
// Start the conversation
|
|
564
|
-
askQuestion()
|
|
491
|
+
askQuestion();
|
|
565
492
|
} catch (error) {
|
|
566
|
-
handleError(
|
|
493
|
+
handleError("Failed to create chat completion", error);
|
|
567
494
|
}
|
|
568
|
-
})
|
|
495
|
+
});
|
|
569
496
|
|
|
570
497
|
chat
|
|
571
498
|
.command(SUBCOMMANDS.CHAT.LIST)
|
|
572
|
-
.description(
|
|
573
|
-
.option(
|
|
574
|
-
.option(
|
|
575
|
-
|
|
576
|
-
'ID of the API key to use from your saved keys'
|
|
577
|
-
)
|
|
578
|
-
.action(async (options) => {
|
|
499
|
+
.description("List available chat models")
|
|
500
|
+
.option("-k, --api-key <key>", "API key to use for this request")
|
|
501
|
+
.option("--api-key-id <id>", "ID of the API key to use from your saved keys")
|
|
502
|
+
.action(async options => {
|
|
579
503
|
try {
|
|
580
504
|
// If API key ID is provided, fetch the actual key
|
|
581
|
-
let apiKey = options.apiKey
|
|
582
|
-
let apiKeyId = options.apiKeyId
|
|
505
|
+
let apiKey = options.apiKey;
|
|
506
|
+
let apiKeyId = options.apiKeyId;
|
|
583
507
|
|
|
584
508
|
// If no API key or API key ID provided, check for default API key
|
|
585
509
|
if (!apiKey && !apiKeyId) {
|
|
586
|
-
const defaultApiKeyManager = DefaultApiKeyManager.getInstance()
|
|
587
|
-
const defaultApiKeyData = defaultApiKeyManager.getDefaultApiKeyData()
|
|
510
|
+
const defaultApiKeyManager = DefaultApiKeyManager.getInstance();
|
|
511
|
+
const defaultApiKeyData = defaultApiKeyManager.getDefaultApiKeyData();
|
|
588
512
|
|
|
589
513
|
if (defaultApiKeyData) {
|
|
590
|
-
apiKeyId = defaultApiKeyData.id
|
|
591
|
-
console.log(
|
|
592
|
-
chalk.dim(`Using default API key: ${defaultApiKeyData.name}`)
|
|
593
|
-
)
|
|
514
|
+
apiKeyId = defaultApiKeyData.id;
|
|
515
|
+
console.log(chalk.dim(`Using default API key: ${defaultApiKeyData.name}`));
|
|
594
516
|
}
|
|
595
517
|
}
|
|
596
518
|
|
|
597
519
|
if (apiKeyId && !apiKey) {
|
|
598
520
|
try {
|
|
599
|
-
const apiKeyService = ApiKeyService.getInstance()
|
|
600
|
-
const keys = await apiKeyService.list()
|
|
601
|
-
const selectedKey = keys.find(
|
|
602
|
-
(key) => key.id.toString() === options.apiKeyId
|
|
603
|
-
)
|
|
521
|
+
const apiKeyService = ApiKeyService.getInstance();
|
|
522
|
+
const keys = await apiKeyService.list();
|
|
523
|
+
const selectedKey = keys.find(key => key.id.toString() === options.apiKeyId);
|
|
604
524
|
|
|
605
525
|
if (!selectedKey) {
|
|
606
526
|
console.log(
|
|
607
527
|
chalk.yellow(
|
|
608
528
|
`API key with ID ${options.apiKeyId} not found. Using default authentication.`
|
|
609
529
|
)
|
|
610
|
-
)
|
|
530
|
+
);
|
|
611
531
|
} else {
|
|
612
|
-
console.log(chalk.dim(`Using API key: ${selectedKey.name}`))
|
|
532
|
+
console.log(chalk.dim(`Using API key: ${selectedKey.name}`));
|
|
613
533
|
|
|
614
534
|
// We need to rotate the key to get the actual key value
|
|
615
535
|
if (
|
|
@@ -619,63 +539,50 @@ export function registerChatCommands(program: Command): void {
|
|
|
619
539
|
)
|
|
620
540
|
)
|
|
621
541
|
) {
|
|
622
|
-
const rotatedKey = await apiKeyService.rotate(options.apiKeyId)
|
|
623
|
-
apiKey = rotatedKey.key
|
|
624
|
-
console.log(
|
|
625
|
-
chalk.green(
|
|
626
|
-
`API key "${selectedKey.name}" rotated successfully.`
|
|
627
|
-
)
|
|
628
|
-
)
|
|
542
|
+
const rotatedKey = await apiKeyService.rotate(options.apiKeyId);
|
|
543
|
+
apiKey = rotatedKey.key;
|
|
544
|
+
console.log(chalk.green(`API key "${selectedKey.name}" rotated successfully.`));
|
|
629
545
|
} else {
|
|
630
|
-
console.log(
|
|
631
|
-
chalk.yellow('Using default authentication instead.')
|
|
632
|
-
)
|
|
546
|
+
console.log(chalk.yellow("Using default authentication instead."));
|
|
633
547
|
}
|
|
634
548
|
}
|
|
635
549
|
} catch (error) {
|
|
636
|
-
console.error(chalk.red(
|
|
637
|
-
console.error(error)
|
|
638
|
-
console.log(chalk.yellow(
|
|
550
|
+
console.error(chalk.red("Error fetching API key:"));
|
|
551
|
+
console.error(error);
|
|
552
|
+
console.log(chalk.yellow("Using default authentication instead."));
|
|
639
553
|
}
|
|
640
554
|
}
|
|
641
555
|
|
|
642
|
-
const chatService = ChatService.getInstance()
|
|
643
|
-
const models = await chatService.listModels(apiKey)
|
|
556
|
+
const chatService = ChatService.getInstance();
|
|
557
|
+
const models = await chatService.listModels(apiKey);
|
|
644
558
|
|
|
645
559
|
// Debug output
|
|
646
560
|
if (program.opts().debug) {
|
|
647
|
-
console.log(chalk.yellow(
|
|
648
|
-
console.log(chalk.yellow(JSON.stringify(models, null, 2)))
|
|
561
|
+
console.log(chalk.yellow("DEBUG: Models response:"));
|
|
562
|
+
console.log(chalk.yellow(JSON.stringify(models, null, 2)));
|
|
649
563
|
}
|
|
650
564
|
|
|
651
|
-
console.log(chalk.bold(
|
|
652
|
-
console.log(chalk.dim(
|
|
653
|
-
console.log(
|
|
654
|
-
|
|
655
|
-
)
|
|
656
|
-
console.log(chalk.dim('─'.repeat(70)))
|
|
565
|
+
console.log(chalk.bold("Available Chat Models:"));
|
|
566
|
+
console.log(chalk.dim("─".repeat(70)));
|
|
567
|
+
console.log(chalk.dim("MODEL ID".padEnd(40)) + chalk.dim("CAPABILITIES"));
|
|
568
|
+
console.log(chalk.dim("─".repeat(70)));
|
|
657
569
|
|
|
658
570
|
// Filter to only show active models
|
|
659
|
-
const activeModels = models.data.filter(
|
|
660
|
-
(model: any) => model.active === true
|
|
661
|
-
)
|
|
571
|
+
const activeModels = models.data.filter((model: any) => model.active === true);
|
|
662
572
|
|
|
663
573
|
activeModels.forEach((model: any) => {
|
|
664
|
-
const capabilities = []
|
|
665
|
-
if (model.capabilities.vision) capabilities.push(
|
|
666
|
-
if (model.capabilities.function_calling)
|
|
667
|
-
|
|
668
|
-
if (model.capabilities.json_mode) capabilities.push('json_mode')
|
|
574
|
+
const capabilities = [];
|
|
575
|
+
if (model.capabilities.vision) capabilities.push("vision");
|
|
576
|
+
if (model.capabilities.function_calling) capabilities.push("function_calling");
|
|
577
|
+
if (model.capabilities.json_mode) capabilities.push("json_mode");
|
|
669
578
|
|
|
670
579
|
// Format model ID in Huggingface compatible format (owner/model)
|
|
671
|
-
const modelId = `${model.owned_by.toLowerCase()}/${model.id}`.padEnd(
|
|
672
|
-
40
|
|
673
|
-
)
|
|
580
|
+
const modelId = `${model.owned_by.toLowerCase()}/${model.id}`.padEnd(40);
|
|
674
581
|
|
|
675
|
-
console.log(modelId + capabilities.join(
|
|
676
|
-
})
|
|
582
|
+
console.log(modelId + capabilities.join(", "));
|
|
583
|
+
});
|
|
677
584
|
} catch (error) {
|
|
678
|
-
handleError(
|
|
585
|
+
handleError("Failed to list chat models", error);
|
|
679
586
|
}
|
|
680
|
-
})
|
|
587
|
+
});
|
|
681
588
|
}
|