feat: wire brain, org, sessionlog, retrospective skills into supervisor
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user