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
|
@@ -24,9 +24,9 @@ function formatDate(dateString) {
|
|
|
24
24
|
const diffTime = Math.abs(now.getTime() - date.getTime());
|
|
25
25
|
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
|
|
26
26
|
if (diffDays === 0)
|
|
27
|
-
return chalk_1.default.green(
|
|
27
|
+
return chalk_1.default.green("Today");
|
|
28
28
|
if (diffDays === 1)
|
|
29
|
-
return chalk_1.default.yellow(
|
|
29
|
+
return chalk_1.default.yellow("Yesterday");
|
|
30
30
|
if (diffDays < 7)
|
|
31
31
|
return chalk_1.default.yellow(`${diffDays} days ago`);
|
|
32
32
|
if (diffDays < 30)
|
|
@@ -41,9 +41,9 @@ function formatLastUsed(dateString) {
|
|
|
41
41
|
const diffTime = Math.abs(now.getTime() - date.getTime());
|
|
42
42
|
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
|
|
43
43
|
if (diffDays === 0)
|
|
44
|
-
return chalk_1.default.green(
|
|
44
|
+
return chalk_1.default.green("Today");
|
|
45
45
|
if (diffDays === 1)
|
|
46
|
-
return chalk_1.default.yellow(
|
|
46
|
+
return chalk_1.default.yellow("Yesterday");
|
|
47
47
|
if (diffDays < 7)
|
|
48
48
|
return chalk_1.default.yellow(`${diffDays} days ago`);
|
|
49
49
|
if (diffDays < 30)
|
|
@@ -56,22 +56,20 @@ function formatLastUsed(dateString) {
|
|
|
56
56
|
* Register API key commands
|
|
57
57
|
*/
|
|
58
58
|
function registerApiKeyCommands(program) {
|
|
59
|
-
const apiKey = program
|
|
60
|
-
.command(api_key_service_1.ApiKeyService.COMMAND_GROUP)
|
|
61
|
-
.description('Manage API keys');
|
|
59
|
+
const apiKey = program.command(api_key_service_1.ApiKeyService.COMMAND_GROUP).description("Manage API keys");
|
|
62
60
|
apiKey
|
|
63
61
|
.command(api_key_service_1.ApiKeyService.COMMANDS.LIST)
|
|
64
|
-
.description(
|
|
62
|
+
.description("List all API keys")
|
|
65
63
|
.action(() => __awaiter(this, void 0, void 0, function* () {
|
|
66
64
|
try {
|
|
67
65
|
const apiKeyService = api_key_service_1.ApiKeyService.getInstance();
|
|
68
66
|
const keys = yield apiKeyService.list();
|
|
69
67
|
if (keys.length === 0) {
|
|
70
|
-
console.log(chalk_1.default.yellow(
|
|
68
|
+
console.log(chalk_1.default.yellow("No API keys found. Create one with `berget api-key create --name <name>`"));
|
|
71
69
|
return;
|
|
72
70
|
}
|
|
73
|
-
console.log(chalk_1.default.bold(
|
|
74
|
-
console.log(
|
|
71
|
+
console.log(chalk_1.default.bold("🔑 Your API keys:"));
|
|
72
|
+
console.log("");
|
|
75
73
|
// Create a more readable table with better spacing and colors
|
|
76
74
|
const idWidth = 10;
|
|
77
75
|
const nameWidth = 30;
|
|
@@ -79,30 +77,24 @@ function registerApiKeyCommands(program) {
|
|
|
79
77
|
const statusWidth = 12;
|
|
80
78
|
const createdWidth = 12;
|
|
81
79
|
const usedWidth = 15;
|
|
82
|
-
console.log(chalk_1.default.dim(
|
|
83
|
-
chalk_1.default.dim(
|
|
84
|
-
chalk_1.default.dim(
|
|
85
|
-
chalk_1.default.dim(
|
|
86
|
-
chalk_1.default.dim(
|
|
87
|
-
chalk_1.default.dim(
|
|
88
|
-
console.log(chalk_1.default.dim(
|
|
80
|
+
console.log(chalk_1.default.dim("ID".padEnd(idWidth)) +
|
|
81
|
+
chalk_1.default.dim("NAME".padEnd(nameWidth)) +
|
|
82
|
+
chalk_1.default.dim("PREFIX".padEnd(prefixWidth)) +
|
|
83
|
+
chalk_1.default.dim("STATUS".padEnd(statusWidth)) +
|
|
84
|
+
chalk_1.default.dim("CREATED".padEnd(createdWidth)) +
|
|
85
|
+
chalk_1.default.dim("LAST USED"));
|
|
86
|
+
console.log(chalk_1.default.dim("─".repeat(idWidth + nameWidth + prefixWidth + statusWidth + createdWidth + usedWidth + 5)));
|
|
89
87
|
keys.forEach((key) => {
|
|
90
|
-
const lastUsed = key.lastUsed
|
|
91
|
-
|
|
92
|
-
: chalk_1.default.yellow('Never used');
|
|
93
|
-
const status = key.active
|
|
94
|
-
? chalk_1.default.green('● Active')
|
|
95
|
-
: chalk_1.default.red('● Inactive');
|
|
88
|
+
const lastUsed = key.lastUsed ? formatLastUsed(key.lastUsed) : chalk_1.default.yellow("Never used");
|
|
89
|
+
const status = key.active ? chalk_1.default.green("● Active") : chalk_1.default.red("● Inactive");
|
|
96
90
|
// Show only first 8 characters of ID for easier reading
|
|
97
91
|
const shortId = chalk_1.default.cyan(String(key.id).substring(0, 8));
|
|
98
92
|
// Format the prefix with better truncation
|
|
99
93
|
const prefixStr = key.prefix.length > prefixWidth
|
|
100
|
-
? key.prefix.substring(0, prefixWidth - 3) +
|
|
94
|
+
? key.prefix.substring(0, prefixWidth - 3) + "..."
|
|
101
95
|
: chalk_1.default.gray(key.prefix);
|
|
102
96
|
// Truncate name if too long
|
|
103
|
-
const nameStr = key.name.length > nameWidth
|
|
104
|
-
? key.name.substring(0, nameWidth - 3) + '...'
|
|
105
|
-
: key.name;
|
|
97
|
+
const nameStr = key.name.length > nameWidth ? key.name.substring(0, nameWidth - 3) + "..." : key.name;
|
|
106
98
|
// Format created date
|
|
107
99
|
const createdDate = formatDate(key.created);
|
|
108
100
|
console.log(shortId.padEnd(idWidth) +
|
|
@@ -112,62 +104,62 @@ function registerApiKeyCommands(program) {
|
|
|
112
104
|
createdDate.padEnd(createdWidth) +
|
|
113
105
|
lastUsed);
|
|
114
106
|
});
|
|
115
|
-
console.log(
|
|
116
|
-
console.log(chalk_1.default.dim(
|
|
117
|
-
console.log(chalk_1.default.dim(
|
|
118
|
-
console.log(chalk_1.default.dim(
|
|
107
|
+
console.log("");
|
|
108
|
+
console.log(chalk_1.default.dim("Use `berget api-key create --name <name>` to create a new API key"));
|
|
109
|
+
console.log(chalk_1.default.dim("Use `berget api-key delete <id>` to delete an API key"));
|
|
110
|
+
console.log(chalk_1.default.dim("Use `berget api-key rotate <id>` to rotate an API key"));
|
|
119
111
|
}
|
|
120
112
|
catch (error) {
|
|
121
|
-
(0, error_handler_1.handleError)(
|
|
113
|
+
(0, error_handler_1.handleError)("Failed to list API keys", error);
|
|
122
114
|
}
|
|
123
115
|
}));
|
|
124
116
|
apiKey
|
|
125
117
|
.command(api_key_service_1.ApiKeyService.COMMANDS.CREATE)
|
|
126
|
-
.description(
|
|
127
|
-
.option(
|
|
128
|
-
.option(
|
|
118
|
+
.description("Create a new API key")
|
|
119
|
+
.option("--name <name>", "Name of the API key")
|
|
120
|
+
.option("--description <description>", "Description of the API key")
|
|
129
121
|
.action((options) => __awaiter(this, void 0, void 0, function* () {
|
|
130
122
|
try {
|
|
131
123
|
if (!options.name) {
|
|
132
|
-
console.error(chalk_1.default.red(
|
|
133
|
-
console.log(
|
|
134
|
-
console.log(
|
|
124
|
+
console.error(chalk_1.default.red("Error: --name is required"));
|
|
125
|
+
console.log("");
|
|
126
|
+
console.log("Usage: berget api-key create --name <name> [--description <description>]");
|
|
135
127
|
return;
|
|
136
128
|
}
|
|
137
|
-
console.log(chalk_1.default.blue(
|
|
129
|
+
console.log(chalk_1.default.blue("Creating API key..."));
|
|
138
130
|
const apiKeyService = api_key_service_1.ApiKeyService.getInstance();
|
|
139
131
|
const result = yield apiKeyService.create({
|
|
140
132
|
name: options.name,
|
|
141
133
|
description: options.description,
|
|
142
134
|
});
|
|
143
|
-
console.log(
|
|
144
|
-
console.log(chalk_1.default.green(
|
|
145
|
-
console.log(
|
|
146
|
-
console.log(chalk_1.default.bold(
|
|
147
|
-
console.log(
|
|
148
|
-
console.log(`${chalk_1.default.dim(
|
|
149
|
-
console.log(`${chalk_1.default.dim(
|
|
135
|
+
console.log("");
|
|
136
|
+
console.log(chalk_1.default.green("✓ API key created"));
|
|
137
|
+
console.log("");
|
|
138
|
+
console.log(chalk_1.default.bold("API key details:"));
|
|
139
|
+
console.log("");
|
|
140
|
+
console.log(`${chalk_1.default.dim("ID:")} ${result.id}`);
|
|
141
|
+
console.log(`${chalk_1.default.dim("Name:")} ${result.name}`);
|
|
150
142
|
if (result.description) {
|
|
151
|
-
console.log(`${chalk_1.default.dim(
|
|
143
|
+
console.log(`${chalk_1.default.dim("Description:")} ${result.description}`);
|
|
152
144
|
}
|
|
153
|
-
console.log(`${chalk_1.default.dim(
|
|
154
|
-
console.log(
|
|
155
|
-
console.log(chalk_1.default.bold(
|
|
145
|
+
console.log(`${chalk_1.default.dim("Created:")} ${new Date(result.created).toLocaleString()}`);
|
|
146
|
+
console.log("");
|
|
147
|
+
console.log(chalk_1.default.bold("API key:"));
|
|
156
148
|
console.log(chalk_1.default.cyan(result.key));
|
|
157
|
-
console.log(
|
|
158
|
-
console.log(chalk_1.default.yellow(
|
|
159
|
-
console.log(chalk_1.default.yellow(
|
|
160
|
-
console.log(
|
|
161
|
-
console.log(chalk_1.default.dim(
|
|
149
|
+
console.log("");
|
|
150
|
+
console.log(chalk_1.default.yellow("⚠️ IMPORTANT: Save this API key in a secure location."));
|
|
151
|
+
console.log(chalk_1.default.yellow(" It will not be displayed again."));
|
|
152
|
+
console.log("");
|
|
153
|
+
console.log(chalk_1.default.dim("Use this key in your applications to authenticate with the Berget API."));
|
|
162
154
|
}
|
|
163
155
|
catch (error) {
|
|
164
|
-
(0, error_handler_1.handleError)(
|
|
156
|
+
(0, error_handler_1.handleError)("Failed to create API key", error);
|
|
165
157
|
}
|
|
166
158
|
}));
|
|
167
159
|
apiKey
|
|
168
160
|
.command(api_key_service_1.ApiKeyService.COMMANDS.DELETE)
|
|
169
|
-
.description(
|
|
170
|
-
.argument(
|
|
161
|
+
.description("Delete an API key")
|
|
162
|
+
.argument("<identifier>", "ID (first 8 chars), full ID, or name of the API key to delete")
|
|
171
163
|
.action((identifier) => __awaiter(this, void 0, void 0, function* () {
|
|
172
164
|
try {
|
|
173
165
|
const apiKeyService = api_key_service_1.ApiKeyService.getInstance();
|
|
@@ -179,39 +171,39 @@ function registerApiKeyCommands(program) {
|
|
|
179
171
|
// 3. Exact name match
|
|
180
172
|
// 4. Partial name match
|
|
181
173
|
// Check for exact matches first (full ID or exact name)
|
|
182
|
-
let exactMatches = keys.filter(
|
|
174
|
+
let exactMatches = keys.filter(key => String(key.id) === identifier || key.name === identifier);
|
|
183
175
|
// If no exact matches, check for short ID matches
|
|
184
176
|
if (exactMatches.length === 0) {
|
|
185
|
-
exactMatches = keys.filter(
|
|
177
|
+
exactMatches = keys.filter(key => String(key.id).substring(0, 8) === identifier);
|
|
186
178
|
}
|
|
187
179
|
// If still no matches, check for partial name matches
|
|
188
180
|
if (exactMatches.length === 0) {
|
|
189
|
-
exactMatches = keys.filter(
|
|
181
|
+
exactMatches = keys.filter(key => key.name.toLowerCase().includes(identifier.toLowerCase()));
|
|
190
182
|
}
|
|
191
183
|
// Handle multiple matches
|
|
192
184
|
if (exactMatches.length > 1) {
|
|
193
185
|
console.error(chalk_1.default.red(`Error: Multiple API keys found matching "${identifier}"`));
|
|
194
|
-
console.log(
|
|
195
|
-
console.log(
|
|
196
|
-
exactMatches.forEach(
|
|
186
|
+
console.log("");
|
|
187
|
+
console.log("Please be more specific. Matching keys:");
|
|
188
|
+
exactMatches.forEach(key => {
|
|
197
189
|
const shortId = String(key.id).substring(0, 8);
|
|
198
190
|
console.log(` ${shortId.padEnd(8)} ${key.name}`);
|
|
199
191
|
});
|
|
200
|
-
console.log(
|
|
201
|
-
console.log(
|
|
192
|
+
console.log("");
|
|
193
|
+
console.log("Use the first 8 characters of the ID to specify which key to delete.");
|
|
202
194
|
return;
|
|
203
195
|
}
|
|
204
196
|
// Handle no matches
|
|
205
197
|
if (exactMatches.length === 0) {
|
|
206
198
|
console.error(chalk_1.default.red(`Error: No API key found matching "${identifier}"`));
|
|
207
|
-
console.log(
|
|
208
|
-
console.log(
|
|
209
|
-
keys.forEach(
|
|
199
|
+
console.log("");
|
|
200
|
+
console.log("Available API keys:");
|
|
201
|
+
keys.forEach(key => {
|
|
210
202
|
const shortId = String(key.id).substring(0, 8);
|
|
211
203
|
console.log(` ${shortId.padEnd(8)} ${key.name}`);
|
|
212
204
|
});
|
|
213
|
-
console.log(
|
|
214
|
-
console.log(
|
|
205
|
+
console.log("");
|
|
206
|
+
console.log("Use the first 8 characters of the ID, full ID, or name to delete.");
|
|
215
207
|
return;
|
|
216
208
|
}
|
|
217
209
|
const matchingKey = exactMatches[0];
|
|
@@ -220,87 +212,87 @@ function registerApiKeyCommands(program) {
|
|
|
220
212
|
console.log(chalk_1.default.blue(`Deleting API key ${shortId} (${matchingKey.name})...`));
|
|
221
213
|
yield apiKeyService.delete(keyId);
|
|
222
214
|
console.log(chalk_1.default.green(`✓ API key ${shortId} (${matchingKey.name}) has been deleted`));
|
|
223
|
-
console.log(
|
|
224
|
-
console.log(chalk_1.default.dim(
|
|
225
|
-
console.log(chalk_1.default.dim(
|
|
215
|
+
console.log("");
|
|
216
|
+
console.log(chalk_1.default.dim("Applications using this key will no longer be able to authenticate."));
|
|
217
|
+
console.log(chalk_1.default.dim("Use `berget api-key list` to see your remaining API keys."));
|
|
226
218
|
}
|
|
227
219
|
catch (error) {
|
|
228
|
-
(0, error_handler_1.handleError)(
|
|
220
|
+
(0, error_handler_1.handleError)("Failed to delete API key", error);
|
|
229
221
|
}
|
|
230
222
|
}));
|
|
231
223
|
apiKey
|
|
232
224
|
.command(api_key_service_1.ApiKeyService.COMMANDS.ROTATE)
|
|
233
|
-
.description(
|
|
234
|
-
.argument(
|
|
225
|
+
.description("Rotate an API key (creates a new one and invalidates the old one)")
|
|
226
|
+
.argument("<id>", "ID of the API key to rotate")
|
|
235
227
|
.action((id) => __awaiter(this, void 0, void 0, function* () {
|
|
236
228
|
try {
|
|
237
229
|
console.log(chalk_1.default.blue(`Rotating API key ${id}...`));
|
|
238
|
-
console.log(chalk_1.default.dim(
|
|
230
|
+
console.log(chalk_1.default.dim("This will invalidate the old key and generate a new one."));
|
|
239
231
|
const apiKeyService = api_key_service_1.ApiKeyService.getInstance();
|
|
240
232
|
const result = yield apiKeyService.rotate(id);
|
|
241
|
-
console.log(
|
|
242
|
-
console.log(chalk_1.default.green(
|
|
243
|
-
console.log(
|
|
244
|
-
console.log(chalk_1.default.bold(
|
|
245
|
-
console.log(
|
|
246
|
-
console.log(`${chalk_1.default.dim(
|
|
247
|
-
console.log(`${chalk_1.default.dim(
|
|
233
|
+
console.log("");
|
|
234
|
+
console.log(chalk_1.default.green("✓ API key rotated"));
|
|
235
|
+
console.log("");
|
|
236
|
+
console.log(chalk_1.default.bold("New API key details:"));
|
|
237
|
+
console.log("");
|
|
238
|
+
console.log(`${chalk_1.default.dim("ID:")} ${result.id}`);
|
|
239
|
+
console.log(`${chalk_1.default.dim("Name:")} ${result.name}`);
|
|
248
240
|
if (result.description) {
|
|
249
|
-
console.log(`${chalk_1.default.dim(
|
|
241
|
+
console.log(`${chalk_1.default.dim("Description:")} ${result.description}`);
|
|
250
242
|
}
|
|
251
|
-
console.log(`${chalk_1.default.dim(
|
|
252
|
-
console.log(
|
|
253
|
-
console.log(chalk_1.default.bold(
|
|
243
|
+
console.log(`${chalk_1.default.dim("Created:")} ${new Date(result.created).toLocaleString()}`);
|
|
244
|
+
console.log("");
|
|
245
|
+
console.log(chalk_1.default.bold("New API key:"));
|
|
254
246
|
console.log(chalk_1.default.cyan(result.key));
|
|
255
|
-
console.log(
|
|
256
|
-
console.log(chalk_1.default.yellow(
|
|
257
|
-
console.log(chalk_1.default.yellow(
|
|
258
|
-
console.log(chalk_1.default.yellow(
|
|
247
|
+
console.log("");
|
|
248
|
+
console.log(chalk_1.default.yellow("⚠️ IMPORTANT: Update your applications with this new API key."));
|
|
249
|
+
console.log(chalk_1.default.yellow(" The old key has been invalidated and will no longer work."));
|
|
250
|
+
console.log(chalk_1.default.yellow(" This new key will not be displayed again."));
|
|
259
251
|
}
|
|
260
252
|
catch (error) {
|
|
261
|
-
(0, error_handler_1.handleError)(
|
|
253
|
+
(0, error_handler_1.handleError)("Failed to rotate API key", error);
|
|
262
254
|
}
|
|
263
255
|
}));
|
|
264
256
|
apiKey
|
|
265
257
|
.command(api_key_service_1.ApiKeyService.COMMANDS.DESCRIBE)
|
|
266
|
-
.description(
|
|
267
|
-
.argument(
|
|
268
|
-
.option(
|
|
269
|
-
.option(
|
|
270
|
-
.action((id,
|
|
258
|
+
.description("Show usage statistics for an API key")
|
|
259
|
+
.argument("<id>", "ID of the API key")
|
|
260
|
+
.option("--start <date>", "Start date (YYYY-MM-DD)")
|
|
261
|
+
.option("--end <date>", "End date (YYYY-MM-DD)")
|
|
262
|
+
.action((id, _options) => __awaiter(this, void 0, void 0, function* () {
|
|
271
263
|
try {
|
|
272
264
|
console.log(chalk_1.default.blue(`Fetching usage statistics for API key ${id}...`));
|
|
273
265
|
const apiKeyService = api_key_service_1.ApiKeyService.getInstance();
|
|
274
266
|
const usage = yield apiKeyService.describe(id);
|
|
275
|
-
console.log(
|
|
267
|
+
console.log("");
|
|
276
268
|
console.log(chalk_1.default.bold(`Usage statistics for API key: ${usage.name} (${id})`));
|
|
277
|
-
console.log(
|
|
269
|
+
console.log("");
|
|
278
270
|
// Period information
|
|
279
271
|
console.log(chalk_1.default.dim(`Period: ${usage.period.start} to ${usage.period.end}`));
|
|
280
|
-
console.log(
|
|
272
|
+
console.log("");
|
|
281
273
|
// Request statistics
|
|
282
|
-
console.log(chalk_1.default.bold(
|
|
274
|
+
console.log(chalk_1.default.bold("Request statistics:"));
|
|
283
275
|
console.log(`Total requests: ${chalk_1.default.cyan(usage.requests.total.toLocaleString())}`);
|
|
284
276
|
// Daily breakdown if available
|
|
285
277
|
if (usage.requests.daily && usage.requests.daily.length > 0) {
|
|
286
|
-
console.log(
|
|
287
|
-
console.log(chalk_1.default.bold(
|
|
288
|
-
console.log(chalk_1.default.dim(
|
|
289
|
-
console.log(chalk_1.default.dim(
|
|
278
|
+
console.log("");
|
|
279
|
+
console.log(chalk_1.default.bold("Daily breakdown:"));
|
|
280
|
+
console.log(chalk_1.default.dim("─".repeat(30)));
|
|
281
|
+
console.log(chalk_1.default.dim("DATE".padEnd(12) + "REQUESTS"));
|
|
290
282
|
usage.requests.daily.forEach((day) => {
|
|
291
283
|
console.log(`${day.date.padEnd(12)}${day.count.toLocaleString()}`);
|
|
292
284
|
});
|
|
293
285
|
}
|
|
294
286
|
// Model usage if available
|
|
295
287
|
if (usage.models && usage.models.length > 0) {
|
|
296
|
-
console.log(
|
|
297
|
-
console.log(chalk_1.default.bold(
|
|
298
|
-
console.log(chalk_1.default.dim(
|
|
299
|
-
console.log(chalk_1.default.dim(
|
|
300
|
-
chalk_1.default.dim(
|
|
301
|
-
chalk_1.default.dim(
|
|
302
|
-
chalk_1.default.dim(
|
|
303
|
-
chalk_1.default.dim(
|
|
288
|
+
console.log("");
|
|
289
|
+
console.log(chalk_1.default.bold("Model usage:"));
|
|
290
|
+
console.log(chalk_1.default.dim("─".repeat(70)));
|
|
291
|
+
console.log(chalk_1.default.dim("MODEL".padEnd(20)) +
|
|
292
|
+
chalk_1.default.dim("REQUESTS".padEnd(10)) +
|
|
293
|
+
chalk_1.default.dim("INPUT".padEnd(12)) +
|
|
294
|
+
chalk_1.default.dim("OUTPUT".padEnd(12)) +
|
|
295
|
+
chalk_1.default.dim("TOTAL TOKENS"));
|
|
304
296
|
usage.models.forEach((model) => {
|
|
305
297
|
console.log(model.name.padEnd(20) +
|
|
306
298
|
model.requests.toString().padEnd(10) +
|
|
@@ -309,22 +301,22 @@ function registerApiKeyCommands(program) {
|
|
|
309
301
|
model.tokens.total.toLocaleString());
|
|
310
302
|
});
|
|
311
303
|
}
|
|
312
|
-
console.log(
|
|
313
|
-
console.log(chalk_1.default.dim(
|
|
304
|
+
console.log("");
|
|
305
|
+
console.log(chalk_1.default.dim("Use these statistics to understand your API usage and optimize your costs."));
|
|
314
306
|
}
|
|
315
307
|
catch (error) {
|
|
316
|
-
(0, error_handler_1.handleError)(
|
|
308
|
+
(0, error_handler_1.handleError)("Failed to get API key usage", error);
|
|
317
309
|
}
|
|
318
310
|
}));
|
|
319
311
|
apiKey
|
|
320
312
|
.command(api_key_service_1.ApiKeyService.COMMANDS.SET_DEFAULT)
|
|
321
|
-
.description(
|
|
322
|
-
.argument(
|
|
313
|
+
.description("Set an API key as the default for chat commands")
|
|
314
|
+
.argument("<id>", "ID of the API key to set as default")
|
|
323
315
|
.action((id) => __awaiter(this, void 0, void 0, function* () {
|
|
324
316
|
try {
|
|
325
317
|
const apiKeyService = api_key_service_1.ApiKeyService.getInstance();
|
|
326
318
|
const keys = yield apiKeyService.list();
|
|
327
|
-
const selectedKey = keys.find(
|
|
319
|
+
const selectedKey = keys.find(key => key.id.toString() === id);
|
|
328
320
|
if (!selectedKey) {
|
|
329
321
|
console.error(chalk_1.default.red(`Error: API key with ID ${id} not found`));
|
|
330
322
|
return;
|
|
@@ -335,39 +327,39 @@ function registerApiKeyCommands(program) {
|
|
|
335
327
|
const rotatedKey = yield apiKeyService.rotate(id);
|
|
336
328
|
defaultApiKeyManager.setDefaultApiKey(id, selectedKey.name, selectedKey.prefix, rotatedKey.key);
|
|
337
329
|
console.log(chalk_1.default.green(`✓ API key "${selectedKey.name}" set as default for chat commands`));
|
|
338
|
-
console.log(
|
|
339
|
-
console.log(chalk_1.default.dim(
|
|
340
|
-
console.log(chalk_1.default.dim(
|
|
330
|
+
console.log("");
|
|
331
|
+
console.log(chalk_1.default.dim("This API key will be used by default when running chat commands"));
|
|
332
|
+
console.log(chalk_1.default.dim("You can override it with --api-key or --api-key-id options"));
|
|
341
333
|
}
|
|
342
334
|
catch (error) {
|
|
343
|
-
(0, error_handler_1.handleError)(
|
|
335
|
+
(0, error_handler_1.handleError)("Failed to set default API key", error);
|
|
344
336
|
}
|
|
345
337
|
}));
|
|
346
338
|
apiKey
|
|
347
339
|
.command(api_key_service_1.ApiKeyService.COMMANDS.GET_DEFAULT)
|
|
348
|
-
.description(
|
|
340
|
+
.description("Show the current default API key")
|
|
349
341
|
.action(() => {
|
|
350
342
|
try {
|
|
351
343
|
const defaultApiKeyManager = default_api_key_1.DefaultApiKeyManager.getInstance();
|
|
352
344
|
const defaultApiKeyData = defaultApiKeyManager.getDefaultApiKeyData();
|
|
353
345
|
if (!defaultApiKeyData) {
|
|
354
|
-
console.log(chalk_1.default.yellow(
|
|
355
|
-
console.log(
|
|
356
|
-
console.log(
|
|
357
|
-
console.log(chalk_1.default.cyan(
|
|
346
|
+
console.log(chalk_1.default.yellow("No default API key set"));
|
|
347
|
+
console.log("");
|
|
348
|
+
console.log("To set a default API key, run:");
|
|
349
|
+
console.log(chalk_1.default.cyan(" berget api-keys set-default <id>"));
|
|
358
350
|
return;
|
|
359
351
|
}
|
|
360
|
-
console.log(chalk_1.default.bold(
|
|
361
|
-
console.log(
|
|
362
|
-
console.log(`${chalk_1.default.dim(
|
|
363
|
-
console.log(`${chalk_1.default.dim(
|
|
364
|
-
console.log(`${chalk_1.default.dim(
|
|
365
|
-
console.log(
|
|
366
|
-
console.log(chalk_1.default.dim(
|
|
367
|
-
console.log(chalk_1.default.dim(
|
|
352
|
+
console.log(chalk_1.default.bold("Default API key:"));
|
|
353
|
+
console.log("");
|
|
354
|
+
console.log(`${chalk_1.default.dim("ID:")} ${defaultApiKeyData.id}`);
|
|
355
|
+
console.log(`${chalk_1.default.dim("Name:")} ${defaultApiKeyData.name}`);
|
|
356
|
+
console.log(`${chalk_1.default.dim("Prefix:")} ${defaultApiKeyData.prefix}`);
|
|
357
|
+
console.log("");
|
|
358
|
+
console.log(chalk_1.default.dim("This API key will be used by default when running chat commands"));
|
|
359
|
+
console.log(chalk_1.default.dim("You can override it with --api-key or --api-key-id options"));
|
|
368
360
|
}
|
|
369
361
|
catch (error) {
|
|
370
|
-
(0, error_handler_1.handleError)(
|
|
362
|
+
(0, error_handler_1.handleError)("Failed to get default API key", error);
|
|
371
363
|
}
|
|
372
364
|
});
|
|
373
365
|
}
|
|
@@ -23,42 +23,42 @@ const error_handler_1 = require("../utils/error-handler");
|
|
|
23
23
|
function registerAuthCommands(program) {
|
|
24
24
|
const auth = program
|
|
25
25
|
.command(auth_service_1.AuthService.COMMAND_GROUP)
|
|
26
|
-
.description(
|
|
26
|
+
.description("Manage authentication and authorization");
|
|
27
27
|
auth
|
|
28
28
|
.command(auth_service_1.AuthService.COMMANDS.LOGIN)
|
|
29
|
-
.description(
|
|
29
|
+
.description("Log in to Berget")
|
|
30
30
|
.action(() => __awaiter(this, void 0, void 0, function* () {
|
|
31
31
|
const authService = auth_service_1.AuthService.getInstance();
|
|
32
32
|
yield authService.login();
|
|
33
33
|
}));
|
|
34
34
|
auth
|
|
35
35
|
.command(auth_service_1.AuthService.COMMANDS.LOGOUT)
|
|
36
|
-
.description(
|
|
36
|
+
.description("Log out from Berget")
|
|
37
37
|
.action(() => {
|
|
38
38
|
(0, client_1.clearAuthToken)();
|
|
39
|
-
console.log(chalk_1.default.green(
|
|
39
|
+
console.log(chalk_1.default.green("You have been logged out from Berget"));
|
|
40
40
|
});
|
|
41
41
|
auth
|
|
42
42
|
.command(auth_service_1.AuthService.COMMANDS.WHOAMI)
|
|
43
|
-
.description(
|
|
43
|
+
.description("Show information about the logged in user")
|
|
44
44
|
.action(() => __awaiter(this, void 0, void 0, function* () {
|
|
45
45
|
try {
|
|
46
46
|
const authService = auth_service_1.AuthService.getInstance();
|
|
47
47
|
const profile = yield authService.whoami();
|
|
48
48
|
if (profile) {
|
|
49
49
|
console.log(chalk_1.default.bold(`Logged in as: ${profile.name || profile.login}`));
|
|
50
|
-
console.log(`Email: ${chalk_1.default.cyan(profile.email ||
|
|
51
|
-
console.log(`Role: ${chalk_1.default.cyan(profile.role ||
|
|
50
|
+
console.log(`Email: ${chalk_1.default.cyan(profile.email || "Not available")}`);
|
|
51
|
+
console.log(`Role: ${chalk_1.default.cyan(profile.role || "Not available")}`);
|
|
52
52
|
if (profile.company) {
|
|
53
53
|
console.log(`Company: ${chalk_1.default.cyan(profile.company.name)}`);
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
else {
|
|
57
|
-
console.log(chalk_1.default.yellow(
|
|
57
|
+
console.log(chalk_1.default.yellow("You are not logged in. Use `berget login` to log in."));
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
catch (error) {
|
|
61
|
-
(0, error_handler_1.handleError)(
|
|
61
|
+
(0, error_handler_1.handleError)("You are not logged in or an error occurred", error);
|
|
62
62
|
}
|
|
63
63
|
}));
|
|
64
64
|
}
|
|
@@ -9,16 +9,16 @@ const chalk_1 = __importDefault(require("chalk"));
|
|
|
9
9
|
* Register autocomplete commands
|
|
10
10
|
*/
|
|
11
11
|
function registerAutocompleteCommands(program) {
|
|
12
|
-
|
|
13
|
-
.command(
|
|
14
|
-
.command(
|
|
15
|
-
.description(
|
|
12
|
+
program
|
|
13
|
+
.command("autocomplete")
|
|
14
|
+
.command("install")
|
|
15
|
+
.description("Install shell autocompletion")
|
|
16
16
|
.action(() => {
|
|
17
|
-
console.log(chalk_1.default.green(
|
|
18
|
-
console.log(chalk_1.default.green(
|
|
19
|
-
console.log(
|
|
20
|
-
console.log(
|
|
21
|
-
console.log(
|
|
17
|
+
console.log(chalk_1.default.green("✓ Berget autocomplete installed in your shell"));
|
|
18
|
+
console.log(chalk_1.default.green("✓ Shell completion for kubectl also installed"));
|
|
19
|
+
console.log("");
|
|
20
|
+
console.log("Restart your shell or run:");
|
|
21
|
+
console.log(" source ~/.bashrc");
|
|
22
22
|
});
|
|
23
23
|
}
|
|
24
24
|
exports.registerAutocompleteCommands = registerAutocompleteCommands;
|
|
@@ -17,19 +17,17 @@ const error_handler_1 = require("../utils/error-handler");
|
|
|
17
17
|
* Register billing commands
|
|
18
18
|
*/
|
|
19
19
|
function registerBillingCommands(program) {
|
|
20
|
-
const billing = program
|
|
21
|
-
.command(command_structure_1.COMMAND_GROUPS.BILLING)
|
|
22
|
-
.description('Manage billing and usage');
|
|
20
|
+
const billing = program.command(command_structure_1.COMMAND_GROUPS.BILLING).description("Manage billing and usage");
|
|
23
21
|
billing
|
|
24
22
|
.command(command_structure_1.SUBCOMMANDS.BILLING.GET_USAGE)
|
|
25
|
-
.description(
|
|
26
|
-
.option(
|
|
23
|
+
.description("Get token usage statistics")
|
|
24
|
+
.option("--model <modelId>", "Get usage for a specific model")
|
|
27
25
|
.action((options) => __awaiter(this, void 0, void 0, function* () {
|
|
28
26
|
try {
|
|
29
27
|
const client = (0, client_1.createAuthenticatedClient)();
|
|
30
28
|
let response;
|
|
31
29
|
if (options.model) {
|
|
32
|
-
const { data, error } = yield client.GET(
|
|
30
|
+
const { data, error } = yield client.GET("/v1/usage/tokens/{modelId}", {
|
|
33
31
|
params: { path: { modelId: options.model } },
|
|
34
32
|
});
|
|
35
33
|
if (error)
|
|
@@ -37,16 +35,16 @@ function registerBillingCommands(program) {
|
|
|
37
35
|
response = data;
|
|
38
36
|
}
|
|
39
37
|
else {
|
|
40
|
-
const { data, error } = yield client.GET(
|
|
38
|
+
const { data, error } = yield client.GET("/v1/usage/tokens");
|
|
41
39
|
if (error)
|
|
42
40
|
throw new Error(JSON.stringify(error));
|
|
43
41
|
response = data;
|
|
44
42
|
}
|
|
45
|
-
console.log(
|
|
43
|
+
console.log("Token Usage:");
|
|
46
44
|
console.log(JSON.stringify(response, null, 2));
|
|
47
45
|
}
|
|
48
46
|
catch (error) {
|
|
49
|
-
(0, error_handler_1.handleError)(
|
|
47
|
+
(0, error_handler_1.handleError)("Failed to get token usage", error);
|
|
50
48
|
}
|
|
51
49
|
}));
|
|
52
50
|
}
|