berget 2.2.7 → 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 +6 -6
- package/.github/workflows/test.yml +1 -1
- package/.prettierrc +5 -3
- package/dist/index.js +24 -25
- package/dist/package.json +5 -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 +195 -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 +7 -7
- 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 +50 -30
- package/index.ts +30 -31
- package/package.json +5 -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 +190 -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 +169 -170
- 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 +6 -6
- 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
|
@@ -23,21 +23,17 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.getProviderModels = exports.getModelConfig = exports.
|
|
27
|
-
const fs = __importStar(require("fs"));
|
|
28
|
-
const path = __importStar(require("path"));
|
|
26
|
+
exports.getProviderModels = exports.getModelConfig = exports.getConfigLoader = exports.getAllAgentConfigs = exports.getAgentConfig = exports.ConfigLoader = void 0;
|
|
27
|
+
const fs = __importStar(require("node:fs"));
|
|
28
|
+
const path = __importStar(require("node:path"));
|
|
29
29
|
const logger_1 = require("./logger");
|
|
30
30
|
class ConfigLoader {
|
|
31
|
+
static instance;
|
|
32
|
+
config = null;
|
|
33
|
+
configPath;
|
|
31
34
|
constructor(configPath) {
|
|
32
|
-
this.config = null;
|
|
33
35
|
// Default to opencode.json in current working directory
|
|
34
|
-
this.configPath = configPath || path.join(process.cwd(),
|
|
35
|
-
}
|
|
36
|
-
static getInstance(configPath) {
|
|
37
|
-
if (!ConfigLoader.instance) {
|
|
38
|
-
ConfigLoader.instance = new ConfigLoader(configPath);
|
|
39
|
-
}
|
|
40
|
-
return ConfigLoader.instance;
|
|
36
|
+
this.configPath = configPath || path.join(process.cwd(), 'opencode.json');
|
|
41
37
|
}
|
|
42
38
|
/**
|
|
43
39
|
* Clear the singleton instance (for testing purposes)
|
|
@@ -45,41 +41,31 @@ class ConfigLoader {
|
|
|
45
41
|
static clearInstance() {
|
|
46
42
|
ConfigLoader.instance = null;
|
|
47
43
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
loadConfig() {
|
|
52
|
-
if (this.config) {
|
|
53
|
-
return this.config;
|
|
54
|
-
}
|
|
55
|
-
try {
|
|
56
|
-
if (!fs.existsSync(this.configPath)) {
|
|
57
|
-
throw new Error(`Configuration file not found: ${this.configPath}`);
|
|
58
|
-
}
|
|
59
|
-
const configContent = fs.readFileSync(this.configPath, "utf8");
|
|
60
|
-
this.config = JSON.parse(configContent);
|
|
61
|
-
logger_1.logger.debug(`Loaded configuration from ${this.configPath}`);
|
|
62
|
-
return this.config;
|
|
63
|
-
}
|
|
64
|
-
catch (error) {
|
|
65
|
-
logger_1.logger.error(`Failed to load configuration from ${this.configPath}:`, error);
|
|
66
|
-
throw new Error(`Failed to load configuration: ${error instanceof Error ? error.message : String(error)}`);
|
|
44
|
+
static getInstance(configPath) {
|
|
45
|
+
if (!ConfigLoader.instance) {
|
|
46
|
+
ConfigLoader.instance = new ConfigLoader(configPath);
|
|
67
47
|
}
|
|
48
|
+
return ConfigLoader.instance;
|
|
68
49
|
}
|
|
69
50
|
/**
|
|
70
51
|
* Get agent configuration by name
|
|
71
52
|
*/
|
|
72
53
|
getAgentConfig(agentName) {
|
|
73
|
-
var _a;
|
|
74
54
|
try {
|
|
75
55
|
const config = this.loadConfig();
|
|
76
|
-
return
|
|
56
|
+
return config.agent?.[agentName] || null;
|
|
77
57
|
}
|
|
78
|
-
catch
|
|
58
|
+
catch {
|
|
79
59
|
// Config file doesn't exist, return null
|
|
80
60
|
return null;
|
|
81
61
|
}
|
|
82
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Get list of all available agent names
|
|
65
|
+
*/
|
|
66
|
+
getAgentNames() {
|
|
67
|
+
return Object.keys(this.getAllAgentConfigs());
|
|
68
|
+
}
|
|
83
69
|
/**
|
|
84
70
|
* Get all agent configurations
|
|
85
71
|
*/
|
|
@@ -88,11 +74,30 @@ class ConfigLoader {
|
|
|
88
74
|
const config = this.loadConfig();
|
|
89
75
|
return config.agent || {};
|
|
90
76
|
}
|
|
91
|
-
catch
|
|
77
|
+
catch {
|
|
78
|
+
// Config file doesn't exist, return empty object
|
|
79
|
+
return {};
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Get command configurations
|
|
84
|
+
*/
|
|
85
|
+
getCommandConfigs() {
|
|
86
|
+
try {
|
|
87
|
+
const config = this.loadConfig();
|
|
88
|
+
return config.command || {};
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
92
91
|
// Config file doesn't exist, return empty object
|
|
93
92
|
return {};
|
|
94
93
|
}
|
|
95
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Get the current configuration path
|
|
97
|
+
*/
|
|
98
|
+
getConfigPath() {
|
|
99
|
+
return this.configPath;
|
|
100
|
+
}
|
|
96
101
|
/**
|
|
97
102
|
* Get model configuration
|
|
98
103
|
*/
|
|
@@ -100,65 +105,78 @@ class ConfigLoader {
|
|
|
100
105
|
try {
|
|
101
106
|
const config = this.loadConfig();
|
|
102
107
|
// Extract from config or fall back to defaults
|
|
103
|
-
const primary = config.model ||
|
|
104
|
-
const small = config.small_model ||
|
|
108
|
+
const primary = config.model || 'berget/glm-4.7';
|
|
109
|
+
const small = config.small_model || 'berget/gpt-oss';
|
|
105
110
|
return { primary, small };
|
|
106
111
|
}
|
|
107
|
-
catch
|
|
112
|
+
catch {
|
|
108
113
|
// Fallback to defaults when no config exists (init scenario)
|
|
109
114
|
return {
|
|
110
|
-
primary:
|
|
111
|
-
small:
|
|
115
|
+
primary: 'berget/glm-4.7',
|
|
116
|
+
small: 'berget/gpt-oss',
|
|
112
117
|
};
|
|
113
118
|
}
|
|
114
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Get list of primary agents (mode: 'primary')
|
|
122
|
+
*/
|
|
123
|
+
getPrimaryAgentNames() {
|
|
124
|
+
const agents = this.getAllAgentConfigs();
|
|
125
|
+
return Object.keys(agents).filter((name) => agents[name].mode === 'primary');
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Get provider configuration
|
|
129
|
+
*/
|
|
130
|
+
getProviderConfig() {
|
|
131
|
+
try {
|
|
132
|
+
const config = this.loadConfig();
|
|
133
|
+
return config.provider || {};
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
// Config file doesn't exist, return empty object
|
|
137
|
+
return {};
|
|
138
|
+
}
|
|
139
|
+
}
|
|
115
140
|
/**
|
|
116
141
|
* Get provider model configuration
|
|
117
142
|
*/
|
|
118
143
|
getProviderModels() {
|
|
119
|
-
var _a, _b;
|
|
120
144
|
try {
|
|
121
145
|
const config = this.loadConfig();
|
|
122
146
|
// Extract from provider configuration
|
|
123
|
-
if (
|
|
147
|
+
if (config.provider?.berget?.models) {
|
|
124
148
|
return config.provider.berget.models;
|
|
125
149
|
}
|
|
126
150
|
}
|
|
127
|
-
catch
|
|
151
|
+
catch {
|
|
128
152
|
// Config file doesn't exist, use fallback defaults
|
|
129
153
|
}
|
|
130
154
|
// Fallback to defaults
|
|
131
155
|
return {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
156
|
+
'glm-4.7': {
|
|
157
|
+
limit: { context: 90000, output: 4000 },
|
|
158
|
+
name: 'GLM-4.7',
|
|
135
159
|
},
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
limit: { output: 4000, context: 128000 },
|
|
160
|
+
'gpt-oss': {
|
|
161
|
+
limit: { context: 128000, output: 4000 },
|
|
139
162
|
modalities: {
|
|
140
|
-
input: [
|
|
141
|
-
output: [
|
|
163
|
+
input: ['text', 'image'],
|
|
164
|
+
output: ['text'],
|
|
142
165
|
},
|
|
166
|
+
name: 'GPT-OSS',
|
|
143
167
|
},
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
168
|
+
'llama-8b': {
|
|
169
|
+
limit: { context: 128000, output: 4000 },
|
|
170
|
+
name: 'llama-3.1-8b',
|
|
147
171
|
},
|
|
148
172
|
};
|
|
149
173
|
}
|
|
150
174
|
/**
|
|
151
|
-
* Get
|
|
175
|
+
* Get list of subagents (mode: 'subagent')
|
|
152
176
|
*/
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
return config.command || {};
|
|
157
|
-
}
|
|
158
|
-
catch (_a) {
|
|
159
|
-
// Config file doesn't exist, return empty object
|
|
160
|
-
return {};
|
|
161
|
-
}
|
|
177
|
+
getSubagentNames() {
|
|
178
|
+
const agents = this.getAllAgentConfigs();
|
|
179
|
+
return Object.keys(agents).filter((name) => agents[name].mode === 'subagent');
|
|
162
180
|
}
|
|
163
181
|
/**
|
|
164
182
|
* Get watcher configuration
|
|
@@ -167,25 +185,12 @@ class ConfigLoader {
|
|
|
167
185
|
try {
|
|
168
186
|
const config = this.loadConfig();
|
|
169
187
|
return (config.watcher || {
|
|
170
|
-
ignore: [
|
|
188
|
+
ignore: ['node_modules', 'dist', '.git', 'coverage'],
|
|
171
189
|
});
|
|
172
190
|
}
|
|
173
|
-
catch
|
|
191
|
+
catch {
|
|
174
192
|
// Config file doesn't exist, return default watcher config
|
|
175
|
-
return { ignore: [
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Get provider configuration
|
|
180
|
-
*/
|
|
181
|
-
getProviderConfig() {
|
|
182
|
-
try {
|
|
183
|
-
const config = this.loadConfig();
|
|
184
|
-
return config.provider || {};
|
|
185
|
-
}
|
|
186
|
-
catch (_a) {
|
|
187
|
-
// Config file doesn't exist, return empty object
|
|
188
|
-
return {};
|
|
193
|
+
return { ignore: ['node_modules', 'dist', '.git', 'coverage'] };
|
|
189
194
|
}
|
|
190
195
|
}
|
|
191
196
|
/**
|
|
@@ -195,24 +200,25 @@ class ConfigLoader {
|
|
|
195
200
|
return agentName in this.getAllAgentConfigs();
|
|
196
201
|
}
|
|
197
202
|
/**
|
|
198
|
-
*
|
|
199
|
-
*/
|
|
200
|
-
getAgentNames() {
|
|
201
|
-
return Object.keys(this.getAllAgentConfigs());
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* Get list of primary agents (mode: 'primary')
|
|
205
|
-
*/
|
|
206
|
-
getPrimaryAgentNames() {
|
|
207
|
-
const agents = this.getAllAgentConfigs();
|
|
208
|
-
return Object.keys(agents).filter(name => agents[name].mode === "primary");
|
|
209
|
-
}
|
|
210
|
-
/**
|
|
211
|
-
* Get list of subagents (mode: 'subagent')
|
|
203
|
+
* Load configuration from opencode.json
|
|
212
204
|
*/
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
205
|
+
loadConfig() {
|
|
206
|
+
if (this.config) {
|
|
207
|
+
return this.config;
|
|
208
|
+
}
|
|
209
|
+
try {
|
|
210
|
+
if (!fs.existsSync(this.configPath)) {
|
|
211
|
+
throw new Error(`Configuration file not found: ${this.configPath}`);
|
|
212
|
+
}
|
|
213
|
+
const configContent = fs.readFileSync(this.configPath, 'utf8');
|
|
214
|
+
this.config = JSON.parse(configContent);
|
|
215
|
+
logger_1.logger.debug(`Loaded configuration from ${this.configPath}`);
|
|
216
|
+
return this.config;
|
|
217
|
+
}
|
|
218
|
+
catch (error) {
|
|
219
|
+
logger_1.logger.error(`Failed to load configuration from ${this.configPath}:`, error);
|
|
220
|
+
throw new Error(`Failed to load configuration: ${error instanceof Error ? error.message : String(error)}`);
|
|
221
|
+
}
|
|
216
222
|
}
|
|
217
223
|
/**
|
|
218
224
|
* Reload configuration from file
|
|
@@ -228,21 +234,8 @@ class ConfigLoader {
|
|
|
228
234
|
this.configPath = configPath;
|
|
229
235
|
this.config = null; // Force reload
|
|
230
236
|
}
|
|
231
|
-
/**
|
|
232
|
-
* Get the current configuration path
|
|
233
|
-
*/
|
|
234
|
-
getConfigPath() {
|
|
235
|
-
return this.configPath;
|
|
236
|
-
}
|
|
237
237
|
}
|
|
238
238
|
exports.ConfigLoader = ConfigLoader;
|
|
239
|
-
/**
|
|
240
|
-
* Convenience function to get the config loader instance
|
|
241
|
-
*/
|
|
242
|
-
function getConfigLoader(configPath) {
|
|
243
|
-
return ConfigLoader.getInstance(configPath);
|
|
244
|
-
}
|
|
245
|
-
exports.getConfigLoader = getConfigLoader;
|
|
246
239
|
/**
|
|
247
240
|
* Convenience function to get agent configuration
|
|
248
241
|
*/
|
|
@@ -257,6 +250,13 @@ function getAllAgentConfigs(configPath) {
|
|
|
257
250
|
return getConfigLoader(configPath).getAllAgentConfigs();
|
|
258
251
|
}
|
|
259
252
|
exports.getAllAgentConfigs = getAllAgentConfigs;
|
|
253
|
+
/**
|
|
254
|
+
* Convenience function to get the config loader instance
|
|
255
|
+
*/
|
|
256
|
+
function getConfigLoader(configPath) {
|
|
257
|
+
return ConfigLoader.getInstance(configPath);
|
|
258
|
+
}
|
|
259
|
+
exports.getConfigLoader = getConfigLoader;
|
|
260
260
|
/**
|
|
261
261
|
* Convenience function to get model configuration
|
|
262
262
|
*/
|
|
@@ -22,38 +22,31 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
22
22
|
__setModuleDefault(result, mod);
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
-
});
|
|
33
|
-
};
|
|
34
25
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
35
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
36
27
|
};
|
|
37
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
29
|
exports.DefaultApiKeyManager = void 0;
|
|
39
|
-
const fs = __importStar(require("fs"));
|
|
40
|
-
const
|
|
41
|
-
const
|
|
30
|
+
const fs = __importStar(require("node:fs"));
|
|
31
|
+
const os = __importStar(require("node:os"));
|
|
32
|
+
const path = __importStar(require("node:path"));
|
|
33
|
+
const node_readline_1 = __importDefault(require("node:readline"));
|
|
42
34
|
const api_key_service_1 = require("../services/api-key-service");
|
|
43
|
-
const readline_1 = __importDefault(require("readline"));
|
|
44
35
|
const logger_1 = require("./logger");
|
|
45
36
|
/**
|
|
46
37
|
* Manages the default API key for chat commands
|
|
47
38
|
*/
|
|
48
39
|
class DefaultApiKeyManager {
|
|
40
|
+
static instance;
|
|
41
|
+
configFilePath;
|
|
42
|
+
defaultApiKey = null;
|
|
49
43
|
constructor() {
|
|
50
|
-
this.defaultApiKey = null;
|
|
51
44
|
// Set up config file path in user's home directory
|
|
52
|
-
const bergetDir = path.join(os.homedir(),
|
|
45
|
+
const bergetDir = path.join(os.homedir(), '.berget');
|
|
53
46
|
if (!fs.existsSync(bergetDir)) {
|
|
54
47
|
fs.mkdirSync(bergetDir, { recursive: true });
|
|
55
48
|
}
|
|
56
|
-
this.configFilePath = path.join(bergetDir,
|
|
49
|
+
this.configFilePath = path.join(bergetDir, 'default-api-key.json');
|
|
57
50
|
this.loadConfig();
|
|
58
51
|
}
|
|
59
52
|
static getInstance() {
|
|
@@ -62,18 +55,133 @@ class DefaultApiKeyManager {
|
|
|
62
55
|
}
|
|
63
56
|
return DefaultApiKeyManager.instance;
|
|
64
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Clear the default API key
|
|
60
|
+
*/
|
|
61
|
+
clearDefaultApiKey() {
|
|
62
|
+
this.defaultApiKey = null;
|
|
63
|
+
this.saveConfig();
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Get the default API key string
|
|
67
|
+
*/
|
|
68
|
+
getDefaultApiKey() {
|
|
69
|
+
return this.defaultApiKey?.key || null;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Get the default API key data object
|
|
73
|
+
*/
|
|
74
|
+
getDefaultApiKeyData() {
|
|
75
|
+
return this.defaultApiKey;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Prompts the user to select a default API key if none is set
|
|
79
|
+
* @returns The selected API key or null if none was selected
|
|
80
|
+
*/
|
|
81
|
+
async promptForDefaultApiKey() {
|
|
82
|
+
try {
|
|
83
|
+
logger_1.logger.debug('promptForDefaultApiKey called');
|
|
84
|
+
// If we already have a default API key, return it
|
|
85
|
+
if (this.defaultApiKey) {
|
|
86
|
+
logger_1.logger.debug('Using existing default API key');
|
|
87
|
+
return this.defaultApiKey.key;
|
|
88
|
+
}
|
|
89
|
+
logger_1.logger.debug('No default API key found, getting ApiKeyService');
|
|
90
|
+
const apiKeyService = api_key_service_1.ApiKeyService.getInstance();
|
|
91
|
+
// Get all API keys
|
|
92
|
+
let apiKeys;
|
|
93
|
+
try {
|
|
94
|
+
logger_1.logger.debug('Calling apiKeyService.list()');
|
|
95
|
+
apiKeys = await apiKeyService.list();
|
|
96
|
+
logger_1.logger.debug(`Got ${apiKeys ? apiKeys.length : 0} API keys`);
|
|
97
|
+
if (!apiKeys || apiKeys.length === 0) {
|
|
98
|
+
logger_1.logger.warn('No API keys found. Create one with:');
|
|
99
|
+
logger_1.logger.info(' berget api-keys create --name "My Key"');
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
// Check if this is an authentication error
|
|
105
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
106
|
+
const isAuthError = errorMessage.includes('Unauthorized') ||
|
|
107
|
+
errorMessage.includes('Authentication failed') ||
|
|
108
|
+
errorMessage.includes('AUTH_FAILED');
|
|
109
|
+
if (isAuthError) {
|
|
110
|
+
logger_1.logger.warn('Authentication required. Please run `berget auth login` first.');
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
logger_1.logger.error('Error fetching API keys:');
|
|
114
|
+
if (error instanceof Error) {
|
|
115
|
+
logger_1.logger.error(error.message);
|
|
116
|
+
logger_1.logger.debug(`API key list error: ${error.message}`);
|
|
117
|
+
logger_1.logger.debug(`Stack: ${error.stack}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
logger_1.logger.info('Select an API key to use as default:');
|
|
123
|
+
// Display available API keys
|
|
124
|
+
for (const [index, key] of apiKeys.entries()) {
|
|
125
|
+
logger_1.logger.log(` ${index + 1}. ${key.name} (${key.prefix}...)`);
|
|
126
|
+
}
|
|
127
|
+
// Create readline interface for user input
|
|
128
|
+
const rl = node_readline_1.default.createInterface({
|
|
129
|
+
input: process.stdin,
|
|
130
|
+
output: process.stdout,
|
|
131
|
+
});
|
|
132
|
+
// Prompt for selection
|
|
133
|
+
const selection = await new Promise((resolve) => {
|
|
134
|
+
rl.question('Enter number (or press Enter to cancel): ', (answer) => {
|
|
135
|
+
rl.close();
|
|
136
|
+
const number_ = Number.parseInt(answer.trim(), 10);
|
|
137
|
+
if (isNaN(number_) || number_ < 1 || number_ > apiKeys.length) {
|
|
138
|
+
resolve(-1); // Invalid selection
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
resolve(number_ - 1); // Convert to zero-based index
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
if (selection === -1) {
|
|
146
|
+
logger_1.logger.warn('No API key selected');
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
const selectedKey = apiKeys[selection];
|
|
150
|
+
// Create a new API key with the selected name
|
|
151
|
+
const newKey = await apiKeyService.create({
|
|
152
|
+
description: 'Created automatically by the Berget CLI for default use',
|
|
153
|
+
name: `CLI Default (copy of ${selectedKey.name})`,
|
|
154
|
+
});
|
|
155
|
+
// Save the new key as default
|
|
156
|
+
this.setDefaultApiKey(newKey.id.toString(), newKey.name, newKey.key.slice(0, 8), // Use first 8 chars as prefix
|
|
157
|
+
newKey.key);
|
|
158
|
+
logger_1.logger.success(`✓ Default API key set to: ${newKey.name}`);
|
|
159
|
+
return newKey.key;
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
logger_1.logger.error('Failed to set default API key:', error);
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Set the default API key
|
|
168
|
+
*/
|
|
169
|
+
setDefaultApiKey(id, name, prefix, key) {
|
|
170
|
+
this.defaultApiKey = { id, key, name, prefix };
|
|
171
|
+
this.saveConfig();
|
|
172
|
+
}
|
|
65
173
|
/**
|
|
66
174
|
* Load default API key from file
|
|
67
175
|
*/
|
|
68
176
|
loadConfig() {
|
|
69
177
|
try {
|
|
70
178
|
if (fs.existsSync(this.configFilePath)) {
|
|
71
|
-
const data = fs.readFileSync(this.configFilePath,
|
|
179
|
+
const data = fs.readFileSync(this.configFilePath, 'utf8');
|
|
72
180
|
this.defaultApiKey = JSON.parse(data);
|
|
73
181
|
}
|
|
74
182
|
}
|
|
75
|
-
catch
|
|
76
|
-
logger_1.logger.debug(
|
|
183
|
+
catch {
|
|
184
|
+
logger_1.logger.debug('Failed to load default API key configuration');
|
|
77
185
|
this.defaultApiKey = null;
|
|
78
186
|
}
|
|
79
187
|
}
|
|
@@ -94,127 +202,9 @@ class DefaultApiKeyManager {
|
|
|
94
202
|
}
|
|
95
203
|
}
|
|
96
204
|
}
|
|
97
|
-
catch
|
|
98
|
-
logger_1.logger.debug(
|
|
205
|
+
catch {
|
|
206
|
+
logger_1.logger.debug('Failed to save default API key configuration');
|
|
99
207
|
}
|
|
100
208
|
}
|
|
101
|
-
/**
|
|
102
|
-
* Set the default API key
|
|
103
|
-
*/
|
|
104
|
-
setDefaultApiKey(id, name, prefix, key) {
|
|
105
|
-
this.defaultApiKey = { id, name, prefix, key };
|
|
106
|
-
this.saveConfig();
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* Get the default API key string
|
|
110
|
-
*/
|
|
111
|
-
getDefaultApiKey() {
|
|
112
|
-
var _a;
|
|
113
|
-
return ((_a = this.defaultApiKey) === null || _a === void 0 ? void 0 : _a.key) || null;
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Get the default API key data object
|
|
117
|
-
*/
|
|
118
|
-
getDefaultApiKeyData() {
|
|
119
|
-
return this.defaultApiKey;
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Clear the default API key
|
|
123
|
-
*/
|
|
124
|
-
clearDefaultApiKey() {
|
|
125
|
-
this.defaultApiKey = null;
|
|
126
|
-
this.saveConfig();
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Prompts the user to select a default API key if none is set
|
|
130
|
-
* @returns The selected API key or null if none was selected
|
|
131
|
-
*/
|
|
132
|
-
promptForDefaultApiKey() {
|
|
133
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
134
|
-
try {
|
|
135
|
-
logger_1.logger.debug("promptForDefaultApiKey called");
|
|
136
|
-
// If we already have a default API key, return it
|
|
137
|
-
if (this.defaultApiKey) {
|
|
138
|
-
logger_1.logger.debug("Using existing default API key");
|
|
139
|
-
return this.defaultApiKey.key;
|
|
140
|
-
}
|
|
141
|
-
logger_1.logger.debug("No default API key found, getting ApiKeyService");
|
|
142
|
-
const apiKeyService = api_key_service_1.ApiKeyService.getInstance();
|
|
143
|
-
// Get all API keys
|
|
144
|
-
let apiKeys;
|
|
145
|
-
try {
|
|
146
|
-
logger_1.logger.debug("Calling apiKeyService.list()");
|
|
147
|
-
apiKeys = yield apiKeyService.list();
|
|
148
|
-
logger_1.logger.debug(`Got ${apiKeys ? apiKeys.length : 0} API keys`);
|
|
149
|
-
if (!apiKeys || apiKeys.length === 0) {
|
|
150
|
-
logger_1.logger.warn("No API keys found. Create one with:");
|
|
151
|
-
logger_1.logger.info(' berget api-keys create --name "My Key"');
|
|
152
|
-
return null;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
catch (error) {
|
|
156
|
-
// Check if this is an authentication error
|
|
157
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
158
|
-
const isAuthError = errorMessage.includes("Unauthorized") ||
|
|
159
|
-
errorMessage.includes("Authentication failed") ||
|
|
160
|
-
errorMessage.includes("AUTH_FAILED");
|
|
161
|
-
if (isAuthError) {
|
|
162
|
-
logger_1.logger.warn("Authentication required. Please run `berget auth login` first.");
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
logger_1.logger.error("Error fetching API keys:");
|
|
166
|
-
if (error instanceof Error) {
|
|
167
|
-
logger_1.logger.error(error.message);
|
|
168
|
-
logger_1.logger.debug(`API key list error: ${error.message}`);
|
|
169
|
-
logger_1.logger.debug(`Stack: ${error.stack}`);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
return null;
|
|
173
|
-
}
|
|
174
|
-
logger_1.logger.info("Select an API key to use as default:");
|
|
175
|
-
// Display available API keys
|
|
176
|
-
apiKeys.forEach((key, index) => {
|
|
177
|
-
logger_1.logger.log(` ${index + 1}. ${key.name} (${key.prefix}...)`);
|
|
178
|
-
});
|
|
179
|
-
// Create readline interface for user input
|
|
180
|
-
const rl = readline_1.default.createInterface({
|
|
181
|
-
input: process.stdin,
|
|
182
|
-
output: process.stdout,
|
|
183
|
-
});
|
|
184
|
-
// Prompt for selection
|
|
185
|
-
const selection = yield new Promise(resolve => {
|
|
186
|
-
rl.question("Enter number (or press Enter to cancel): ", answer => {
|
|
187
|
-
rl.close();
|
|
188
|
-
const num = parseInt(answer.trim(), 10);
|
|
189
|
-
if (isNaN(num) || num < 1 || num > apiKeys.length) {
|
|
190
|
-
resolve(-1); // Invalid selection
|
|
191
|
-
}
|
|
192
|
-
else {
|
|
193
|
-
resolve(num - 1); // Convert to zero-based index
|
|
194
|
-
}
|
|
195
|
-
});
|
|
196
|
-
});
|
|
197
|
-
if (selection === -1) {
|
|
198
|
-
logger_1.logger.warn("No API key selected");
|
|
199
|
-
return null;
|
|
200
|
-
}
|
|
201
|
-
const selectedKey = apiKeys[selection];
|
|
202
|
-
// Create a new API key with the selected name
|
|
203
|
-
const newKey = yield apiKeyService.create({
|
|
204
|
-
name: `CLI Default (copy of ${selectedKey.name})`,
|
|
205
|
-
description: "Created automatically by the Berget CLI for default use",
|
|
206
|
-
});
|
|
207
|
-
// Save the new key as default
|
|
208
|
-
this.setDefaultApiKey(newKey.id.toString(), newKey.name, newKey.key.substring(0, 8), // Use first 8 chars as prefix
|
|
209
|
-
newKey.key);
|
|
210
|
-
logger_1.logger.success(`✓ Default API key set to: ${newKey.name}`);
|
|
211
|
-
return newKey.key;
|
|
212
|
-
}
|
|
213
|
-
catch (error) {
|
|
214
|
-
logger_1.logger.error("Failed to set default API key:", error);
|
|
215
|
-
return null;
|
|
216
|
-
}
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
209
|
}
|
|
220
210
|
exports.DefaultApiKeyManager = DefaultApiKeyManager;
|