berget 2.2.7 → 2.2.9
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 +1 -1
- package/.prettierrc +5 -3
- package/dist/index.js +24 -25
- package/dist/package.json +7 -3
- package/dist/src/agents/app.js +8 -8
- package/dist/src/agents/backend.js +3 -3
- package/dist/src/agents/devops.js +8 -8
- package/dist/src/agents/frontend.js +3 -3
- package/dist/src/agents/fullstack.js +3 -3
- package/dist/src/agents/index.js +18 -18
- package/dist/src/agents/quality.js +8 -8
- package/dist/src/agents/security.js +8 -8
- package/dist/src/client.js +115 -127
- package/dist/src/commands/api-keys.js +181 -202
- package/dist/src/commands/auth.js +16 -25
- package/dist/src/commands/autocomplete.js +8 -8
- package/dist/src/commands/billing.js +10 -19
- package/dist/src/commands/chat.js +139 -170
- package/dist/src/commands/clusters.js +21 -30
- package/dist/src/commands/code/__tests__/auth-sync.test.js +189 -186
- package/dist/src/commands/code/__tests__/fake-api-key-service.js +3 -13
- package/dist/src/commands/code/__tests__/fake-auth-service.js +21 -29
- package/dist/src/commands/code/__tests__/fake-command-runner.js +22 -33
- package/dist/src/commands/code/__tests__/fake-file-store.js +19 -41
- package/dist/src/commands/code/__tests__/fake-prompter.js +81 -97
- package/dist/src/commands/code/__tests__/setup-flow.test.js +295 -295
- package/dist/src/commands/code/adapters/clack-prompter.js +15 -32
- package/dist/src/commands/code/adapters/fs-file-store.js +25 -44
- package/dist/src/commands/code/adapters/spawn-command-runner.js +27 -41
- package/dist/src/commands/code/auth-sync.js +215 -228
- package/dist/src/commands/code/errors.js +15 -12
- package/dist/src/commands/code/setup.js +390 -425
- package/dist/src/commands/code.js +279 -294
- package/dist/src/commands/index.js +5 -5
- package/dist/src/commands/models.js +16 -25
- package/dist/src/commands/users.js +9 -18
- package/dist/src/constants/command-structure.js +138 -138
- package/dist/src/services/api-key-service.js +132 -152
- package/dist/src/services/auth-service.js +81 -95
- package/dist/src/services/browser-auth.js +121 -131
- package/dist/src/services/chat-service.js +369 -386
- package/dist/src/services/cluster-service.js +47 -62
- package/dist/src/services/collaborator-service.js +9 -21
- package/dist/src/services/flux-service.js +13 -25
- package/dist/src/services/helm-service.js +9 -21
- package/dist/src/services/kubectl-service.js +15 -29
- package/dist/src/utils/config-checker.js +8 -8
- package/dist/src/utils/config-loader.js +109 -109
- package/dist/src/utils/default-api-key.js +129 -139
- package/dist/src/utils/env-manager.js +55 -66
- package/dist/src/utils/error-handler.js +62 -62
- package/dist/src/utils/logger.js +74 -67
- package/dist/src/utils/markdown-renderer.js +28 -28
- package/dist/src/utils/opencode-validator.js +67 -69
- package/dist/src/utils/token-manager.js +67 -65
- package/dist/tests/commands/chat.test.js +30 -39
- package/dist/tests/commands/code.test.js +186 -195
- package/dist/tests/utils/config-loader.test.js +107 -107
- package/dist/tests/utils/env-manager.test.js +81 -90
- package/dist/tests/utils/opencode-validator.test.js +42 -41
- package/dist/vitest.config.js +1 -1
- package/eslint.config.mjs +65 -30
- package/index.ts +30 -31
- package/package.json +7 -3
- package/src/agents/app.ts +9 -9
- package/src/agents/backend.ts +4 -4
- package/src/agents/devops.ts +9 -9
- package/src/agents/frontend.ts +4 -4
- package/src/agents/fullstack.ts +4 -4
- package/src/agents/index.ts +27 -25
- package/src/agents/quality.ts +9 -9
- package/src/agents/security.ts +9 -9
- package/src/agents/types.ts +10 -10
- package/src/client.ts +85 -77
- package/src/commands/api-keys.ts +180 -185
- package/src/commands/auth.ts +15 -14
- package/src/commands/autocomplete.ts +10 -10
- package/src/commands/billing.ts +13 -12
- package/src/commands/chat.ts +145 -142
- package/src/commands/clusters.ts +20 -19
- package/src/commands/code/__tests__/auth-sync.test.ts +176 -175
- package/src/commands/code/__tests__/fake-api-key-service.ts +2 -2
- package/src/commands/code/__tests__/fake-auth-service.ts +18 -18
- package/src/commands/code/__tests__/fake-command-runner.ts +28 -22
- package/src/commands/code/__tests__/fake-file-store.ts +15 -15
- package/src/commands/code/__tests__/fake-prompter.ts +86 -85
- package/src/commands/code/__tests__/setup-flow.test.ts +253 -251
- package/src/commands/code/adapters/clack-prompter.ts +32 -30
- package/src/commands/code/adapters/fs-file-store.ts +18 -17
- package/src/commands/code/adapters/spawn-command-runner.ts +20 -15
- package/src/commands/code/auth-sync.ts +210 -210
- package/src/commands/code/errors.ts +11 -11
- package/src/commands/code/ports/auth-services.ts +7 -7
- package/src/commands/code/ports/command-runner.ts +2 -2
- package/src/commands/code/ports/file-store.ts +3 -3
- package/src/commands/code/ports/prompter.ts +13 -13
- package/src/commands/code/setup.ts +408 -406
- package/src/commands/code.ts +288 -287
- package/src/commands/index.ts +11 -10
- package/src/commands/models.ts +19 -18
- package/src/commands/users.ts +11 -10
- package/src/constants/command-structure.ts +159 -159
- package/src/services/api-key-service.ts +85 -85
- package/src/services/auth-service.ts +55 -54
- package/src/services/browser-auth.ts +62 -62
- package/src/services/chat-service.ts +170 -171
- package/src/services/cluster-service.ts +28 -28
- package/src/services/collaborator-service.ts +6 -6
- package/src/services/flux-service.ts +17 -17
- package/src/services/helm-service.ts +11 -11
- package/src/services/kubectl-service.ts +12 -12
- package/src/types/api.d.ts +1933 -1933
- package/src/types/json.d.ts +1 -1
- package/src/utils/config-checker.ts +7 -7
- package/src/utils/config-loader.ts +130 -129
- package/src/utils/default-api-key.ts +81 -80
- package/src/utils/env-manager.ts +37 -37
- package/src/utils/error-handler.ts +64 -64
- package/src/utils/logger.ts +72 -66
- package/src/utils/markdown-renderer.ts +28 -28
- package/src/utils/opencode-validator.ts +72 -71
- package/src/utils/token-manager.ts +69 -68
- package/tests/commands/chat.test.ts +32 -31
- package/tests/commands/code.test.ts +182 -181
- package/tests/utils/config-loader.test.ts +111 -110
- package/tests/utils/env-manager.test.ts +83 -79
- package/tests/utils/opencode-validator.test.ts +43 -42
- package/tsconfig.json +2 -1
- package/vitest.config.ts +2 -2
|
@@ -1,194 +1,174 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
3
|
exports.ApiKeyService = void 0;
|
|
13
4
|
const client_1 = require("../client");
|
|
14
|
-
const error_handler_1 = require("../utils/error-handler");
|
|
15
5
|
const command_structure_1 = require("../constants/command-structure");
|
|
6
|
+
const error_handler_1 = require("../utils/error-handler");
|
|
16
7
|
/**
|
|
17
8
|
* Service for managing API keys
|
|
18
9
|
* Command group: api-keys
|
|
19
10
|
*/
|
|
20
11
|
class ApiKeyService {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
12
|
+
// Command group name for this service
|
|
13
|
+
static COMMAND_GROUP = command_structure_1.COMMAND_GROUPS.API_KEYS;
|
|
14
|
+
// Subcommands for this service
|
|
15
|
+
static COMMANDS = command_structure_1.SUBCOMMANDS.API_KEYS;
|
|
16
|
+
static instance;
|
|
17
|
+
client = (0, client_1.createAuthenticatedClient)();
|
|
18
|
+
constructor() { }
|
|
24
19
|
static getInstance() {
|
|
25
20
|
if (!ApiKeyService.instance) {
|
|
26
21
|
ApiKeyService.instance = new ApiKeyService();
|
|
27
22
|
}
|
|
28
23
|
return ApiKeyService.instance;
|
|
29
24
|
}
|
|
30
|
-
/**
|
|
31
|
-
* List all API keys
|
|
32
|
-
* Command: berget api-keys list
|
|
33
|
-
*/
|
|
34
|
-
list() {
|
|
35
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
36
|
-
try {
|
|
37
|
-
const { data, error } = yield this.client.GET("/v1/api-keys");
|
|
38
|
-
if (error)
|
|
39
|
-
throw error;
|
|
40
|
-
return data || [];
|
|
41
|
-
}
|
|
42
|
-
catch (error) {
|
|
43
|
-
(0, error_handler_1.handleError)("Failed to list API keys", error);
|
|
44
|
-
throw error;
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
25
|
/**
|
|
49
26
|
* Create a new API key
|
|
50
27
|
* Command: berget api-keys create
|
|
51
28
|
*/
|
|
52
|
-
create(options) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
if (options.description && options.description.length > 500) {
|
|
64
|
-
throw new Error("API key description must be 500 characters or less");
|
|
65
|
-
}
|
|
66
|
-
const { data, error } = yield this.client.POST("/v1/api-keys", {
|
|
67
|
-
body: options,
|
|
68
|
-
});
|
|
69
|
-
if (error) {
|
|
70
|
-
// Enhanced error handling with specific troubleshooting
|
|
71
|
-
// Handle specific error cases
|
|
72
|
-
if (typeof error === "object" && error !== null) {
|
|
73
|
-
const errorObj = error;
|
|
74
|
-
if (((_a = errorObj.error) === null || _a === void 0 ? void 0 : _a.code) === "API_KEY_CREATION_FAILED") {
|
|
75
|
-
let detailedMessage = "Failed to create API key. This could be due to:\n";
|
|
76
|
-
detailedMessage += "• Account limits or quota restrictions\n";
|
|
77
|
-
detailedMessage += "• Insufficient permissions for API key creation\n";
|
|
78
|
-
detailedMessage += "• Temporary server issues\n";
|
|
79
|
-
detailedMessage += "• Billing or subscription issues\n\n";
|
|
80
|
-
detailedMessage += "Troubleshooting steps:\n";
|
|
81
|
-
detailedMessage += "1. Check if you have reached your API key limit\n";
|
|
82
|
-
detailedMessage += "2. Verify your account has API key creation permissions\n";
|
|
83
|
-
detailedMessage += "3. Check your billing status and subscription\n";
|
|
84
|
-
detailedMessage += "4. Try again in a few minutes if this is a temporary issue\n";
|
|
85
|
-
detailedMessage += "5. Contact support if the problem persists";
|
|
86
|
-
throw new Error(detailedMessage);
|
|
87
|
-
}
|
|
88
|
-
if (((_b = errorObj.error) === null || _b === void 0 ? void 0 : _b.code) === "USER_NOT_FOUND") {
|
|
89
|
-
throw new Error("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");
|
|
90
|
-
}
|
|
91
|
-
if (((_c = errorObj.error) === null || _c === void 0 ? void 0 : _c.code) === "QUOTA_EXCEEDED") {
|
|
92
|
-
throw new Error("You have reached your API key limit. Please delete existing keys or contact support to increase your quota.");
|
|
93
|
-
}
|
|
94
|
-
if (((_d = errorObj.error) === null || _d === void 0 ? void 0 : _d.code) === "INSUFFICIENT_PERMISSIONS") {
|
|
95
|
-
throw new Error("Your account does not have permission to create API keys. Please contact your administrator.");
|
|
96
|
-
}
|
|
97
|
-
if (((_e = errorObj.error) === null || _e === void 0 ? void 0 : _e.code) === "BILLING_REQUIRED") {
|
|
98
|
-
throw new Error("A valid billing method is required to create API keys. Please add a payment method.");
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
throw new Error(JSON.stringify(error));
|
|
102
|
-
}
|
|
103
|
-
if (!data) {
|
|
104
|
-
throw new Error("No data received from server");
|
|
105
|
-
}
|
|
106
|
-
return data;
|
|
29
|
+
async create(options) {
|
|
30
|
+
try {
|
|
31
|
+
// Validate input before sending request
|
|
32
|
+
if (!options.name || options.name.trim().length === 0) {
|
|
33
|
+
throw new Error('API key name is required and cannot be empty');
|
|
34
|
+
}
|
|
35
|
+
if (options.name.length > 100) {
|
|
36
|
+
throw new Error('API key name must be 100 characters or less');
|
|
37
|
+
}
|
|
38
|
+
if (options.description && options.description.length > 500) {
|
|
39
|
+
throw new Error('API key description must be 500 characters or less');
|
|
107
40
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
41
|
+
const { data, error } = await this.client.POST('/v1/api-keys', {
|
|
42
|
+
body: options,
|
|
43
|
+
});
|
|
44
|
+
if (error) {
|
|
45
|
+
// Enhanced error handling with specific troubleshooting
|
|
46
|
+
// Handle specific error cases
|
|
47
|
+
if (typeof error === 'object' && error !== null) {
|
|
48
|
+
const errorObject = error;
|
|
49
|
+
if (errorObject.error?.code === 'API_KEY_CREATION_FAILED') {
|
|
50
|
+
let detailedMessage = 'Failed to create API key. This could be due to:\n';
|
|
51
|
+
detailedMessage += '• Account limits or quota restrictions\n';
|
|
52
|
+
detailedMessage += '• Insufficient permissions for API key creation\n';
|
|
53
|
+
detailedMessage += '• Temporary server issues\n';
|
|
54
|
+
detailedMessage += '• Billing or subscription issues\n\n';
|
|
55
|
+
detailedMessage += 'Troubleshooting steps:\n';
|
|
56
|
+
detailedMessage += '1. Check if you have reached your API key limit\n';
|
|
57
|
+
detailedMessage += '2. Verify your account has API key creation permissions\n';
|
|
58
|
+
detailedMessage += '3. Check your billing status and subscription\n';
|
|
59
|
+
detailedMessage += '4. Try again in a few minutes if this is a temporary issue\n';
|
|
60
|
+
detailedMessage += '5. Contact support if the problem persists';
|
|
61
|
+
throw new Error(detailedMessage);
|
|
114
62
|
}
|
|
115
|
-
if (error
|
|
116
|
-
throw new Error(
|
|
63
|
+
if (errorObject.error?.code === 'USER_NOT_FOUND') {
|
|
64
|
+
throw new Error('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');
|
|
117
65
|
}
|
|
118
|
-
if (error
|
|
119
|
-
throw new Error(
|
|
66
|
+
if (errorObject.error?.code === 'QUOTA_EXCEEDED') {
|
|
67
|
+
throw new Error('You have reached your API key limit. Please delete existing keys or contact support to increase your quota.');
|
|
120
68
|
}
|
|
121
|
-
if (error
|
|
122
|
-
throw new Error(
|
|
69
|
+
if (errorObject.error?.code === 'INSUFFICIENT_PERMISSIONS') {
|
|
70
|
+
throw new Error('Your account does not have permission to create API keys. Please contact your administrator.');
|
|
71
|
+
}
|
|
72
|
+
if (errorObject.error?.code === 'BILLING_REQUIRED') {
|
|
73
|
+
throw new Error('A valid billing method is required to create API keys. Please add a payment method.');
|
|
123
74
|
}
|
|
124
75
|
}
|
|
125
|
-
throw error;
|
|
76
|
+
throw new Error(JSON.stringify(error));
|
|
77
|
+
}
|
|
78
|
+
if (!data) {
|
|
79
|
+
throw new Error('No data received from server');
|
|
126
80
|
}
|
|
127
|
-
|
|
81
|
+
return data;
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
console.error('Failed to create API key:', error);
|
|
85
|
+
// Add additional context for common issues
|
|
86
|
+
if (error instanceof Error) {
|
|
87
|
+
if (error.message.includes('ECONNREFUSED')) {
|
|
88
|
+
throw new Error('Cannot connect to Berget API. Please check your internet connection.');
|
|
89
|
+
}
|
|
90
|
+
if (error.message.includes('ENOTFOUND')) {
|
|
91
|
+
throw new Error('Cannot resolve Berget API hostname. Please check your DNS settings.');
|
|
92
|
+
}
|
|
93
|
+
if (error.message.includes('401') || error.message.includes('Unauthorized')) {
|
|
94
|
+
throw new Error('Authentication failed. Please run `berget auth login` to log in again.');
|
|
95
|
+
}
|
|
96
|
+
if (error.message.includes('403')) {
|
|
97
|
+
throw new Error('Access forbidden. Your account may not have permission to create API keys.');
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
128
102
|
}
|
|
129
103
|
/**
|
|
130
104
|
* Delete an API key
|
|
131
105
|
* Command: berget api-keys delete
|
|
132
106
|
*/
|
|
133
|
-
delete(id) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
}
|
|
147
|
-
});
|
|
107
|
+
async delete(id) {
|
|
108
|
+
try {
|
|
109
|
+
const { error } = await this.client.DELETE('/v1/api-keys/{id}', {
|
|
110
|
+
params: { path: { id } },
|
|
111
|
+
});
|
|
112
|
+
if (error)
|
|
113
|
+
throw new Error(JSON.stringify(error));
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
console.error('Failed to delete API key:', error);
|
|
118
|
+
throw error;
|
|
119
|
+
}
|
|
148
120
|
}
|
|
149
121
|
/**
|
|
150
|
-
*
|
|
151
|
-
* Command: berget api-keys
|
|
122
|
+
* Get usage statistics for an API key
|
|
123
|
+
* Command: berget api-keys describe
|
|
152
124
|
*/
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
}
|
|
167
|
-
});
|
|
125
|
+
async describe(id) {
|
|
126
|
+
try {
|
|
127
|
+
const { data, error } = await this.client.GET('/v1/api-keys/{id}/usage', {
|
|
128
|
+
params: { path: { id } },
|
|
129
|
+
});
|
|
130
|
+
if (error)
|
|
131
|
+
throw new Error(JSON.stringify(error));
|
|
132
|
+
return data;
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
console.error('Failed to get API key usage:', error);
|
|
136
|
+
throw error;
|
|
137
|
+
}
|
|
168
138
|
}
|
|
169
139
|
/**
|
|
170
|
-
*
|
|
171
|
-
* Command: berget api-keys
|
|
140
|
+
* List all API keys
|
|
141
|
+
* Command: berget api-keys list
|
|
172
142
|
*/
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
params: { path: { id } },
|
|
178
|
-
});
|
|
179
|
-
if (error)
|
|
180
|
-
throw new Error(JSON.stringify(error));
|
|
181
|
-
return data;
|
|
182
|
-
}
|
|
183
|
-
catch (error) {
|
|
184
|
-
console.error("Failed to get API key usage:", error);
|
|
143
|
+
async list() {
|
|
144
|
+
try {
|
|
145
|
+
const { data, error } = await this.client.GET('/v1/api-keys');
|
|
146
|
+
if (error)
|
|
185
147
|
throw error;
|
|
186
|
-
|
|
187
|
-
}
|
|
148
|
+
return data || [];
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
(0, error_handler_1.handleError)('Failed to list API keys', error);
|
|
152
|
+
throw error;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Rotate an API key
|
|
157
|
+
* Command: berget api-keys rotate
|
|
158
|
+
*/
|
|
159
|
+
async rotate(id) {
|
|
160
|
+
try {
|
|
161
|
+
const { data, error } = await this.client.PUT('/v1/api-keys/{id}/rotate', {
|
|
162
|
+
params: { path: { id } },
|
|
163
|
+
});
|
|
164
|
+
if (error)
|
|
165
|
+
throw new Error(JSON.stringify(error));
|
|
166
|
+
return data;
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
console.error('Failed to rotate API key:', error);
|
|
170
|
+
throw error;
|
|
171
|
+
}
|
|
188
172
|
}
|
|
189
173
|
}
|
|
190
174
|
exports.ApiKeyService = ApiKeyService;
|
|
191
|
-
// Command group name for this service
|
|
192
|
-
ApiKeyService.COMMAND_GROUP = command_structure_1.COMMAND_GROUPS.API_KEYS;
|
|
193
|
-
// Subcommands for this service
|
|
194
|
-
ApiKeyService.COMMANDS = command_structure_1.SUBCOMMANDS.API_KEYS;
|
|
@@ -1,44 +1,31 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
4
|
};
|
|
14
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
6
|
exports.AuthService = void 0;
|
|
16
|
-
const client_1 = require("../client");
|
|
17
7
|
const chalk_1 = __importDefault(require("chalk"));
|
|
18
|
-
const
|
|
8
|
+
const client_1 = require("../client");
|
|
19
9
|
const command_structure_1 = require("../constants/command-structure");
|
|
10
|
+
const error_handler_1 = require("../utils/error-handler");
|
|
20
11
|
const browser_auth_1 = require("./browser-auth");
|
|
21
12
|
// Keycloak configuration based on environment
|
|
22
|
-
const isStageMode = process.argv.includes(
|
|
23
|
-
const isLocalMode = process.argv.includes(
|
|
24
|
-
const KEYCLOAK_URL = isStageMode || isLocalMode ?
|
|
25
|
-
const KEYCLOAK_REALM =
|
|
26
|
-
const KEYCLOAK_CLIENT_ID =
|
|
13
|
+
const isStageMode = process.argv.includes('--stage');
|
|
14
|
+
const isLocalMode = process.argv.includes('--local');
|
|
15
|
+
const KEYCLOAK_URL = isStageMode || isLocalMode ? 'https://keycloak.stage.berget.ai' : 'https://keycloak.berget.ai';
|
|
16
|
+
const KEYCLOAK_REALM = 'berget';
|
|
17
|
+
const KEYCLOAK_CLIENT_ID = 'berget-code';
|
|
27
18
|
const CALLBACK_PORT = 8787;
|
|
28
|
-
function makeBrowserAuth(debug) {
|
|
29
|
-
return new browser_auth_1.BrowserAuth({
|
|
30
|
-
keycloakUrl: KEYCLOAK_URL,
|
|
31
|
-
realm: KEYCLOAK_REALM,
|
|
32
|
-
clientId: KEYCLOAK_CLIENT_ID,
|
|
33
|
-
callbackPort: CALLBACK_PORT,
|
|
34
|
-
debug,
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
19
|
/**
|
|
38
20
|
* Service for authentication operations
|
|
39
21
|
* Command group: auth
|
|
40
22
|
*/
|
|
41
23
|
class AuthService {
|
|
24
|
+
// Command group name for this service
|
|
25
|
+
static COMMAND_GROUP = command_structure_1.COMMAND_GROUPS.AUTH;
|
|
26
|
+
// Subcommands for this service
|
|
27
|
+
static COMMANDS = command_structure_1.SUBCOMMANDS.AUTH;
|
|
28
|
+
static instance;
|
|
42
29
|
constructor() { }
|
|
43
30
|
static getInstance() {
|
|
44
31
|
if (!AuthService.instance) {
|
|
@@ -46,93 +33,92 @@ class AuthService {
|
|
|
46
33
|
}
|
|
47
34
|
return AuthService.instance;
|
|
48
35
|
}
|
|
49
|
-
whoami() {
|
|
50
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
51
|
-
try {
|
|
52
|
-
// Create fresh client to ensure we have the latest token
|
|
53
|
-
const client = (0, client_1.createAuthenticatedClient)();
|
|
54
|
-
const { data: profile, error } = yield client.GET("/v1/users/me");
|
|
55
|
-
if (error) {
|
|
56
|
-
return null;
|
|
57
|
-
}
|
|
58
|
-
return profile;
|
|
59
|
-
}
|
|
60
|
-
catch (_a) {
|
|
61
|
-
return null;
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
36
|
/**
|
|
66
37
|
* Browser-based PKCE login for interactive CLI use.
|
|
67
38
|
* Prints status to stdout/stderr. Use loginInteractive() when you need
|
|
68
39
|
* a silent, UI-agnostic result (e.g. inside the setup wizard).
|
|
69
40
|
*/
|
|
70
|
-
login() {
|
|
71
|
-
|
|
41
|
+
async login() {
|
|
42
|
+
try {
|
|
43
|
+
(0, client_1.clearAuthToken)();
|
|
44
|
+
console.log(chalk_1.default.blue('Initiating login process...'));
|
|
45
|
+
const auth = makeBrowserAuth(process.argv.includes('--debug'));
|
|
46
|
+
const result = await auth.start();
|
|
47
|
+
if (!result.success) {
|
|
48
|
+
console.log(chalk_1.default.red(`\nAuthentication failed: ${result.error || 'Unknown error'}`));
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
(0, client_1.saveAuthToken)(result.accessToken, result.refreshToken, result.expiresIn);
|
|
52
|
+
if (process.argv.includes('--debug')) {
|
|
53
|
+
console.log(chalk_1.default.yellow('DEBUG: Token data received:'));
|
|
54
|
+
console.log(chalk_1.default.yellow(JSON.stringify({
|
|
55
|
+
expires_in: result.expiresIn,
|
|
56
|
+
}, null, 2)));
|
|
57
|
+
}
|
|
58
|
+
console.log(chalk_1.default.green('\n✓ Successfully logged in to Berget'));
|
|
72
59
|
try {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const result = yield auth.start();
|
|
77
|
-
if (!result.success) {
|
|
78
|
-
console.log(chalk_1.default.red(`\nAuthentication failed: ${result.error || "Unknown error"}`));
|
|
79
|
-
return false;
|
|
60
|
+
const profile = await this.whoami();
|
|
61
|
+
if (profile?.email) {
|
|
62
|
+
console.log(chalk_1.default.green(`Logged in as ${profile.name || profile.email}`));
|
|
80
63
|
}
|
|
81
|
-
(0, client_1.saveAuthToken)(result.accessToken, result.refreshToken, result.expiresIn);
|
|
82
|
-
if (process.argv.includes("--debug")) {
|
|
83
|
-
console.log(chalk_1.default.yellow("DEBUG: Token data received:"));
|
|
84
|
-
console.log(chalk_1.default.yellow(JSON.stringify({
|
|
85
|
-
expires_in: result.expiresIn,
|
|
86
|
-
}, null, 2)));
|
|
87
|
-
}
|
|
88
|
-
console.log(chalk_1.default.green("\n✓ Successfully logged in to Berget"));
|
|
89
|
-
try {
|
|
90
|
-
const profile = yield this.whoami();
|
|
91
|
-
if (profile === null || profile === void 0 ? void 0 : profile.email) {
|
|
92
|
-
console.log(chalk_1.default.green(`Logged in as ${profile.name || profile.email}`));
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
catch (_a) {
|
|
96
|
-
// Ignore errors fetching profile
|
|
97
|
-
}
|
|
98
|
-
console.log(chalk_1.default.cyan("\nNext steps:"));
|
|
99
|
-
console.log(chalk_1.default.cyan(" • Create an API key: berget api-keys create"));
|
|
100
|
-
console.log(chalk_1.default.cyan(" • Setup OpenCode: berget code init"));
|
|
101
|
-
return true;
|
|
102
64
|
}
|
|
103
|
-
catch
|
|
104
|
-
|
|
105
|
-
return false;
|
|
65
|
+
catch {
|
|
66
|
+
// Ignore errors fetching profile
|
|
106
67
|
}
|
|
107
|
-
|
|
68
|
+
console.log(chalk_1.default.cyan('\nNext steps:'));
|
|
69
|
+
console.log(chalk_1.default.cyan(' • Create an API key: berget api-keys create'));
|
|
70
|
+
console.log(chalk_1.default.cyan(' • Setup OpenCode: berget code init'));
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
(0, error_handler_1.handleError)('Login failed', error);
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
108
77
|
}
|
|
109
78
|
/**
|
|
110
79
|
* Browser-based PKCE login for wizard / programmatic use.
|
|
111
80
|
* Does NOT print to stdout — returns tokens so callers can display
|
|
112
81
|
* their own UI (e.g. via clack/prompts).
|
|
113
82
|
*/
|
|
114
|
-
loginInteractive() {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
(0, client_1.saveAuthToken)(result.accessToken, result.refreshToken, result.expiresIn);
|
|
122
|
-
}
|
|
123
|
-
return result;
|
|
83
|
+
async loginInteractive() {
|
|
84
|
+
try {
|
|
85
|
+
(0, client_1.clearAuthToken)();
|
|
86
|
+
const auth = makeBrowserAuth(process.argv.includes('--debug'));
|
|
87
|
+
const result = await auth.start();
|
|
88
|
+
if (result.success) {
|
|
89
|
+
(0, client_1.saveAuthToken)(result.accessToken, result.refreshToken, result.expiresIn);
|
|
124
90
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
return {
|
|
95
|
+
error: error instanceof Error ? error.message : String(error),
|
|
96
|
+
success: false,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async whoami() {
|
|
101
|
+
try {
|
|
102
|
+
// Create fresh client to ensure we have the latest token
|
|
103
|
+
const client = (0, client_1.createAuthenticatedClient)();
|
|
104
|
+
const { data: profile, error } = await client.GET('/v1/users/me');
|
|
105
|
+
if (error) {
|
|
106
|
+
return null;
|
|
130
107
|
}
|
|
131
|
-
|
|
108
|
+
return profile;
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
132
113
|
}
|
|
133
114
|
}
|
|
134
115
|
exports.AuthService = AuthService;
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
116
|
+
function makeBrowserAuth(debug) {
|
|
117
|
+
return new browser_auth_1.BrowserAuth({
|
|
118
|
+
callbackPort: CALLBACK_PORT,
|
|
119
|
+
clientId: KEYCLOAK_CLIENT_ID,
|
|
120
|
+
debug,
|
|
121
|
+
keycloakUrl: KEYCLOAK_URL,
|
|
122
|
+
realm: KEYCLOAK_REALM,
|
|
123
|
+
});
|
|
124
|
+
}
|