feat: wire brain, org, sessionlog, retrospective skills into supervisor

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Mathias Bergqvist
2026-04-17 20:52:16 +02:00
parent 23dd355b8a
commit e98bb2ba65
5 changed files with 56 additions and 3 deletions

View File

@@ -6,3 +6,12 @@ SUPERVISOR_MODELS_FILE=./config/models.yaml
# LiteLLM gateway (iguana) # LiteLLM gateway (iguana)
LITELLM_BASE_URL=http://iguana:4000 LITELLM_BASE_URL=http://iguana:4000
LITELLM_API_KEY=your-litellm-master-key LITELLM_API_KEY=your-litellm-master-key
# Ingestion server
INGEST_BASE_URL=http://localhost:3300
INGEST_PORT=3300
INGEST_BRAIN_DIR=./brain
# Brain directories
SUPERVISOR_SESSIONS_DIR=./brain/sessions
SUPERVISOR_BRAIN_DIR=./brain

View File

@@ -1,6 +1,7 @@
package main package main
import ( import (
"context"
"log/slog" "log/slog"
"net/http" "net/http"
"os" "os"
@@ -9,7 +10,12 @@ import (
iexec "github.com/mathiasbq/supervisor/internal/exec" iexec "github.com/mathiasbq/supervisor/internal/exec"
"github.com/mathiasbq/supervisor/internal/mcp" "github.com/mathiasbq/supervisor/internal/mcp"
"github.com/mathiasbq/supervisor/internal/registry" "github.com/mathiasbq/supervisor/internal/registry"
"github.com/mathiasbq/supervisor/internal/skills/brain"
"github.com/mathiasbq/supervisor/internal/skills/org"
"github.com/mathiasbq/supervisor/internal/skills/retrospective"
"github.com/mathiasbq/supervisor/internal/skills/sessionlog"
"github.com/mathiasbq/supervisor/internal/skills/tdd" "github.com/mathiasbq/supervisor/internal/skills/tdd"
"github.com/mathiasbq/supervisor/internal/tier"
) )
func main() { func main() {
@@ -39,12 +45,22 @@ func main() {
os.Exit(1) os.Exit(1)
} }
retroPrompt, err := os.ReadFile(cfg.ConfigDir + "/retrospective.md")
if err != nil {
logger.Error("read retrospective.md", "path", cfg.ConfigDir+"/retrospective.md", "err", err)
os.Exit(1)
}
executor := iexec.New(iexec.Config{ executor := iexec.New(iexec.Config{
SystemPrompt: string(systemPrompt), SystemPrompt: string(systemPrompt),
LiteLLMBaseURL: cfg.LiteLLMBaseURL, LiteLLMBaseURL: cfg.LiteLLMBaseURL,
LiteLLMAPIKey: cfg.LiteLLMAPIKey, LiteLLMAPIKey: cfg.LiteLLMAPIKey,
}) })
tierFn := func(ctx context.Context) tier.Info {
return tier.Detect(ctx, "https://api.anthropic.com", cfg.LiteLLMBaseURL)
}
reg := registry.New() reg := registry.New()
reg.Register(tdd.New(tdd.Config{ reg.Register(tdd.New(tdd.Config{
SystemPrompt: string(systemPrompt), SystemPrompt: string(systemPrompt),
@@ -52,6 +68,21 @@ func main() {
DefaultModel: models.Resolve("tdd", ""), DefaultModel: models.Resolve("tdd", ""),
ExecutorFn: executor.Run, ExecutorFn: executor.Run,
})) }))
reg.Register(brain.New(brain.Config{
IngestBaseURL: cfg.IngestBaseURL,
}))
reg.Register(org.New(org.Config{
TierFn: tierFn,
}))
reg.Register(sessionlog.New(sessionlog.Config{
SessionsDir: cfg.SessionsDir,
}))
reg.Register(retrospective.New(retrospective.Config{
SkillPrompt: string(retroPrompt),
DefaultModel: models.Resolve("retrospective", ""),
SessionsDir: cfg.SessionsDir,
ExecutorFn: executor.Run,
}))
srv := mcp.NewServer(reg) srv := mcp.NewServer(reg)
mux := http.NewServeMux() mux := http.NewServeMux()

View File

@@ -5,6 +5,7 @@
default: ollama/qwen3-coder-30b-tuned default: ollama/qwen3-coder-30b-tuned
skills: skills:
tdd: ollama/qwen3-coder-30b-tuned tdd: ollama/qwen3-coder-30b-tuned
review: ollama/devstral-tuned review: ollama/devstral-tuned
debug: ollama/deepseek-r1-tuned debug: ollama/deepseek-r1-tuned
retrospective: ollama/qwen3-coder-30b-tuned

View File

@@ -8,6 +8,9 @@ type Config struct {
LiteLLMAPIKey string // LITELLM_API_KEY LiteLLMAPIKey string // LITELLM_API_KEY
ConfigDir string // SUPERVISOR_CONFIG_DIR, default ./config/supervisor ConfigDir string // SUPERVISOR_CONFIG_DIR, default ./config/supervisor
ModelsFile string // SUPERVISOR_MODELS_FILE, default <ConfigDir>/../models.yaml ModelsFile string // SUPERVISOR_MODELS_FILE, default <ConfigDir>/../models.yaml
IngestBaseURL string // INGEST_BASE_URL, default http://localhost:3300
SessionsDir string // SUPERVISOR_SESSIONS_DIR, default ./brain/sessions
BrainDir string // SUPERVISOR_BRAIN_DIR, default ./brain
} }
func Load() (Config, error) { func Load() (Config, error) {
@@ -18,6 +21,9 @@ func Load() (Config, error) {
ConfigDir: envOr("SUPERVISOR_CONFIG_DIR", "./config/supervisor"), ConfigDir: envOr("SUPERVISOR_CONFIG_DIR", "./config/supervisor"),
} }
cfg.ModelsFile = envOr("SUPERVISOR_MODELS_FILE", cfg.ConfigDir+"/../models.yaml") cfg.ModelsFile = envOr("SUPERVISOR_MODELS_FILE", cfg.ConfigDir+"/../models.yaml")
cfg.IngestBaseURL = envOr("INGEST_BASE_URL", "http://localhost:3300")
cfg.SessionsDir = envOr("SUPERVISOR_SESSIONS_DIR", "./brain/sessions")
cfg.BrainDir = envOr("SUPERVISOR_BRAIN_DIR", "./brain")
return cfg, nil return cfg, nil
} }

View File

@@ -13,12 +13,18 @@ func TestLoadDefaults(t *testing.T) {
t.Setenv("LITELLM_BASE_URL", "") t.Setenv("LITELLM_BASE_URL", "")
t.Setenv("LITELLM_API_KEY", "") t.Setenv("LITELLM_API_KEY", "")
t.Setenv("SUPERVISOR_CONFIG_DIR", "") t.Setenv("SUPERVISOR_CONFIG_DIR", "")
t.Setenv("INGEST_BASE_URL", "")
t.Setenv("SUPERVISOR_SESSIONS_DIR", "")
t.Setenv("SUPERVISOR_BRAIN_DIR", "")
cfg, err := config.Load() cfg, err := config.Load()
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "3200", cfg.Port) assert.Equal(t, "3200", cfg.Port)
assert.Equal(t, "http://iguana:4000", cfg.LiteLLMBaseURL) assert.Equal(t, "http://iguana:4000", cfg.LiteLLMBaseURL)
assert.Equal(t, "./config/supervisor", cfg.ConfigDir) assert.Equal(t, "./config/supervisor", cfg.ConfigDir)
assert.Equal(t, "http://localhost:3300", cfg.IngestBaseURL)
assert.Equal(t, "./brain/sessions", cfg.SessionsDir)
assert.Equal(t, "./brain", cfg.BrainDir)
} }
func TestLoadFromEnv(t *testing.T) { func TestLoadFromEnv(t *testing.T) {