feat(config): Add multi-agent support with pluggable registry

Implements agent abstraction layer to support multiple AI coding agents.

Built-in presets (E2E tested):
- Claude Code (default)
- Gemini CLI
- OpenAI Codex

Key changes:
- Add AgentRegistry with built-in presets and custom agent support
- Add TownSettings with default_agent and custom agents map
- Add Agent field to RigSettings for per-rig agent selection
- Update ResolveAgentConfig for hierarchical config resolution
- Update spawn paths to use configured agent instead of hardcoded claude

Configuration hierarchy (first match wins):
1. Rig's Runtime config (backwards compat)
2. Rig's Agent -> custom agents -> built-in presets
3. Town's default_agent setting
4. Fallback to Claude

Additional agents (aider, opencode, etc.) can be added via config file:
settings/agents.json

Addresses Issue #10: Agent Agnostic Engine with Multi-provider support

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
mayor
2026-01-04 14:46:54 -05:00
committed by Raymond Weitekamp
parent 8dea4acf8c
commit ea1a41f1f5
7 changed files with 709 additions and 20 deletions

View File

@@ -28,6 +28,38 @@ type MayorConfig struct {
DefaultCrewName string `json:"default_crew_name,omitempty"` // default crew name for new rigs
}
// CurrentTownSettingsVersion is the current schema version for TownSettings.
const CurrentTownSettingsVersion = 1
// TownSettings represents town-level behavioral configuration (settings/config.json).
// This contains agent configuration that applies to all rigs unless overridden.
type TownSettings struct {
Type string `json:"type"` // "town-settings"
Version int `json:"version"` // schema version
// DefaultAgent is the name of the agent preset to use by default.
// Can be a built-in preset ("claude", "gemini", "codex")
// or a custom agent name defined in settings/agents.json.
// Default: "claude"
DefaultAgent string `json:"default_agent,omitempty"`
// Agents defines custom agent configurations or overrides.
// Keys are agent names that can be referenced by DefaultAgent or rig settings.
// Values override or extend the built-in presets.
// Example: {"gemini": {"command": "/custom/path/to/gemini"}}
Agents map[string]*RuntimeConfig `json:"agents,omitempty"`
}
// NewTownSettings creates a new TownSettings with defaults.
func NewTownSettings() *TownSettings {
return &TownSettings{
Type: "town-settings",
Version: CurrentTownSettingsVersion,
DefaultAgent: "claude",
Agents: make(map[string]*RuntimeConfig),
}
}
// DaemonConfig represents daemon process settings.
type DaemonConfig struct {
HeartbeatInterval string `json:"heartbeat_interval,omitempty"` // e.g., "30s"
@@ -98,7 +130,14 @@ type RigSettings struct {
Theme *ThemeConfig `json:"theme,omitempty"` // tmux theme settings
Namepool *NamepoolConfig `json:"namepool,omitempty"` // polecat name pool settings
Crew *CrewConfig `json:"crew,omitempty"` // crew startup settings
Runtime *RuntimeConfig `json:"runtime,omitempty"` // LLM runtime settings
Runtime *RuntimeConfig `json:"runtime,omitempty"` // LLM runtime settings (deprecated: use Agent)
// Agent selects which agent preset to use for this rig.
// Can be a built-in preset ("claude", "gemini", "codex")
// or a custom agent defined in settings/agents.json.
// If empty, uses the town's default_agent setting.
// Takes precedence over Runtime if both are set.
Agent string `json:"agent,omitempty"`
}
// CrewConfig represents crew workspace settings for a rig.