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
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
import { createAuthenticatedClient } from
|
|
2
|
-
import { handleError } from
|
|
3
|
-
import { COMMAND_GROUPS, SUBCOMMANDS } from
|
|
1
|
+
import { createAuthenticatedClient } from "../client";
|
|
2
|
+
import { handleError } from "../utils/error-handler";
|
|
3
|
+
import { COMMAND_GROUPS, SUBCOMMANDS } from "../constants/command-structure";
|
|
4
4
|
|
|
5
5
|
export interface ApiKey {
|
|
6
|
-
id: number
|
|
7
|
-
name: string
|
|
8
|
-
description: string | null
|
|
9
|
-
created: string
|
|
10
|
-
lastUsed: string | null
|
|
11
|
-
prefix: string
|
|
12
|
-
active: boolean
|
|
13
|
-
modified: string
|
|
6
|
+
id: number;
|
|
7
|
+
name: string;
|
|
8
|
+
description: string | null;
|
|
9
|
+
created: string;
|
|
10
|
+
lastUsed: string | null;
|
|
11
|
+
prefix: string;
|
|
12
|
+
active: boolean;
|
|
13
|
+
modified: string;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export interface CreateApiKeyOptions {
|
|
17
|
-
name: string
|
|
18
|
-
description?: string
|
|
17
|
+
name: string;
|
|
18
|
+
description?: string;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
export interface ApiKeyResponse {
|
|
22
|
-
id: number
|
|
23
|
-
name: string
|
|
24
|
-
description: string | null
|
|
25
|
-
key: string
|
|
26
|
-
created: string
|
|
22
|
+
id: number;
|
|
23
|
+
name: string;
|
|
24
|
+
description: string | null;
|
|
25
|
+
key: string;
|
|
26
|
+
created: string;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
/**
|
|
@@ -31,22 +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()
|
|
34
|
+
private static instance: ApiKeyService;
|
|
35
|
+
private client = createAuthenticatedClient();
|
|
36
36
|
|
|
37
37
|
// Command group name for this service
|
|
38
|
-
public static readonly COMMAND_GROUP = COMMAND_GROUPS.API_KEYS
|
|
38
|
+
public static readonly COMMAND_GROUP = COMMAND_GROUPS.API_KEYS;
|
|
39
39
|
|
|
40
40
|
// Subcommands for this service
|
|
41
|
-
public static readonly COMMANDS = SUBCOMMANDS.API_KEYS
|
|
41
|
+
public static readonly COMMANDS = SUBCOMMANDS.API_KEYS;
|
|
42
42
|
|
|
43
43
|
private constructor() {}
|
|
44
44
|
|
|
45
45
|
public static getInstance(): ApiKeyService {
|
|
46
46
|
if (!ApiKeyService.instance) {
|
|
47
|
-
ApiKeyService.instance = new ApiKeyService()
|
|
47
|
+
ApiKeyService.instance = new ApiKeyService();
|
|
48
48
|
}
|
|
49
|
-
return ApiKeyService.instance
|
|
49
|
+
return ApiKeyService.instance;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
/**
|
|
@@ -55,12 +55,12 @@ export class ApiKeyService {
|
|
|
55
55
|
*/
|
|
56
56
|
public async list(): Promise<ApiKey[]> {
|
|
57
57
|
try {
|
|
58
|
-
const { data, error } = await this.client.GET(
|
|
59
|
-
if (error) throw error
|
|
60
|
-
return data || []
|
|
58
|
+
const { data, error } = await this.client.GET("/v1/api-keys");
|
|
59
|
+
if (error) throw error;
|
|
60
|
+
return data || [];
|
|
61
61
|
} catch (error) {
|
|
62
|
-
handleError(
|
|
63
|
-
throw error
|
|
62
|
+
handleError("Failed to list API keys", error);
|
|
63
|
+
throw error;
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
|
|
@@ -72,116 +72,102 @@ export class ApiKeyService {
|
|
|
72
72
|
try {
|
|
73
73
|
// Validate input before sending request
|
|
74
74
|
if (!options.name || options.name.trim().length === 0) {
|
|
75
|
-
throw new Error(
|
|
75
|
+
throw new Error("API key name is required and cannot be empty");
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
if (options.name.length > 100) {
|
|
79
|
-
throw new Error(
|
|
79
|
+
throw new Error("API key name must be 100 characters or less");
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
if (options.description && options.description.length > 500) {
|
|
83
|
-
throw new Error(
|
|
83
|
+
throw new Error("API key description must be 500 characters or less");
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
const { data, error } = await this.client.POST(
|
|
86
|
+
const { data, error } = await this.client.POST("/v1/api-keys", {
|
|
87
87
|
body: options,
|
|
88
|
-
})
|
|
88
|
+
});
|
|
89
89
|
|
|
90
90
|
if (error) {
|
|
91
91
|
// Enhanced error handling with specific troubleshooting
|
|
92
92
|
|
|
93
93
|
// Handle specific error cases
|
|
94
|
-
if (typeof error ===
|
|
95
|
-
const errorObj = error as any
|
|
96
|
-
|
|
97
|
-
if (errorObj.error?.code ===
|
|
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)
|
|
94
|
+
if (typeof error === "object" && error !== null) {
|
|
95
|
+
const errorObj = error as any;
|
|
96
|
+
|
|
97
|
+
if (errorObj.error?.code === "API_KEY_CREATION_FAILED") {
|
|
98
|
+
let detailedMessage = "Failed to create API key. This could be due to:\n";
|
|
99
|
+
detailedMessage += "• Account limits or quota restrictions\n";
|
|
100
|
+
detailedMessage += "• Insufficient permissions for API key creation\n";
|
|
101
|
+
detailedMessage += "• Temporary server issues\n";
|
|
102
|
+
detailedMessage += "• Billing or subscription issues\n\n";
|
|
103
|
+
detailedMessage += "Troubleshooting steps:\n";
|
|
104
|
+
detailedMessage += "1. Check if you have reached your API key limit\n";
|
|
105
|
+
detailedMessage += "2. Verify your account has API key creation permissions\n";
|
|
106
|
+
detailedMessage += "3. Check your billing status and subscription\n";
|
|
107
|
+
detailedMessage += "4. Try again in a few minutes if this is a temporary issue\n";
|
|
108
|
+
detailedMessage += "5. Contact support if the problem persists";
|
|
109
|
+
|
|
110
|
+
throw new Error(detailedMessage);
|
|
116
111
|
}
|
|
117
112
|
|
|
118
|
-
if (errorObj.error?.code ===
|
|
113
|
+
if (errorObj.error?.code === "USER_NOT_FOUND") {
|
|
119
114
|
throw new Error(
|
|
120
|
-
|
|
121
|
-
)
|
|
115
|
+
"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"
|
|
116
|
+
);
|
|
122
117
|
}
|
|
123
118
|
|
|
124
|
-
if (errorObj.error?.code ===
|
|
119
|
+
if (errorObj.error?.code === "QUOTA_EXCEEDED") {
|
|
125
120
|
throw new Error(
|
|
126
|
-
|
|
127
|
-
)
|
|
121
|
+
"You have reached your API key limit. Please delete existing keys or contact support to increase your quota."
|
|
122
|
+
);
|
|
128
123
|
}
|
|
129
124
|
|
|
130
|
-
if (errorObj.error?.code ===
|
|
125
|
+
if (errorObj.error?.code === "INSUFFICIENT_PERMISSIONS") {
|
|
131
126
|
throw new Error(
|
|
132
|
-
|
|
133
|
-
)
|
|
127
|
+
"Your account does not have permission to create API keys. Please contact your administrator."
|
|
128
|
+
);
|
|
134
129
|
}
|
|
135
130
|
|
|
136
|
-
if (errorObj.error?.code ===
|
|
131
|
+
if (errorObj.error?.code === "BILLING_REQUIRED") {
|
|
137
132
|
throw new Error(
|
|
138
|
-
|
|
139
|
-
)
|
|
133
|
+
"A valid billing method is required to create API keys. Please add a payment method."
|
|
134
|
+
);
|
|
140
135
|
}
|
|
141
136
|
}
|
|
142
137
|
|
|
143
|
-
throw new Error(JSON.stringify(error))
|
|
138
|
+
throw new Error(JSON.stringify(error));
|
|
144
139
|
}
|
|
145
140
|
|
|
146
141
|
if (!data) {
|
|
147
|
-
throw new Error(
|
|
142
|
+
throw new Error("No data received from server");
|
|
148
143
|
}
|
|
149
144
|
|
|
150
|
-
return data
|
|
145
|
+
return data;
|
|
151
146
|
} catch (error) {
|
|
152
|
-
console.error(
|
|
147
|
+
console.error("Failed to create API key:", error);
|
|
153
148
|
|
|
154
149
|
// Add additional context for common issues
|
|
155
150
|
if (error instanceof Error) {
|
|
156
|
-
if (error.message.includes(
|
|
157
|
-
throw new Error(
|
|
158
|
-
'Cannot connect to Berget API. Please check your internet connection.',
|
|
159
|
-
)
|
|
151
|
+
if (error.message.includes("ECONNREFUSED")) {
|
|
152
|
+
throw new Error("Cannot connect to Berget API. Please check your internet connection.");
|
|
160
153
|
}
|
|
161
154
|
|
|
162
|
-
if (error.message.includes(
|
|
163
|
-
throw new Error(
|
|
164
|
-
'Cannot resolve Berget API hostname. Please check your DNS settings.',
|
|
165
|
-
)
|
|
155
|
+
if (error.message.includes("ENOTFOUND")) {
|
|
156
|
+
throw new Error("Cannot resolve Berget API hostname. Please check your DNS settings.");
|
|
166
157
|
}
|
|
167
158
|
|
|
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
|
-
)
|
|
159
|
+
if (error.message.includes("401") || error.message.includes("Unauthorized")) {
|
|
160
|
+
throw new Error("Authentication failed. Please run `berget auth login` to log in again.");
|
|
175
161
|
}
|
|
176
162
|
|
|
177
|
-
if (error.message.includes(
|
|
163
|
+
if (error.message.includes("403")) {
|
|
178
164
|
throw new Error(
|
|
179
|
-
|
|
180
|
-
)
|
|
165
|
+
"Access forbidden. Your account may not have permission to create API keys."
|
|
166
|
+
);
|
|
181
167
|
}
|
|
182
168
|
}
|
|
183
169
|
|
|
184
|
-
throw error
|
|
170
|
+
throw error;
|
|
185
171
|
}
|
|
186
172
|
}
|
|
187
173
|
|
|
@@ -191,14 +177,14 @@ export class ApiKeyService {
|
|
|
191
177
|
*/
|
|
192
178
|
public async delete(id: string): Promise<boolean> {
|
|
193
179
|
try {
|
|
194
|
-
const { error } = await this.client.DELETE(
|
|
180
|
+
const { error } = await this.client.DELETE("/v1/api-keys/{id}", {
|
|
195
181
|
params: { path: { id } },
|
|
196
|
-
})
|
|
197
|
-
if (error) throw new Error(JSON.stringify(error))
|
|
198
|
-
return true
|
|
182
|
+
});
|
|
183
|
+
if (error) throw new Error(JSON.stringify(error));
|
|
184
|
+
return true;
|
|
199
185
|
} catch (error) {
|
|
200
|
-
console.error(
|
|
201
|
-
throw error
|
|
186
|
+
console.error("Failed to delete API key:", error);
|
|
187
|
+
throw error;
|
|
202
188
|
}
|
|
203
189
|
}
|
|
204
190
|
|
|
@@ -208,17 +194,14 @@ export class ApiKeyService {
|
|
|
208
194
|
*/
|
|
209
195
|
public async rotate(id: string): Promise<ApiKeyResponse> {
|
|
210
196
|
try {
|
|
211
|
-
const { data, error } = await this.client.PUT(
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
)
|
|
217
|
-
if (error) throw new Error(JSON.stringify(error))
|
|
218
|
-
return data!
|
|
197
|
+
const { data, error } = await this.client.PUT("/v1/api-keys/{id}/rotate", {
|
|
198
|
+
params: { path: { id } },
|
|
199
|
+
});
|
|
200
|
+
if (error) throw new Error(JSON.stringify(error));
|
|
201
|
+
return data!;
|
|
219
202
|
} catch (error) {
|
|
220
|
-
console.error(
|
|
221
|
-
throw error
|
|
203
|
+
console.error("Failed to rotate API key:", error);
|
|
204
|
+
throw error;
|
|
222
205
|
}
|
|
223
206
|
}
|
|
224
207
|
|
|
@@ -228,14 +211,14 @@ export class ApiKeyService {
|
|
|
228
211
|
*/
|
|
229
212
|
public async describe(id: string): Promise<any> {
|
|
230
213
|
try {
|
|
231
|
-
const { data, error } = await this.client.GET(
|
|
214
|
+
const { data, error } = await this.client.GET("/v1/api-keys/{id}/usage", {
|
|
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(
|
|
238
|
-
throw error
|
|
220
|
+
console.error("Failed to get API key usage:", error);
|
|
221
|
+
throw error;
|
|
239
222
|
}
|
|
240
223
|
}
|
|
241
224
|
}
|