berget 2.2.6 → 2.2.8
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 +2 -2
- package/.github/workflows/test.yml +10 -4
- package/.husky/pre-commit +1 -0
- package/.prettierignore +15 -0
- package/.prettierrc +7 -3
- package/CONTRIBUTING.md +38 -0
- package/README.md +2 -148
- package/dist/index.js +10 -11
- 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 +97 -117
- package/dist/src/commands/api-keys.js +75 -90
- package/dist/src/commands/auth.js +7 -16
- package/dist/src/commands/autocomplete.js +1 -1
- package/dist/src/commands/billing.js +6 -17
- package/dist/src/commands/chat.js +68 -101
- package/dist/src/commands/clusters.js +9 -18
- package/dist/src/commands/code/__tests__/auth-sync.test.js +351 -0
- package/dist/src/commands/code/__tests__/fake-api-key-service.js +13 -0
- package/dist/src/commands/code/__tests__/fake-auth-service.js +47 -0
- package/dist/src/commands/code/__tests__/fake-command-runner.js +21 -34
- package/dist/src/commands/code/__tests__/fake-file-store.js +20 -33
- package/dist/src/commands/code/__tests__/fake-prompter.js +83 -57
- package/dist/src/commands/code/__tests__/setup-flow.test.js +359 -92
- package/dist/src/commands/code/adapters/clack-prompter.js +15 -22
- package/dist/src/commands/code/adapters/fs-file-store.js +26 -40
- package/dist/src/commands/code/adapters/spawn-command-runner.js +27 -37
- package/dist/src/commands/code/auth-sync.js +270 -0
- package/dist/src/commands/code/errors.js +12 -9
- package/dist/src/commands/code/ports/auth-services.js +2 -0
- package/dist/src/commands/code/setup.js +387 -281
- package/dist/src/commands/code.js +205 -332
- package/dist/src/commands/index.js +5 -5
- package/dist/src/commands/models.js +6 -17
- package/dist/src/commands/users.js +5 -16
- package/dist/src/constants/command-structure.js +104 -104
- package/dist/src/services/api-key-service.js +132 -157
- package/dist/src/services/auth-service.js +89 -342
- package/dist/src/services/browser-auth.js +268 -0
- package/dist/src/services/chat-service.js +371 -401
- package/dist/src/services/cluster-service.js +47 -62
- package/dist/src/services/collaborator-service.js +10 -25
- package/dist/src/services/flux-service.js +14 -29
- package/dist/src/services/helm-service.js +10 -25
- package/dist/src/services/kubectl-service.js +16 -33
- package/dist/src/utils/config-checker.js +3 -3
- package/dist/src/utils/config-loader.js +95 -95
- package/dist/src/utils/default-api-key.js +124 -134
- package/dist/src/utils/env-manager.js +55 -66
- package/dist/src/utils/error-handler.js +20 -21
- package/dist/src/utils/logger.js +72 -65
- package/dist/src/utils/markdown-renderer.js +27 -27
- package/dist/src/utils/opencode-validator.js +63 -68
- package/dist/src/utils/token-manager.js +74 -45
- package/dist/tests/commands/chat.test.js +16 -25
- package/dist/tests/commands/code.test.js +95 -104
- package/dist/tests/utils/config-loader.test.js +48 -48
- package/dist/tests/utils/env-manager.test.js +43 -52
- package/dist/tests/utils/opencode-validator.test.js +22 -21
- package/dist/vitest.config.js +1 -1
- package/eslint.config.mjs +67 -0
- package/index.ts +35 -42
- 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 +73 -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 +118 -152
- package/src/commands/api-keys.ts +241 -333
- package/src/commands/auth.ts +22 -27
- package/src/commands/autocomplete.ts +9 -9
- package/src/commands/billing.ts +20 -24
- package/src/commands/chat.ts +248 -338
- package/src/commands/clusters.ts +27 -26
- package/src/commands/code/__tests__/auth-sync.test.ts +482 -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 +45 -42
- package/src/commands/code/__tests__/fake-file-store.ts +32 -23
- package/src/commands/code/__tests__/fake-prompter.ts +116 -77
- package/src/commands/code/__tests__/setup-flow.test.ts +624 -268
- package/src/commands/code/adapters/clack-prompter.ts +53 -39
- package/src/commands/code/adapters/fs-file-store.ts +32 -27
- package/src/commands/code/adapters/spawn-command-runner.ts +38 -29
- package/src/commands/code/auth-sync.ts +329 -0
- package/src/commands/code/errors.ts +18 -18
- 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 +570 -340
- package/src/commands/code.ts +338 -539
- package/src/commands/index.ts +20 -19
- package/src/commands/models.ts +28 -32
- package/src/commands/users.ts +15 -21
- package/src/constants/command-structure.ts +134 -157
- package/src/services/api-key-service.ts +105 -122
- package/src/services/auth-service.ts +99 -345
- package/src/services/browser-auth.ts +296 -0
- package/src/services/chat-service.ts +265 -299
- package/src/services/cluster-service.ts +42 -45
- package/src/services/collaborator-service.ts +14 -19
- package/src/services/flux-service.ts +23 -25
- package/src/services/helm-service.ts +19 -21
- package/src/services/kubectl-service.ts +17 -19
- package/src/types/api.d.ts +1905 -1907
- package/src/types/json.d.ts +2 -2
- package/src/utils/config-checker.ts +10 -10
- package/src/utils/config-loader.ts +162 -178
- package/src/utils/default-api-key.ts +114 -125
- package/src/utils/env-manager.ts +53 -57
- package/src/utils/error-handler.ts +61 -56
- package/src/utils/logger.ts +79 -73
- package/src/utils/markdown-renderer.ts +31 -31
- package/src/utils/opencode-validator.ts +85 -89
- package/src/utils/token-manager.ts +108 -87
- 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 +53 -62
- package/tests/commands/code.test.ts +265 -310
- package/tests/utils/config-loader.test.ts +189 -188
- package/tests/utils/env-manager.test.ts +110 -113
- package/tests/utils/opencode-validator.test.ts +52 -56
- package/tsconfig.json +4 -3
- package/vitest.config.ts +3 -3
- package/AGENTS.md +0 -374
- package/TODO.md +0 -19
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
import { createAuthenticatedClient } from '../client'
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { createAuthenticatedClient } from '../client';
|
|
2
|
+
import { COMMAND_GROUPS, SUBCOMMANDS } from '../constants/command-structure';
|
|
3
|
+
import { handleError } from '../utils/error-handler';
|
|
4
4
|
|
|
5
5
|
export interface ApiKey {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
description:
|
|
9
|
-
|
|
10
|
-
lastUsed:
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
active: boolean;
|
|
7
|
+
created: string;
|
|
8
|
+
description: null | string;
|
|
9
|
+
id: number;
|
|
10
|
+
lastUsed: null | string;
|
|
11
|
+
modified: string;
|
|
12
|
+
name: string;
|
|
13
|
+
prefix: string;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
export interface
|
|
17
|
-
|
|
18
|
-
description
|
|
16
|
+
export interface ApiKeyResponse {
|
|
17
|
+
created: string;
|
|
18
|
+
description: null | string;
|
|
19
|
+
id: number;
|
|
20
|
+
key: string;
|
|
21
|
+
name: string;
|
|
19
22
|
}
|
|
20
23
|
|
|
21
|
-
export interface
|
|
22
|
-
|
|
23
|
-
name: string
|
|
24
|
-
description: string | null
|
|
25
|
-
key: string
|
|
26
|
-
created: string
|
|
24
|
+
export interface CreateApiKeyOptions {
|
|
25
|
+
description?: string;
|
|
26
|
+
name: string;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
/**
|
|
@@ -31,37 +31,22 @@ export interface ApiKeyResponse {
|
|
|
31
31
|
* Command group: api-keys
|
|
32
32
|
*/
|
|
33
33
|
export class ApiKeyService {
|
|
34
|
-
private static instance: ApiKeyService
|
|
35
|
-
private client = createAuthenticatedClient()
|
|
36
|
-
|
|
37
34
|
// Command group name for this service
|
|
38
|
-
public static readonly COMMAND_GROUP = COMMAND_GROUPS.API_KEYS
|
|
39
|
-
|
|
35
|
+
public static readonly COMMAND_GROUP = COMMAND_GROUPS.API_KEYS;
|
|
40
36
|
// Subcommands for this service
|
|
41
|
-
public static readonly COMMANDS = SUBCOMMANDS.API_KEYS
|
|
37
|
+
public static readonly COMMANDS = SUBCOMMANDS.API_KEYS;
|
|
38
|
+
|
|
39
|
+
private static instance: ApiKeyService;
|
|
40
|
+
|
|
41
|
+
private client = createAuthenticatedClient();
|
|
42
42
|
|
|
43
43
|
private constructor() {}
|
|
44
44
|
|
|
45
45
|
public static getInstance(): ApiKeyService {
|
|
46
46
|
if (!ApiKeyService.instance) {
|
|
47
|
-
ApiKeyService.instance = new ApiKeyService()
|
|
48
|
-
}
|
|
49
|
-
return ApiKeyService.instance
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* List all API keys
|
|
54
|
-
* Command: berget api-keys list
|
|
55
|
-
*/
|
|
56
|
-
public async list(): Promise<ApiKey[]> {
|
|
57
|
-
try {
|
|
58
|
-
const { data, error } = await this.client.GET('/v1/api-keys')
|
|
59
|
-
if (error) throw error
|
|
60
|
-
return data || []
|
|
61
|
-
} catch (error) {
|
|
62
|
-
handleError('Failed to list API keys', error)
|
|
63
|
-
throw error
|
|
47
|
+
ApiKeyService.instance = new ApiKeyService();
|
|
64
48
|
}
|
|
49
|
+
return ApiKeyService.instance;
|
|
65
50
|
}
|
|
66
51
|
|
|
67
52
|
/**
|
|
@@ -72,116 +57,102 @@ export class ApiKeyService {
|
|
|
72
57
|
try {
|
|
73
58
|
// Validate input before sending request
|
|
74
59
|
if (!options.name || options.name.trim().length === 0) {
|
|
75
|
-
throw new Error('API key name is required and cannot be empty')
|
|
60
|
+
throw new Error('API key name is required and cannot be empty');
|
|
76
61
|
}
|
|
77
62
|
|
|
78
63
|
if (options.name.length > 100) {
|
|
79
|
-
throw new Error('API key name must be 100 characters or less')
|
|
64
|
+
throw new Error('API key name must be 100 characters or less');
|
|
80
65
|
}
|
|
81
66
|
|
|
82
67
|
if (options.description && options.description.length > 500) {
|
|
83
|
-
throw new Error('API key description must be 500 characters or less')
|
|
68
|
+
throw new Error('API key description must be 500 characters or less');
|
|
84
69
|
}
|
|
85
70
|
|
|
86
71
|
const { data, error } = await this.client.POST('/v1/api-keys', {
|
|
87
72
|
body: options,
|
|
88
|
-
})
|
|
73
|
+
});
|
|
89
74
|
|
|
90
75
|
if (error) {
|
|
91
76
|
// Enhanced error handling with specific troubleshooting
|
|
92
77
|
|
|
93
78
|
// Handle specific error cases
|
|
94
79
|
if (typeof error === 'object' && error !== null) {
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
if (
|
|
98
|
-
let detailedMessage =
|
|
99
|
-
|
|
100
|
-
detailedMessage += '•
|
|
101
|
-
detailedMessage +=
|
|
102
|
-
|
|
103
|
-
detailedMessage += '
|
|
104
|
-
detailedMessage += '
|
|
105
|
-
detailedMessage += '
|
|
106
|
-
detailedMessage +=
|
|
107
|
-
|
|
108
|
-
detailedMessage +=
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
detailedMessage +=
|
|
112
|
-
'4. Try again in a few minutes if this is a temporary issue\n'
|
|
113
|
-
detailedMessage += '5. Contact support if the problem persists'
|
|
114
|
-
|
|
115
|
-
throw new Error(detailedMessage)
|
|
80
|
+
const errorObject = error as any;
|
|
81
|
+
|
|
82
|
+
if (errorObject.error?.code === 'API_KEY_CREATION_FAILED') {
|
|
83
|
+
let detailedMessage = 'Failed to create API key. This could be due to:\n';
|
|
84
|
+
detailedMessage += '• Account limits or quota restrictions\n';
|
|
85
|
+
detailedMessage += '• Insufficient permissions for API key creation\n';
|
|
86
|
+
detailedMessage += '• Temporary server issues\n';
|
|
87
|
+
detailedMessage += '• Billing or subscription issues\n\n';
|
|
88
|
+
detailedMessage += 'Troubleshooting steps:\n';
|
|
89
|
+
detailedMessage += '1. Check if you have reached your API key limit\n';
|
|
90
|
+
detailedMessage += '2. Verify your account has API key creation permissions\n';
|
|
91
|
+
detailedMessage += '3. Check your billing status and subscription\n';
|
|
92
|
+
detailedMessage += '4. Try again in a few minutes if this is a temporary issue\n';
|
|
93
|
+
detailedMessage += '5. Contact support if the problem persists';
|
|
94
|
+
|
|
95
|
+
throw new Error(detailedMessage);
|
|
116
96
|
}
|
|
117
97
|
|
|
118
|
-
if (
|
|
98
|
+
if (errorObject.error?.code === 'USER_NOT_FOUND') {
|
|
119
99
|
throw new Error(
|
|
120
100
|
'Your account is still being set up. Please wait a moment and try again.\n\nIf this issue persists, please contact support at support@berget.ai',
|
|
121
|
-
)
|
|
101
|
+
);
|
|
122
102
|
}
|
|
123
103
|
|
|
124
|
-
if (
|
|
104
|
+
if (errorObject.error?.code === 'QUOTA_EXCEEDED') {
|
|
125
105
|
throw new Error(
|
|
126
106
|
'You have reached your API key limit. Please delete existing keys or contact support to increase your quota.',
|
|
127
|
-
)
|
|
107
|
+
);
|
|
128
108
|
}
|
|
129
109
|
|
|
130
|
-
if (
|
|
110
|
+
if (errorObject.error?.code === 'INSUFFICIENT_PERMISSIONS') {
|
|
131
111
|
throw new Error(
|
|
132
112
|
'Your account does not have permission to create API keys. Please contact your administrator.',
|
|
133
|
-
)
|
|
113
|
+
);
|
|
134
114
|
}
|
|
135
115
|
|
|
136
|
-
if (
|
|
116
|
+
if (errorObject.error?.code === 'BILLING_REQUIRED') {
|
|
137
117
|
throw new Error(
|
|
138
118
|
'A valid billing method is required to create API keys. Please add a payment method.',
|
|
139
|
-
)
|
|
119
|
+
);
|
|
140
120
|
}
|
|
141
121
|
}
|
|
142
122
|
|
|
143
|
-
throw new Error(JSON.stringify(error))
|
|
123
|
+
throw new Error(JSON.stringify(error));
|
|
144
124
|
}
|
|
145
125
|
|
|
146
126
|
if (!data) {
|
|
147
|
-
throw new Error('No data received from server')
|
|
127
|
+
throw new Error('No data received from server');
|
|
148
128
|
}
|
|
149
129
|
|
|
150
|
-
return data
|
|
130
|
+
return data;
|
|
151
131
|
} catch (error) {
|
|
152
|
-
console.error('Failed to create API key:', error)
|
|
132
|
+
console.error('Failed to create API key:', error);
|
|
153
133
|
|
|
154
134
|
// Add additional context for common issues
|
|
155
135
|
if (error instanceof Error) {
|
|
156
136
|
if (error.message.includes('ECONNREFUSED')) {
|
|
157
|
-
throw new Error(
|
|
158
|
-
'Cannot connect to Berget API. Please check your internet connection.',
|
|
159
|
-
)
|
|
137
|
+
throw new Error('Cannot connect to Berget API. Please check your internet connection.');
|
|
160
138
|
}
|
|
161
139
|
|
|
162
140
|
if (error.message.includes('ENOTFOUND')) {
|
|
163
|
-
throw new Error(
|
|
164
|
-
'Cannot resolve Berget API hostname. Please check your DNS settings.',
|
|
165
|
-
)
|
|
141
|
+
throw new Error('Cannot resolve Berget API hostname. Please check your DNS settings.');
|
|
166
142
|
}
|
|
167
143
|
|
|
168
|
-
if (
|
|
169
|
-
|
|
170
|
-
error.message.includes('Unauthorized')
|
|
171
|
-
) {
|
|
172
|
-
throw new Error(
|
|
173
|
-
'Authentication failed. Please run `berget auth login` to log in again.',
|
|
174
|
-
)
|
|
144
|
+
if (error.message.includes('401') || error.message.includes('Unauthorized')) {
|
|
145
|
+
throw new Error('Authentication failed. Please run `berget auth login` to log in again.');
|
|
175
146
|
}
|
|
176
147
|
|
|
177
148
|
if (error.message.includes('403')) {
|
|
178
149
|
throw new Error(
|
|
179
150
|
'Access forbidden. Your account may not have permission to create API keys.',
|
|
180
|
-
)
|
|
151
|
+
);
|
|
181
152
|
}
|
|
182
153
|
}
|
|
183
154
|
|
|
184
|
-
throw error
|
|
155
|
+
throw error;
|
|
185
156
|
}
|
|
186
157
|
}
|
|
187
158
|
|
|
@@ -193,49 +164,61 @@ export class ApiKeyService {
|
|
|
193
164
|
try {
|
|
194
165
|
const { error } = await this.client.DELETE('/v1/api-keys/{id}', {
|
|
195
166
|
params: { path: { id } },
|
|
196
|
-
})
|
|
197
|
-
if (error) throw new Error(JSON.stringify(error))
|
|
198
|
-
return true
|
|
167
|
+
});
|
|
168
|
+
if (error) throw new Error(JSON.stringify(error));
|
|
169
|
+
return true;
|
|
199
170
|
} catch (error) {
|
|
200
|
-
console.error('Failed to delete API key:', error)
|
|
201
|
-
throw error
|
|
171
|
+
console.error('Failed to delete API key:', error);
|
|
172
|
+
throw error;
|
|
202
173
|
}
|
|
203
174
|
}
|
|
204
175
|
|
|
205
176
|
/**
|
|
206
|
-
*
|
|
207
|
-
* Command: berget api-keys
|
|
177
|
+
* Get usage statistics for an API key
|
|
178
|
+
* Command: berget api-keys describe
|
|
208
179
|
*/
|
|
209
|
-
public async
|
|
180
|
+
public async describe(id: string): Promise<any> {
|
|
210
181
|
try {
|
|
211
|
-
const { data, error } = await this.client.
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
)
|
|
217
|
-
if (error) throw new Error(JSON.stringify(error))
|
|
218
|
-
return data!
|
|
182
|
+
const { data, error } = await this.client.GET('/v1/api-keys/{id}/usage', {
|
|
183
|
+
params: { path: { id } },
|
|
184
|
+
});
|
|
185
|
+
if (error) throw new Error(JSON.stringify(error));
|
|
186
|
+
return data;
|
|
219
187
|
} catch (error) {
|
|
220
|
-
console.error('Failed to
|
|
221
|
-
throw error
|
|
188
|
+
console.error('Failed to get API key usage:', error);
|
|
189
|
+
throw error;
|
|
222
190
|
}
|
|
223
191
|
}
|
|
224
192
|
|
|
225
193
|
/**
|
|
226
|
-
*
|
|
227
|
-
* Command: berget api-keys
|
|
194
|
+
* List all API keys
|
|
195
|
+
* Command: berget api-keys list
|
|
228
196
|
*/
|
|
229
|
-
public async
|
|
197
|
+
public async list(): Promise<ApiKey[]> {
|
|
230
198
|
try {
|
|
231
|
-
const { data, error } = await this.client.GET('/v1/api-keys
|
|
199
|
+
const { data, error } = await this.client.GET('/v1/api-keys');
|
|
200
|
+
if (error) throw error;
|
|
201
|
+
return data || [];
|
|
202
|
+
} catch (error) {
|
|
203
|
+
handleError('Failed to list API keys', error);
|
|
204
|
+
throw error;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Rotate an API key
|
|
210
|
+
* Command: berget api-keys rotate
|
|
211
|
+
*/
|
|
212
|
+
public async rotate(id: string): Promise<ApiKeyResponse> {
|
|
213
|
+
try {
|
|
214
|
+
const { data, error } = await this.client.PUT('/v1/api-keys/{id}/rotate', {
|
|
232
215
|
params: { path: { id } },
|
|
233
|
-
})
|
|
234
|
-
if (error) throw new Error(JSON.stringify(error))
|
|
235
|
-
return data
|
|
216
|
+
});
|
|
217
|
+
if (error) throw new Error(JSON.stringify(error));
|
|
218
|
+
return data!;
|
|
236
219
|
} catch (error) {
|
|
237
|
-
console.error('Failed to
|
|
238
|
-
throw error
|
|
220
|
+
console.error('Failed to rotate API key:', error);
|
|
221
|
+
throw error;
|
|
239
222
|
}
|
|
240
223
|
}
|
|
241
224
|
}
|