Files
Sidekick/config.go
T

102 lines
3.3 KiB
Go
Raw Normal View History

2026-03-21 16:20:16 +02:00
package sidekick
import (
"os"
"strings"
"time"
"github.com/BurntSushi/toml"
)
// ProjectConfig represents the root of the TOML configuration
type ProjectConfig struct {
ToolResponseThreshold int `toml:"tool_response_threshold"`
MCPListener MCPListenerConfig `toml:"mcp_listener"`
Models map[string]ModelConfig `toml:"models"`
MCPServers map[string]MCPServerConfig `toml:"mcp_servers"`
Agents map[string]AgentConfig `toml:"agents"`
}
// MCPListenerConfig configures the MCP server exposed by Sidekick
type MCPListenerConfig struct {
Transport string `toml:"transport"` // "stdio" or "http"
Port int `toml:"port"` // used if transport is "http"
}
// ModelConfig holds configuration for the LLM
type ModelConfig struct {
ModelID string `toml:"model_id"`
Endpoint string `toml:"endpoint"`
APIKey string `toml:"api_key"`
Temperature float32 `toml:"temperature"`
MaxTokens int `toml:"max_tokens"`
TimeoutSecs int `toml:"timeout_secs"`
Timeout time.Duration `toml:"-"`
}
// MCPServerConfig configures a single MCP server connection
type MCPServerConfig struct {
Transport string `toml:"transport"` // "stdio", "sse", "http", "websocket"
Command string `toml:"command"` // for stdio
Args []string `toml:"args"` // for stdio
Env []string `toml:"env"` // for stdio, format "KEY=VALUE"
URL string `toml:"url"` // for HTTP/SSE/WebSocket
}
// AgentConfig holds configuration for a specific agent instance
type AgentConfig struct {
ID string `toml:"-"`
Role Role `toml:"role"`
ModelID string `toml:"model_id"`
Goals []string `toml:"goals"`
SystemPrompt string `toml:"system_prompt"`
Description string `toml:"description"`
MaxIterations int `toml:"max_iterations"`
Toolsets []string `toml:"toolsets"` // Allowed tool namespaces (MCP servers)
Subagents []string `toml:"subagents"` // Allowed subagent IDs
ToolResponseThreshold int `toml:"-"`
}
// resolveEnv checks if a string starts with "env:" and resolves it
func resolveEnv(val string) string {
if strings.HasPrefix(val, "env:") {
envVar := strings.TrimPrefix(val, "env:")
return os.Getenv(envVar)
}
return val
}
// Resolve applies environment variable resolution to relevant fields
func (m *ModelConfig) Resolve() {
m.ModelID = resolveEnv(m.ModelID)
m.Endpoint = resolveEnv(m.Endpoint)
m.APIKey = resolveEnv(m.APIKey)
if m.TimeoutSecs > 0 {
m.Timeout = time.Duration(m.TimeoutSecs) * time.Second
}
if m.Timeout == 0 {
m.Timeout = 120 * time.Second
}
}
// LoadConfig parses a TOML configuration file into ProjectConfig
func LoadConfig(path string) (*ProjectConfig, error) {
var cfg ProjectConfig
if _, err := toml.DecodeFile(path, &cfg); err != nil {
return nil, err
}
if cfg.ToolResponseThreshold <= 0 {
cfg.ToolResponseThreshold = 10000
}
for k, m := range cfg.Models {
m.Resolve()
cfg.Models[k] = m
}
for k, a := range cfg.Agents {
a.ID = k
a.ToolResponseThreshold = cfg.ToolResponseThreshold
cfg.Agents[k] = a
}
return &cfg, nil
}