berget 2.2.6 → 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 +6 -6
- package/.github/workflows/test.yml +11 -5
- 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 +28 -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 +5 -7
- package/dist/src/commands/code/__tests__/fake-file-store.js +9 -0
- package/dist/src/commands/code/__tests__/fake-prompter.js +60 -18
- package/dist/src/commands/code/__tests__/setup-flow.test.js +374 -107
- package/dist/src/commands/code/adapters/clack-prompter.js +10 -0
- package/dist/src/commands/code/adapters/fs-file-store.js +8 -3
- package/dist/src/commands/code/adapters/spawn-command-runner.js +15 -11
- package/dist/src/commands/code/auth-sync.js +283 -0
- package/dist/src/commands/code/errors.js +4 -4
- package/dist/src/commands/code/ports/auth-services.js +2 -0
- package/dist/src/commands/code/setup.js +234 -93
- package/dist/src/commands/code.js +139 -251
- package/dist/src/commands/models.js +13 -15
- package/dist/src/commands/users.js +6 -8
- package/dist/src/constants/command-structure.js +116 -116
- 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 +147 -147
- 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 +33 -33
- package/dist/vitest.config.js +1 -1
- package/eslint.config.mjs +47 -0
- package/index.ts +42 -48
- package/package.json +28 -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 +39 -42
- package/src/commands/code/__tests__/fake-file-store.ts +32 -23
- package/src/commands/code/__tests__/fake-prompter.ts +107 -69
- package/src/commands/code/__tests__/setup-flow.test.ts +624 -270
- package/src/commands/code/adapters/clack-prompter.ts +50 -38
- package/src/commands/code/adapters/fs-file-store.ts +31 -27
- package/src/commands/code/adapters/spawn-command-runner.ts +33 -29
- package/src/commands/code/auth-sync.ts +329 -0
- package/src/commands/code/errors.ts +15 -15
- package/src/commands/code/ports/auth-services.ts +14 -0
- package/src/commands/code/ports/command-runner.ts +8 -4
- package/src/commands/code/ports/file-store.ts +5 -4
- package/src/commands/code/ports/prompter.ts +24 -18
- package/src/commands/code/setup.ts +545 -317
- package/src/commands/code.ts +271 -473
- 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 +119 -142
- 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 +1 -0
- package/templates/agents/backend.md +1 -0
- package/templates/agents/devops.md +2 -0
- package/templates/agents/frontend.md +1 -0
- package/templates/agents/fullstack.md +1 -0
- package/templates/agents/quality.md +45 -40
- package/templates/agents/security.md +1 -0
- package/tests/commands/chat.test.ts +60 -70
- package/tests/commands/code.test.ts +330 -376
- 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 +58 -63
- package/tsconfig.json +2 -2
- package/vitest.config.ts +3 -3
- package/AGENTS.md +0 -374
- package/TODO.md +0 -19
|
@@ -38,10 +38,10 @@ function confirm(question) {
|
|
|
38
38
|
input: process.stdin,
|
|
39
39
|
output: process.stdout,
|
|
40
40
|
});
|
|
41
|
-
return new Promise(
|
|
42
|
-
rl.question(question,
|
|
41
|
+
return new Promise(resolve => {
|
|
42
|
+
rl.question(question, answer => {
|
|
43
43
|
rl.close();
|
|
44
|
-
resolve(answer.toLowerCase() ===
|
|
44
|
+
resolve(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
|
|
45
45
|
});
|
|
46
46
|
});
|
|
47
47
|
});
|
|
@@ -50,19 +50,17 @@ function confirm(question) {
|
|
|
50
50
|
* Register chat commands
|
|
51
51
|
*/
|
|
52
52
|
function registerChatCommands(program) {
|
|
53
|
-
const chat = program
|
|
54
|
-
.command(command_structure_1.COMMAND_GROUPS.CHAT)
|
|
55
|
-
.description('Interact with AI chat models');
|
|
53
|
+
const chat = program.command(command_structure_1.COMMAND_GROUPS.CHAT).description("Interact with AI chat models");
|
|
56
54
|
chat
|
|
57
55
|
.command(command_structure_1.SUBCOMMANDS.CHAT.RUN)
|
|
58
|
-
.description(
|
|
59
|
-
.argument(
|
|
60
|
-
.option(
|
|
61
|
-
.option(
|
|
62
|
-
.option(
|
|
63
|
-
.option(
|
|
64
|
-
.option(
|
|
65
|
-
.option(
|
|
56
|
+
.description("Run a chat session with a specified model")
|
|
57
|
+
.argument("[message]", "Message to send directly (skips interactive mode)")
|
|
58
|
+
.option("-m, --model <model>", "Model to use (default: glm-4.7)")
|
|
59
|
+
.option("-t, --temperature <temp>", "Temperature (0-1)", parseFloat)
|
|
60
|
+
.option("--max-tokens <tokens>", "Maximum tokens to generate", parseInt)
|
|
61
|
+
.option("-k, --api-key <key>", "API key to use for this chat session")
|
|
62
|
+
.option("--api-key-id <id>", "ID of the API key to use from your saved keys")
|
|
63
|
+
.option("--no-stream", "Disable streaming (streaming is enabled by default)")
|
|
66
64
|
.action((message, options) => __awaiter(this, void 0, void 0, function* () {
|
|
67
65
|
var _a, e_1, _b, _c;
|
|
68
66
|
try {
|
|
@@ -76,7 +74,7 @@ function registerChatCommands(program) {
|
|
|
76
74
|
console.log(chalk_1.default.dim(`Using API key from BERGET_API_KEY environment variable`));
|
|
77
75
|
apiKey = envApiKey;
|
|
78
76
|
// Debug the API key (first few characters only)
|
|
79
|
-
if (process.argv.includes(
|
|
77
|
+
if (process.argv.includes("--debug")) {
|
|
80
78
|
console.log(chalk_1.default.yellow(`DEBUG: API key from env starts with: ${envApiKey.substring(0, 4)}...`));
|
|
81
79
|
}
|
|
82
80
|
}
|
|
@@ -103,22 +101,22 @@ function registerChatCommands(program) {
|
|
|
103
101
|
}
|
|
104
102
|
else {
|
|
105
103
|
// No default API key, prompt the user to create one
|
|
106
|
-
console.log(chalk_1.default.yellow(
|
|
104
|
+
console.log(chalk_1.default.yellow("No default API key set."));
|
|
107
105
|
// Try to prompt for a default API key
|
|
108
106
|
apiKey = yield defaultApiKeyManager.promptForDefaultApiKey();
|
|
109
107
|
if (!apiKey) {
|
|
110
|
-
console.log(chalk_1.default.red(
|
|
111
|
-
console.log(chalk_1.default.yellow(
|
|
108
|
+
console.log(chalk_1.default.red("Error: An API key is required to use the chat command."));
|
|
109
|
+
console.log(chalk_1.default.yellow("You can:"));
|
|
112
110
|
console.log(chalk_1.default.yellow('1. Create an API key with: berget api-keys create --name "My Key"'));
|
|
113
|
-
console.log(chalk_1.default.yellow(
|
|
114
|
-
console.log(chalk_1.default.yellow(
|
|
111
|
+
console.log(chalk_1.default.yellow("2. Set a default API key with: berget api-keys set-default <id>"));
|
|
112
|
+
console.log(chalk_1.default.yellow("3. Provide an API key with the --api-key option"));
|
|
115
113
|
return;
|
|
116
114
|
}
|
|
117
115
|
}
|
|
118
116
|
}
|
|
119
117
|
catch (error) {
|
|
120
|
-
if (process.argv.includes(
|
|
121
|
-
console.log(chalk_1.default.yellow(
|
|
118
|
+
if (process.argv.includes("--debug")) {
|
|
119
|
+
console.log(chalk_1.default.yellow("DEBUG: Error checking default API key:"));
|
|
122
120
|
console.log(chalk_1.default.yellow(String(error)));
|
|
123
121
|
}
|
|
124
122
|
}
|
|
@@ -128,7 +126,7 @@ function registerChatCommands(program) {
|
|
|
128
126
|
try {
|
|
129
127
|
const apiKeyService = api_key_service_1.ApiKeyService.getInstance();
|
|
130
128
|
const keys = yield apiKeyService.list();
|
|
131
|
-
const selectedKey = keys.find(
|
|
129
|
+
const selectedKey = keys.find(key => key.id.toString() === options.apiKeyId);
|
|
132
130
|
if (!selectedKey) {
|
|
133
131
|
console.log(chalk_1.default.yellow(`API key with ID ${options.apiKeyId} not found. Using default authentication.`));
|
|
134
132
|
}
|
|
@@ -141,24 +139,24 @@ function registerChatCommands(program) {
|
|
|
141
139
|
console.log(chalk_1.default.green(`API key "${selectedKey.name}" rotated successfully.`));
|
|
142
140
|
}
|
|
143
141
|
else {
|
|
144
|
-
console.log(chalk_1.default.yellow(
|
|
142
|
+
console.log(chalk_1.default.yellow("Using default authentication instead."));
|
|
145
143
|
}
|
|
146
144
|
}
|
|
147
145
|
}
|
|
148
146
|
catch (error) {
|
|
149
147
|
// Check if this is an authentication error
|
|
150
148
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
151
|
-
const isAuthError = errorMessage.includes(
|
|
152
|
-
errorMessage.includes(
|
|
153
|
-
errorMessage.includes(
|
|
149
|
+
const isAuthError = errorMessage.includes("Unauthorized") ||
|
|
150
|
+
errorMessage.includes("Authentication failed") ||
|
|
151
|
+
errorMessage.includes("AUTH_FAILED");
|
|
154
152
|
if (isAuthError) {
|
|
155
|
-
console.log(chalk_1.default.yellow(
|
|
153
|
+
console.log(chalk_1.default.yellow("Authentication required. Please run `berget auth login` first."));
|
|
156
154
|
}
|
|
157
155
|
else {
|
|
158
|
-
console.error(chalk_1.default.red(
|
|
156
|
+
console.error(chalk_1.default.red("Error fetching API key:"));
|
|
159
157
|
console.error(error);
|
|
160
158
|
}
|
|
161
|
-
console.log(chalk_1.default.yellow(
|
|
159
|
+
console.log(chalk_1.default.yellow("Using default authentication instead."));
|
|
162
160
|
}
|
|
163
161
|
}
|
|
164
162
|
// Verify we have authentication before starting chat
|
|
@@ -166,13 +164,13 @@ function registerChatCommands(program) {
|
|
|
166
164
|
try {
|
|
167
165
|
auth_service_1.AuthService.getInstance();
|
|
168
166
|
}
|
|
169
|
-
catch (
|
|
170
|
-
console.log(chalk_1.default.red(
|
|
171
|
-
console.log(chalk_1.default.yellow(
|
|
172
|
-
console.log(chalk_1.default.yellow(
|
|
173
|
-
console.log(chalk_1.default.yellow(
|
|
174
|
-
console.log(chalk_1.default.yellow(
|
|
175
|
-
console.log(chalk_1.default.yellow(
|
|
167
|
+
catch (_d) {
|
|
168
|
+
console.log(chalk_1.default.red("Error: Authentication required for chat"));
|
|
169
|
+
console.log(chalk_1.default.yellow("Please either:"));
|
|
170
|
+
console.log(chalk_1.default.yellow("1. Log in with `berget auth login`"));
|
|
171
|
+
console.log(chalk_1.default.yellow("2. Provide an API key with `--api-key`"));
|
|
172
|
+
console.log(chalk_1.default.yellow("3. Provide an API key ID with `--api-key-id`"));
|
|
173
|
+
console.log(chalk_1.default.yellow("4. Set a default API key with `berget api-keys set-default <id>`"));
|
|
176
174
|
return;
|
|
177
175
|
}
|
|
178
176
|
}
|
|
@@ -181,20 +179,20 @@ function registerChatCommands(program) {
|
|
|
181
179
|
// Add system message if provided
|
|
182
180
|
if (options.system) {
|
|
183
181
|
messages.push({
|
|
184
|
-
role:
|
|
182
|
+
role: "system",
|
|
185
183
|
content: options.system,
|
|
186
184
|
});
|
|
187
185
|
}
|
|
188
186
|
// Check if input is being piped in
|
|
189
187
|
let inputMessage = message;
|
|
190
|
-
let stdinContent =
|
|
188
|
+
let stdinContent = "";
|
|
191
189
|
if (!process.stdin.isTTY) {
|
|
192
190
|
// Read from stdin (piped input)
|
|
193
191
|
const chunks = [];
|
|
194
192
|
try {
|
|
195
|
-
for (var
|
|
196
|
-
_c =
|
|
197
|
-
|
|
193
|
+
for (var _e = true, _f = __asyncValues(process.stdin), _g; _g = yield _f.next(), _a = _g.done, !_a; _e = true) {
|
|
194
|
+
_c = _g.value;
|
|
195
|
+
_e = false;
|
|
198
196
|
const chunk = _c;
|
|
199
197
|
chunks.push(chunk);
|
|
200
198
|
}
|
|
@@ -202,11 +200,11 @@ function registerChatCommands(program) {
|
|
|
202
200
|
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
203
201
|
finally {
|
|
204
202
|
try {
|
|
205
|
-
if (!
|
|
203
|
+
if (!_e && !_a && (_b = _f.return)) yield _b.call(_f);
|
|
206
204
|
}
|
|
207
205
|
finally { if (e_1) throw e_1.error; }
|
|
208
206
|
}
|
|
209
|
-
stdinContent = Buffer.concat(chunks).toString(
|
|
207
|
+
stdinContent = Buffer.concat(chunks).toString("utf8").trim();
|
|
210
208
|
}
|
|
211
209
|
// Combine stdin content with message if both exist
|
|
212
210
|
if (stdinContent && message) {
|
|
@@ -219,13 +217,13 @@ function registerChatCommands(program) {
|
|
|
219
217
|
if (inputMessage) {
|
|
220
218
|
// Add user message
|
|
221
219
|
messages.push({
|
|
222
|
-
role:
|
|
220
|
+
role: "user",
|
|
223
221
|
content: inputMessage,
|
|
224
222
|
});
|
|
225
223
|
try {
|
|
226
224
|
// Call the API
|
|
227
225
|
const completionOptions = {
|
|
228
|
-
model: options.model ||
|
|
226
|
+
model: options.model || "openai/gpt-oss",
|
|
229
227
|
messages: messages,
|
|
230
228
|
temperature: options.temperature !== undefined ? options.temperature : 0.7,
|
|
231
229
|
max_tokens: options.maxTokens || 4096,
|
|
@@ -237,7 +235,7 @@ function registerChatCommands(program) {
|
|
|
237
235
|
}
|
|
238
236
|
// Add streaming support (now default)
|
|
239
237
|
if (completionOptions.stream) {
|
|
240
|
-
let assistantResponse =
|
|
238
|
+
let assistantResponse = "";
|
|
241
239
|
// Stream the response in real-time
|
|
242
240
|
completionOptions.onChunk = (chunk) => {
|
|
243
241
|
if (chunk.choices &&
|
|
@@ -250,7 +248,7 @@ function registerChatCommands(program) {
|
|
|
250
248
|
}
|
|
251
249
|
catch (error) {
|
|
252
250
|
// Handle EPIPE errors gracefully (when pipe is closed)
|
|
253
|
-
if (error.code ===
|
|
251
|
+
if (error.code === "EPIPE") {
|
|
254
252
|
// Stop streaming if the pipe is closed
|
|
255
253
|
return;
|
|
256
254
|
}
|
|
@@ -263,9 +261,9 @@ function registerChatCommands(program) {
|
|
|
263
261
|
yield chatService.createCompletion(completionOptions);
|
|
264
262
|
}
|
|
265
263
|
catch (streamError) {
|
|
266
|
-
console.error(chalk_1.default.red(
|
|
264
|
+
console.error(chalk_1.default.red("\nStreaming error:"), streamError);
|
|
267
265
|
// Fallback to non-streaming if streaming fails
|
|
268
|
-
console.log(chalk_1.default.yellow(
|
|
266
|
+
console.log(chalk_1.default.yellow("Falling back to non-streaming mode..."));
|
|
269
267
|
completionOptions.stream = false;
|
|
270
268
|
delete completionOptions.onChunk;
|
|
271
269
|
const response = yield chatService.createCompletion(completionOptions);
|
|
@@ -286,9 +284,9 @@ function registerChatCommands(program) {
|
|
|
286
284
|
!response.choices ||
|
|
287
285
|
!response.choices[0] ||
|
|
288
286
|
!response.choices[0].message) {
|
|
289
|
-
console.error(chalk_1.default.red(
|
|
290
|
-
console.error(chalk_1.default.red(
|
|
291
|
-
throw new Error(
|
|
287
|
+
console.error(chalk_1.default.red("Error: Unexpected response format from API"));
|
|
288
|
+
console.error(chalk_1.default.red("Response:", JSON.stringify(response, null, 2)));
|
|
289
|
+
throw new Error("Unexpected response format from API");
|
|
292
290
|
}
|
|
293
291
|
// Get assistant's response
|
|
294
292
|
const assistantMessage = response.choices[0].message.content;
|
|
@@ -302,7 +300,7 @@ function registerChatCommands(program) {
|
|
|
302
300
|
return;
|
|
303
301
|
}
|
|
304
302
|
catch (error) {
|
|
305
|
-
console.error(chalk_1.default.red(
|
|
303
|
+
console.error(chalk_1.default.red("Error: Failed to get response"));
|
|
306
304
|
if (error instanceof Error) {
|
|
307
305
|
console.error(chalk_1.default.red(error.message));
|
|
308
306
|
}
|
|
@@ -315,25 +313,25 @@ function registerChatCommands(program) {
|
|
|
315
313
|
output: process.stdout,
|
|
316
314
|
});
|
|
317
315
|
console.log(chalk_1.default.cyan('Chat with Berget AI (type "exit" to quit)'));
|
|
318
|
-
console.log(chalk_1.default.cyan(
|
|
316
|
+
console.log(chalk_1.default.cyan("----------------------------------------"));
|
|
319
317
|
// Start the conversation loop
|
|
320
318
|
const askQuestion = () => {
|
|
321
|
-
rl.question(chalk_1.default.green(
|
|
319
|
+
rl.question(chalk_1.default.green("You: "), (input) => __awaiter(this, void 0, void 0, function* () {
|
|
322
320
|
// Check if user wants to exit
|
|
323
|
-
if (input.toLowerCase() ===
|
|
324
|
-
console.log(chalk_1.default.cyan(
|
|
321
|
+
if (input.toLowerCase() === "exit") {
|
|
322
|
+
console.log(chalk_1.default.cyan("Goodbye!"));
|
|
325
323
|
rl.close();
|
|
326
324
|
return;
|
|
327
325
|
}
|
|
328
326
|
// Add user message
|
|
329
327
|
messages.push({
|
|
330
|
-
role:
|
|
328
|
+
role: "user",
|
|
331
329
|
content: input,
|
|
332
330
|
});
|
|
333
331
|
try {
|
|
334
332
|
// Call the API
|
|
335
333
|
const completionOptions = {
|
|
336
|
-
model: options.model ||
|
|
334
|
+
model: options.model || "openai/gpt-oss",
|
|
337
335
|
messages: messages,
|
|
338
336
|
temperature: options.temperature !== undefined ? options.temperature : 0.7,
|
|
339
337
|
max_tokens: options.maxTokens || 4096,
|
|
@@ -345,8 +343,8 @@ function registerChatCommands(program) {
|
|
|
345
343
|
}
|
|
346
344
|
// Add streaming support (now default)
|
|
347
345
|
if (completionOptions.stream) {
|
|
348
|
-
let assistantResponse =
|
|
349
|
-
console.log(chalk_1.default.blue(
|
|
346
|
+
let assistantResponse = "";
|
|
347
|
+
console.log(chalk_1.default.blue("Assistant: "));
|
|
350
348
|
// Stream the response in real-time
|
|
351
349
|
completionOptions.onChunk = (chunk) => {
|
|
352
350
|
if (chunk.choices &&
|
|
@@ -359,7 +357,7 @@ function registerChatCommands(program) {
|
|
|
359
357
|
}
|
|
360
358
|
catch (error) {
|
|
361
359
|
// Handle EPIPE errors gracefully (when pipe is closed)
|
|
362
|
-
if (error.code ===
|
|
360
|
+
if (error.code === "EPIPE") {
|
|
363
361
|
// Stop streaming if the pipe is closed
|
|
364
362
|
return;
|
|
365
363
|
}
|
|
@@ -372,9 +370,9 @@ function registerChatCommands(program) {
|
|
|
372
370
|
yield chatService.createCompletion(completionOptions);
|
|
373
371
|
}
|
|
374
372
|
catch (streamError) {
|
|
375
|
-
console.error(chalk_1.default.red(
|
|
373
|
+
console.error(chalk_1.default.red("\nStreaming error:"), streamError);
|
|
376
374
|
// Fallback to non-streaming if streaming fails
|
|
377
|
-
console.log(chalk_1.default.yellow(
|
|
375
|
+
console.log(chalk_1.default.yellow("Falling back to non-streaming mode..."));
|
|
378
376
|
completionOptions.stream = false;
|
|
379
377
|
delete completionOptions.onChunk;
|
|
380
378
|
const response = yield chatService.createCompletion(completionOptions);
|
|
@@ -386,10 +384,10 @@ function registerChatCommands(program) {
|
|
|
386
384
|
console.log(assistantResponse);
|
|
387
385
|
}
|
|
388
386
|
}
|
|
389
|
-
console.log(
|
|
387
|
+
console.log("\n");
|
|
390
388
|
// Add assistant response to messages
|
|
391
389
|
messages.push({
|
|
392
|
-
role:
|
|
390
|
+
role: "assistant",
|
|
393
391
|
content: assistantResponse,
|
|
394
392
|
});
|
|
395
393
|
// Continue the conversation
|
|
@@ -399,7 +397,7 @@ function registerChatCommands(program) {
|
|
|
399
397
|
const response = yield chatService.createCompletion(completionOptions);
|
|
400
398
|
// Debug output
|
|
401
399
|
if (program.opts().debug) {
|
|
402
|
-
console.log(chalk_1.default.yellow(
|
|
400
|
+
console.log(chalk_1.default.yellow("DEBUG: Full response:"));
|
|
403
401
|
console.log(chalk_1.default.yellow(JSON.stringify(response, null, 2)));
|
|
404
402
|
}
|
|
405
403
|
// Check if response has the expected structure
|
|
@@ -407,19 +405,19 @@ function registerChatCommands(program) {
|
|
|
407
405
|
!response.choices ||
|
|
408
406
|
!response.choices[0] ||
|
|
409
407
|
!response.choices[0].message) {
|
|
410
|
-
console.error(chalk_1.default.red(
|
|
411
|
-
console.error(chalk_1.default.red(
|
|
412
|
-
throw new Error(
|
|
408
|
+
console.error(chalk_1.default.red("Error: Unexpected response format from API"));
|
|
409
|
+
console.error(chalk_1.default.red("Response:", JSON.stringify(response, null, 2)));
|
|
410
|
+
throw new Error("Unexpected response format from API");
|
|
413
411
|
}
|
|
414
412
|
// Get assistant's response
|
|
415
413
|
const assistantMessage = response.choices[0].message.content;
|
|
416
414
|
// Add to messages array
|
|
417
415
|
messages.push({
|
|
418
|
-
role:
|
|
416
|
+
role: "assistant",
|
|
419
417
|
content: assistantMessage,
|
|
420
418
|
});
|
|
421
419
|
// Display the response
|
|
422
|
-
console.log(chalk_1.default.blue(
|
|
420
|
+
console.log(chalk_1.default.blue("Assistant: "));
|
|
423
421
|
// Check if the response contains markdown and render it if it does
|
|
424
422
|
if ((0, markdown_renderer_1.containsMarkdown)(assistantMessage)) {
|
|
425
423
|
console.log((0, markdown_renderer_1.renderMarkdown)(assistantMessage));
|
|
@@ -432,7 +430,7 @@ function registerChatCommands(program) {
|
|
|
432
430
|
askQuestion();
|
|
433
431
|
}
|
|
434
432
|
catch (error) {
|
|
435
|
-
console.error(chalk_1.default.red(
|
|
433
|
+
console.error(chalk_1.default.red("Error: Failed to get response"));
|
|
436
434
|
if (error instanceof Error) {
|
|
437
435
|
console.error(chalk_1.default.red(error.message));
|
|
438
436
|
}
|
|
@@ -445,14 +443,14 @@ function registerChatCommands(program) {
|
|
|
445
443
|
askQuestion();
|
|
446
444
|
}
|
|
447
445
|
catch (error) {
|
|
448
|
-
(0, error_handler_1.handleError)(
|
|
446
|
+
(0, error_handler_1.handleError)("Failed to create chat completion", error);
|
|
449
447
|
}
|
|
450
448
|
}));
|
|
451
449
|
chat
|
|
452
450
|
.command(command_structure_1.SUBCOMMANDS.CHAT.LIST)
|
|
453
|
-
.description(
|
|
454
|
-
.option(
|
|
455
|
-
.option(
|
|
451
|
+
.description("List available chat models")
|
|
452
|
+
.option("-k, --api-key <key>", "API key to use for this request")
|
|
453
|
+
.option("--api-key-id <id>", "ID of the API key to use from your saved keys")
|
|
456
454
|
.action((options) => __awaiter(this, void 0, void 0, function* () {
|
|
457
455
|
try {
|
|
458
456
|
// If API key ID is provided, fetch the actual key
|
|
@@ -471,7 +469,7 @@ function registerChatCommands(program) {
|
|
|
471
469
|
try {
|
|
472
470
|
const apiKeyService = api_key_service_1.ApiKeyService.getInstance();
|
|
473
471
|
const keys = yield apiKeyService.list();
|
|
474
|
-
const selectedKey = keys.find(
|
|
472
|
+
const selectedKey = keys.find(key => key.id.toString() === options.apiKeyId);
|
|
475
473
|
if (!selectedKey) {
|
|
476
474
|
console.log(chalk_1.default.yellow(`API key with ID ${options.apiKeyId} not found. Using default authentication.`));
|
|
477
475
|
}
|
|
@@ -484,44 +482,44 @@ function registerChatCommands(program) {
|
|
|
484
482
|
console.log(chalk_1.default.green(`API key "${selectedKey.name}" rotated successfully.`));
|
|
485
483
|
}
|
|
486
484
|
else {
|
|
487
|
-
console.log(chalk_1.default.yellow(
|
|
485
|
+
console.log(chalk_1.default.yellow("Using default authentication instead."));
|
|
488
486
|
}
|
|
489
487
|
}
|
|
490
488
|
}
|
|
491
489
|
catch (error) {
|
|
492
|
-
console.error(chalk_1.default.red(
|
|
490
|
+
console.error(chalk_1.default.red("Error fetching API key:"));
|
|
493
491
|
console.error(error);
|
|
494
|
-
console.log(chalk_1.default.yellow(
|
|
492
|
+
console.log(chalk_1.default.yellow("Using default authentication instead."));
|
|
495
493
|
}
|
|
496
494
|
}
|
|
497
495
|
const chatService = chat_service_1.ChatService.getInstance();
|
|
498
496
|
const models = yield chatService.listModels(apiKey);
|
|
499
497
|
// Debug output
|
|
500
498
|
if (program.opts().debug) {
|
|
501
|
-
console.log(chalk_1.default.yellow(
|
|
499
|
+
console.log(chalk_1.default.yellow("DEBUG: Models response:"));
|
|
502
500
|
console.log(chalk_1.default.yellow(JSON.stringify(models, null, 2)));
|
|
503
501
|
}
|
|
504
|
-
console.log(chalk_1.default.bold(
|
|
505
|
-
console.log(chalk_1.default.dim(
|
|
506
|
-
console.log(chalk_1.default.dim(
|
|
507
|
-
console.log(chalk_1.default.dim(
|
|
502
|
+
console.log(chalk_1.default.bold("Available Chat Models:"));
|
|
503
|
+
console.log(chalk_1.default.dim("─".repeat(70)));
|
|
504
|
+
console.log(chalk_1.default.dim("MODEL ID".padEnd(40)) + chalk_1.default.dim("CAPABILITIES"));
|
|
505
|
+
console.log(chalk_1.default.dim("─".repeat(70)));
|
|
508
506
|
// Filter to only show active models
|
|
509
507
|
const activeModels = models.data.filter((model) => model.active === true);
|
|
510
508
|
activeModels.forEach((model) => {
|
|
511
509
|
const capabilities = [];
|
|
512
510
|
if (model.capabilities.vision)
|
|
513
|
-
capabilities.push(
|
|
511
|
+
capabilities.push("vision");
|
|
514
512
|
if (model.capabilities.function_calling)
|
|
515
|
-
capabilities.push(
|
|
513
|
+
capabilities.push("function_calling");
|
|
516
514
|
if (model.capabilities.json_mode)
|
|
517
|
-
capabilities.push(
|
|
515
|
+
capabilities.push("json_mode");
|
|
518
516
|
// Format model ID in Huggingface compatible format (owner/model)
|
|
519
517
|
const modelId = `${model.owned_by.toLowerCase()}/${model.id}`.padEnd(40);
|
|
520
|
-
console.log(modelId + capabilities.join(
|
|
518
|
+
console.log(modelId + capabilities.join(", "));
|
|
521
519
|
});
|
|
522
520
|
}
|
|
523
521
|
catch (error) {
|
|
524
|
-
(0, error_handler_1.handleError)(
|
|
522
|
+
(0, error_handler_1.handleError)("Failed to list chat models", error);
|
|
525
523
|
}
|
|
526
524
|
}));
|
|
527
525
|
}
|
|
@@ -18,51 +18,51 @@ const error_handler_1 = require("../utils/error-handler");
|
|
|
18
18
|
function registerClusterCommands(program) {
|
|
19
19
|
const cluster = program
|
|
20
20
|
.command(cluster_service_1.ClusterService.COMMAND_GROUP)
|
|
21
|
-
.description(
|
|
21
|
+
.description("Manage Berget clusters");
|
|
22
22
|
cluster
|
|
23
23
|
.command(cluster_service_1.ClusterService.COMMANDS.LIST)
|
|
24
|
-
.description(
|
|
24
|
+
.description("List all Berget clusters")
|
|
25
25
|
.action(() => __awaiter(this, void 0, void 0, function* () {
|
|
26
26
|
try {
|
|
27
27
|
const clusterService = cluster_service_1.ClusterService.getInstance();
|
|
28
28
|
const clusters = yield clusterService.list();
|
|
29
|
-
console.log(
|
|
29
|
+
console.log("NAME STATUS NODES CREATED");
|
|
30
30
|
clusters.forEach((cluster) => {
|
|
31
31
|
console.log(`${cluster.name.padEnd(22)} ${cluster.status.padEnd(9)} ${String(cluster.nodes).padEnd(8)} ${cluster.created}`);
|
|
32
32
|
});
|
|
33
33
|
}
|
|
34
34
|
catch (error) {
|
|
35
|
-
(0, error_handler_1.handleError)(
|
|
35
|
+
(0, error_handler_1.handleError)("Failed to list clusters", error);
|
|
36
36
|
}
|
|
37
37
|
}));
|
|
38
38
|
cluster
|
|
39
39
|
.command(cluster_service_1.ClusterService.COMMANDS.GET_USAGE)
|
|
40
|
-
.description(
|
|
41
|
-
.argument(
|
|
40
|
+
.description("Get usage metrics for a specific cluster")
|
|
41
|
+
.argument("<clusterId>", "Cluster ID")
|
|
42
42
|
.action((clusterId) => __awaiter(this, void 0, void 0, function* () {
|
|
43
43
|
try {
|
|
44
44
|
const clusterService = cluster_service_1.ClusterService.getInstance();
|
|
45
45
|
const usage = yield clusterService.getUsage(clusterId);
|
|
46
|
-
console.log(
|
|
46
|
+
console.log("Cluster Usage:");
|
|
47
47
|
console.log(JSON.stringify(usage, null, 2));
|
|
48
48
|
}
|
|
49
49
|
catch (error) {
|
|
50
|
-
(0, error_handler_1.handleError)(
|
|
50
|
+
(0, error_handler_1.handleError)("Failed to get cluster usage", error);
|
|
51
51
|
}
|
|
52
52
|
}));
|
|
53
53
|
cluster
|
|
54
54
|
.command(cluster_service_1.ClusterService.COMMANDS.DESCRIBE)
|
|
55
|
-
.description(
|
|
56
|
-
.argument(
|
|
55
|
+
.description("Get detailed information about a cluster")
|
|
56
|
+
.argument("<clusterId>", "Cluster ID")
|
|
57
57
|
.action((clusterId) => __awaiter(this, void 0, void 0, function* () {
|
|
58
58
|
try {
|
|
59
59
|
const clusterService = cluster_service_1.ClusterService.getInstance();
|
|
60
60
|
const clusterInfo = yield clusterService.describe(clusterId);
|
|
61
|
-
console.log(
|
|
61
|
+
console.log("Cluster Details:");
|
|
62
62
|
console.log(JSON.stringify(clusterInfo, null, 2));
|
|
63
63
|
}
|
|
64
64
|
catch (error) {
|
|
65
|
-
(0, error_handler_1.handleError)(
|
|
65
|
+
(0, error_handler_1.handleError)("Failed to describe cluster", error);
|
|
66
66
|
}
|
|
67
67
|
}));
|
|
68
68
|
}
|