berget 2.0.3 → 2.0.4
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/AGENTS.md +29 -0
- package/dist/index.js +2 -0
- package/dist/package.json +1 -1
- package/dist/src/commands/api-keys.js +55 -7
- package/dist/src/commands/code.js +103 -57
- package/dist/src/constants/command-structure.js +2 -0
- package/dist/src/services/api-key-service.js +64 -1
- package/dist/src/utils/config-loader.js +217 -0
- package/dist/tests/utils/config-loader.test.js +182 -0
- package/index.ts +19 -19
- package/opencode.json +1 -1
- package/package.json +1 -1
- package/src/commands/api-keys.ts +93 -8
- package/src/commands/code.ts +119 -58
- package/src/constants/command-structure.ts +2 -0
- package/src/services/api-key-service.ts +100 -2
- package/src/utils/config-loader.ts +261 -0
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import * as fs from 'fs'
|
|
2
|
+
import * as path from 'path'
|
|
3
|
+
import { logger } from './logger'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Centralized agent configuration loader
|
|
7
|
+
* Loads all agent configurations from opencode.json as the single source of truth
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export interface AgentConfig {
|
|
11
|
+
model: string
|
|
12
|
+
temperature: number
|
|
13
|
+
top_p: number
|
|
14
|
+
mode: 'primary' | 'subagent'
|
|
15
|
+
permission: {
|
|
16
|
+
edit: 'allow' | 'deny'
|
|
17
|
+
bash: 'allow' | 'deny'
|
|
18
|
+
webfetch: 'allow' | 'deny'
|
|
19
|
+
}
|
|
20
|
+
description?: string
|
|
21
|
+
prompt?: string
|
|
22
|
+
note?: string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface ModelConfig {
|
|
26
|
+
primary: string
|
|
27
|
+
small: string
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface ProviderModelConfig {
|
|
31
|
+
name: string
|
|
32
|
+
limit: {
|
|
33
|
+
output: number
|
|
34
|
+
context: number
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface OpenCodeConfig {
|
|
39
|
+
$schema?: string
|
|
40
|
+
username?: string
|
|
41
|
+
theme?: string
|
|
42
|
+
share?: string
|
|
43
|
+
autoupdate?: boolean
|
|
44
|
+
model?: string
|
|
45
|
+
small_model?: string
|
|
46
|
+
agent?: Record<string, AgentConfig>
|
|
47
|
+
command?: Record<string, any>
|
|
48
|
+
watcher?: Record<string, any>
|
|
49
|
+
provider?: Record<string, any>
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export class ConfigLoader {
|
|
53
|
+
private static instance: ConfigLoader
|
|
54
|
+
private config: OpenCodeConfig | null = null
|
|
55
|
+
private configPath: string
|
|
56
|
+
|
|
57
|
+
private constructor(configPath?: string) {
|
|
58
|
+
// Default to opencode.json in current working directory
|
|
59
|
+
this.configPath = configPath || path.join(process.cwd(), 'opencode.json')
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public static getInstance(configPath?: string): ConfigLoader {
|
|
63
|
+
if (!ConfigLoader.instance) {
|
|
64
|
+
ConfigLoader.instance = new ConfigLoader(configPath)
|
|
65
|
+
}
|
|
66
|
+
return ConfigLoader.instance
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Load configuration from opencode.json
|
|
71
|
+
*/
|
|
72
|
+
public loadConfig(): OpenCodeConfig {
|
|
73
|
+
if (this.config) {
|
|
74
|
+
return this.config
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
if (!fs.existsSync(this.configPath)) {
|
|
79
|
+
throw new Error(`Configuration file not found: ${this.configPath}`)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const configContent = fs.readFileSync(this.configPath, 'utf8')
|
|
83
|
+
this.config = JSON.parse(configContent) as OpenCodeConfig
|
|
84
|
+
|
|
85
|
+
logger.debug(`Loaded configuration from ${this.configPath}`)
|
|
86
|
+
return this.config
|
|
87
|
+
} catch (error) {
|
|
88
|
+
logger.error(`Failed to load configuration from ${this.configPath}:`, error)
|
|
89
|
+
throw new Error(`Failed to load configuration: ${error instanceof Error ? error.message : String(error)}`)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Get agent configuration by name
|
|
95
|
+
*/
|
|
96
|
+
public getAgentConfig(agentName: string): AgentConfig | null {
|
|
97
|
+
const config = this.loadConfig()
|
|
98
|
+
return config.agent?.[agentName] || null
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Get all agent configurations
|
|
103
|
+
*/
|
|
104
|
+
public getAllAgentConfigs(): Record<string, AgentConfig> {
|
|
105
|
+
const config = this.loadConfig()
|
|
106
|
+
return config.agent || {}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Get model configuration
|
|
111
|
+
*/
|
|
112
|
+
public getModelConfig(): ModelConfig {
|
|
113
|
+
const config = this.loadConfig()
|
|
114
|
+
|
|
115
|
+
// Extract from config or fall back to defaults
|
|
116
|
+
const primary = config.model || 'berget/deepseek-r1'
|
|
117
|
+
const small = config.small_model || 'berget/gpt-oss'
|
|
118
|
+
|
|
119
|
+
return { primary, small }
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Get provider model configuration
|
|
124
|
+
*/
|
|
125
|
+
public getProviderModels(): Record<string, ProviderModelConfig> {
|
|
126
|
+
const config = this.loadConfig()
|
|
127
|
+
|
|
128
|
+
// Extract from provider configuration
|
|
129
|
+
if (config.provider?.berget?.models) {
|
|
130
|
+
return config.provider.berget.models as Record<string, ProviderModelConfig>
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Fallback to defaults
|
|
134
|
+
return {
|
|
135
|
+
'deepseek-r1': {
|
|
136
|
+
name: 'GLM-4.6',
|
|
137
|
+
limit: { output: 4000, context: 90000 }
|
|
138
|
+
},
|
|
139
|
+
'gpt-oss': {
|
|
140
|
+
name: 'GPT-OSS',
|
|
141
|
+
limit: { output: 4000, context: 128000 }
|
|
142
|
+
},
|
|
143
|
+
'llama-8b': {
|
|
144
|
+
name: 'llama-3.1-8b',
|
|
145
|
+
limit: { output: 4000, context: 128000 }
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Get command configurations
|
|
152
|
+
*/
|
|
153
|
+
public getCommandConfigs(): Record<string, any> {
|
|
154
|
+
const config = this.loadConfig()
|
|
155
|
+
return config.command || {}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Get watcher configuration
|
|
160
|
+
*/
|
|
161
|
+
public getWatcherConfig(): Record<string, any> {
|
|
162
|
+
const config = this.loadConfig()
|
|
163
|
+
return config.watcher || { ignore: ['node_modules', 'dist', '.git', 'coverage'] }
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Get provider configuration
|
|
168
|
+
*/
|
|
169
|
+
public getProviderConfig(): Record<string, any> {
|
|
170
|
+
const config = this.loadConfig()
|
|
171
|
+
return config.provider || {}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Check if an agent exists
|
|
176
|
+
*/
|
|
177
|
+
public hasAgent(agentName: string): boolean {
|
|
178
|
+
return agentName in this.getAllAgentConfigs()
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Get list of all available agent names
|
|
183
|
+
*/
|
|
184
|
+
public getAgentNames(): string[] {
|
|
185
|
+
return Object.keys(this.getAllAgentConfigs())
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Get list of primary agents (mode: 'primary')
|
|
190
|
+
*/
|
|
191
|
+
public getPrimaryAgentNames(): string[] {
|
|
192
|
+
const agents = this.getAllAgentConfigs()
|
|
193
|
+
return Object.keys(agents).filter(name => agents[name].mode === 'primary')
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Get list of subagents (mode: 'subagent')
|
|
198
|
+
*/
|
|
199
|
+
public getSubagentNames(): string[] {
|
|
200
|
+
const agents = this.getAllAgentConfigs()
|
|
201
|
+
return Object.keys(agents).filter(name => agents[name].mode === 'subagent')
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Reload configuration from file
|
|
206
|
+
*/
|
|
207
|
+
public reloadConfig(): OpenCodeConfig {
|
|
208
|
+
this.config = null
|
|
209
|
+
return this.loadConfig()
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Set custom configuration path (for testing or different environments)
|
|
214
|
+
*/
|
|
215
|
+
public setConfigPath(configPath: string): void {
|
|
216
|
+
this.configPath = configPath
|
|
217
|
+
this.config = null // Force reload
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Get the current configuration path
|
|
222
|
+
*/
|
|
223
|
+
public getConfigPath(): string {
|
|
224
|
+
return this.configPath
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Convenience function to get the config loader instance
|
|
230
|
+
*/
|
|
231
|
+
export function getConfigLoader(configPath?: string): ConfigLoader {
|
|
232
|
+
return ConfigLoader.getInstance(configPath)
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Convenience function to get agent configuration
|
|
237
|
+
*/
|
|
238
|
+
export function getAgentConfig(agentName: string, configPath?: string): AgentConfig | null {
|
|
239
|
+
return getConfigLoader(configPath).getAgentConfig(agentName)
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Convenience function to get all agent configurations
|
|
244
|
+
*/
|
|
245
|
+
export function getAllAgentConfigs(configPath?: string): Record<string, AgentConfig> {
|
|
246
|
+
return getConfigLoader(configPath).getAllAgentConfigs()
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Convenience function to get model configuration
|
|
251
|
+
*/
|
|
252
|
+
export function getModelConfig(configPath?: string): ModelConfig {
|
|
253
|
+
return getConfigLoader(configPath).getModelConfig()
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Convenience function to get provider models
|
|
258
|
+
*/
|
|
259
|
+
export function getProviderModels(configPath?: string): Record<string, ProviderModelConfig> {
|
|
260
|
+
return getConfigLoader(configPath).getProviderModels()
|
|
261
|
+
}
|