berget 2.0.2 → 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.
@@ -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
+ }